/drivers/media/video/samsung/fimg2d3x/

3.0'>archive/unc-master-3.0 The LITMUS^RT kernel.Bjoern Brandenburg
aboutsummaryrefslogblamecommitdiffstats
path: root/security/device_cgroup.c
blob: 5ba78701adc3ab868079ee180b1fc2e4ffc3b95f (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
  
                                            








                                
                           
                           











                                                      

                                      






                              
                            




                                       

  




                                                                                

                                                                           
                                                                                

 




                                                                            


















                                                                             
                                                           

                                           















                                                                



                                                           
                                                 
 
                                                      


                               













                                                                 
                                                                         


                 







                                                                 

                             





                                                           












                                                                           

                                                                  

                 


























                                                                             
                                      










                                                                       


















                                                                         

                    
                    
                



                                               
                               


















                                    
                                             
 
                    
                                 
            
                                      

 

                                                                        
 
                                                                   
                                      
                                                         
 

                                                                  
                                            



                                                                      
         
                          
 
                 
























                                                                             
                                                      










                                                               
                                                      

                                                                
                                                         
                                  



                                          
                                                














                                                                           

                                                                    
 
                      
                   
                  




                                     






                                     

                              







                                    
                               

            

                               




                                 

                                                        
                
                               
         

                               






                                 

                                                        
                
                               
         

                               















                                                       
                                       



                 

                           


                                                         



                                                 
                               
         

                 
 







                                                                          
                        





                                           
                                                        



                                       
                                                       

                                      




                                                      



















                                                                      







                                                               
 
                        


                                             
                                                                   














                                                                      
                                  

                         
 
                          





                                              


                                      
                        


                                             













                                                               
                                  

                         
 
                          
 

                      
/*
 * device_cgroup.c - device cgroup subsystem
 *
 * Copyright 2007 IBM Corp
 */

#include <linux/device_cgroup.h>
#include <linux/cgroup.h>
#include <linux/ctype.h>
#include <linux/list.h>
#include <linux/uaccess.h>
#include <linux/seq_file.h>
#include <linux/rcupdate.h>

#define ACC_MKNOD 1
#define ACC_READ  2
#define ACC_WRITE 4
#define ACC_MASK (ACC_MKNOD | ACC_READ | ACC_WRITE)

#define DEV_BLOCK 1
#define DEV_CHAR  2
#define DEV_ALL   4  /* this represents all devices */

/*
 * whitelist locking rules:
 * hold cgroup_lock() for update/read.
 * hold rcu_read_lock() for read.
 */

struct dev_whitelist_item {
	u32 major, minor;
	short type;
	short access;
	struct list_head list;
	struct rcu_head rcu;
};

struct dev_cgroup {
	struct cgroup_subsys_state css;
	struct list_head whitelist;
};

static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s)
{
	return container_of(s, struct dev_cgroup, css);
}

static inline struct dev_cgroup *cgroup_to_devcgroup(struct cgroup *cgroup)
{
	return css_to_devcgroup(cgroup_subsys_state(cgroup, devices_subsys_id));
}

static inline struct dev_cgroup *task_devcgroup(struct task_struct *task)
{
	return css_to_devcgroup(task_subsys_state(task, devices_subsys_id));
}

struct cgroup_subsys devices_subsys;

static int devcgroup_can_attach(struct cgroup_subsys *ss,
		struct cgroup *new_cgroup, struct task_struct *task)
{
	if (current != task && !capable(CAP_SYS_ADMIN))
			return -EPERM;

	return 0;
}

/*
 * called under cgroup_lock()
 */
static int dev_whitelist_copy(struct list_head *dest, struct list_head *orig)
{
	struct dev_whitelist_item *wh, *tmp, *new;

	list_for_each_entry(wh, orig, list) {
		new = kmemdup(wh, sizeof(*wh), GFP_KERNEL);
		if (!new)
			goto free_and_exit;
		list_add_tail(&new->list, dest);
	}

	return 0;

free_and_exit:
	list_for_each_entry_safe(wh, tmp, dest, list) {
		list_del(&wh->list);
		kfree(wh);
	}
	return -ENOMEM;
}

/* Stupid prototype - don't bother combining existing entries */
/*
 * called under cgroup_lock()
 */
static int dev_whitelist_add(struct dev_cgroup *dev_cgroup,
			struct dev_whitelist_item *wh)
{
	struct dev_whitelist_item *whcopy, *walk;

	whcopy = kmemdup(wh, sizeof(*wh), GFP_KERNEL);
	if (!whcopy)
		return -ENOMEM;

	list_for_each_entry(walk, &dev_cgroup->whitelist, list) {
		if (walk->type != wh->type)
			continue;
		if (walk->major != wh->major)
			continue;
		if (walk->minor != wh->minor)
			continue;

		walk->access |= wh->access;
		kfree(whcopy);
		whcopy = NULL;
	}

	if (whcopy != NULL)
		list_add_tail_rcu(&whcopy->list, &dev_cgroup->whitelist);
	return 0;
}

static void whitelist_item_free(struct rcu_head *rcu)
{
	struct dev_whitelist_item *item;

	item = container_of(rcu, struct dev_whitelist_item, rcu);
	kfree(item);
}

/*
 * called under cgroup_lock()
 */
static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup,
			struct dev_whitelist_item *wh)
{
	struct dev_whitelist_item *walk, *tmp;

	list_for_each_entry_safe(walk, tmp, &dev_cgroup->whitelist, list) {
		if (walk->type == DEV_ALL)
			goto remove;
		if (walk->type != wh->type)
			continue;