1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * sysctl.c: General linux system control interface
4 */
5
6 #include <linux/sysctl.h>
7 #include <linux/bitmap.h>
8 #include <linux/proc_fs.h>
9 #include <linux/ctype.h>
10 #include <linux/init.h>
11 #include <linux/kernel.h>
12 #include <linux/kobject.h>
13 #include <linux/highuid.h>
14 #include <linux/writeback.h>
15 #include <linux/initrd.h>
16 #include <linux/limits.h>
17 #include <linux/syscalls.h>
18 #include <linux/capability.h>
19
20 #include "../lib/kstrtox.h"
21
22 #include <linux/uaccess.h>
23 #include <asm/processor.h>
24
25 /* shared constants to be used in various sysctls */
26 const int sysctl_vals[] = { 0, 1, 2, 3, 4, 100, 200, 1000, 3000, INT_MAX, 65535, -1 };
27 EXPORT_SYMBOL(sysctl_vals);
28
29 const unsigned long sysctl_long_vals[] = { 0, 1, LONG_MAX };
30 EXPORT_SYMBOL_GPL(sysctl_long_vals);
31
32 #if defined(CONFIG_SYSCTL)
33
34 /* Constants used for minimum and maximum */
35 static const int ngroups_max = NGROUPS_MAX;
36 static const int cap_last_cap = CAP_LAST_CAP;
37
38 #ifdef CONFIG_PROC_SYSCTL
39
40 /**
41 * enum sysctl_writes_mode - supported sysctl write modes
42 *
43 * @SYSCTL_WRITES_LEGACY: each write syscall must fully contain the sysctl value
44 * to be written, and multiple writes on the same sysctl file descriptor
45 * will rewrite the sysctl value, regardless of file position. No warning
46 * is issued when the initial position is not 0.
47 * @SYSCTL_WRITES_WARN: same as above but warn when the initial file position is
48 * not 0.
49 * @SYSCTL_WRITES_STRICT: writes to numeric sysctl entries must always be at
50 * file position 0 and the value must be fully contained in the buffer
51 * sent to the write syscall. If dealing with strings respect the file
52 * position, but restrict this to the max length of the buffer, anything
53 * passed the max length will be ignored. Multiple writes will append
54 * to the buffer.
55 *
56 * These write modes control how current file position affects the behavior of
57 * updating internal kernel (SYSCTL_USER_TO_KERN) sysctl values through the proc
58 * interface on each write.
59 */
60 enum sysctl_writes_mode {
61 SYSCTL_WRITES_LEGACY = -1,
62 SYSCTL_WRITES_WARN = 0,
63 SYSCTL_WRITES_STRICT = 1,
64 };
65
66 static enum sysctl_writes_mode sysctl_writes_strict = SYSCTL_WRITES_STRICT;
67 #endif /* CONFIG_PROC_SYSCTL */
68 #endif /* CONFIG_SYSCTL */
69
70 /*
71 * /proc/sys support
72 */
73
74 #ifdef CONFIG_PROC_SYSCTL
75
_proc_do_string(char * data,int maxlen,int dir,char * buffer,size_t * lenp,loff_t * ppos)76 static int _proc_do_string(char *data, int maxlen, int dir,
77 char *buffer, size_t *lenp, loff_t *ppos)
78 {
79 size_t len;
80 char c, *p;
81
82 if (!data || !maxlen || !*lenp) {
83 *lenp = 0;
84 return 0;
85 }
86
87 if (SYSCTL_USER_TO_KERN(dir)) {
88 if (sysctl_writes_strict == SYSCTL_WRITES_STRICT) {
89 /* Only continue writes not past the end of buffer. */
90 len = strlen(data);
91 if (len > maxlen - 1)
92 len = maxlen - 1;
93
94 if (*ppos > len)
95 return 0;
96 len = *ppos;
97 } else {
98 /* Start writing from beginning of buffer. */
99 len = 0;
100 }
101
102 *ppos += *lenp;
103 p = buffer;
104 while ((p - buffer) < *lenp && len < maxlen - 1) {
105 c = *(p++);
106 if (c == 0 || c == '\n')
107 break;
108 data[len++] = c;
109 }
110 data[len] = 0;
111 } else {
112 len = strlen(data);
113 if (len > maxlen)
114 len = maxlen;
115
116 if (*ppos > len) {
117 *lenp = 0;
118 return 0;
119 }
120
121 data += *ppos;
122 len -= *ppos;
123
124 if (len > *lenp)
125 len = *lenp;
126 if (len)
127 memcpy(buffer, data, len);
128 if (len < *lenp) {
129 buffer[len] = '\n';
130 len++;
131 }
132 *lenp = len;
133 *ppos += len;
134 }
135 return 0;
136 }
137
warn_sysctl_write(const struct ctl_table * table)138 static void warn_sysctl_write(const struct ctl_table *table)
139 {
140 pr_warn_once("%s wrote to %s when file position was not 0!\n"
141 "This will not be supported in the future. To silence this\n"
142 "warning, set kernel.sysctl_writes_strict = -1\n",
143 current->comm, table->procname);
144 }
145
146 /**
147 * proc_first_pos_non_zero_ignore - check if first position is allowed
148 * @ppos: file position
149 * @table: the sysctl table
150 *
151 * Returns true if the first position is non-zero and the sysctl_writes_strict
152 * mode indicates this is not allowed for numeric input types. String proc
153 * handlers can ignore the return value.
154 */
proc_first_pos_non_zero_ignore(loff_t * ppos,const struct ctl_table * table)155 static bool proc_first_pos_non_zero_ignore(loff_t *ppos,
156 const struct ctl_table *table)
157 {
158 if (!*ppos)
159 return false;
160
161 switch (sysctl_writes_strict) {
162 case SYSCTL_WRITES_STRICT:
163 return true;
164 case SYSCTL_WRITES_WARN:
165 warn_sysctl_write(table);
166 return false;
167 default:
168 return false;
169 }
170 }
171
172 /**
173 * proc_dostring - read a string sysctl
174 * @table: the sysctl table
175 * @dir: %TRUE if this is a write to the sysctl file
176 * @buffer: the user buffer
177 * @lenp: the size of the user buffer
178 * @ppos: file position
179 *
180 * Reads/writes a string from/to the user buffer. If the kernel
181 * buffer provided is not large enough to hold the string, the
182 * string is truncated. The copied string is %NULL-terminated.
183 * If the string is being read by the user process, it is copied
184 * and a newline '\n' is added. It is truncated if the buffer is
185 * not large enough.
186 *
187 * Returns 0 on success.
188 */
proc_dostring(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)189 int proc_dostring(const struct ctl_table *table, int dir,
190 void *buffer, size_t *lenp, loff_t *ppos)
191 {
192 if (SYSCTL_USER_TO_KERN(dir))
193 proc_first_pos_non_zero_ignore(ppos, table);
194
195 return _proc_do_string(table->data, table->maxlen, dir, buffer, lenp,
196 ppos);
197 }
198
proc_skip_spaces(char ** buf,size_t * size)199 static void proc_skip_spaces(char **buf, size_t *size)
200 {
201 while (*size) {
202 if (!isspace(**buf))
203 break;
204 (*size)--;
205 (*buf)++;
206 }
207 }
208
proc_skip_char(char ** buf,size_t * size,const char v)209 static void proc_skip_char(char **buf, size_t *size, const char v)
210 {
211 while (*size) {
212 if (**buf != v)
213 break;
214 (*size)--;
215 (*buf)++;
216 }
217 }
218
219 /**
220 * strtoul_lenient - parse an ASCII formatted integer from a buffer and only
221 * fail on overflow
222 *
223 * @cp: kernel buffer containing the string to parse
224 * @endp: pointer to store the trailing characters
225 * @base: the base to use
226 * @res: where the parsed integer will be stored
227 *
228 * In case of success 0 is returned and @res will contain the parsed integer,
229 * @endp will hold any trailing characters.
230 * This function will fail the parse on overflow. If there wasn't an overflow
231 * the function will defer the decision what characters count as invalid to the
232 * caller.
233 */
strtoul_lenient(const char * cp,char ** endp,unsigned int base,unsigned long * res)234 static int strtoul_lenient(const char *cp, char **endp, unsigned int base,
235 unsigned long *res)
236 {
237 unsigned long long result;
238 unsigned int rv;
239
240 cp = _parse_integer_fixup_radix(cp, &base);
241 rv = _parse_integer(cp, base, &result);
242 if ((rv & KSTRTOX_OVERFLOW) || (result != (unsigned long)result))
243 return -ERANGE;
244
245 cp += rv;
246
247 if (endp)
248 *endp = (char *)cp;
249
250 *res = (unsigned long)result;
251 return 0;
252 }
253
254 #define TMPBUFLEN 22
255 /**
256 * proc_get_long - reads an ASCII formatted integer from a user buffer
257 *
258 * @buf: a kernel buffer
259 * @size: size of the kernel buffer
260 * @val: this is where the number will be stored
261 * @neg: set to %TRUE if number is negative
262 * @perm_tr: a vector which contains the allowed trailers
263 * @perm_tr_len: size of the perm_tr vector
264 * @tr: pointer to store the trailer character
265 *
266 * In case of success %0 is returned and @buf and @size are updated with
267 * the amount of bytes read. If @tr is non-NULL and a trailing
268 * character exists (size is non-zero after returning from this
269 * function), @tr is updated with the trailing character.
270 */
proc_get_long(char ** buf,size_t * size,unsigned long * val,bool * neg,const char * perm_tr,unsigned perm_tr_len,char * tr)271 static int proc_get_long(char **buf, size_t *size,
272 unsigned long *val, bool *neg,
273 const char *perm_tr, unsigned perm_tr_len, char *tr)
274 {
275 char *p, tmp[TMPBUFLEN];
276 ssize_t len = *size;
277
278 if (len <= 0)
279 return -EINVAL;
280
281 if (len > TMPBUFLEN - 1)
282 len = TMPBUFLEN - 1;
283
284 memcpy(tmp, *buf, len);
285
286 tmp[len] = 0;
287 p = tmp;
288 if (*p == '-' && *size > 1) {
289 *neg = true;
290 p++;
291 } else
292 *neg = false;
293 if (!isdigit(*p))
294 return -EINVAL;
295
296 if (strtoul_lenient(p, &p, 0, val))
297 return -EINVAL;
298
299 len = p - tmp;
300
301 /* We don't know if the next char is whitespace thus we may accept
302 * invalid integers (e.g. 1234...a) or two integers instead of one
303 * (e.g. 123...1). So lets not allow such large numbers. */
304 if (len == TMPBUFLEN - 1)
305 return -EINVAL;
306
307 if (len < *size && perm_tr_len && !memchr(perm_tr, *p, perm_tr_len))
308 return -EINVAL;
309
310 if (tr && (len < *size))
311 *tr = *p;
312
313 *buf += len;
314 *size -= len;
315
316 return 0;
317 }
318
319 /**
320 * proc_put_long - converts an integer to a decimal ASCII formatted string
321 *
322 * @buf: the user buffer
323 * @size: the size of the user buffer
324 * @val: the integer to be converted
325 * @neg: sign of the number, %TRUE for negative
326 *
327 * In case of success @buf and @size are updated with the amount of bytes
328 * written.
329 */
proc_put_long(void ** buf,size_t * size,unsigned long val,bool neg)330 static void proc_put_long(void **buf, size_t *size, unsigned long val, bool neg)
331 {
332 int len;
333 char tmp[TMPBUFLEN], *p = tmp;
334
335 sprintf(p, "%s%lu", neg ? "-" : "", val);
336 len = strlen(tmp);
337 if (len > *size)
338 len = *size;
339 memcpy(*buf, tmp, len);
340 *size -= len;
341 *buf += len;
342 }
343 #undef TMPBUFLEN
344
proc_put_char(void ** buf,size_t * size,char c)345 static void proc_put_char(void **buf, size_t *size, char c)
346 {
347 if (*size) {
348 char **buffer = (char **)buf;
349 **buffer = c;
350
351 (*size)--;
352 (*buffer)++;
353 *buf = *buffer;
354 }
355 }
356
357 /**
358 * proc_uint_u2k_conv_uop - Assign user value to a kernel pointer
359 *
360 * @u_ptr: pointer to user space variable
361 * @k_ptr: pointer to kernel variable
362 * @u_ptr_op: execute this function before assigning to k_ptr
363 *
364 * Uses WRITE_ONCE to assign value to k_ptr. Executes u_ptr_op if
365 * not NULL. Check that the values are less than UINT_MAX to avoid
366 * having to support wrap around from userspace.
367 *
368 * returns 0 on success.
369 */
proc_uint_u2k_conv_uop(const ulong * u_ptr,uint * k_ptr,ulong (* u_ptr_op)(const ulong))370 int proc_uint_u2k_conv_uop(const ulong *u_ptr, uint *k_ptr,
371 ulong (*u_ptr_op)(const ulong))
372 {
373 ulong u = u_ptr_op ? u_ptr_op(*u_ptr) : *u_ptr;
374
375 if (u > UINT_MAX)
376 return -EINVAL;
377 WRITE_ONCE(*k_ptr, u);
378 return 0;
379 }
380
381 /**
382 * proc_uint_k2u_conv - Assign kernel value to a user space pointer
383 *
384 * @u_ptr: pointer to user space variable
385 * @k_ptr: pointer to kernel variable
386 *
387 * Uses READ_ONCE to assign value to u_ptr.
388 *
389 * returns 0 on success.
390 */
proc_uint_k2u_conv(ulong * u_ptr,const uint * k_ptr)391 int proc_uint_k2u_conv(ulong *u_ptr, const uint *k_ptr)
392 {
393 uint val = READ_ONCE(*k_ptr);
394 *u_ptr = (ulong)val;
395 return 0;
396 }
397
398 /**
399 * proc_uint_conv - Change user or kernel pointer based on direction
400 *
401 * @u_ptr: pointer to user variable
402 * @k_ptr: pointer to kernel variable
403 * @dir: %TRUE if this is a write to the sysctl file
404 * @tbl: the sysctl table
405 * @k_ptr_range_check: Check range for k_ptr when %TRUE
406 * @user_to_kern: Callback used to assign value from user to kernel var
407 * @kern_to_user: Callback used to assign value from kernel to user var
408 *
409 * When direction is kernel to user, then the u_ptr is modified.
410 * When direction is user to kernel, then the k_ptr is modified.
411 *
412 * Returns 0 on success
413 */
proc_uint_conv(ulong * u_ptr,uint * k_ptr,int dir,const struct ctl_table * tbl,bool k_ptr_range_check,int (* user_to_kern)(const ulong * u_ptr,uint * k_ptr),int (* kern_to_user)(ulong * u_ptr,const uint * k_ptr))414 int proc_uint_conv(ulong *u_ptr, uint *k_ptr, int dir,
415 const struct ctl_table *tbl, bool k_ptr_range_check,
416 int (*user_to_kern)(const ulong *u_ptr, uint *k_ptr),
417 int (*kern_to_user)(ulong *u_ptr, const uint *k_ptr))
418 {
419 if (SYSCTL_KERN_TO_USER(dir))
420 return kern_to_user(u_ptr, k_ptr);
421
422 if (k_ptr_range_check) {
423 uint tmp_k;
424 int ret;
425
426 if (!tbl)
427 return -EINVAL;
428 ret = user_to_kern(u_ptr, &tmp_k);
429 if (ret)
430 return ret;
431 if ((tbl->extra1 &&
432 *(uint *)tbl->extra1 > tmp_k) ||
433 (tbl->extra2 &&
434 *(uint *)tbl->extra2 < tmp_k))
435 return -ERANGE;
436 WRITE_ONCE(*k_ptr, tmp_k);
437 } else
438 return user_to_kern(u_ptr, k_ptr);
439 return 0;
440 }
441
proc_uint_u2k_conv(const ulong * u_ptr,uint * k_ptr)442 static int proc_uint_u2k_conv(const ulong *u_ptr, uint *k_ptr)
443 {
444 return proc_uint_u2k_conv_uop(u_ptr, k_ptr, NULL);
445 }
446
do_proc_uint_conv(ulong * u_ptr,uint * k_ptr,int dir,const struct ctl_table * tbl)447 static int do_proc_uint_conv(ulong *u_ptr, uint *k_ptr, int dir,
448 const struct ctl_table *tbl)
449 {
450 return proc_uint_conv(u_ptr, k_ptr, dir, tbl, false,
451 proc_uint_u2k_conv, proc_uint_k2u_conv);
452 }
453
do_proc_uint_conv_minmax(ulong * u_ptr,uint * k_ptr,int dir,const struct ctl_table * tbl)454 static int do_proc_uint_conv_minmax(ulong *u_ptr, uint *k_ptr, int dir,
455 const struct ctl_table *tbl)
456 {
457 return proc_uint_conv(u_ptr, k_ptr, dir, tbl, true,
458 proc_uint_u2k_conv, proc_uint_k2u_conv);
459 }
460
461 /**
462 * proc_int_k2u_conv_kop - Assign kernel value to a user space pointer
463 * @u_ptr: pointer to user space variable
464 * @k_ptr: pointer to kernel variable
465 * @negp: assigned %TRUE if the converted kernel value is negative;
466 * %FALSE otherweise
467 * @k_ptr_op: execute this function before assigning to u_ptr
468 *
469 * Uses READ_ONCE to get value from k_ptr. Executes k_ptr_op before assigning
470 * to u_ptr if not NULL. Does **not** check for overflow.
471 *
472 * Returns: 0 on success.
473 */
proc_int_k2u_conv_kop(ulong * u_ptr,const int * k_ptr,bool * negp,ulong (* k_ptr_op)(const ulong))474 int proc_int_k2u_conv_kop(ulong *u_ptr, const int *k_ptr, bool *negp,
475 ulong (*k_ptr_op)(const ulong))
476 {
477 int val = READ_ONCE(*k_ptr);
478
479 if (val < 0) {
480 *negp = true;
481 *u_ptr = k_ptr_op ? -k_ptr_op((ulong)val) : -(ulong)val;
482 } else {
483 *negp = false;
484 *u_ptr = k_ptr_op ? k_ptr_op((ulong)val) : (ulong) val;
485 }
486 return 0;
487 }
488
489 /**
490 * proc_int_u2k_conv_uop - Assign user value to a kernel pointer
491 * @u_ptr: pointer to user space variable
492 * @k_ptr: pointer to kernel variable
493 * @negp: If %TRUE, the converted user value is made negative.
494 * @u_ptr_op: execute this function before assigning to k_ptr
495 *
496 * Uses WRITE_ONCE to assign value to k_ptr. Executes u_ptr_op if
497 * not NULL. Check for overflow with UINT_MAX.
498 *
499 * Returns: 0 on success.
500 */
proc_int_u2k_conv_uop(const ulong * u_ptr,int * k_ptr,const bool * negp,ulong (* u_ptr_op)(const ulong))501 int proc_int_u2k_conv_uop(const ulong *u_ptr, int *k_ptr, const bool *negp,
502 ulong (*u_ptr_op)(const ulong))
503 {
504 ulong u = u_ptr_op ? u_ptr_op(*u_ptr) : *u_ptr;
505
506 if (*negp) {
507 if (u > (ulong) INT_MAX + 1)
508 return -EINVAL;
509 WRITE_ONCE(*k_ptr, -u);
510 } else {
511 if (u > (ulong) INT_MAX)
512 return -EINVAL;
513 WRITE_ONCE(*k_ptr, u);
514 }
515 return 0;
516 }
517
proc_int_conv(bool * negp,ulong * u_ptr,int * k_ptr,int dir,const struct ctl_table * tbl,bool k_ptr_range_check,int (* user_to_kern)(const bool * negp,const ulong * u_ptr,int * k_ptr),int (* kern_to_user)(bool * negp,ulong * u_ptr,const int * k_ptr))518 int proc_int_conv(bool *negp, ulong *u_ptr, int *k_ptr, int dir,
519 const struct ctl_table *tbl, bool k_ptr_range_check,
520 int (*user_to_kern)(const bool *negp, const ulong *u_ptr, int *k_ptr),
521 int (*kern_to_user)(bool *negp, ulong *u_ptr, const int *k_ptr))
522 {
523 if (SYSCTL_KERN_TO_USER(dir))
524 return kern_to_user(negp, u_ptr, k_ptr);
525
526 if (k_ptr_range_check) {
527 int tmp_k, ret;
528
529 if (!tbl)
530 return -EINVAL;
531 ret = user_to_kern(negp, u_ptr, &tmp_k);
532 if (ret)
533 return ret;
534 if ((tbl->extra1 && *(int *)tbl->extra1 > tmp_k) ||
535 (tbl->extra2 && *(int *)tbl->extra2 < tmp_k))
536 return -EINVAL;
537 WRITE_ONCE(*k_ptr, tmp_k);
538 } else
539 return user_to_kern(negp, u_ptr, k_ptr);
540 return 0;
541 }
542
543
544
sysctl_user_to_kern_int_conv(const bool * negp,const ulong * u_ptr,int * k_ptr)545 static int sysctl_user_to_kern_int_conv(const bool *negp, const ulong *u_ptr,
546 int *k_ptr)
547 {
548 return proc_int_u2k_conv_uop(u_ptr, k_ptr, negp, NULL);
549 }
550
sysctl_kern_to_user_int_conv(bool * negp,ulong * u_ptr,const int * k_ptr)551 static int sysctl_kern_to_user_int_conv(bool *negp, ulong *u_ptr, const int *k_ptr)
552 {
553 return proc_int_k2u_conv_kop(u_ptr, k_ptr, negp, NULL);
554 }
555
do_proc_int_conv(bool * negp,unsigned long * u_ptr,int * k_ptr,int dir,const struct ctl_table * tbl)556 static int do_proc_int_conv(bool *negp, unsigned long *u_ptr, int *k_ptr,
557 int dir, const struct ctl_table *tbl)
558 {
559 return proc_int_conv(negp, u_ptr, k_ptr, dir, tbl, false,
560 sysctl_user_to_kern_int_conv,
561 sysctl_kern_to_user_int_conv);
562
563 }
564
do_proc_int_conv_minmax(bool * negp,unsigned long * u_ptr,int * k_ptr,int dir,const struct ctl_table * tbl)565 static int do_proc_int_conv_minmax(bool *negp, unsigned long *u_ptr, int *k_ptr,
566 int dir, const struct ctl_table *tbl)
567 {
568 return proc_int_conv(negp, u_ptr, k_ptr, dir, tbl, true,
569 sysctl_user_to_kern_int_conv,
570 sysctl_kern_to_user_int_conv);
571 }
572
573 static const char proc_wspace_sep[] = { ' ', '\t', '\n' };
574
do_proc_dointvec(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos,int (* conv)(bool * negp,unsigned long * u_ptr,int * k_ptr,int dir,const struct ctl_table * table))575 static int do_proc_dointvec(const struct ctl_table *table, int dir,
576 void *buffer, size_t *lenp, loff_t *ppos,
577 int (*conv)(bool *negp, unsigned long *u_ptr, int *k_ptr,
578 int dir, const struct ctl_table *table))
579 {
580 int *i, vleft, first = 1, err = 0;
581 size_t left;
582 char *p;
583
584 if (!table->data || !table->maxlen || !*lenp ||
585 (*ppos && SYSCTL_KERN_TO_USER(dir))) {
586 *lenp = 0;
587 return 0;
588 }
589
590 i = (int *) table->data;
591 vleft = table->maxlen / sizeof(*i);
592 left = *lenp;
593
594 if (!conv)
595 conv = do_proc_int_conv;
596
597 if (SYSCTL_USER_TO_KERN(dir)) {
598 if (proc_first_pos_non_zero_ignore(ppos, table))
599 goto out;
600
601 if (left > PAGE_SIZE - 1)
602 left = PAGE_SIZE - 1;
603 p = buffer;
604 }
605
606 for (; left && vleft--; i++, first=0) {
607 unsigned long lval;
608 bool neg;
609
610 if (SYSCTL_USER_TO_KERN(dir)) {
611 proc_skip_spaces(&p, &left);
612
613 if (!left)
614 break;
615 err = proc_get_long(&p, &left, &lval, &neg,
616 proc_wspace_sep,
617 sizeof(proc_wspace_sep), NULL);
618 if (err)
619 break;
620 if (conv(&neg, &lval, i, 1, table)) {
621 err = -EINVAL;
622 break;
623 }
624 } else {
625 if (conv(&neg, &lval, i, 0, table)) {
626 err = -EINVAL;
627 break;
628 }
629 if (!first)
630 proc_put_char(&buffer, &left, '\t');
631 proc_put_long(&buffer, &left, lval, neg);
632 }
633 }
634
635 if (SYSCTL_KERN_TO_USER(dir) && !first && left && !err)
636 proc_put_char(&buffer, &left, '\n');
637 if (SYSCTL_USER_TO_KERN(dir) && !err && left)
638 proc_skip_spaces(&p, &left);
639 if (SYSCTL_USER_TO_KERN(dir) && first)
640 return err ? : -EINVAL;
641 *lenp -= left;
642 out:
643 *ppos += *lenp;
644 return err;
645 }
646
do_proc_douintvec_w(const struct ctl_table * table,void * buffer,size_t * lenp,loff_t * ppos,int (* conv)(unsigned long * u_ptr,unsigned int * k_ptr,int dir,const struct ctl_table * table))647 static int do_proc_douintvec_w(const struct ctl_table *table, void *buffer,
648 size_t *lenp, loff_t *ppos,
649 int (*conv)(unsigned long *u_ptr,
650 unsigned int *k_ptr, int dir,
651 const struct ctl_table *table))
652 {
653 unsigned long lval;
654 int err = 0;
655 size_t left;
656 bool neg;
657 char *p = buffer;
658
659 left = *lenp;
660
661 if (proc_first_pos_non_zero_ignore(ppos, table))
662 goto bail_early;
663
664 if (left > PAGE_SIZE - 1)
665 left = PAGE_SIZE - 1;
666
667 proc_skip_spaces(&p, &left);
668 if (!left) {
669 err = -EINVAL;
670 goto out_free;
671 }
672
673 err = proc_get_long(&p, &left, &lval, &neg,
674 proc_wspace_sep,
675 sizeof(proc_wspace_sep), NULL);
676 if (err || neg) {
677 err = -EINVAL;
678 goto out_free;
679 }
680
681 if (conv(&lval, (unsigned int *) table->data, 1, table)) {
682 err = -EINVAL;
683 goto out_free;
684 }
685
686 if (!err && left)
687 proc_skip_spaces(&p, &left);
688
689 out_free:
690 if (err)
691 return -EINVAL;
692
693 return 0;
694
695 bail_early:
696 *ppos += *lenp;
697 return err;
698 }
699
do_proc_douintvec_r(const struct ctl_table * table,void * buffer,size_t * lenp,loff_t * ppos,int (* conv)(unsigned long * u_ptr,unsigned int * k_ptr,int dir,const struct ctl_table * table))700 static int do_proc_douintvec_r(const struct ctl_table *table, void *buffer,
701 size_t *lenp, loff_t *ppos,
702 int (*conv)(unsigned long *u_ptr,
703 unsigned int *k_ptr, int dir,
704 const struct ctl_table *table))
705 {
706 unsigned long lval;
707 int err = 0;
708 size_t left;
709
710 left = *lenp;
711
712 if (conv(&lval, (unsigned int *) table->data, 0, table)) {
713 err = -EINVAL;
714 goto out;
715 }
716
717 proc_put_long(&buffer, &left, lval, false);
718 if (!left)
719 goto out;
720
721 proc_put_char(&buffer, &left, '\n');
722
723 out:
724 *lenp -= left;
725 *ppos += *lenp;
726
727 return err;
728 }
729
do_proc_douintvec(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos,int (* conv)(unsigned long * u_ptr,unsigned int * k_ptr,int dir,const struct ctl_table * table))730 static int do_proc_douintvec(const struct ctl_table *table, int dir,
731 void *buffer, size_t *lenp, loff_t *ppos,
732 int (*conv)(unsigned long *u_ptr,
733 unsigned int *k_ptr, int dir,
734 const struct ctl_table *table))
735 {
736 unsigned int vleft;
737
738 if (!table->data || !table->maxlen || !*lenp ||
739 (*ppos && SYSCTL_KERN_TO_USER(dir))) {
740 *lenp = 0;
741 return 0;
742 }
743
744 vleft = table->maxlen / sizeof(unsigned int);
745
746 /*
747 * Arrays are not supported, keep this simple. *Do not* add
748 * support for them.
749 */
750 if (vleft != 1) {
751 *lenp = 0;
752 return -EINVAL;
753 }
754
755 if (!conv)
756 conv = do_proc_uint_conv;
757
758 if (SYSCTL_USER_TO_KERN(dir))
759 return do_proc_douintvec_w(table, buffer, lenp, ppos, conv);
760 return do_proc_douintvec_r(table, buffer, lenp, ppos, conv);
761 }
762
763 /**
764 * proc_douintvec_conv - read a vector of unsigned ints with a custom converter
765 *
766 * @table: the sysctl table
767 * @dir: %TRUE if this is a write to the sysctl file
768 * @buffer: the user buffer
769 * @lenp: the size of the user buffer
770 * @ppos: file position
771 * @conv: Custom converter call back
772 *
773 * Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
774 * values from/to the user buffer, treated as an ASCII string. Negative
775 * strings are not allowed.
776 *
777 * Returns 0 on success
778 */
proc_douintvec_conv(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos,int (* conv)(unsigned long * u_ptr,unsigned int * k_ptr,int dir,const struct ctl_table * table))779 int proc_douintvec_conv(const struct ctl_table *table, int dir, void *buffer,
780 size_t *lenp, loff_t *ppos,
781 int (*conv)(unsigned long *u_ptr, unsigned int *k_ptr,
782 int dir, const struct ctl_table *table))
783 {
784 return do_proc_douintvec(table, dir, buffer, lenp, ppos, conv);
785 }
786
787 /**
788 * proc_dobool - read/write a bool
789 * @table: the sysctl table
790 * @dir: %TRUE if this is a write to the sysctl file
791 * @buffer: the user buffer
792 * @lenp: the size of the user buffer
793 * @ppos: file position
794 *
795 * Reads/writes one integer value from/to the user buffer,
796 * treated as an ASCII string.
797 *
798 * table->data must point to a bool variable and table->maxlen must
799 * be sizeof(bool).
800 *
801 * Returns 0 on success.
802 */
proc_dobool(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)803 int proc_dobool(const struct ctl_table *table, int dir, void *buffer,
804 size_t *lenp, loff_t *ppos)
805 {
806 struct ctl_table tmp;
807 bool *data = table->data;
808 int res, val;
809
810 /* Do not support arrays yet. */
811 if (table->maxlen != sizeof(bool))
812 return -EINVAL;
813
814 tmp = *table;
815 tmp.maxlen = sizeof(val);
816 tmp.data = &val;
817
818 val = READ_ONCE(*data);
819 res = proc_dointvec(&tmp, dir, buffer, lenp, ppos);
820 if (res)
821 return res;
822 if (SYSCTL_USER_TO_KERN(dir))
823 WRITE_ONCE(*data, val);
824 return 0;
825 }
826
827 /**
828 * proc_dointvec - read a vector of integers
829 * @table: the sysctl table
830 * @dir: %TRUE if this is a write to the sysctl file
831 * @buffer: the user buffer
832 * @lenp: the size of the user buffer
833 * @ppos: file position
834 *
835 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
836 * values from/to the user buffer, treated as an ASCII string.
837 *
838 * Returns 0 on success.
839 */
proc_dointvec(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)840 int proc_dointvec(const struct ctl_table *table, int dir, void *buffer,
841 size_t *lenp, loff_t *ppos)
842 {
843 return do_proc_dointvec(table, dir, buffer, lenp, ppos, NULL);
844 }
845
846 /**
847 * proc_douintvec - read a vector of unsigned integers
848 * @table: the sysctl table
849 * @dir: %TRUE if this is a write to the sysctl file
850 * @buffer: the user buffer
851 * @lenp: the size of the user buffer
852 * @ppos: file position
853 *
854 * Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
855 * values from/to the user buffer, treated as an ASCII string.
856 *
857 * Returns 0 on success.
858 */
proc_douintvec(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)859 int proc_douintvec(const struct ctl_table *table, int dir, void *buffer,
860 size_t *lenp, loff_t *ppos)
861 {
862 return do_proc_douintvec(table, dir, buffer, lenp, ppos,
863 do_proc_uint_conv);
864 }
865
866 /**
867 * proc_dointvec_minmax - read a vector of integers with min/max values
868 * @table: the sysctl table
869 * @dir: %TRUE if this is a write to the sysctl file
870 * @buffer: the user buffer
871 * @lenp: the size of the user buffer
872 * @ppos: file position
873 *
874 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
875 * values from/to the user buffer, treated as an ASCII string.
876 *
877 * This routine will ensure the values are within the range specified by
878 * table->extra1 (min) and table->extra2 (max).
879 *
880 * Returns 0 on success or -EINVAL when the range check fails and
881 * SYSCTL_USER_TO_KERN(dir) == true
882 */
proc_dointvec_minmax(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)883 int proc_dointvec_minmax(const struct ctl_table *table, int dir,
884 void *buffer, size_t *lenp, loff_t *ppos)
885 {
886 return do_proc_dointvec(table, dir, buffer, lenp, ppos,
887 do_proc_int_conv_minmax);
888 }
889
890 /**
891 * proc_douintvec_minmax - read a vector of unsigned ints with min/max values
892 * @table: the sysctl table
893 * @dir: %TRUE if this is a write to the sysctl file
894 * @buffer: the user buffer
895 * @lenp: the size of the user buffer
896 * @ppos: file position
897 *
898 * Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
899 * values from/to the user buffer, treated as an ASCII string. Negative
900 * strings are not allowed.
901 *
902 * When changing the kernel variable, this routine will ensure the values
903 * are within the range specified by table->extra1 (min) and table->extra2
904 * (max). And Check that the values are less than UINT_MAX to avoid having to
905 * support wrap around uses from userspace.
906 *
907 * Returns 0 on success or -ERANGE when range check failes and
908 * SYSCTL_USER_TO_KERN(dir) == true
909 */
proc_douintvec_minmax(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)910 int proc_douintvec_minmax(const struct ctl_table *table, int dir,
911 void *buffer, size_t *lenp, loff_t *ppos)
912 {
913 return do_proc_douintvec(table, dir, buffer, lenp, ppos,
914 do_proc_uint_conv_minmax);
915 }
916
917 /**
918 * proc_dou8vec_minmax - read a vector of unsigned chars with min/max values
919 * @table: the sysctl table
920 * @dir: %TRUE if this is a write to the sysctl file
921 * @buffer: the user buffer
922 * @lenp: the size of the user buffer
923 * @ppos: file position
924 *
925 * Reads/writes up to table->maxlen/sizeof(u8) unsigned chars
926 * values from/to the user buffer, treated as an ASCII string. Negative
927 * strings are not allowed.
928 *
929 * This routine will ensure the values are within the range specified by
930 * table->extra1 (min) and table->extra2 (max).
931 *
932 * Returns 0 on success or an error on SYSCTL_USER_TO_KERN(dir) == true
933 * and the range check fails.
934 */
proc_dou8vec_minmax(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)935 int proc_dou8vec_minmax(const struct ctl_table *table, int dir,
936 void *buffer, size_t *lenp, loff_t *ppos)
937 {
938 struct ctl_table tmp;
939 unsigned int min = 0, max = 255U, val;
940 u8 *data = table->data;
941 int res;
942
943 /* Do not support arrays yet. */
944 if (table->maxlen != sizeof(u8))
945 return -EINVAL;
946
947 tmp = *table;
948
949 tmp.maxlen = sizeof(val);
950 tmp.data = &val;
951 if (!tmp.extra1)
952 tmp.extra1 = (unsigned int *) &min;
953 if (!tmp.extra2)
954 tmp.extra2 = (unsigned int *) &max;
955
956 val = READ_ONCE(*data);
957 res = do_proc_douintvec(&tmp, dir, buffer, lenp, ppos,
958 do_proc_uint_conv_minmax);
959 if (res)
960 return res;
961 if (SYSCTL_USER_TO_KERN(dir))
962 WRITE_ONCE(*data, val);
963 return 0;
964 }
965 EXPORT_SYMBOL_GPL(proc_dou8vec_minmax);
966
do_proc_doulongvec_minmax(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos,unsigned long convmul,unsigned long convdiv)967 static int do_proc_doulongvec_minmax(const struct ctl_table *table, int dir,
968 void *buffer, size_t *lenp, loff_t *ppos,
969 unsigned long convmul,
970 unsigned long convdiv)
971 {
972 unsigned long *i, *min, *max;
973 int vleft, first = 1, err = 0;
974 size_t left;
975 char *p;
976
977 if (!table->data || !table->maxlen || !*lenp ||
978 (*ppos && SYSCTL_KERN_TO_USER(dir))) {
979 *lenp = 0;
980 return 0;
981 }
982
983 i = table->data;
984 min = table->extra1;
985 max = table->extra2;
986 vleft = table->maxlen / sizeof(unsigned long);
987 left = *lenp;
988
989 if (SYSCTL_USER_TO_KERN(dir)) {
990 if (proc_first_pos_non_zero_ignore(ppos, table))
991 goto out;
992
993 if (left > PAGE_SIZE - 1)
994 left = PAGE_SIZE - 1;
995 p = buffer;
996 }
997
998 for (; left && vleft--; i++, first = 0) {
999 unsigned long val;
1000
1001 if (SYSCTL_USER_TO_KERN(dir)) {
1002 bool neg;
1003
1004 proc_skip_spaces(&p, &left);
1005 if (!left)
1006 break;
1007
1008 err = proc_get_long(&p, &left, &val, &neg,
1009 proc_wspace_sep,
1010 sizeof(proc_wspace_sep), NULL);
1011 if (err || neg) {
1012 err = -EINVAL;
1013 break;
1014 }
1015
1016 val = convmul * val / convdiv;
1017 if ((min && val < *min) || (max && val > *max)) {
1018 err = -EINVAL;
1019 break;
1020 }
1021 WRITE_ONCE(*i, val);
1022 } else {
1023 val = convdiv * READ_ONCE(*i) / convmul;
1024 if (!first)
1025 proc_put_char(&buffer, &left, '\t');
1026 proc_put_long(&buffer, &left, val, false);
1027 }
1028 }
1029
1030 if (SYSCTL_KERN_TO_USER(dir) && !first && left && !err)
1031 proc_put_char(&buffer, &left, '\n');
1032 if (SYSCTL_USER_TO_KERN(dir) && !err)
1033 proc_skip_spaces(&p, &left);
1034 if (SYSCTL_USER_TO_KERN(dir) && first)
1035 return err ? : -EINVAL;
1036 *lenp -= left;
1037 out:
1038 *ppos += *lenp;
1039 return err;
1040 }
1041
proc_doulongvec_minmax_conv(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos,unsigned long convmul,unsigned long convdiv)1042 int proc_doulongvec_minmax_conv(const struct ctl_table *table, int dir,
1043 void *buffer, size_t *lenp, loff_t *ppos,
1044 unsigned long convmul, unsigned long convdiv)
1045 {
1046 return do_proc_doulongvec_minmax(table, dir, buffer, lenp, ppos,
1047 convmul, convdiv);
1048 }
1049
1050 /**
1051 * proc_doulongvec_minmax - read a vector of long integers with min/max values
1052 * @table: the sysctl table
1053 * @dir: %TRUE if this is a write to the sysctl file
1054 * @buffer: the user buffer
1055 * @lenp: the size of the user buffer
1056 * @ppos: file position
1057 *
1058 * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
1059 * values from/to the user buffer, treated as an ASCII string.
1060 *
1061 * This routine will ensure the values are within the range specified by
1062 * table->extra1 (min) and table->extra2 (max).
1063 *
1064 * Returns 0 on success.
1065 */
proc_doulongvec_minmax(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)1066 int proc_doulongvec_minmax(const struct ctl_table *table, int dir,
1067 void *buffer, size_t *lenp, loff_t *ppos)
1068 {
1069 return proc_doulongvec_minmax_conv(table, dir, buffer, lenp, ppos, 1l, 1l);
1070 }
1071
1072 /**
1073 * proc_dointvec_conv - read a vector of ints with a custom converter
1074 * @table: the sysctl table
1075 * @dir: %TRUE if this is a write to the sysctl file
1076 * @buffer: the user buffer
1077 * @lenp: the size of the user buffer
1078 * @ppos: file position
1079 * @conv: Custom converter call back
1080 *
1081 * Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
1082 * values from/to the user buffer, treated as an ASCII string. Negative
1083 * strings are not allowed.
1084 *
1085 * Returns: 0 on success
1086 */
1087
proc_dointvec_conv(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos,int (* conv)(bool * negp,unsigned long * u_ptr,int * k_ptr,int dir,const struct ctl_table * table))1088 int proc_dointvec_conv(const struct ctl_table *table, int dir, void *buffer,
1089 size_t *lenp, loff_t *ppos,
1090 int (*conv)(bool *negp, unsigned long *u_ptr, int *k_ptr,
1091 int dir, const struct ctl_table *table))
1092 {
1093 return do_proc_dointvec(table, dir, buffer, lenp, ppos, conv);
1094 }
1095
1096 /**
1097 * proc_do_large_bitmap - read/write from/to a large bitmap
1098 * @table: the sysctl table
1099 * @dir: %TRUE if this is a write to the sysctl file
1100 * @buffer: the user buffer
1101 * @lenp: the size of the user buffer
1102 * @ppos: file position
1103 *
1104 * The bitmap is stored at table->data and the bitmap length (in bits)
1105 * in table->maxlen.
1106 *
1107 * We use a range comma separated format (e.g. 1,3-4,10-10) so that
1108 * large bitmaps may be represented in a compact manner. Writing into
1109 * the file will clear the bitmap then update it with the given input.
1110 *
1111 * Returns 0 on success.
1112 */
proc_do_large_bitmap(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)1113 int proc_do_large_bitmap(const struct ctl_table *table, int dir,
1114 void *buffer, size_t *lenp, loff_t *ppos)
1115 {
1116 int err = 0;
1117 size_t left = *lenp;
1118 unsigned long bitmap_len = table->maxlen;
1119 unsigned long *bitmap = *(unsigned long **) table->data;
1120 unsigned long *tmp_bitmap = NULL;
1121 char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
1122
1123 if (!bitmap || !bitmap_len || !left || (*ppos && SYSCTL_KERN_TO_USER(dir))) {
1124 *lenp = 0;
1125 return 0;
1126 }
1127
1128 if (SYSCTL_USER_TO_KERN(dir)) {
1129 char *p = buffer;
1130 size_t skipped = 0;
1131
1132 if (left > PAGE_SIZE - 1) {
1133 left = PAGE_SIZE - 1;
1134 /* How much of the buffer we'll skip this pass */
1135 skipped = *lenp - left;
1136 }
1137
1138 tmp_bitmap = bitmap_zalloc(bitmap_len, GFP_KERNEL);
1139 if (!tmp_bitmap)
1140 return -ENOMEM;
1141 proc_skip_char(&p, &left, '\n');
1142 while (!err && left) {
1143 unsigned long val_a, val_b;
1144 bool neg;
1145 size_t saved_left;
1146
1147 /* In case we stop parsing mid-number, we can reset */
1148 saved_left = left;
1149 err = proc_get_long(&p, &left, &val_a, &neg, tr_a,
1150 sizeof(tr_a), &c);
1151 /*
1152 * If we consumed the entirety of a truncated buffer or
1153 * only one char is left (may be a "-"), then stop here,
1154 * reset, & come back for more.
1155 */
1156 if ((left <= 1) && skipped) {
1157 left = saved_left;
1158 break;
1159 }
1160
1161 if (err)
1162 break;
1163 if (val_a >= bitmap_len || neg) {
1164 err = -EINVAL;
1165 break;
1166 }
1167
1168 val_b = val_a;
1169 if (left) {
1170 p++;
1171 left--;
1172 }
1173
1174 if (c == '-') {
1175 err = proc_get_long(&p, &left, &val_b,
1176 &neg, tr_b, sizeof(tr_b),
1177 &c);
1178 /*
1179 * If we consumed all of a truncated buffer or
1180 * then stop here, reset, & come back for more.
1181 */
1182 if (!left && skipped) {
1183 left = saved_left;
1184 break;
1185 }
1186
1187 if (err)
1188 break;
1189 if (val_b >= bitmap_len || neg ||
1190 val_a > val_b) {
1191 err = -EINVAL;
1192 break;
1193 }
1194 if (left) {
1195 p++;
1196 left--;
1197 }
1198 }
1199
1200 bitmap_set(tmp_bitmap, val_a, val_b - val_a + 1);
1201 proc_skip_char(&p, &left, '\n');
1202 }
1203 left += skipped;
1204 } else {
1205 unsigned long bit_a, bit_b = 0;
1206 bool first = 1;
1207
1208 while (left) {
1209 bit_a = find_next_bit(bitmap, bitmap_len, bit_b);
1210 if (bit_a >= bitmap_len)
1211 break;
1212 bit_b = find_next_zero_bit(bitmap, bitmap_len,
1213 bit_a + 1) - 1;
1214
1215 if (!first)
1216 proc_put_char(&buffer, &left, ',');
1217 proc_put_long(&buffer, &left, bit_a, false);
1218 if (bit_a != bit_b) {
1219 proc_put_char(&buffer, &left, '-');
1220 proc_put_long(&buffer, &left, bit_b, false);
1221 }
1222
1223 first = 0; bit_b++;
1224 }
1225 proc_put_char(&buffer, &left, '\n');
1226 }
1227
1228 if (!err) {
1229 if (SYSCTL_USER_TO_KERN(dir)) {
1230 if (*ppos)
1231 bitmap_or(bitmap, bitmap, tmp_bitmap, bitmap_len);
1232 else
1233 bitmap_copy(bitmap, tmp_bitmap, bitmap_len);
1234 }
1235 *lenp -= left;
1236 *ppos += *lenp;
1237 }
1238
1239 bitmap_free(tmp_bitmap);
1240 return err;
1241 }
1242
1243 #else /* CONFIG_PROC_SYSCTL */
1244
proc_dostring(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)1245 int proc_dostring(const struct ctl_table *table, int dir,
1246 void *buffer, size_t *lenp, loff_t *ppos)
1247 {
1248 return -ENOSYS;
1249 }
1250
proc_dobool(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)1251 int proc_dobool(const struct ctl_table *table, int dir,
1252 void *buffer, size_t *lenp, loff_t *ppos)
1253 {
1254 return -ENOSYS;
1255 }
1256
proc_dointvec(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)1257 int proc_dointvec(const struct ctl_table *table, int dir,
1258 void *buffer, size_t *lenp, loff_t *ppos)
1259 {
1260 return -ENOSYS;
1261 }
1262
proc_douintvec(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)1263 int proc_douintvec(const struct ctl_table *table, int dir,
1264 void *buffer, size_t *lenp, loff_t *ppos)
1265 {
1266 return -ENOSYS;
1267 }
1268
proc_dointvec_minmax(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)1269 int proc_dointvec_minmax(const struct ctl_table *table, int dir,
1270 void *buffer, size_t *lenp, loff_t *ppos)
1271 {
1272 return -ENOSYS;
1273 }
1274
proc_douintvec_minmax(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)1275 int proc_douintvec_minmax(const struct ctl_table *table, int dir,
1276 void *buffer, size_t *lenp, loff_t *ppos)
1277 {
1278 return -ENOSYS;
1279 }
1280
proc_douintvec_conv(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos,int (* conv)(unsigned long * lvalp,unsigned int * valp,int write,const struct ctl_table * table))1281 int proc_douintvec_conv(const struct ctl_table *table, int write, void *buffer,
1282 size_t *lenp, loff_t *ppos,
1283 int (*conv)(unsigned long *lvalp, unsigned int *valp,
1284 int write, const struct ctl_table *table))
1285 {
1286 return -ENOSYS;
1287 }
1288
proc_uint_k2u_conv(ulong * u_ptr,const uint * k_ptr)1289 int proc_uint_k2u_conv(ulong *u_ptr, const uint *k_ptr)
1290 {
1291 return -ENOSYS;
1292 }
1293
proc_uint_u2k_conv_uop(const ulong * u_ptr,uint * k_ptr,ulong (* u_ptr_op)(const ulong))1294 int proc_uint_u2k_conv_uop(const ulong *u_ptr, uint *k_ptr,
1295 ulong (*u_ptr_op)(const ulong))
1296 {
1297 return -ENOSYS;
1298 }
1299
proc_uint_conv(ulong * u_ptr,uint * k_ptr,int dir,const struct ctl_table * tbl,bool k_ptr_range_check,int (* user_to_kern)(const ulong * u_ptr,uint * k_ptr),int (* kern_to_user)(ulong * u_ptr,const uint * k_ptr))1300 int proc_uint_conv(ulong *u_ptr, uint *k_ptr, int dir,
1301 const struct ctl_table *tbl, bool k_ptr_range_check,
1302 int (*user_to_kern)(const ulong *u_ptr, uint *k_ptr),
1303 int (*kern_to_user)(ulong *u_ptr, const uint *k_ptr))
1304 {
1305 return -ENOSYS;
1306 }
1307
proc_dou8vec_minmax(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)1308 int proc_dou8vec_minmax(const struct ctl_table *table, int dir,
1309 void *buffer, size_t *lenp, loff_t *ppos)
1310 {
1311 return -ENOSYS;
1312 }
1313
proc_doulongvec_minmax(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)1314 int proc_doulongvec_minmax(const struct ctl_table *table, int dir,
1315 void *buffer, size_t *lenp, loff_t *ppos)
1316 {
1317 return -ENOSYS;
1318 }
1319
proc_doulongvec_minmax_conv(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos,unsigned long convmul,unsigned long convdiv)1320 int proc_doulongvec_minmax_conv(const struct ctl_table *table, int dir,
1321 void *buffer, size_t *lenp, loff_t *ppos,
1322 unsigned long convmul, unsigned long convdiv)
1323 {
1324 return -ENOSYS;
1325 }
1326
proc_dointvec_conv(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos,int (* conv)(bool * negp,unsigned long * u_ptr,int * k_ptr,int dir,const struct ctl_table * table))1327 int proc_dointvec_conv(const struct ctl_table *table, int dir, void *buffer,
1328 size_t *lenp, loff_t *ppos,
1329 int (*conv)(bool *negp, unsigned long *u_ptr, int *k_ptr,
1330 int dir, const struct ctl_table *table))
1331 {
1332 return -ENOSYS;
1333 }
1334
proc_do_large_bitmap(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)1335 int proc_do_large_bitmap(const struct ctl_table *table, int dir,
1336 void *buffer, size_t *lenp, loff_t *ppos)
1337 {
1338 return -ENOSYS;
1339 }
1340
1341 #endif /* CONFIG_PROC_SYSCTL */
1342
1343 #if defined(CONFIG_SYSCTL)
proc_do_static_key(const struct ctl_table * table,int dir,void * buffer,size_t * lenp,loff_t * ppos)1344 int proc_do_static_key(const struct ctl_table *table, int dir,
1345 void *buffer, size_t *lenp, loff_t *ppos)
1346 {
1347 struct static_key *key = (struct static_key *)table->data;
1348 static DEFINE_MUTEX(static_key_mutex);
1349 int val, ret;
1350 struct ctl_table tmp = {
1351 .data = &val,
1352 .maxlen = sizeof(val),
1353 .mode = table->mode,
1354 .extra1 = SYSCTL_ZERO,
1355 .extra2 = SYSCTL_ONE,
1356 };
1357
1358 if (SYSCTL_USER_TO_KERN(dir) && !capable(CAP_SYS_ADMIN))
1359 return -EPERM;
1360
1361 mutex_lock(&static_key_mutex);
1362 val = static_key_enabled(key);
1363 ret = proc_dointvec_minmax(&tmp, dir, buffer, lenp, ppos);
1364 if (SYSCTL_USER_TO_KERN(dir) && !ret) {
1365 if (val)
1366 static_key_enable(key);
1367 else
1368 static_key_disable(key);
1369 }
1370 mutex_unlock(&static_key_mutex);
1371 return ret;
1372 }
1373
1374 static const struct ctl_table sysctl_subsys_table[] = {
1375 #ifdef CONFIG_PROC_SYSCTL
1376 {
1377 .procname = "sysctl_writes_strict",
1378 .data = &sysctl_writes_strict,
1379 .maxlen = sizeof(int),
1380 .mode = 0644,
1381 .proc_handler = proc_dointvec_minmax,
1382 .extra1 = SYSCTL_NEG_ONE,
1383 .extra2 = SYSCTL_ONE,
1384 },
1385 #endif
1386 {
1387 .procname = "ngroups_max",
1388 .data = (void *)&ngroups_max,
1389 .maxlen = sizeof (int),
1390 .mode = 0444,
1391 .proc_handler = proc_dointvec,
1392 },
1393 {
1394 .procname = "cap_last_cap",
1395 .data = (void *)&cap_last_cap,
1396 .maxlen = sizeof(int),
1397 .mode = 0444,
1398 .proc_handler = proc_dointvec,
1399 },
1400 #ifdef CONFIG_SYSCTL_ARCH_UNALIGN_ALLOW
1401 {
1402 .procname = "unaligned-trap",
1403 .data = &unaligned_enabled,
1404 .maxlen = sizeof(int),
1405 .mode = 0644,
1406 .proc_handler = proc_dointvec,
1407 },
1408 #endif
1409 #ifdef CONFIG_SYSCTL_ARCH_UNALIGN_NO_WARN
1410 {
1411 .procname = "ignore-unaligned-usertrap",
1412 .data = &no_unaligned_warning,
1413 .maxlen = sizeof (int),
1414 .mode = 0644,
1415 .proc_handler = proc_dointvec,
1416 },
1417 #endif
1418 };
1419
sysctl_init_bases(void)1420 int __init sysctl_init_bases(void)
1421 {
1422 register_sysctl_init("kernel", sysctl_subsys_table);
1423
1424 return 0;
1425 }
1426 #endif /* CONFIG_SYSCTL */
1427 /*
1428 * No sense putting this after each symbol definition, twice,
1429 * exception granted :-)
1430 */
1431 EXPORT_SYMBOL(proc_dobool);
1432 EXPORT_SYMBOL(proc_dointvec);
1433 EXPORT_SYMBOL(proc_douintvec);
1434 EXPORT_SYMBOL(proc_dointvec_minmax);
1435 EXPORT_SYMBOL_GPL(proc_douintvec_minmax);
1436 EXPORT_SYMBOL(proc_dostring);
1437 EXPORT_SYMBOL(proc_doulongvec_minmax);
1438 EXPORT_SYMBOL(proc_do_large_bitmap);
1439