selinuxfs: switch to memdup_user_nul()
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 24 Dec 2015 05:08:06 +0000 (00:08 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 4 Jan 2016 15:27:39 +0000 (10:27 -0500)
Nothing in there gives a damn about the buffer alignment - it
just parses its contents.  So the use of get_zeroed_page()
doesn't buy us anything - might as well had been kmalloc(),
which makes that code equivalent to open-coded memdup_user_nul()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
security/selinux/selinuxfs.c

index c02da25d7b631992aa7841ca98250b08b48d8477..73c60baa90a4736de9b4598946b4407ef1e05d16 100644 (file)
@@ -147,23 +147,16 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
        ssize_t length;
        int new_value;
 
-       length = -ENOMEM;
        if (count >= PAGE_SIZE)
-               goto out;
+               return -ENOMEM;
 
        /* No partial writes. */
-       length = -EINVAL;
        if (*ppos != 0)
-               goto out;
-
-       length = -ENOMEM;
-       page = (char *)get_zeroed_page(GFP_KERNEL);
-       if (!page)
-               goto out;
+               return -EINVAL;
 
-       length = -EFAULT;
-       if (copy_from_user(page, buf, count))
-               goto out;
+       page = memdup_user_nul(buf, count);
+       if (IS_ERR(page))
+               return PTR_ERR(page);
 
        length = -EINVAL;
        if (sscanf(page, "%d", &new_value) != 1)
@@ -186,7 +179,7 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
        }
        length = count;
 out:
-       free_page((unsigned long) page);
+       kfree(page);
        return length;
 }
 #else
@@ -275,27 +268,20 @@ static ssize_t sel_write_disable(struct file *file, const char __user *buf,
                                 size_t count, loff_t *ppos)
 
 {
-       char *page = NULL;
+       char *page;
        ssize_t length;
        int new_value;
 
-       length = -ENOMEM;
        if (count >= PAGE_SIZE)
-               goto out;
+               return -ENOMEM;
 
        /* No partial writes. */
-       length = -EINVAL;
        if (*ppos != 0)
-               goto out;
-
-       length = -ENOMEM;
-       page = (char *)get_zeroed_page(GFP_KERNEL);
-       if (!page)
-               goto out;
+               return -EINVAL;
 
-       length = -EFAULT;
-       if (copy_from_user(page, buf, count))
-               goto out;
+       page = memdup_user_nul(buf, count);
+       if (IS_ERR(page))
+               return PTR_ERR(page);
 
        length = -EINVAL;
        if (sscanf(page, "%d", &new_value) != 1)
@@ -313,7 +299,7 @@ static ssize_t sel_write_disable(struct file *file, const char __user *buf,
 
        length = count;
 out:
-       free_page((unsigned long) page);
+       kfree(page);
        return length;
 }
 #else
@@ -611,31 +597,24 @@ static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf,
 static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
                                      size_t count, loff_t *ppos)
 {
-       char *page = NULL;
+       char *page;
        ssize_t length;
        unsigned int new_value;
 
        length = task_has_security(current, SECURITY__SETCHECKREQPROT);
        if (length)
-               goto out;
+               return length;
 
-       length = -ENOMEM;
        if (count >= PAGE_SIZE)
-               goto out;
+               return -ENOMEM;
 
        /* No partial writes. */
-       length = -EINVAL;
        if (*ppos != 0)
-               goto out;
-
-       length = -ENOMEM;
-       page = (char *)get_zeroed_page(GFP_KERNEL);
-       if (!page)
-               goto out;
+               return -EINVAL;
 
-       length = -EFAULT;
-       if (copy_from_user(page, buf, count))
-               goto out;
+       page = memdup_user_nul(buf, count);
+       if (IS_ERR(page))
+               return PTR_ERR(page);
 
        length = -EINVAL;
        if (sscanf(page, "%u", &new_value) != 1)
@@ -644,7 +623,7 @@ static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
        selinux_checkreqprot = new_value ? 1 : 0;
        length = count;
 out:
-       free_page((unsigned long) page);
+       kfree(page);
        return length;
 }
 static const struct file_operations sel_checkreqprot_ops = {
@@ -1100,14 +1079,12 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
        if (*ppos != 0)
                goto out;
 
-       length = -ENOMEM;
-       page = (char *)get_zeroed_page(GFP_KERNEL);
-       if (!page)
-               goto out;
-
-       length = -EFAULT;
-       if (copy_from_user(page, buf, count))
+       page = memdup_user_nul(buf, count);
+       if (IS_ERR(page)) {
+               length = PTR_ERR(page);
+               page = NULL;
                goto out;
+       }
 
        length = -EINVAL;
        if (sscanf(page, "%d", &new_value) != 1)
@@ -1121,7 +1098,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
 
 out:
        mutex_unlock(&sel_mutex);
-       free_page((unsigned long) page);
+       kfree(page);
        return length;
 }
 
@@ -1154,14 +1131,12 @@ static ssize_t sel_commit_bools_write(struct file *filep,
        if (*ppos != 0)
                goto out;
 
-       length = -ENOMEM;
-       page = (char *)get_zeroed_page(GFP_KERNEL);
-       if (!page)
-               goto out;
-
-       length = -EFAULT;
-       if (copy_from_user(page, buf, count))
+       page = memdup_user_nul(buf, count);
+       if (IS_ERR(page)) {
+               length = PTR_ERR(page);
+               page = NULL;
                goto out;
+       }
 
        length = -EINVAL;
        if (sscanf(page, "%d", &new_value) != 1)
@@ -1176,7 +1151,7 @@ static ssize_t sel_commit_bools_write(struct file *filep,
 
 out:
        mutex_unlock(&sel_mutex);
-       free_page((unsigned long) page);
+       kfree(page);
        return length;
 }
 
@@ -1292,31 +1267,24 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file,
                                             size_t count, loff_t *ppos)
 
 {
-       char *page = NULL;
+       char *page;
        ssize_t ret;
        int new_value;
 
        ret = task_has_security(current, SECURITY__SETSECPARAM);
        if (ret)
-               goto out;
+               return ret;
 
-       ret = -ENOMEM;
        if (count >= PAGE_SIZE)
-               goto out;
+               return -ENOMEM;
 
        /* No partial writes. */
-       ret = -EINVAL;
        if (*ppos != 0)
-               goto out;
-
-       ret = -ENOMEM;
-       page = (char *)get_zeroed_page(GFP_KERNEL);
-       if (!page)
-               goto out;
+               return -EINVAL;
 
-       ret = -EFAULT;
-       if (copy_from_user(page, buf, count))
-               goto out;
+       page = memdup_user_nul(buf, count);
+       if (IS_ERR(page))
+               return PTR_ERR(page);
 
        ret = -EINVAL;
        if (sscanf(page, "%u", &new_value) != 1)
@@ -1326,7 +1294,7 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file,
 
        ret = count;
 out:
-       free_page((unsigned long)page);
+       kfree(page);
        return ret;
 }