aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sysctl.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-01-12 20:11:47 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-12 20:11:47 -0500
commit33caf82acf4dc420bf0f0136b886f7b27ecf90c5 (patch)
treeb24b0b5c8f257ae7db3b8df939821a0856869895 /kernel/sysctl.c
parentca9706a282943899981e83604f2ed13e88ce4239 (diff)
parentbbddca8e8fac07ece3938e03526b5d00fa791a4c (diff)
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 'kernel/sysctl.c')
-rw-r--r--kernel/sysctl.c79
1 files changed, 28 insertions, 51 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index dc6858d6639e..5faf89ac9ec0 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -2047,9 +2047,8 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
2047 void *data) 2047 void *data)
2048{ 2048{
2049 int *i, vleft, first = 1, err = 0; 2049 int *i, vleft, first = 1, err = 0;
2050 unsigned long page = 0;
2051 size_t left; 2050 size_t left;
2052 char *kbuf; 2051 char *kbuf = NULL, *p;
2053 2052
2054 if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) { 2053 if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
2055 *lenp = 0; 2054 *lenp = 0;
@@ -2078,15 +2077,9 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
2078 2077
2079 if (left > PAGE_SIZE - 1) 2078 if (left > PAGE_SIZE - 1)
2080 left = PAGE_SIZE - 1; 2079 left = PAGE_SIZE - 1;
2081 page = __get_free_page(GFP_TEMPORARY); 2080 p = kbuf = memdup_user_nul(buffer, left);
2082 kbuf = (char *) page; 2081 if (IS_ERR(kbuf))
2083 if (!kbuf) 2082 return PTR_ERR(kbuf);
2084 return -ENOMEM;
2085 if (copy_from_user(kbuf, buffer, left)) {
2086 err = -EFAULT;
2087 goto free;
2088 }
2089 kbuf[left] = 0;
2090 } 2083 }
2091 2084
2092 for (; left && vleft--; i++, first=0) { 2085 for (; left && vleft--; i++, first=0) {
@@ -2094,11 +2087,11 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
2094 bool neg; 2087 bool neg;
2095 2088
2096 if (write) { 2089 if (write) {
2097 left -= proc_skip_spaces(&kbuf); 2090 left -= proc_skip_spaces(&p);
2098 2091
2099 if (!left) 2092 if (!left)
2100 break; 2093 break;
2101 err = proc_get_long(&kbuf, &left, &lval, &neg, 2094 err = proc_get_long(&p, &left, &lval, &neg,
2102 proc_wspace_sep, 2095 proc_wspace_sep,
2103 sizeof(proc_wspace_sep), NULL); 2096 sizeof(proc_wspace_sep), NULL);
2104 if (err) 2097 if (err)
@@ -2125,10 +2118,9 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
2125 if (!write && !first && left && !err) 2118 if (!write && !first && left && !err)
2126 err = proc_put_char(&buffer, &left, '\n'); 2119 err = proc_put_char(&buffer, &left, '\n');
2127 if (write && !err && left) 2120 if (write && !err && left)
2128 left -= proc_skip_spaces(&kbuf); 2121 left -= proc_skip_spaces(&p);
2129free:
2130 if (write) { 2122 if (write) {
2131 free_page(page); 2123 kfree(kbuf);
2132 if (first) 2124 if (first)
2133 return err ? : -EINVAL; 2125 return err ? : -EINVAL;
2134 } 2126 }
@@ -2310,9 +2302,8 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
2310{ 2302{
2311 unsigned long *i, *min, *max; 2303 unsigned long *i, *min, *max;
2312 int vleft, first = 1, err = 0; 2304 int vleft, first = 1, err = 0;
2313 unsigned long page = 0;
2314 size_t left; 2305 size_t left;
2315 char *kbuf; 2306 char *kbuf = NULL, *p;
2316 2307
2317 if (!data || !table->maxlen || !*lenp || (*ppos && !write)) { 2308 if (!data || !table->maxlen || !*lenp || (*ppos && !write)) {
2318 *lenp = 0; 2309 *lenp = 0;
@@ -2340,15 +2331,9 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
2340 2331
2341 if (left > PAGE_SIZE - 1) 2332 if (left > PAGE_SIZE - 1)
2342 left = PAGE_SIZE - 1; 2333 left = PAGE_SIZE - 1;
2343 page = __get_free_page(GFP_TEMPORARY); 2334 p = kbuf = memdup_user_nul(buffer, left);
2344 kbuf = (char *) page; 2335 if (IS_ERR(kbuf))
2345 if (!kbuf) 2336 return PTR_ERR(kbuf);
2346 return -ENOMEM;
2347 if (copy_from_user(kbuf, buffer, left)) {
2348 err = -EFAULT;
2349 goto free;
2350 }
2351 kbuf[left] = 0;
2352 } 2337 }
2353 2338
2354 for (; left && vleft--; i++, first = 0) { 2339 for (; left && vleft--; i++, first = 0) {
@@ -2357,9 +2342,9 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
2357 if (write) { 2342 if (write) {
2358 bool neg; 2343 bool neg;
2359 2344
2360 left -= proc_skip_spaces(&kbuf); 2345 left -= proc_skip_spaces(&p);
2361 2346
2362 err = proc_get_long(&kbuf, &left, &val, &neg, 2347 err = proc_get_long(&p, &left, &val, &neg,
2363 proc_wspace_sep, 2348 proc_wspace_sep,
2364 sizeof(proc_wspace_sep), NULL); 2349 sizeof(proc_wspace_sep), NULL);
2365 if (err) 2350 if (err)
@@ -2385,10 +2370,9 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
2385 if (!write && !first && left && !err) 2370 if (!write && !first && left && !err)
2386 err = proc_put_char(&buffer, &left, '\n'); 2371 err = proc_put_char(&buffer, &left, '\n');
2387 if (write && !err) 2372 if (write && !err)
2388 left -= proc_skip_spaces(&kbuf); 2373 left -= proc_skip_spaces(&p);
2389free:
2390 if (write) { 2374 if (write) {
2391 free_page(page); 2375 kfree(kbuf);
2392 if (first) 2376 if (first)
2393 return err ? : -EINVAL; 2377 return err ? : -EINVAL;
2394 } 2378 }
@@ -2650,34 +2634,27 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
2650 } 2634 }
2651 2635
2652 if (write) { 2636 if (write) {
2653 unsigned long page = 0; 2637 char *kbuf, *p;
2654 char *kbuf;
2655 2638
2656 if (left > PAGE_SIZE - 1) 2639 if (left > PAGE_SIZE - 1)
2657 left = PAGE_SIZE - 1; 2640 left = PAGE_SIZE - 1;
2658 2641
2659 page = __get_free_page(GFP_TEMPORARY); 2642 p = kbuf = memdup_user_nul(buffer, left);
2660 kbuf = (char *) page; 2643 if (IS_ERR(kbuf))
2661 if (!kbuf) 2644 return PTR_ERR(kbuf);
2662 return -ENOMEM;
2663 if (copy_from_user(kbuf, buffer, left)) {
2664 free_page(page);
2665 return -EFAULT;
2666 }
2667 kbuf[left] = 0;
2668 2645
2669 tmp_bitmap = kzalloc(BITS_TO_LONGS(bitmap_len) * sizeof(unsigned long), 2646 tmp_bitmap = kzalloc(BITS_TO_LONGS(bitmap_len) * sizeof(unsigned long),
2670 GFP_KERNEL); 2647 GFP_KERNEL);
2671 if (!tmp_bitmap) { 2648 if (!tmp_bitmap) {
2672 free_page(page); 2649 kfree(kbuf);
2673 return -ENOMEM; 2650 return -ENOMEM;
2674 } 2651 }
2675 proc_skip_char(&kbuf, &left, '\n'); 2652 proc_skip_char(&p, &left, '\n');
2676 while (!err && left) { 2653 while (!err && left) {
2677 unsigned long val_a, val_b; 2654 unsigned long val_a, val_b;
2678 bool neg; 2655 bool neg;
2679 2656
2680 err = proc_get_long(&kbuf, &left, &val_a, &neg, tr_a, 2657 err = proc_get_long(&p, &left, &val_a, &neg, tr_a,
2681 sizeof(tr_a), &c); 2658 sizeof(tr_a), &c);
2682 if (err) 2659 if (err)
2683 break; 2660 break;
@@ -2688,12 +2665,12 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
2688 2665
2689 val_b = val_a; 2666 val_b = val_a;
2690 if (left) { 2667 if (left) {
2691 kbuf++; 2668 p++;
2692 left--; 2669 left--;
2693 } 2670 }
2694 2671
2695 if (c == '-') { 2672 if (c == '-') {
2696 err = proc_get_long(&kbuf, &left, &val_b, 2673 err = proc_get_long(&p, &left, &val_b,
2697 &neg, tr_b, sizeof(tr_b), 2674 &neg, tr_b, sizeof(tr_b),
2698 &c); 2675 &c);
2699 if (err) 2676 if (err)
@@ -2704,16 +2681,16 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
2704 break; 2681 break;
2705 } 2682 }
2706 if (left) { 2683 if (left) {
2707 kbuf++; 2684 p++;
2708 left--; 2685 left--;
2709 } 2686 }
2710 } 2687 }
2711 2688
2712 bitmap_set(tmp_bitmap, val_a, val_b - val_a + 1); 2689 bitmap_set(tmp_bitmap, val_a, val_b - val_a + 1);
2713 first = 0; 2690 first = 0;
2714 proc_skip_char(&kbuf, &left, '\n'); 2691 proc_skip_char(&p, &left, '\n');
2715 } 2692 }
2716 free_page(page); 2693 kfree(kbuf);
2717 } else { 2694 } else {
2718 unsigned long bit_a, bit_b = 0; 2695 unsigned long bit_a, bit_b = 0;
2719 2696