Merge branch 'post-2.6.15' of git://brick.kernel.dk/data/git/linux-2.6-block
[sfrench/cifs-2.6.git] / security / selinux / selinuxfs.c
index a45cc971e73588bdc0c2e5a74774736c854f713d..e59da6398d44508ca902c7dad417ddb0cdba888a 100644 (file)
@@ -105,7 +105,7 @@ static ssize_t sel_write_enforce(struct file * file, const char __user * buf,
        ssize_t length;
        int new_value;
 
-       if (count < 0 || count >= PAGE_SIZE)
+       if (count >= PAGE_SIZE)
                return -ENOMEM;
        if (*ppos != 0) {
                /* No partial writes. */
@@ -155,7 +155,7 @@ static ssize_t sel_write_disable(struct file * file, const char __user * buf,
        int new_value;
        extern int selinux_disable(void);
 
-       if (count < 0 || count >= PAGE_SIZE)
+       if (count >= PAGE_SIZE)
                return -ENOMEM;
        if (*ppos != 0) {
                /* No partial writes. */
@@ -242,7 +242,7 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
                goto out;
        }
 
-       if ((count < 0) || (count > 64 * 1024 * 1024)
+       if ((count > 64 * 1024 * 1024)
            || (data = vmalloc(count)) == NULL) {
                length = -ENOMEM;
                goto out;
@@ -271,46 +271,38 @@ static struct file_operations sel_load_ops = {
        .write          = sel_write_load,
 };
 
-
-static ssize_t sel_write_context(struct file * file, const char __user * buf,
-                                size_t count, loff_t *ppos)
-
+static ssize_t sel_write_context(struct file * file, char *buf, size_t size)
 {
-       char *page;
-       u32 sid;
+       char *canon;
+       u32 sid, len;
        ssize_t length;
 
        length = task_has_security(current, SECURITY__CHECK_CONTEXT);
        if (length)
                return length;
 
-       if (count < 0 || count >= PAGE_SIZE)
-               return -ENOMEM;
-       if (*ppos != 0) {
-               /* No partial writes. */
-               return -EINVAL;
-       }
-       page = (char*)get_zeroed_page(GFP_KERNEL);
-       if (!page)
-               return -ENOMEM;
-       length = -EFAULT;
-       if (copy_from_user(page, buf, count))
-               goto out;
+       length = security_context_to_sid(buf, size, &sid);
+       if (length < 0)
+               return length;
 
-       length = security_context_to_sid(page, count, &sid);
+       length = security_sid_to_context(sid, &canon, &len);
        if (length < 0)
+               return length;
+
+       if (len > SIMPLE_TRANSACTION_LIMIT) {
+               printk(KERN_ERR "%s:  context size (%u) exceeds payload "
+                      "max\n", __FUNCTION__, len);
+               length = -ERANGE;
                goto out;
+       }
 
-       length = count;
+       memcpy(buf, canon, len);
+       length = len;
 out:
-       free_page((unsigned long) page);
+       kfree(canon);
        return length;
 }
 
-static struct file_operations sel_context_ops = {
-       .write          = sel_write_context,
-};
-
 static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf,
                                     size_t count, loff_t *ppos)
 {
@@ -332,7 +324,7 @@ static ssize_t sel_write_checkreqprot(struct file * file, const char __user * bu
        if (length)
                return length;
 
-       if (count < 0 || count >= PAGE_SIZE)
+       if (count >= PAGE_SIZE)
                return -ENOMEM;
        if (*ppos != 0) {
                /* No partial writes. */
@@ -375,6 +367,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
        [SEL_RELABEL] = sel_write_relabel,
        [SEL_USER] = sel_write_user,
        [SEL_MEMBER] = sel_write_member,
+       [SEL_CONTEXT] = sel_write_context,
 };
 
 static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
@@ -383,7 +376,7 @@ static ssize_t selinux_transaction_write(struct file *file, const char __user *b
        char *data;
        ssize_t rv;
 
-       if (ino >= sizeof(write_op)/sizeof(write_op[0]) || !write_op[ino])
+       if (ino >= ARRAY_SIZE(write_op) || !write_op[ino])
                return -EINVAL;
 
        data = simple_transaction_get(file, buf, size);
@@ -424,15 +417,13 @@ static ssize_t sel_write_access(struct file * file, char *buf, size_t size)
                return length;
 
        length = -ENOMEM;
-       scon = kmalloc(size+1, GFP_KERNEL);
+       scon = kzalloc(size+1, GFP_KERNEL);
        if (!scon)
                return length;
-       memset(scon, 0, size+1);
 
-       tcon = kmalloc(size+1, GFP_KERNEL);
+       tcon = kzalloc(size+1, GFP_KERNEL);
        if (!tcon)
                goto out;
-       memset(tcon, 0, size+1);
 
        length = -EINVAL;
        if (sscanf(buf, "%s %s %hu %x", scon, tcon, &tclass, &req) != 4)
@@ -475,15 +466,13 @@ static ssize_t sel_write_create(struct file * file, char *buf, size_t size)
                return length;
 
        length = -ENOMEM;
-       scon = kmalloc(size+1, GFP_KERNEL);
+       scon = kzalloc(size+1, GFP_KERNEL);
        if (!scon)
                return length;
-       memset(scon, 0, size+1);
 
-       tcon = kmalloc(size+1, GFP_KERNEL);
+       tcon = kzalloc(size+1, GFP_KERNEL);
        if (!tcon)
                goto out;
-       memset(tcon, 0, size+1);
 
        length = -EINVAL;
        if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
@@ -536,15 +525,13 @@ static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size)
                return length;
 
        length = -ENOMEM;
-       scon = kmalloc(size+1, GFP_KERNEL);
+       scon = kzalloc(size+1, GFP_KERNEL);
        if (!scon)
                return length;
-       memset(scon, 0, size+1);
 
-       tcon = kmalloc(size+1, GFP_KERNEL);
+       tcon = kzalloc(size+1, GFP_KERNEL);
        if (!tcon)
                goto out;
-       memset(tcon, 0, size+1);
 
        length = -EINVAL;
        if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
@@ -595,15 +582,13 @@ static ssize_t sel_write_user(struct file * file, char *buf, size_t size)
                return length;
 
        length = -ENOMEM;
-       con = kmalloc(size+1, GFP_KERNEL);
+       con = kzalloc(size+1, GFP_KERNEL);
        if (!con)
                return length;
-       memset(con, 0, size+1);
 
-       user = kmalloc(size+1, GFP_KERNEL);
+       user = kzalloc(size+1, GFP_KERNEL);
        if (!user)
                goto out;
-       memset(user, 0, size+1);
 
        length = -EINVAL;
        if (sscanf(buf, "%s %s", con, user) != 2)
@@ -658,15 +643,13 @@ static ssize_t sel_write_member(struct file * file, char *buf, size_t size)
                return length;
 
        length = -ENOMEM;
-       scon = kmalloc(size+1, GFP_KERNEL);
+       scon = kzalloc(size+1, GFP_KERNEL);
        if (!scon)
                return length;
-       memset(scon, 0, size+1);
 
-       tcon = kmalloc(size+1, GFP_KERNEL);
+       tcon = kzalloc(size+1, GFP_KERNEL);
        if (!tcon)
                goto out;
-       memset(tcon, 0, size+1);
 
        length = -EINVAL;
        if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
@@ -739,7 +722,7 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
        if (!filep->f_op)
                goto out;
 
-       if (count < 0 || count > PAGE_SIZE) {
+       if (count > PAGE_SIZE) {
                ret = -EINVAL;
                goto out;
        }
@@ -800,7 +783,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
        if (!filep->f_op)
                goto out;
 
-       if (count < 0 || count >= PAGE_SIZE) {
+       if (count >= PAGE_SIZE) {
                length = -ENOMEM;
                goto out;
        }
@@ -858,7 +841,7 @@ static ssize_t sel_commit_bools_write(struct file *filep,
        if (!filep->f_op)
                goto out;
 
-       if (count < 0 || count >= PAGE_SIZE) {
+       if (count >= PAGE_SIZE) {
                length = -ENOMEM;
                goto out;
        }
@@ -924,7 +907,7 @@ static void sel_remove_bools(struct dentry *de)
 
        file_list_lock();
        list_for_each(p, &sb->s_files) {
-               struct file * filp = list_entry(p, struct file, f_list);
+               struct file * filp = list_entry(p, struct file, f_u.fu_list);
                struct dentry * dentry = filp->f_dentry;
 
                if (dentry->d_parent != de) {
@@ -1032,7 +1015,7 @@ static ssize_t sel_write_avc_cache_threshold(struct file * file,
        ssize_t ret;
        int new_value;
 
-       if (count < 0 || count >= PAGE_SIZE) {
+       if (count >= PAGE_SIZE) {
                ret = -ENOMEM;
                goto out;
        }
@@ -1178,7 +1161,7 @@ static int sel_make_avc_files(struct dentry *dir)
 #endif
        };
 
-       for (i = 0; i < sizeof (files) / sizeof (files[0]); i++) {
+       for (i = 0; i < ARRAY_SIZE(files); i++) {
                struct inode *inode;
                struct dentry *dentry;
 
@@ -1230,7 +1213,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
        static struct tree_descr selinux_files[] = {
                [SEL_LOAD] = {"load", &sel_load_ops, S_IRUSR|S_IWUSR},
                [SEL_ENFORCE] = {"enforce", &sel_enforce_ops, S_IRUGO|S_IWUSR},
-               [SEL_CONTEXT] = {"context", &sel_context_ops, S_IRUGO|S_IWUGO},
+               [SEL_CONTEXT] = {"context", &transaction_ops, S_IRUGO|S_IWUGO},
                [SEL_ACCESS] = {"access", &transaction_ops, S_IRUGO|S_IWUGO},
                [SEL_CREATE] = {"create", &transaction_ops, S_IRUGO|S_IWUGO},
                [SEL_RELABEL] = {"relabel", &transaction_ops, S_IRUGO|S_IWUGO},