summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/integrity/iint.c11
-rw-r--r--security/selinux/selinuxfs.c114
-rw-r--r--security/smack/smackfs.c114
-rw-r--r--security/tomoyo/securityfs_if.c11
4 files changed, 82 insertions, 168 deletions
diff --git a/security/integrity/iint.c b/security/integrity/iint.c
index 3d2f5b45c8cb..c2e3ccd4b510 100644
--- a/security/integrity/iint.c
+++ b/security/integrity/iint.c
@@ -234,12 +234,13 @@ int __init integrity_read_file(const char *path, char **data)
}
rc = integrity_kernel_read(file, 0, buf, size);
- if (rc < 0)
- kfree(buf);
- else if (rc != size)
- rc = -EIO;
- else
+ if (rc == size) {
*data = buf;
+ } else {
+ kfree(buf);
+ if (rc >= 0)
+ rc = -EIO;
+ }
out:
fput(file);
return rc;
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index c02da25d7b63..73c60baa90a4 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -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;
}
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 94bd9e41c9ec..e249a66db533 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -497,14 +497,9 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
}
}
- data = kmalloc(count + 1, GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
-
- if (copy_from_user(data, buf, count) != 0) {
- rc = -EFAULT;
- goto out;
- }
+ data = memdup_user_nul(buf, count);
+ if (IS_ERR(data))
+ return PTR_ERR(data);
/*
* In case of parsing only part of user buf,
@@ -884,16 +879,10 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
(count < SMK_CIPSOMIN || count > SMK_CIPSOMAX))
return -EINVAL;
- data = kzalloc(count + 1, GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
-
- if (copy_from_user(data, buf, count) != 0) {
- rc = -EFAULT;
- goto unlockedout;
- }
+ data = memdup_user_nul(buf, count);
+ if (IS_ERR(data))
+ return PTR_ERR(data);
- data[count] = '\0';
rule = data;
/*
* Only allow one writer at a time. Writes should be
@@ -946,7 +935,6 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
out:
mutex_unlock(&smack_cipso_lock);
-unlockedout:
kfree(data);
return rc;
}
@@ -1187,14 +1175,9 @@ static ssize_t smk_write_net4addr(struct file *file, const char __user *buf,
if (count < SMK_NETLBLADDRMIN)
return -EINVAL;
- data = kzalloc(count + 1, GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
-
- if (copy_from_user(data, buf, count) != 0) {
- rc = -EFAULT;
- goto free_data_out;
- }
+ data = memdup_user_nul(buf, count);
+ if (IS_ERR(data))
+ return PTR_ERR(data);
smack = kzalloc(count + 1, GFP_KERNEL);
if (smack == NULL) {
@@ -1202,8 +1185,6 @@ static ssize_t smk_write_net4addr(struct file *file, const char __user *buf,
goto free_data_out;
}
- data[count] = '\0';
-
rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%u %s",
&host[0], &host[1], &host[2], &host[3], &masks, smack);
if (rc != 6) {
@@ -1454,14 +1435,9 @@ static ssize_t smk_write_net6addr(struct file *file, const char __user *buf,
if (count < SMK_NETLBLADDRMIN)
return -EINVAL;
- data = kzalloc(count + 1, GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
-
- if (copy_from_user(data, buf, count) != 0) {
- rc = -EFAULT;
- goto free_data_out;
- }
+ data = memdup_user_nul(buf, count);
+ if (IS_ERR(data))
+ return PTR_ERR(data);
smack = kzalloc(count + 1, GFP_KERNEL);
if (smack == NULL) {
@@ -1469,8 +1445,6 @@ static ssize_t smk_write_net6addr(struct file *file, const char __user *buf,
goto free_data_out;
}
- data[count] = '\0';
-
i = sscanf(data, "%x:%x:%x:%x:%x:%x:%x:%x/%u %s",
&scanned[0], &scanned[1], &scanned[2], &scanned[3],
&scanned[4], &scanned[5], &scanned[6], &scanned[7],
@@ -1865,14 +1839,9 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
- data = kzalloc(count + 1, GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
-
- if (copy_from_user(data, buf, count) != 0) {
- rc = -EFAULT;
- goto out;
- }
+ data = memdup_user_nul(buf, count);
+ if (IS_ERR(data))
+ return PTR_ERR(data);
skp = smk_import_entry(data, count);
if (IS_ERR(skp)) {
@@ -2041,14 +2010,9 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
- data = kzalloc(count + 1, GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
-
- if (copy_from_user(data, buf, count) != 0) {
- kfree(data);
- return -EFAULT;
- }
+ data = memdup_user_nul(buf, count);
+ if (IS_ERR(data))
+ return PTR_ERR(data);
rc = smk_parse_label_list(data, &list_tmp);
kfree(data);
@@ -2133,14 +2097,9 @@ static ssize_t smk_write_unconfined(struct file *file, const char __user *buf,
if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
- data = kzalloc(count + 1, GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
-
- if (copy_from_user(data, buf, count) != 0) {
- rc = -EFAULT;
- goto freeout;
- }
+ data = memdup_user_nul(buf, count);
+ if (IS_ERR(data))
+ return PTR_ERR(data);
/*
* Clear the smack_unconfined on invalid label errors. This means
@@ -2696,19 +2655,15 @@ static ssize_t smk_write_syslog(struct file *file, const char __user *buf,
if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
- data = kzalloc(count + 1, GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
+ data = memdup_user_nul(buf, count);
+ if (IS_ERR(data))
+ return PTR_ERR(data);
- if (copy_from_user(data, buf, count) != 0)
- rc = -EFAULT;
- else {
- skp = smk_import_entry(data, count);
- if (IS_ERR(skp))
- rc = PTR_ERR(skp);
- else
- smack_syslog_label = skp;
- }
+ skp = smk_import_entry(data, count);
+ if (IS_ERR(skp))
+ rc = PTR_ERR(skp);
+ else
+ smack_syslog_label = skp;
kfree(data);
return rc;
@@ -2798,14 +2753,9 @@ static ssize_t smk_write_relabel_self(struct file *file, const char __user *buf,
if (*ppos != 0)
return -EINVAL;
- data = kzalloc(count + 1, GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
-
- if (copy_from_user(data, buf, count) != 0) {
- kfree(data);
- return -EFAULT;
- }
+ data = memdup_user_nul(buf, count);
+ if (IS_ERR(data))
+ return PTR_ERR(data);
rc = smk_parse_label_list(data, &list_tmp);
kfree(data);
diff --git a/security/tomoyo/securityfs_if.c b/security/tomoyo/securityfs_if.c
index 179a955b319d..06ab41b1ff28 100644
--- a/security/tomoyo/securityfs_if.c
+++ b/security/tomoyo/securityfs_if.c
@@ -43,13 +43,9 @@ static ssize_t tomoyo_write_self(struct file *file, const char __user *buf,
int error;
if (!count || count >= TOMOYO_EXEC_TMPSIZE - 10)
return -ENOMEM;
- data = kzalloc(count + 1, GFP_NOFS);
- if (!data)
- return -ENOMEM;
- if (copy_from_user(data, buf, count)) {
- error = -EFAULT;
- goto out;
- }
+ data = memdup_user_nul(buf, count);
+ if (IS_ERR(data))
+ return PTR_ERR(data);
tomoyo_normalize_line(data);
if (tomoyo_correct_domain(data)) {
const int idx = tomoyo_read_lock();
@@ -87,7 +83,6 @@ static ssize_t tomoyo_write_self(struct file *file, const char __user *buf,
tomoyo_read_unlock(idx);
} else
error = -EINVAL;
-out:
kfree(data);
return error ? error : count;
}