diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-13 04:11:47 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-13 04:11:47 +0300 |
commit | 33caf82acf4dc420bf0f0136b886f7b27ecf90c5 (patch) | |
tree | b24b0b5c8f257ae7db3b8df939821a0856869895 /security | |
parent | ca9706a282943899981e83604f2ed13e88ce4239 (diff) | |
parent | bbddca8e8fac07ece3938e03526b5d00fa791a4c (diff) | |
download | linux-33caf82acf4dc420bf0f0136b886f7b27ecf90c5.tar.xz |
Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull misc vfs updates from Al Viro:
"All kinds of stuff. That probably should've been 5 or 6 separate
branches, but by the time I'd realized how large and mixed that bag
had become it had been too close to -final to play with rebasing.
Some fs/namei.c cleanups there, memdup_user_nul() introduction and
switching open-coded instances, burying long-dead code, whack-a-mole
of various kinds, several new helpers for ->llseek(), assorted
cleanups and fixes from various people, etc.
One piece probably deserves special mention - Neil's
lookup_one_len_unlocked(). Similar to lookup_one_len(), but gets
called without ->i_mutex and tries to avoid ever taking it. That, of
course, means that it's not useful for any directory modifications,
but things like getting inode attributes in nfds readdirplus are fine
with that. I really should've asked for moratorium on lookup-related
changes this cycle, but since I hadn't done that early enough... I
*am* asking for that for the coming cycle, though - I'm going to try
and get conversion of i_mutex to rwsem with ->lookup() done under lock
taken shared.
There will be a patch closer to the end of the window, along the lines
of the one Linus had posted last May - mechanical conversion of
->i_mutex accesses to inode_lock()/inode_unlock()/inode_trylock()/
inode_is_locked()/inode_lock_nested(). To quote Linus back then:
-----
| This is an automated patch using
|
| sed 's/mutex_lock(&\(.*\)->i_mutex)/inode_lock(\1)/'
| sed 's/mutex_unlock(&\(.*\)->i_mutex)/inode_unlock(\1)/'
| sed 's/mutex_lock_nested(&\(.*\)->i_mutex,[ ]*I_MUTEX_\([A-Z0-9_]*\))/inode_lock_nested(\1, I_MUTEX_\2)/'
| sed 's/mutex_is_locked(&\(.*\)->i_mutex)/inode_is_locked(\1)/'
| sed 's/mutex_trylock(&\(.*\)->i_mutex)/inode_trylock(\1)/'
|
| with a very few manual fixups
-----
I'm going to send that once the ->i_mutex-affecting stuff in -next
gets mostly merged (or when Linus says he's about to stop taking
merges)"
* 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (63 commits)
nfsd: don't hold i_mutex over userspace upcalls
fs:affs:Replace time_t with time64_t
fs/9p: use fscache mutex rather than spinlock
proc: add a reschedule point in proc_readfd_common()
logfs: constify logfs_block_ops structures
fcntl: allow to set O_DIRECT flag on pipe
fs: __generic_file_splice_read retry lookup on AOP_TRUNCATED_PAGE
fs: xattr: Use kvfree()
[s390] page_to_phys() always returns a multiple of PAGE_SIZE
nbd: use ->compat_ioctl()
fs: use block_device name vsprintf helper
lib/vsprintf: add %*pg format specifier
fs: use gendisk->disk_name where possible
poll: plug an unused argument to do_poll
amdkfd: don't open-code memdup_user()
cdrom: don't open-code memdup_user()
rsxx: don't open-code memdup_user()
mtip32xx: don't open-code memdup_user()
[um] mconsole: don't open-code memdup_user_nul()
[um] hostaudio: don't open-code memdup_user()
...
Diffstat (limited to 'security')
-rw-r--r-- | security/integrity/iint.c | 11 | ||||
-rw-r--r-- | security/selinux/selinuxfs.c | 114 | ||||
-rw-r--r-- | security/smack/smackfs.c | 114 | ||||
-rw-r--r-- | security/tomoyo/securityfs_if.c | 11 |
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; } |