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/times.h>
17 #include <linux/limits.h>
18 #include <linux/syscalls.h>
19 #include <linux/capability.h>
20
21 #include "../lib/kstrtox.h"
22
23 #include <linux/uaccess.h>
24 #include <asm/processor.h>
25
26 /* shared constants to be used in various sysctls */
27 const int sysctl_vals[] = { 0, 1, 2, 3, 4, 100, 200, 1000, 3000, INT_MAX, 65535, -1 };
28 EXPORT_SYMBOL(sysctl_vals);
29
30 const unsigned long sysctl_long_vals[] = { 0, 1, LONG_MAX };
31 EXPORT_SYMBOL_GPL(sysctl_long_vals);
32
33 #if defined(CONFIG_SYSCTL)
34
35 /* Constants used for minimum and maximum */
36 static const int ngroups_max = NGROUPS_MAX;
37 static const int cap_last_cap = CAP_LAST_CAP;
38
39 #ifdef CONFIG_PROC_SYSCTL
40
41 /**
42 * enum sysctl_writes_mode - supported sysctl write modes
43 *
44 * @SYSCTL_WRITES_LEGACY: each write syscall must fully contain the sysctl value
45 * to be written, and multiple writes on the same sysctl file descriptor
46 * will rewrite the sysctl value, regardless of file position. No warning
47 * is issued when the initial position is not 0.
48 * @SYSCTL_WRITES_WARN: same as above but warn when the initial file position is
49 * not 0.
50 * @SYSCTL_WRITES_STRICT: writes to numeric sysctl entries must always be at
51 * file position 0 and the value must be fully contained in the buffer
52 * sent to the write syscall. If dealing with strings respect the file
53 * position, but restrict this to the max length of the buffer, anything
54 * passed the max length will be ignored. Multiple writes will append
55 * to the buffer.
56 *
57 * These write modes control how current file position affects the behavior of
58 * updating sysctl values through the proc 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 write,char * buffer,size_t * lenp,loff_t * ppos)76 static int _proc_do_string(char *data, int maxlen, int write,
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 (write) {
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 * @write: %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 write,void * buffer,size_t * lenp,loff_t * ppos)189 int proc_dostring(const struct ctl_table *table, int write,
190 void *buffer, size_t *lenp, loff_t *ppos)
191 {
192 if (write)
193 proc_first_pos_non_zero_ignore(ppos, table);
194
195 return _proc_do_string(table->data, table->maxlen, write, 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
do_proc_dointvec_conv(bool * negp,unsigned long * lvalp,int * valp,int write,void * data)357 static int do_proc_dointvec_conv(bool *negp, unsigned long *lvalp,
358 int *valp,
359 int write, void *data)
360 {
361 if (write) {
362 if (*negp) {
363 if (*lvalp > (unsigned long) INT_MAX + 1)
364 return -EINVAL;
365 WRITE_ONCE(*valp, -*lvalp);
366 } else {
367 if (*lvalp > (unsigned long) INT_MAX)
368 return -EINVAL;
369 WRITE_ONCE(*valp, *lvalp);
370 }
371 } else {
372 int val = READ_ONCE(*valp);
373 if (val < 0) {
374 *negp = true;
375 *lvalp = -(unsigned long)val;
376 } else {
377 *negp = false;
378 *lvalp = (unsigned long)val;
379 }
380 }
381 return 0;
382 }
383
do_proc_douintvec_conv(unsigned long * lvalp,unsigned int * valp,int write,void * data)384 static int do_proc_douintvec_conv(unsigned long *lvalp,
385 unsigned int *valp,
386 int write, void *data)
387 {
388 if (write) {
389 if (*lvalp > UINT_MAX)
390 return -EINVAL;
391 WRITE_ONCE(*valp, *lvalp);
392 } else {
393 unsigned int val = READ_ONCE(*valp);
394 *lvalp = (unsigned long)val;
395 }
396 return 0;
397 }
398
399 static const char proc_wspace_sep[] = { ' ', '\t', '\n' };
400
__do_proc_dointvec(void * tbl_data,const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos,int (* conv)(bool * negp,unsigned long * lvalp,int * valp,int write,void * data),void * data)401 static int __do_proc_dointvec(void *tbl_data, const struct ctl_table *table,
402 int write, void *buffer,
403 size_t *lenp, loff_t *ppos,
404 int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
405 int write, void *data),
406 void *data)
407 {
408 int *i, vleft, first = 1, err = 0;
409 size_t left;
410 char *p;
411
412 if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
413 *lenp = 0;
414 return 0;
415 }
416
417 i = (int *) tbl_data;
418 vleft = table->maxlen / sizeof(*i);
419 left = *lenp;
420
421 if (!conv)
422 conv = do_proc_dointvec_conv;
423
424 if (write) {
425 if (proc_first_pos_non_zero_ignore(ppos, table))
426 goto out;
427
428 if (left > PAGE_SIZE - 1)
429 left = PAGE_SIZE - 1;
430 p = buffer;
431 }
432
433 for (; left && vleft--; i++, first=0) {
434 unsigned long lval;
435 bool neg;
436
437 if (write) {
438 proc_skip_spaces(&p, &left);
439
440 if (!left)
441 break;
442 err = proc_get_long(&p, &left, &lval, &neg,
443 proc_wspace_sep,
444 sizeof(proc_wspace_sep), NULL);
445 if (err)
446 break;
447 if (conv(&neg, &lval, i, 1, data)) {
448 err = -EINVAL;
449 break;
450 }
451 } else {
452 if (conv(&neg, &lval, i, 0, data)) {
453 err = -EINVAL;
454 break;
455 }
456 if (!first)
457 proc_put_char(&buffer, &left, '\t');
458 proc_put_long(&buffer, &left, lval, neg);
459 }
460 }
461
462 if (!write && !first && left && !err)
463 proc_put_char(&buffer, &left, '\n');
464 if (write && !err && left)
465 proc_skip_spaces(&p, &left);
466 if (write && first)
467 return err ? : -EINVAL;
468 *lenp -= left;
469 out:
470 *ppos += *lenp;
471 return err;
472 }
473
do_proc_dointvec(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos,int (* conv)(bool * negp,unsigned long * lvalp,int * valp,int write,void * data),void * data)474 static int do_proc_dointvec(const struct ctl_table *table, int write,
475 void *buffer, size_t *lenp, loff_t *ppos,
476 int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
477 int write, void *data),
478 void *data)
479 {
480 return __do_proc_dointvec(table->data, table, write,
481 buffer, lenp, ppos, conv, data);
482 }
483
do_proc_douintvec_w(unsigned int * tbl_data,const struct ctl_table * table,void * buffer,size_t * lenp,loff_t * ppos,int (* conv)(unsigned long * lvalp,unsigned int * valp,int write,void * data),void * data)484 static int do_proc_douintvec_w(unsigned int *tbl_data,
485 const struct ctl_table *table,
486 void *buffer,
487 size_t *lenp, loff_t *ppos,
488 int (*conv)(unsigned long *lvalp,
489 unsigned int *valp,
490 int write, void *data),
491 void *data)
492 {
493 unsigned long lval;
494 int err = 0;
495 size_t left;
496 bool neg;
497 char *p = buffer;
498
499 left = *lenp;
500
501 if (proc_first_pos_non_zero_ignore(ppos, table))
502 goto bail_early;
503
504 if (left > PAGE_SIZE - 1)
505 left = PAGE_SIZE - 1;
506
507 proc_skip_spaces(&p, &left);
508 if (!left) {
509 err = -EINVAL;
510 goto out_free;
511 }
512
513 err = proc_get_long(&p, &left, &lval, &neg,
514 proc_wspace_sep,
515 sizeof(proc_wspace_sep), NULL);
516 if (err || neg) {
517 err = -EINVAL;
518 goto out_free;
519 }
520
521 if (conv(&lval, tbl_data, 1, data)) {
522 err = -EINVAL;
523 goto out_free;
524 }
525
526 if (!err && left)
527 proc_skip_spaces(&p, &left);
528
529 out_free:
530 if (err)
531 return -EINVAL;
532
533 return 0;
534
535 /* This is in keeping with old __do_proc_dointvec() */
536 bail_early:
537 *ppos += *lenp;
538 return err;
539 }
540
do_proc_douintvec_r(unsigned int * tbl_data,void * buffer,size_t * lenp,loff_t * ppos,int (* conv)(unsigned long * lvalp,unsigned int * valp,int write,void * data),void * data)541 static int do_proc_douintvec_r(unsigned int *tbl_data, void *buffer,
542 size_t *lenp, loff_t *ppos,
543 int (*conv)(unsigned long *lvalp,
544 unsigned int *valp,
545 int write, void *data),
546 void *data)
547 {
548 unsigned long lval;
549 int err = 0;
550 size_t left;
551
552 left = *lenp;
553
554 if (conv(&lval, tbl_data, 0, data)) {
555 err = -EINVAL;
556 goto out;
557 }
558
559 proc_put_long(&buffer, &left, lval, false);
560 if (!left)
561 goto out;
562
563 proc_put_char(&buffer, &left, '\n');
564
565 out:
566 *lenp -= left;
567 *ppos += *lenp;
568
569 return err;
570 }
571
__do_proc_douintvec(void * tbl_data,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,void * data),void * data)572 static int __do_proc_douintvec(void *tbl_data, const struct ctl_table *table,
573 int write, void *buffer,
574 size_t *lenp, loff_t *ppos,
575 int (*conv)(unsigned long *lvalp,
576 unsigned int *valp,
577 int write, void *data),
578 void *data)
579 {
580 unsigned int *i, vleft;
581
582 if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
583 *lenp = 0;
584 return 0;
585 }
586
587 i = (unsigned int *) tbl_data;
588 vleft = table->maxlen / sizeof(*i);
589
590 /*
591 * Arrays are not supported, keep this simple. *Do not* add
592 * support for them.
593 */
594 if (vleft != 1) {
595 *lenp = 0;
596 return -EINVAL;
597 }
598
599 if (!conv)
600 conv = do_proc_douintvec_conv;
601
602 if (write)
603 return do_proc_douintvec_w(i, table, buffer, lenp, ppos,
604 conv, data);
605 return do_proc_douintvec_r(i, buffer, lenp, ppos, conv, data);
606 }
607
do_proc_douintvec(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,void * data),void * data)608 int do_proc_douintvec(const struct ctl_table *table, int write,
609 void *buffer, size_t *lenp, loff_t *ppos,
610 int (*conv)(unsigned long *lvalp,
611 unsigned int *valp,
612 int write, void *data),
613 void *data)
614 {
615 return __do_proc_douintvec(table->data, table, write,
616 buffer, lenp, ppos, conv, data);
617 }
618
619 /**
620 * proc_dobool - read/write a bool
621 * @table: the sysctl table
622 * @write: %TRUE if this is a write to the sysctl file
623 * @buffer: the user buffer
624 * @lenp: the size of the user buffer
625 * @ppos: file position
626 *
627 * Reads/writes one integer value from/to the user buffer,
628 * treated as an ASCII string.
629 *
630 * table->data must point to a bool variable and table->maxlen must
631 * be sizeof(bool).
632 *
633 * Returns 0 on success.
634 */
proc_dobool(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)635 int proc_dobool(const struct ctl_table *table, int write, void *buffer,
636 size_t *lenp, loff_t *ppos)
637 {
638 struct ctl_table tmp;
639 bool *data = table->data;
640 int res, val;
641
642 /* Do not support arrays yet. */
643 if (table->maxlen != sizeof(bool))
644 return -EINVAL;
645
646 tmp = *table;
647 tmp.maxlen = sizeof(val);
648 tmp.data = &val;
649
650 val = READ_ONCE(*data);
651 res = proc_dointvec(&tmp, write, buffer, lenp, ppos);
652 if (res)
653 return res;
654 if (write)
655 WRITE_ONCE(*data, val);
656 return 0;
657 }
658
659 /**
660 * proc_dointvec - read a vector of integers
661 * @table: the sysctl table
662 * @write: %TRUE if this is a write to the sysctl file
663 * @buffer: the user buffer
664 * @lenp: the size of the user buffer
665 * @ppos: file position
666 *
667 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
668 * values from/to the user buffer, treated as an ASCII string.
669 *
670 * Returns 0 on success.
671 */
proc_dointvec(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)672 int proc_dointvec(const struct ctl_table *table, int write, void *buffer,
673 size_t *lenp, loff_t *ppos)
674 {
675 return do_proc_dointvec(table, write, buffer, lenp, ppos, NULL, NULL);
676 }
677
678 /**
679 * proc_douintvec - read a vector of unsigned integers
680 * @table: the sysctl table
681 * @write: %TRUE if this is a write to the sysctl file
682 * @buffer: the user buffer
683 * @lenp: the size of the user buffer
684 * @ppos: file position
685 *
686 * Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
687 * values from/to the user buffer, treated as an ASCII string.
688 *
689 * Returns 0 on success.
690 */
proc_douintvec(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)691 int proc_douintvec(const struct ctl_table *table, int write, void *buffer,
692 size_t *lenp, loff_t *ppos)
693 {
694 return do_proc_douintvec(table, write, buffer, lenp, ppos,
695 do_proc_douintvec_conv, NULL);
696 }
697
698 /**
699 * struct do_proc_dointvec_minmax_conv_param - proc_dointvec_minmax() range checking structure
700 * @min: pointer to minimum allowable value
701 * @max: pointer to maximum allowable value
702 *
703 * The do_proc_dointvec_minmax_conv_param structure provides the
704 * minimum and maximum values for doing range checking for those sysctl
705 * parameters that use the proc_dointvec_minmax() handler.
706 */
707 struct do_proc_dointvec_minmax_conv_param {
708 int *min;
709 int *max;
710 };
711
do_proc_dointvec_minmax_conv(bool * negp,unsigned long * lvalp,int * valp,int write,void * data)712 static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp,
713 int *valp,
714 int write, void *data)
715 {
716 int tmp, ret;
717 struct do_proc_dointvec_minmax_conv_param *param = data;
718 /*
719 * If writing, first do so via a temporary local int so we can
720 * bounds-check it before touching *valp.
721 */
722 int *ip = write ? &tmp : valp;
723
724 ret = do_proc_dointvec_conv(negp, lvalp, ip, write, data);
725 if (ret)
726 return ret;
727
728 if (write) {
729 if ((param->min && *param->min > tmp) ||
730 (param->max && *param->max < tmp))
731 return -EINVAL;
732 WRITE_ONCE(*valp, tmp);
733 }
734
735 return 0;
736 }
737
738 /**
739 * proc_dointvec_minmax - read a vector of integers with min/max values
740 * @table: the sysctl table
741 * @write: %TRUE if this is a write to the sysctl file
742 * @buffer: the user buffer
743 * @lenp: the size of the user buffer
744 * @ppos: file position
745 *
746 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
747 * values from/to the user buffer, treated as an ASCII string.
748 *
749 * This routine will ensure the values are within the range specified by
750 * table->extra1 (min) and table->extra2 (max).
751 *
752 * Returns 0 on success or -EINVAL on write when the range check fails.
753 */
proc_dointvec_minmax(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)754 int proc_dointvec_minmax(const struct ctl_table *table, int write,
755 void *buffer, size_t *lenp, loff_t *ppos)
756 {
757 struct do_proc_dointvec_minmax_conv_param param = {
758 .min = (int *) table->extra1,
759 .max = (int *) table->extra2,
760 };
761 return do_proc_dointvec(table, write, buffer, lenp, ppos,
762 do_proc_dointvec_minmax_conv, ¶m);
763 }
764
765 /**
766 * struct do_proc_douintvec_minmax_conv_param - proc_douintvec_minmax() range checking structure
767 * @min: pointer to minimum allowable value
768 * @max: pointer to maximum allowable value
769 *
770 * The do_proc_douintvec_minmax_conv_param structure provides the
771 * minimum and maximum values for doing range checking for those sysctl
772 * parameters that use the proc_douintvec_minmax() handler.
773 */
774 struct do_proc_douintvec_minmax_conv_param {
775 unsigned int *min;
776 unsigned int *max;
777 };
778
do_proc_douintvec_minmax_conv(unsigned long * lvalp,unsigned int * valp,int write,void * data)779 static int do_proc_douintvec_minmax_conv(unsigned long *lvalp,
780 unsigned int *valp,
781 int write, void *data)
782 {
783 int ret;
784 unsigned int tmp;
785 struct do_proc_douintvec_minmax_conv_param *param = data;
786 /* write via temporary local uint for bounds-checking */
787 unsigned int *up = write ? &tmp : valp;
788
789 ret = do_proc_douintvec_conv(lvalp, up, write, data);
790 if (ret)
791 return ret;
792
793 if (write) {
794 if ((param->min && *param->min > tmp) ||
795 (param->max && *param->max < tmp))
796 return -ERANGE;
797
798 WRITE_ONCE(*valp, tmp);
799 }
800
801 return 0;
802 }
803
804 /**
805 * proc_douintvec_minmax - read a vector of unsigned ints with min/max values
806 * @table: the sysctl table
807 * @write: %TRUE if this is a write to the sysctl file
808 * @buffer: the user buffer
809 * @lenp: the size of the user buffer
810 * @ppos: file position
811 *
812 * Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
813 * values from/to the user buffer, treated as an ASCII string. Negative
814 * strings are not allowed.
815 *
816 * This routine will ensure the values are within the range specified by
817 * table->extra1 (min) and table->extra2 (max). There is a final sanity
818 * check for UINT_MAX to avoid having to support wrap around uses from
819 * userspace.
820 *
821 * Returns 0 on success or -ERANGE on write when the range check fails.
822 */
proc_douintvec_minmax(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)823 int proc_douintvec_minmax(const struct ctl_table *table, int write,
824 void *buffer, size_t *lenp, loff_t *ppos)
825 {
826 struct do_proc_douintvec_minmax_conv_param param = {
827 .min = (unsigned int *) table->extra1,
828 .max = (unsigned int *) table->extra2,
829 };
830 return do_proc_douintvec(table, write, buffer, lenp, ppos,
831 do_proc_douintvec_minmax_conv, ¶m);
832 }
833
834 /**
835 * proc_dou8vec_minmax - read a vector of unsigned chars with min/max values
836 * @table: the sysctl table
837 * @write: %TRUE if this is a write to the sysctl file
838 * @buffer: the user buffer
839 * @lenp: the size of the user buffer
840 * @ppos: file position
841 *
842 * Reads/writes up to table->maxlen/sizeof(u8) unsigned chars
843 * values from/to the user buffer, treated as an ASCII string. Negative
844 * strings are not allowed.
845 *
846 * This routine will ensure the values are within the range specified by
847 * table->extra1 (min) and table->extra2 (max).
848 *
849 * Returns 0 on success or an error on write when the range check fails.
850 */
proc_dou8vec_minmax(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)851 int proc_dou8vec_minmax(const struct ctl_table *table, int write,
852 void *buffer, size_t *lenp, loff_t *ppos)
853 {
854 struct ctl_table tmp;
855 unsigned int min = 0, max = 255U, val;
856 u8 *data = table->data;
857 struct do_proc_douintvec_minmax_conv_param param = {
858 .min = &min,
859 .max = &max,
860 };
861 int res;
862
863 /* Do not support arrays yet. */
864 if (table->maxlen != sizeof(u8))
865 return -EINVAL;
866
867 if (table->extra1)
868 min = *(unsigned int *) table->extra1;
869 if (table->extra2)
870 max = *(unsigned int *) table->extra2;
871
872 tmp = *table;
873
874 tmp.maxlen = sizeof(val);
875 tmp.data = &val;
876 val = READ_ONCE(*data);
877 res = do_proc_douintvec(&tmp, write, buffer, lenp, ppos,
878 do_proc_douintvec_minmax_conv, ¶m);
879 if (res)
880 return res;
881 if (write)
882 WRITE_ONCE(*data, val);
883 return 0;
884 }
885 EXPORT_SYMBOL_GPL(proc_dou8vec_minmax);
886
__do_proc_doulongvec_minmax(void * data,const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos,unsigned long convmul,unsigned long convdiv)887 static int __do_proc_doulongvec_minmax(void *data,
888 const struct ctl_table *table, int write,
889 void *buffer, size_t *lenp, loff_t *ppos,
890 unsigned long convmul, unsigned long convdiv)
891 {
892 unsigned long *i, *min, *max;
893 int vleft, first = 1, err = 0;
894 size_t left;
895 char *p;
896
897 if (!data || !table->maxlen || !*lenp || (*ppos && !write)) {
898 *lenp = 0;
899 return 0;
900 }
901
902 i = data;
903 min = table->extra1;
904 max = table->extra2;
905 vleft = table->maxlen / sizeof(unsigned long);
906 left = *lenp;
907
908 if (write) {
909 if (proc_first_pos_non_zero_ignore(ppos, table))
910 goto out;
911
912 if (left > PAGE_SIZE - 1)
913 left = PAGE_SIZE - 1;
914 p = buffer;
915 }
916
917 for (; left && vleft--; i++, first = 0) {
918 unsigned long val;
919
920 if (write) {
921 bool neg;
922
923 proc_skip_spaces(&p, &left);
924 if (!left)
925 break;
926
927 err = proc_get_long(&p, &left, &val, &neg,
928 proc_wspace_sep,
929 sizeof(proc_wspace_sep), NULL);
930 if (err || neg) {
931 err = -EINVAL;
932 break;
933 }
934
935 val = convmul * val / convdiv;
936 if ((min && val < *min) || (max && val > *max)) {
937 err = -EINVAL;
938 break;
939 }
940 WRITE_ONCE(*i, val);
941 } else {
942 val = convdiv * READ_ONCE(*i) / convmul;
943 if (!first)
944 proc_put_char(&buffer, &left, '\t');
945 proc_put_long(&buffer, &left, val, false);
946 }
947 }
948
949 if (!write && !first && left && !err)
950 proc_put_char(&buffer, &left, '\n');
951 if (write && !err)
952 proc_skip_spaces(&p, &left);
953 if (write && first)
954 return err ? : -EINVAL;
955 *lenp -= left;
956 out:
957 *ppos += *lenp;
958 return err;
959 }
960
do_proc_doulongvec_minmax(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos,unsigned long convmul,unsigned long convdiv)961 static int do_proc_doulongvec_minmax(const struct ctl_table *table, int write,
962 void *buffer, size_t *lenp, loff_t *ppos, unsigned long convmul,
963 unsigned long convdiv)
964 {
965 return __do_proc_doulongvec_minmax(table->data, table, write,
966 buffer, lenp, ppos, convmul, convdiv);
967 }
968
969 /**
970 * proc_doulongvec_minmax - read a vector of long integers with min/max values
971 * @table: the sysctl table
972 * @write: %TRUE if this is a write to the sysctl file
973 * @buffer: the user buffer
974 * @lenp: the size of the user buffer
975 * @ppos: file position
976 *
977 * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
978 * values from/to the user buffer, treated as an ASCII string.
979 *
980 * This routine will ensure the values are within the range specified by
981 * table->extra1 (min) and table->extra2 (max).
982 *
983 * Returns 0 on success.
984 */
proc_doulongvec_minmax(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)985 int proc_doulongvec_minmax(const struct ctl_table *table, int write,
986 void *buffer, size_t *lenp, loff_t *ppos)
987 {
988 return do_proc_doulongvec_minmax(table, write, buffer, lenp, ppos, 1l, 1l);
989 }
990
991 /**
992 * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values
993 * @table: the sysctl table
994 * @write: %TRUE if this is a write to the sysctl file
995 * @buffer: the user buffer
996 * @lenp: the size of the user buffer
997 * @ppos: file position
998 *
999 * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
1000 * values from/to the user buffer, treated as an ASCII string. The values
1001 * are treated as milliseconds, and converted to jiffies when they are stored.
1002 *
1003 * This routine will ensure the values are within the range specified by
1004 * table->extra1 (min) and table->extra2 (max).
1005 *
1006 * Returns 0 on success.
1007 */
proc_doulongvec_ms_jiffies_minmax(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1008 int proc_doulongvec_ms_jiffies_minmax(const struct ctl_table *table, int write,
1009 void *buffer, size_t *lenp, loff_t *ppos)
1010 {
1011 return do_proc_doulongvec_minmax(table, write, buffer,
1012 lenp, ppos, HZ, 1000l);
1013 }
1014
1015
do_proc_dointvec_jiffies_conv(bool * negp,unsigned long * lvalp,int * valp,int write,void * data)1016 static int do_proc_dointvec_jiffies_conv(bool *negp, unsigned long *lvalp,
1017 int *valp,
1018 int write, void *data)
1019 {
1020 if (write) {
1021 if (*lvalp > INT_MAX / HZ)
1022 return 1;
1023 if (*negp)
1024 WRITE_ONCE(*valp, -*lvalp * HZ);
1025 else
1026 WRITE_ONCE(*valp, *lvalp * HZ);
1027 } else {
1028 int val = READ_ONCE(*valp);
1029 unsigned long lval;
1030 if (val < 0) {
1031 *negp = true;
1032 lval = -(unsigned long)val;
1033 } else {
1034 *negp = false;
1035 lval = (unsigned long)val;
1036 }
1037 *lvalp = lval / HZ;
1038 }
1039 return 0;
1040 }
1041
do_proc_dointvec_userhz_jiffies_conv(bool * negp,unsigned long * lvalp,int * valp,int write,void * data)1042 static int do_proc_dointvec_userhz_jiffies_conv(bool *negp, unsigned long *lvalp,
1043 int *valp,
1044 int write, void *data)
1045 {
1046 if (write) {
1047 if (USER_HZ < HZ && *lvalp > (LONG_MAX / HZ) * USER_HZ)
1048 return 1;
1049 *valp = clock_t_to_jiffies(*negp ? -*lvalp : *lvalp);
1050 } else {
1051 int val = *valp;
1052 unsigned long lval;
1053 if (val < 0) {
1054 *negp = true;
1055 lval = -(unsigned long)val;
1056 } else {
1057 *negp = false;
1058 lval = (unsigned long)val;
1059 }
1060 *lvalp = jiffies_to_clock_t(lval);
1061 }
1062 return 0;
1063 }
1064
do_proc_dointvec_ms_jiffies_conv(bool * negp,unsigned long * lvalp,int * valp,int write,void * data)1065 static int do_proc_dointvec_ms_jiffies_conv(bool *negp, unsigned long *lvalp,
1066 int *valp,
1067 int write, void *data)
1068 {
1069 if (write) {
1070 unsigned long jif = msecs_to_jiffies(*negp ? -*lvalp : *lvalp);
1071
1072 if (jif > INT_MAX)
1073 return 1;
1074 WRITE_ONCE(*valp, (int)jif);
1075 } else {
1076 int val = READ_ONCE(*valp);
1077 unsigned long lval;
1078 if (val < 0) {
1079 *negp = true;
1080 lval = -(unsigned long)val;
1081 } else {
1082 *negp = false;
1083 lval = (unsigned long)val;
1084 }
1085 *lvalp = jiffies_to_msecs(lval);
1086 }
1087 return 0;
1088 }
1089
do_proc_dointvec_ms_jiffies_minmax_conv(bool * negp,unsigned long * lvalp,int * valp,int write,void * data)1090 static int do_proc_dointvec_ms_jiffies_minmax_conv(bool *negp, unsigned long *lvalp,
1091 int *valp, int write, void *data)
1092 {
1093 int tmp, ret;
1094 struct do_proc_dointvec_minmax_conv_param *param = data;
1095 /*
1096 * If writing, first do so via a temporary local int so we can
1097 * bounds-check it before touching *valp.
1098 */
1099 int *ip = write ? &tmp : valp;
1100
1101 ret = do_proc_dointvec_ms_jiffies_conv(negp, lvalp, ip, write, data);
1102 if (ret)
1103 return ret;
1104
1105 if (write) {
1106 if ((param->min && *param->min > tmp) ||
1107 (param->max && *param->max < tmp))
1108 return -EINVAL;
1109 *valp = tmp;
1110 }
1111 return 0;
1112 }
1113
1114 /**
1115 * proc_dointvec_jiffies - read a vector of integers as seconds
1116 * @table: the sysctl table
1117 * @write: %TRUE if this is a write to the sysctl file
1118 * @buffer: the user buffer
1119 * @lenp: the size of the user buffer
1120 * @ppos: file position
1121 *
1122 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1123 * values from/to the user buffer, treated as an ASCII string.
1124 * The values read are assumed to be in seconds, and are converted into
1125 * jiffies.
1126 *
1127 * Returns 0 on success.
1128 */
proc_dointvec_jiffies(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1129 int proc_dointvec_jiffies(const struct ctl_table *table, int write,
1130 void *buffer, size_t *lenp, loff_t *ppos)
1131 {
1132 return do_proc_dointvec(table,write,buffer,lenp,ppos,
1133 do_proc_dointvec_jiffies_conv,NULL);
1134 }
1135
proc_dointvec_ms_jiffies_minmax(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1136 int proc_dointvec_ms_jiffies_minmax(const struct ctl_table *table, int write,
1137 void *buffer, size_t *lenp, loff_t *ppos)
1138 {
1139 struct do_proc_dointvec_minmax_conv_param param = {
1140 .min = (int *) table->extra1,
1141 .max = (int *) table->extra2,
1142 };
1143 return do_proc_dointvec(table, write, buffer, lenp, ppos,
1144 do_proc_dointvec_ms_jiffies_minmax_conv, ¶m);
1145 }
1146
1147 /**
1148 * proc_dointvec_userhz_jiffies - read a vector of integers as 1/USER_HZ seconds
1149 * @table: the sysctl table
1150 * @write: %TRUE if this is a write to the sysctl file
1151 * @buffer: the user buffer
1152 * @lenp: the size of the user buffer
1153 * @ppos: pointer to the file position
1154 *
1155 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1156 * values from/to the user buffer, treated as an ASCII string.
1157 * The values read are assumed to be in 1/USER_HZ seconds, and
1158 * are converted into jiffies.
1159 *
1160 * Returns 0 on success.
1161 */
proc_dointvec_userhz_jiffies(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1162 int proc_dointvec_userhz_jiffies(const struct ctl_table *table, int write,
1163 void *buffer, size_t *lenp, loff_t *ppos)
1164 {
1165 return do_proc_dointvec(table, write, buffer, lenp, ppos,
1166 do_proc_dointvec_userhz_jiffies_conv, NULL);
1167 }
1168
1169 /**
1170 * proc_dointvec_ms_jiffies - read a vector of integers as 1 milliseconds
1171 * @table: the sysctl table
1172 * @write: %TRUE if this is a write to the sysctl file
1173 * @buffer: the user buffer
1174 * @lenp: the size of the user buffer
1175 * @ppos: the current position in the file
1176 *
1177 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1178 * values from/to the user buffer, treated as an ASCII string.
1179 * The values read are assumed to be in 1/1000 seconds, and
1180 * are converted into jiffies.
1181 *
1182 * Returns 0 on success.
1183 */
proc_dointvec_ms_jiffies(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1184 int proc_dointvec_ms_jiffies(const struct ctl_table *table, int write, void *buffer,
1185 size_t *lenp, loff_t *ppos)
1186 {
1187 return do_proc_dointvec(table, write, buffer, lenp, ppos,
1188 do_proc_dointvec_ms_jiffies_conv, NULL);
1189 }
1190
1191 /**
1192 * proc_do_large_bitmap - read/write from/to a large bitmap
1193 * @table: the sysctl table
1194 * @write: %TRUE if this is a write to the sysctl file
1195 * @buffer: the user buffer
1196 * @lenp: the size of the user buffer
1197 * @ppos: file position
1198 *
1199 * The bitmap is stored at table->data and the bitmap length (in bits)
1200 * in table->maxlen.
1201 *
1202 * We use a range comma separated format (e.g. 1,3-4,10-10) so that
1203 * large bitmaps may be represented in a compact manner. Writing into
1204 * the file will clear the bitmap then update it with the given input.
1205 *
1206 * Returns 0 on success.
1207 */
proc_do_large_bitmap(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1208 int proc_do_large_bitmap(const struct ctl_table *table, int write,
1209 void *buffer, size_t *lenp, loff_t *ppos)
1210 {
1211 int err = 0;
1212 size_t left = *lenp;
1213 unsigned long bitmap_len = table->maxlen;
1214 unsigned long *bitmap = *(unsigned long **) table->data;
1215 unsigned long *tmp_bitmap = NULL;
1216 char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
1217
1218 if (!bitmap || !bitmap_len || !left || (*ppos && !write)) {
1219 *lenp = 0;
1220 return 0;
1221 }
1222
1223 if (write) {
1224 char *p = buffer;
1225 size_t skipped = 0;
1226
1227 if (left > PAGE_SIZE - 1) {
1228 left = PAGE_SIZE - 1;
1229 /* How much of the buffer we'll skip this pass */
1230 skipped = *lenp - left;
1231 }
1232
1233 tmp_bitmap = bitmap_zalloc(bitmap_len, GFP_KERNEL);
1234 if (!tmp_bitmap)
1235 return -ENOMEM;
1236 proc_skip_char(&p, &left, '\n');
1237 while (!err && left) {
1238 unsigned long val_a, val_b;
1239 bool neg;
1240 size_t saved_left;
1241
1242 /* In case we stop parsing mid-number, we can reset */
1243 saved_left = left;
1244 err = proc_get_long(&p, &left, &val_a, &neg, tr_a,
1245 sizeof(tr_a), &c);
1246 /*
1247 * If we consumed the entirety of a truncated buffer or
1248 * only one char is left (may be a "-"), then stop here,
1249 * reset, & come back for more.
1250 */
1251 if ((left <= 1) && skipped) {
1252 left = saved_left;
1253 break;
1254 }
1255
1256 if (err)
1257 break;
1258 if (val_a >= bitmap_len || neg) {
1259 err = -EINVAL;
1260 break;
1261 }
1262
1263 val_b = val_a;
1264 if (left) {
1265 p++;
1266 left--;
1267 }
1268
1269 if (c == '-') {
1270 err = proc_get_long(&p, &left, &val_b,
1271 &neg, tr_b, sizeof(tr_b),
1272 &c);
1273 /*
1274 * If we consumed all of a truncated buffer or
1275 * then stop here, reset, & come back for more.
1276 */
1277 if (!left && skipped) {
1278 left = saved_left;
1279 break;
1280 }
1281
1282 if (err)
1283 break;
1284 if (val_b >= bitmap_len || neg ||
1285 val_a > val_b) {
1286 err = -EINVAL;
1287 break;
1288 }
1289 if (left) {
1290 p++;
1291 left--;
1292 }
1293 }
1294
1295 bitmap_set(tmp_bitmap, val_a, val_b - val_a + 1);
1296 proc_skip_char(&p, &left, '\n');
1297 }
1298 left += skipped;
1299 } else {
1300 unsigned long bit_a, bit_b = 0;
1301 bool first = 1;
1302
1303 while (left) {
1304 bit_a = find_next_bit(bitmap, bitmap_len, bit_b);
1305 if (bit_a >= bitmap_len)
1306 break;
1307 bit_b = find_next_zero_bit(bitmap, bitmap_len,
1308 bit_a + 1) - 1;
1309
1310 if (!first)
1311 proc_put_char(&buffer, &left, ',');
1312 proc_put_long(&buffer, &left, bit_a, false);
1313 if (bit_a != bit_b) {
1314 proc_put_char(&buffer, &left, '-');
1315 proc_put_long(&buffer, &left, bit_b, false);
1316 }
1317
1318 first = 0; bit_b++;
1319 }
1320 proc_put_char(&buffer, &left, '\n');
1321 }
1322
1323 if (!err) {
1324 if (write) {
1325 if (*ppos)
1326 bitmap_or(bitmap, bitmap, tmp_bitmap, bitmap_len);
1327 else
1328 bitmap_copy(bitmap, tmp_bitmap, bitmap_len);
1329 }
1330 *lenp -= left;
1331 *ppos += *lenp;
1332 }
1333
1334 bitmap_free(tmp_bitmap);
1335 return err;
1336 }
1337
1338 #else /* CONFIG_PROC_SYSCTL */
1339
proc_dostring(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1340 int proc_dostring(const struct ctl_table *table, int write,
1341 void *buffer, size_t *lenp, loff_t *ppos)
1342 {
1343 return -ENOSYS;
1344 }
1345
proc_dobool(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1346 int proc_dobool(const struct ctl_table *table, int write,
1347 void *buffer, size_t *lenp, loff_t *ppos)
1348 {
1349 return -ENOSYS;
1350 }
1351
proc_dointvec(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1352 int proc_dointvec(const struct ctl_table *table, int write,
1353 void *buffer, size_t *lenp, loff_t *ppos)
1354 {
1355 return -ENOSYS;
1356 }
1357
proc_douintvec(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1358 int proc_douintvec(const struct ctl_table *table, int write,
1359 void *buffer, size_t *lenp, loff_t *ppos)
1360 {
1361 return -ENOSYS;
1362 }
1363
proc_dointvec_minmax(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1364 int proc_dointvec_minmax(const struct ctl_table *table, int write,
1365 void *buffer, size_t *lenp, loff_t *ppos)
1366 {
1367 return -ENOSYS;
1368 }
1369
proc_douintvec_minmax(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1370 int proc_douintvec_minmax(const struct ctl_table *table, int write,
1371 void *buffer, size_t *lenp, loff_t *ppos)
1372 {
1373 return -ENOSYS;
1374 }
1375
proc_dou8vec_minmax(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1376 int proc_dou8vec_minmax(const struct ctl_table *table, int write,
1377 void *buffer, size_t *lenp, loff_t *ppos)
1378 {
1379 return -ENOSYS;
1380 }
1381
proc_dointvec_jiffies(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1382 int proc_dointvec_jiffies(const struct ctl_table *table, int write,
1383 void *buffer, size_t *lenp, loff_t *ppos)
1384 {
1385 return -ENOSYS;
1386 }
1387
proc_dointvec_ms_jiffies_minmax(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1388 int proc_dointvec_ms_jiffies_minmax(const struct ctl_table *table, int write,
1389 void *buffer, size_t *lenp, loff_t *ppos)
1390 {
1391 return -ENOSYS;
1392 }
1393
proc_dointvec_userhz_jiffies(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1394 int proc_dointvec_userhz_jiffies(const struct ctl_table *table, int write,
1395 void *buffer, size_t *lenp, loff_t *ppos)
1396 {
1397 return -ENOSYS;
1398 }
1399
proc_dointvec_ms_jiffies(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1400 int proc_dointvec_ms_jiffies(const struct ctl_table *table, int write,
1401 void *buffer, size_t *lenp, loff_t *ppos)
1402 {
1403 return -ENOSYS;
1404 }
1405
proc_doulongvec_minmax(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1406 int proc_doulongvec_minmax(const struct ctl_table *table, int write,
1407 void *buffer, size_t *lenp, loff_t *ppos)
1408 {
1409 return -ENOSYS;
1410 }
1411
proc_doulongvec_ms_jiffies_minmax(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1412 int proc_doulongvec_ms_jiffies_minmax(const struct ctl_table *table, int write,
1413 void *buffer, size_t *lenp, loff_t *ppos)
1414 {
1415 return -ENOSYS;
1416 }
1417
proc_do_large_bitmap(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1418 int proc_do_large_bitmap(const struct ctl_table *table, int write,
1419 void *buffer, size_t *lenp, loff_t *ppos)
1420 {
1421 return -ENOSYS;
1422 }
1423
1424 #endif /* CONFIG_PROC_SYSCTL */
1425
1426 #if defined(CONFIG_SYSCTL)
proc_do_static_key(const struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)1427 int proc_do_static_key(const struct ctl_table *table, int write,
1428 void *buffer, size_t *lenp, loff_t *ppos)
1429 {
1430 struct static_key *key = (struct static_key *)table->data;
1431 static DEFINE_MUTEX(static_key_mutex);
1432 int val, ret;
1433 struct ctl_table tmp = {
1434 .data = &val,
1435 .maxlen = sizeof(val),
1436 .mode = table->mode,
1437 .extra1 = SYSCTL_ZERO,
1438 .extra2 = SYSCTL_ONE,
1439 };
1440
1441 if (write && !capable(CAP_SYS_ADMIN))
1442 return -EPERM;
1443
1444 mutex_lock(&static_key_mutex);
1445 val = static_key_enabled(key);
1446 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
1447 if (write && !ret) {
1448 if (val)
1449 static_key_enable(key);
1450 else
1451 static_key_disable(key);
1452 }
1453 mutex_unlock(&static_key_mutex);
1454 return ret;
1455 }
1456
1457 static const struct ctl_table sysctl_subsys_table[] = {
1458 #ifdef CONFIG_PROC_SYSCTL
1459 {
1460 .procname = "sysctl_writes_strict",
1461 .data = &sysctl_writes_strict,
1462 .maxlen = sizeof(int),
1463 .mode = 0644,
1464 .proc_handler = proc_dointvec_minmax,
1465 .extra1 = SYSCTL_NEG_ONE,
1466 .extra2 = SYSCTL_ONE,
1467 },
1468 #endif
1469 {
1470 .procname = "ngroups_max",
1471 .data = (void *)&ngroups_max,
1472 .maxlen = sizeof (int),
1473 .mode = 0444,
1474 .proc_handler = proc_dointvec,
1475 },
1476 {
1477 .procname = "cap_last_cap",
1478 .data = (void *)&cap_last_cap,
1479 .maxlen = sizeof(int),
1480 .mode = 0444,
1481 .proc_handler = proc_dointvec,
1482 },
1483 #ifdef CONFIG_SYSCTL_ARCH_UNALIGN_ALLOW
1484 {
1485 .procname = "unaligned-trap",
1486 .data = &unaligned_enabled,
1487 .maxlen = sizeof(int),
1488 .mode = 0644,
1489 .proc_handler = proc_dointvec,
1490 },
1491 #endif
1492 #ifdef CONFIG_SYSCTL_ARCH_UNALIGN_NO_WARN
1493 {
1494 .procname = "ignore-unaligned-usertrap",
1495 .data = &no_unaligned_warning,
1496 .maxlen = sizeof (int),
1497 .mode = 0644,
1498 .proc_handler = proc_dointvec,
1499 },
1500 #endif
1501 };
1502
sysctl_init_bases(void)1503 int __init sysctl_init_bases(void)
1504 {
1505 register_sysctl_init("kernel", sysctl_subsys_table);
1506
1507 return 0;
1508 }
1509 #endif /* CONFIG_SYSCTL */
1510 /*
1511 * No sense putting this after each symbol definition, twice,
1512 * exception granted :-)
1513 */
1514 EXPORT_SYMBOL(proc_dobool);
1515 EXPORT_SYMBOL(proc_dointvec);
1516 EXPORT_SYMBOL(proc_douintvec);
1517 EXPORT_SYMBOL(proc_dointvec_jiffies);
1518 EXPORT_SYMBOL(proc_dointvec_minmax);
1519 EXPORT_SYMBOL_GPL(proc_douintvec_minmax);
1520 EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
1521 EXPORT_SYMBOL(proc_dointvec_ms_jiffies);
1522 EXPORT_SYMBOL(proc_dostring);
1523 EXPORT_SYMBOL(proc_doulongvec_minmax);
1524 EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
1525 EXPORT_SYMBOL(proc_do_large_bitmap);
1526