kernel/*: switch to memdup_user_nul()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
e4e85bb091
commit
70f6cbb6f9
|
@ -2047,9 +2047,8 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
int *i, vleft, first = 1, err = 0;
|
int *i, vleft, first = 1, err = 0;
|
||||||
unsigned long page = 0;
|
|
||||||
size_t left;
|
size_t left;
|
||||||
char *kbuf;
|
char *kbuf = NULL, *p;
|
||||||
|
|
||||||
if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
|
if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
|
||||||
*lenp = 0;
|
*lenp = 0;
|
||||||
|
@ -2078,15 +2077,9 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
|
||||||
|
|
||||||
if (left > PAGE_SIZE - 1)
|
if (left > PAGE_SIZE - 1)
|
||||||
left = PAGE_SIZE - 1;
|
left = PAGE_SIZE - 1;
|
||||||
page = __get_free_page(GFP_TEMPORARY);
|
p = kbuf = memdup_user_nul(buffer, left);
|
||||||
kbuf = (char *) page;
|
if (IS_ERR(kbuf))
|
||||||
if (!kbuf)
|
return PTR_ERR(kbuf);
|
||||||
return -ENOMEM;
|
|
||||||
if (copy_from_user(kbuf, buffer, left)) {
|
|
||||||
err = -EFAULT;
|
|
||||||
goto free;
|
|
||||||
}
|
|
||||||
kbuf[left] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; left && vleft--; i++, first=0) {
|
for (; left && vleft--; i++, first=0) {
|
||||||
|
@ -2094,11 +2087,11 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
|
||||||
bool neg;
|
bool neg;
|
||||||
|
|
||||||
if (write) {
|
if (write) {
|
||||||
left -= proc_skip_spaces(&kbuf);
|
left -= proc_skip_spaces(&p);
|
||||||
|
|
||||||
if (!left)
|
if (!left)
|
||||||
break;
|
break;
|
||||||
err = proc_get_long(&kbuf, &left, &lval, &neg,
|
err = proc_get_long(&p, &left, &lval, &neg,
|
||||||
proc_wspace_sep,
|
proc_wspace_sep,
|
||||||
sizeof(proc_wspace_sep), NULL);
|
sizeof(proc_wspace_sep), NULL);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -2125,10 +2118,9 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
|
||||||
if (!write && !first && left && !err)
|
if (!write && !first && left && !err)
|
||||||
err = proc_put_char(&buffer, &left, '\n');
|
err = proc_put_char(&buffer, &left, '\n');
|
||||||
if (write && !err && left)
|
if (write && !err && left)
|
||||||
left -= proc_skip_spaces(&kbuf);
|
left -= proc_skip_spaces(&p);
|
||||||
free:
|
|
||||||
if (write) {
|
if (write) {
|
||||||
free_page(page);
|
kfree(kbuf);
|
||||||
if (first)
|
if (first)
|
||||||
return err ? : -EINVAL;
|
return err ? : -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -2310,9 +2302,8 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
|
||||||
{
|
{
|
||||||
unsigned long *i, *min, *max;
|
unsigned long *i, *min, *max;
|
||||||
int vleft, first = 1, err = 0;
|
int vleft, first = 1, err = 0;
|
||||||
unsigned long page = 0;
|
|
||||||
size_t left;
|
size_t left;
|
||||||
char *kbuf;
|
char *kbuf = NULL, *p;
|
||||||
|
|
||||||
if (!data || !table->maxlen || !*lenp || (*ppos && !write)) {
|
if (!data || !table->maxlen || !*lenp || (*ppos && !write)) {
|
||||||
*lenp = 0;
|
*lenp = 0;
|
||||||
|
@ -2340,15 +2331,9 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
|
||||||
|
|
||||||
if (left > PAGE_SIZE - 1)
|
if (left > PAGE_SIZE - 1)
|
||||||
left = PAGE_SIZE - 1;
|
left = PAGE_SIZE - 1;
|
||||||
page = __get_free_page(GFP_TEMPORARY);
|
p = kbuf = memdup_user_nul(buffer, left);
|
||||||
kbuf = (char *) page;
|
if (IS_ERR(kbuf))
|
||||||
if (!kbuf)
|
return PTR_ERR(kbuf);
|
||||||
return -ENOMEM;
|
|
||||||
if (copy_from_user(kbuf, buffer, left)) {
|
|
||||||
err = -EFAULT;
|
|
||||||
goto free;
|
|
||||||
}
|
|
||||||
kbuf[left] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; left && vleft--; i++, first = 0) {
|
for (; left && vleft--; i++, first = 0) {
|
||||||
|
@ -2357,9 +2342,9 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
|
||||||
if (write) {
|
if (write) {
|
||||||
bool neg;
|
bool neg;
|
||||||
|
|
||||||
left -= proc_skip_spaces(&kbuf);
|
left -= proc_skip_spaces(&p);
|
||||||
|
|
||||||
err = proc_get_long(&kbuf, &left, &val, &neg,
|
err = proc_get_long(&p, &left, &val, &neg,
|
||||||
proc_wspace_sep,
|
proc_wspace_sep,
|
||||||
sizeof(proc_wspace_sep), NULL);
|
sizeof(proc_wspace_sep), NULL);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -2385,10 +2370,9 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
|
||||||
if (!write && !first && left && !err)
|
if (!write && !first && left && !err)
|
||||||
err = proc_put_char(&buffer, &left, '\n');
|
err = proc_put_char(&buffer, &left, '\n');
|
||||||
if (write && !err)
|
if (write && !err)
|
||||||
left -= proc_skip_spaces(&kbuf);
|
left -= proc_skip_spaces(&p);
|
||||||
free:
|
|
||||||
if (write) {
|
if (write) {
|
||||||
free_page(page);
|
kfree(kbuf);
|
||||||
if (first)
|
if (first)
|
||||||
return err ? : -EINVAL;
|
return err ? : -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -2650,34 +2634,27 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write) {
|
if (write) {
|
||||||
unsigned long page = 0;
|
char *kbuf, *p;
|
||||||
char *kbuf;
|
|
||||||
|
|
||||||
if (left > PAGE_SIZE - 1)
|
if (left > PAGE_SIZE - 1)
|
||||||
left = PAGE_SIZE - 1;
|
left = PAGE_SIZE - 1;
|
||||||
|
|
||||||
page = __get_free_page(GFP_TEMPORARY);
|
p = kbuf = memdup_user_nul(buffer, left);
|
||||||
kbuf = (char *) page;
|
if (IS_ERR(kbuf))
|
||||||
if (!kbuf)
|
return PTR_ERR(kbuf);
|
||||||
return -ENOMEM;
|
|
||||||
if (copy_from_user(kbuf, buffer, left)) {
|
|
||||||
free_page(page);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
kbuf[left] = 0;
|
|
||||||
|
|
||||||
tmp_bitmap = kzalloc(BITS_TO_LONGS(bitmap_len) * sizeof(unsigned long),
|
tmp_bitmap = kzalloc(BITS_TO_LONGS(bitmap_len) * sizeof(unsigned long),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!tmp_bitmap) {
|
if (!tmp_bitmap) {
|
||||||
free_page(page);
|
kfree(kbuf);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
proc_skip_char(&kbuf, &left, '\n');
|
proc_skip_char(&p, &left, '\n');
|
||||||
while (!err && left) {
|
while (!err && left) {
|
||||||
unsigned long val_a, val_b;
|
unsigned long val_a, val_b;
|
||||||
bool neg;
|
bool neg;
|
||||||
|
|
||||||
err = proc_get_long(&kbuf, &left, &val_a, &neg, tr_a,
|
err = proc_get_long(&p, &left, &val_a, &neg, tr_a,
|
||||||
sizeof(tr_a), &c);
|
sizeof(tr_a), &c);
|
||||||
if (err)
|
if (err)
|
||||||
break;
|
break;
|
||||||
|
@ -2688,12 +2665,12 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
|
||||||
|
|
||||||
val_b = val_a;
|
val_b = val_a;
|
||||||
if (left) {
|
if (left) {
|
||||||
kbuf++;
|
p++;
|
||||||
left--;
|
left--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == '-') {
|
if (c == '-') {
|
||||||
err = proc_get_long(&kbuf, &left, &val_b,
|
err = proc_get_long(&p, &left, &val_b,
|
||||||
&neg, tr_b, sizeof(tr_b),
|
&neg, tr_b, sizeof(tr_b),
|
||||||
&c);
|
&c);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -2704,16 +2681,16 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (left) {
|
if (left) {
|
||||||
kbuf++;
|
p++;
|
||||||
left--;
|
left--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bitmap_set(tmp_bitmap, val_a, val_b - val_a + 1);
|
bitmap_set(tmp_bitmap, val_a, val_b - val_a + 1);
|
||||||
first = 0;
|
first = 0;
|
||||||
proc_skip_char(&kbuf, &left, '\n');
|
proc_skip_char(&p, &left, '\n');
|
||||||
}
|
}
|
||||||
free_page(page);
|
kfree(kbuf);
|
||||||
} else {
|
} else {
|
||||||
unsigned long bit_a, bit_b = 0;
|
unsigned long bit_a, bit_b = 0;
|
||||||
|
|
||||||
|
|
|
@ -1340,15 +1340,9 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
|
||||||
if (cnt >= PAGE_SIZE)
|
if (cnt >= PAGE_SIZE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
buf = (char *)__get_free_page(GFP_TEMPORARY);
|
buf = memdup_user_nul(ubuf, cnt);
|
||||||
if (!buf)
|
if (IS_ERR(buf))
|
||||||
return -ENOMEM;
|
return PTR_ERR(buf);
|
||||||
|
|
||||||
if (copy_from_user(buf, ubuf, cnt)) {
|
|
||||||
free_page((unsigned long) buf);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
buf[cnt] = '\0';
|
|
||||||
|
|
||||||
mutex_lock(&event_mutex);
|
mutex_lock(&event_mutex);
|
||||||
file = event_file_data(filp);
|
file = event_file_data(filp);
|
||||||
|
@ -1356,7 +1350,7 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
|
||||||
err = apply_event_filter(file, buf);
|
err = apply_event_filter(file, buf);
|
||||||
mutex_unlock(&event_mutex);
|
mutex_unlock(&event_mutex);
|
||||||
|
|
||||||
free_page((unsigned long) buf);
|
kfree(buf);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -1507,18 +1501,12 @@ subsystem_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
|
||||||
if (cnt >= PAGE_SIZE)
|
if (cnt >= PAGE_SIZE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
buf = (char *)__get_free_page(GFP_TEMPORARY);
|
buf = memdup_user_nul(ubuf, cnt);
|
||||||
if (!buf)
|
if (IS_ERR(buf))
|
||||||
return -ENOMEM;
|
return PTR_ERR(buf);
|
||||||
|
|
||||||
if (copy_from_user(buf, ubuf, cnt)) {
|
|
||||||
free_page((unsigned long) buf);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
buf[cnt] = '\0';
|
|
||||||
|
|
||||||
err = apply_subsystem_event_filter(dir, buf);
|
err = apply_subsystem_event_filter(dir, buf);
|
||||||
free_page((unsigned long) buf);
|
kfree(buf);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
|
|
@ -237,28 +237,23 @@ static ssize_t event_trigger_regex_write(struct file *file,
|
||||||
if (cnt >= PAGE_SIZE)
|
if (cnt >= PAGE_SIZE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
buf = (char *)__get_free_page(GFP_TEMPORARY);
|
buf = memdup_user_nul(ubuf, cnt);
|
||||||
if (!buf)
|
if (IS_ERR(buf))
|
||||||
return -ENOMEM;
|
return PTR_ERR(buf);
|
||||||
|
|
||||||
if (copy_from_user(buf, ubuf, cnt)) {
|
|
||||||
free_page((unsigned long)buf);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
buf[cnt] = '\0';
|
|
||||||
strim(buf);
|
strim(buf);
|
||||||
|
|
||||||
mutex_lock(&event_mutex);
|
mutex_lock(&event_mutex);
|
||||||
event_file = event_file_data(file);
|
event_file = event_file_data(file);
|
||||||
if (unlikely(!event_file)) {
|
if (unlikely(!event_file)) {
|
||||||
mutex_unlock(&event_mutex);
|
mutex_unlock(&event_mutex);
|
||||||
free_page((unsigned long)buf);
|
kfree(buf);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
ret = trigger_process_regex(event_file, buf);
|
ret = trigger_process_regex(event_file, buf);
|
||||||
mutex_unlock(&event_mutex);
|
mutex_unlock(&event_mutex);
|
||||||
|
|
||||||
free_page((unsigned long)buf);
|
kfree(buf);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
|
@ -602,8 +602,7 @@ static ssize_t map_write(struct file *file, const char __user *buf,
|
||||||
struct uid_gid_map new_map;
|
struct uid_gid_map new_map;
|
||||||
unsigned idx;
|
unsigned idx;
|
||||||
struct uid_gid_extent *extent = NULL;
|
struct uid_gid_extent *extent = NULL;
|
||||||
unsigned long page = 0;
|
char *kbuf = NULL, *pos, *next_line;
|
||||||
char *kbuf, *pos, *next_line;
|
|
||||||
ssize_t ret = -EINVAL;
|
ssize_t ret = -EINVAL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -638,23 +637,18 @@ static ssize_t map_write(struct file *file, const char __user *buf,
|
||||||
if (cap_valid(cap_setid) && !file_ns_capable(file, ns, CAP_SYS_ADMIN))
|
if (cap_valid(cap_setid) && !file_ns_capable(file, ns, CAP_SYS_ADMIN))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Get a buffer */
|
|
||||||
ret = -ENOMEM;
|
|
||||||
page = __get_free_page(GFP_TEMPORARY);
|
|
||||||
kbuf = (char *) page;
|
|
||||||
if (!page)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* Only allow < page size writes at the beginning of the file */
|
/* Only allow < page size writes at the beginning of the file */
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
if ((*ppos != 0) || (count >= PAGE_SIZE))
|
if ((*ppos != 0) || (count >= PAGE_SIZE))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Slurp in the user data */
|
/* Slurp in the user data */
|
||||||
ret = -EFAULT;
|
kbuf = memdup_user_nul(buf, count);
|
||||||
if (copy_from_user(kbuf, buf, count))
|
if (IS_ERR(kbuf)) {
|
||||||
|
ret = PTR_ERR(kbuf);
|
||||||
|
kbuf = NULL;
|
||||||
goto out;
|
goto out;
|
||||||
kbuf[count] = '\0';
|
}
|
||||||
|
|
||||||
/* Parse the user data */
|
/* Parse the user data */
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
@ -756,8 +750,7 @@ static ssize_t map_write(struct file *file, const char __user *buf,
|
||||||
ret = count;
|
ret = count;
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&userns_state_mutex);
|
mutex_unlock(&userns_state_mutex);
|
||||||
if (page)
|
kfree(kbuf);
|
||||||
free_page(page);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue