hc
2024-05-10 10ebd8556b7990499c896a550e3d416b444211e6
kernel/kernel/sysctl.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * sysctl.c: General linux system control interface
34 *
....@@ -66,7 +67,10 @@
6667 #include <linux/kexec.h>
6768 #include <linux/bpf.h>
6869 #include <linux/mount.h>
69
-#include <linux/pipe_fs_i.h>
70
+#include <linux/userfaultfd_k.h>
71
+#include <linux/coredump.h>
72
+#include <linux/latencytop.h>
73
+#include <linux/pid.h>
7074
7175 #include "../lib/kstrtox.h"
7276
....@@ -93,7 +97,9 @@
9397 #ifdef CONFIG_CHR_DEV_SG
9498 #include <scsi/sg.h>
9599 #endif
96
-
100
+#ifdef CONFIG_STACKLEAK_RUNTIME_DISABLE
101
+#include <linux/stackleak.h>
102
+#endif
97103 #ifdef CONFIG_LOCKUP_DETECTOR
98104 #include <linux/nmi.h>
99105 #endif
....@@ -101,38 +107,16 @@
101107 #if defined(CONFIG_SYSCTL)
102108
103109 /* External variables not in a header file. */
104
-extern int suid_dumpable;
105
-#ifdef CONFIG_COREDUMP
106
-extern int core_uses_pid;
107
-extern char core_pattern[];
108
-extern unsigned int core_pipe_limit;
109
-#endif
110
-extern int pid_max;
111110 extern int extra_free_kbytes;
112
-extern int pid_max_min, pid_max_max;
113
-extern int percpu_pagelist_fraction;
114
-extern int latencytop_enabled;
115
-extern unsigned int sysctl_nr_open_min, sysctl_nr_open_max;
116
-#ifndef CONFIG_MMU
117
-extern int sysctl_nr_trim_pages;
118
-#endif
119111
120112 /* Constants used for minimum and maximum */
121113 #ifdef CONFIG_LOCKUP_DETECTOR
122114 static int sixty = 60;
123115 #endif
124116
125
-static int __maybe_unused neg_one = -1;
126
-
127
-static int zero;
128
-static int __maybe_unused one = 1;
129
-static int __maybe_unused two = 2;
130
-static int __maybe_unused four = 4;
131117 static unsigned long zero_ul;
132118 static unsigned long one_ul = 1;
133119 static unsigned long long_max = LONG_MAX;
134
-static int one_hundred = 100;
135
-static int one_thousand = 1000;
136120 #ifdef CONFIG_PRINTK
137121 static int ten_thousand = 10000;
138122 #endif
....@@ -161,24 +145,6 @@
161145 #ifdef CONFIG_INOTIFY_USER
162146 #include <linux/inotify.h>
163147 #endif
164
-#ifdef CONFIG_SPARC
165
-#endif
166
-
167
-#ifdef __hppa__
168
-extern int pwrsw_enabled;
169
-#endif
170
-
171
-#ifdef CONFIG_SYSCTL_ARCH_UNALIGN_ALLOW
172
-extern int unaligned_enabled;
173
-#endif
174
-
175
-#ifdef CONFIG_IA64
176
-extern int unaligned_dump_stack;
177
-#endif
178
-
179
-#ifdef CONFIG_SYSCTL_ARCH_UNALIGN_NO_WARN
180
-extern int no_unaligned_warning;
181
-#endif
182148
183149 #ifdef CONFIG_PROC_SYSCTL
184150
....@@ -186,17 +152,17 @@
186152 * enum sysctl_writes_mode - supported sysctl write modes
187153 *
188154 * @SYSCTL_WRITES_LEGACY: each write syscall must fully contain the sysctl value
189
- * to be written, and multiple writes on the same sysctl file descriptor
190
- * will rewrite the sysctl value, regardless of file position. No warning
191
- * is issued when the initial position is not 0.
155
+ * to be written, and multiple writes on the same sysctl file descriptor
156
+ * will rewrite the sysctl value, regardless of file position. No warning
157
+ * is issued when the initial position is not 0.
192158 * @SYSCTL_WRITES_WARN: same as above but warn when the initial file position is
193
- * not 0.
159
+ * not 0.
194160 * @SYSCTL_WRITES_STRICT: writes to numeric sysctl entries must always be at
195
- * file position 0 and the value must be fully contained in the buffer
196
- * sent to the write syscall. If dealing with strings respect the file
197
- * position, but restrict this to the max length of the buffer, anything
198
- * passed the max lenght will be ignored. Multiple writes will append
199
- * to the buffer.
161
+ * file position 0 and the value must be fully contained in the buffer
162
+ * sent to the write syscall. If dealing with strings respect the file
163
+ * position, but restrict this to the max length of the buffer, anything
164
+ * passed the max length will be ignored. Multiple writes will append
165
+ * to the buffer.
200166 *
201167 * These write modes control how current file position affects the behavior of
202168 * updating sysctl values through the proc interface on each write.
....@@ -208,119 +174,12 @@
208174 };
209175
210176 static enum sysctl_writes_mode sysctl_writes_strict = SYSCTL_WRITES_STRICT;
177
+#endif /* CONFIG_PROC_SYSCTL */
211178
212
-static int proc_do_cad_pid(struct ctl_table *table, int write,
213
- void __user *buffer, size_t *lenp, loff_t *ppos);
214
-static int proc_taint(struct ctl_table *table, int write,
215
- void __user *buffer, size_t *lenp, loff_t *ppos);
216
-#endif
217
-
218
-#ifdef CONFIG_PRINTK
219
-static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
220
- void __user *buffer, size_t *lenp, loff_t *ppos);
221
-#endif
222
-
223
-static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write,
224
- void __user *buffer, size_t *lenp, loff_t *ppos);
225
-#ifdef CONFIG_COREDUMP
226
-static int proc_dostring_coredump(struct ctl_table *table, int write,
227
- void __user *buffer, size_t *lenp, loff_t *ppos);
228
-#endif
229
-static int proc_dopipe_max_size(struct ctl_table *table, int write,
230
- void __user *buffer, size_t *lenp, loff_t *ppos);
231
-
232
-#ifdef CONFIG_MAGIC_SYSRQ
233
-/* Note: sysrq code uses its own private copy */
234
-static int __sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE;
235
-
236
-static int sysrq_sysctl_handler(struct ctl_table *table, int write,
237
- void __user *buffer, size_t *lenp,
238
- loff_t *ppos)
239
-{
240
- int error;
241
-
242
- error = proc_dointvec(table, write, buffer, lenp, ppos);
243
- if (error)
244
- return error;
245
-
246
- if (write)
247
- sysrq_toggle_support(__sysrq_enabled);
248
-
249
- return 0;
250
-}
251
-
252
-#endif
253
-
254
-#ifdef CONFIG_BPF_SYSCALL
255
-static int bpf_unpriv_handler(struct ctl_table *table, int write,
256
- void *buffer, size_t *lenp, loff_t *ppos)
257
-{
258
- int ret, unpriv_enable = *(int *)table->data;
259
- bool locked_state = unpriv_enable == 1;
260
- struct ctl_table tmp = *table;
261
-
262
- if (write && !capable(CAP_SYS_ADMIN))
263
- return -EPERM;
264
-
265
- tmp.data = &unpriv_enable;
266
- ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
267
- if (write && !ret) {
268
- if (locked_state && unpriv_enable != 1)
269
- return -EPERM;
270
- *(int *)table->data = unpriv_enable;
271
- }
272
- return ret;
273
-}
274
-#endif
275
-
276
-static struct ctl_table kern_table[];
277
-static struct ctl_table vm_table[];
278
-static struct ctl_table fs_table[];
279
-static struct ctl_table debug_table[];
280
-static struct ctl_table dev_table[];
281
-extern struct ctl_table random_table[];
282
-#ifdef CONFIG_EPOLL
283
-extern struct ctl_table epoll_table[];
284
-#endif
285
-
286
-#ifdef CONFIG_FW_LOADER_USER_HELPER
287
-extern struct ctl_table firmware_config_table[];
288
-#endif
289
-
290
-#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
179
+#if defined(HAVE_ARCH_PICK_MMAP_LAYOUT) || \
180
+ defined(CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT)
291181 int sysctl_legacy_va_layout;
292182 #endif
293
-
294
-/* The default sysctl tables: */
295
-
296
-static struct ctl_table sysctl_base_table[] = {
297
- {
298
- .procname = "kernel",
299
- .mode = 0555,
300
- .child = kern_table,
301
- },
302
- {
303
- .procname = "vm",
304
- .mode = 0555,
305
- .child = vm_table,
306
- },
307
- {
308
- .procname = "fs",
309
- .mode = 0555,
310
- .child = fs_table,
311
- },
312
- {
313
- .procname = "debug",
314
- .mode = 0555,
315
- .child = debug_table,
316
- },
317
- {
318
- .procname = "dev",
319
- .mode = 0555,
320
- .child = dev_table,
321
- },
322
- { }
323
-};
324183
325184 #ifdef CONFIG_SCHED_DEBUG
326185 static int min_sched_granularity_ns = 100000; /* 100 usecs */
....@@ -338,6 +197,1552 @@
338197 static int max_extfrag_threshold = 1000;
339198 #endif
340199
200
+#endif /* CONFIG_SYSCTL */
201
+
202
+#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_SYSCTL)
203
+static int bpf_stats_handler(struct ctl_table *table, int write,
204
+ void *buffer, size_t *lenp, loff_t *ppos)
205
+{
206
+ struct static_key *key = (struct static_key *)table->data;
207
+ static int saved_val;
208
+ int val, ret;
209
+ struct ctl_table tmp = {
210
+ .data = &val,
211
+ .maxlen = sizeof(val),
212
+ .mode = table->mode,
213
+ .extra1 = SYSCTL_ZERO,
214
+ .extra2 = SYSCTL_ONE,
215
+ };
216
+
217
+ if (write && !capable(CAP_SYS_ADMIN))
218
+ return -EPERM;
219
+
220
+ mutex_lock(&bpf_stats_enabled_mutex);
221
+ val = saved_val;
222
+ ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
223
+ if (write && !ret && val != saved_val) {
224
+ if (val)
225
+ static_key_slow_inc(key);
226
+ else
227
+ static_key_slow_dec(key);
228
+ saved_val = val;
229
+ }
230
+ mutex_unlock(&bpf_stats_enabled_mutex);
231
+ return ret;
232
+}
233
+
234
+void __weak unpriv_ebpf_notify(int new_state)
235
+{
236
+}
237
+
238
+static int bpf_unpriv_handler(struct ctl_table *table, int write,
239
+ void *buffer, size_t *lenp, loff_t *ppos)
240
+{
241
+ int ret, unpriv_enable = *(int *)table->data;
242
+ bool locked_state = unpriv_enable == 1;
243
+ struct ctl_table tmp = *table;
244
+
245
+ if (write && !capable(CAP_SYS_ADMIN))
246
+ return -EPERM;
247
+
248
+ tmp.data = &unpriv_enable;
249
+ ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
250
+ if (write && !ret) {
251
+ if (locked_state && unpriv_enable != 1)
252
+ return -EPERM;
253
+ *(int *)table->data = unpriv_enable;
254
+ }
255
+
256
+ unpriv_ebpf_notify(unpriv_enable);
257
+
258
+ return ret;
259
+}
260
+#endif /* CONFIG_BPF_SYSCALL && CONFIG_SYSCTL */
261
+
262
+/*
263
+ * /proc/sys support
264
+ */
265
+
266
+#ifdef CONFIG_PROC_SYSCTL
267
+
268
+static int _proc_do_string(char *data, int maxlen, int write,
269
+ char *buffer, size_t *lenp, loff_t *ppos)
270
+{
271
+ size_t len;
272
+ char c, *p;
273
+
274
+ if (!data || !maxlen || !*lenp) {
275
+ *lenp = 0;
276
+ return 0;
277
+ }
278
+
279
+ if (write) {
280
+ if (sysctl_writes_strict == SYSCTL_WRITES_STRICT) {
281
+ /* Only continue writes not past the end of buffer. */
282
+ len = strlen(data);
283
+ if (len > maxlen - 1)
284
+ len = maxlen - 1;
285
+
286
+ if (*ppos > len)
287
+ return 0;
288
+ len = *ppos;
289
+ } else {
290
+ /* Start writing from beginning of buffer. */
291
+ len = 0;
292
+ }
293
+
294
+ *ppos += *lenp;
295
+ p = buffer;
296
+ while ((p - buffer) < *lenp && len < maxlen - 1) {
297
+ c = *(p++);
298
+ if (c == 0 || c == '\n')
299
+ break;
300
+ data[len++] = c;
301
+ }
302
+ data[len] = 0;
303
+ } else {
304
+ len = strlen(data);
305
+ if (len > maxlen)
306
+ len = maxlen;
307
+
308
+ if (*ppos > len) {
309
+ *lenp = 0;
310
+ return 0;
311
+ }
312
+
313
+ data += *ppos;
314
+ len -= *ppos;
315
+
316
+ if (len > *lenp)
317
+ len = *lenp;
318
+ if (len)
319
+ memcpy(buffer, data, len);
320
+ if (len < *lenp) {
321
+ buffer[len] = '\n';
322
+ len++;
323
+ }
324
+ *lenp = len;
325
+ *ppos += len;
326
+ }
327
+ return 0;
328
+}
329
+
330
+static void warn_sysctl_write(struct ctl_table *table)
331
+{
332
+ pr_warn_once("%s wrote to %s when file position was not 0!\n"
333
+ "This will not be supported in the future. To silence this\n"
334
+ "warning, set kernel.sysctl_writes_strict = -1\n",
335
+ current->comm, table->procname);
336
+}
337
+
338
+/**
339
+ * proc_first_pos_non_zero_ignore - check if first position is allowed
340
+ * @ppos: file position
341
+ * @table: the sysctl table
342
+ *
343
+ * Returns true if the first position is non-zero and the sysctl_writes_strict
344
+ * mode indicates this is not allowed for numeric input types. String proc
345
+ * handlers can ignore the return value.
346
+ */
347
+static bool proc_first_pos_non_zero_ignore(loff_t *ppos,
348
+ struct ctl_table *table)
349
+{
350
+ if (!*ppos)
351
+ return false;
352
+
353
+ switch (sysctl_writes_strict) {
354
+ case SYSCTL_WRITES_STRICT:
355
+ return true;
356
+ case SYSCTL_WRITES_WARN:
357
+ warn_sysctl_write(table);
358
+ return false;
359
+ default:
360
+ return false;
361
+ }
362
+}
363
+
364
+/**
365
+ * proc_dostring - read a string sysctl
366
+ * @table: the sysctl table
367
+ * @write: %TRUE if this is a write to the sysctl file
368
+ * @buffer: the user buffer
369
+ * @lenp: the size of the user buffer
370
+ * @ppos: file position
371
+ *
372
+ * Reads/writes a string from/to the user buffer. If the kernel
373
+ * buffer provided is not large enough to hold the string, the
374
+ * string is truncated. The copied string is %NULL-terminated.
375
+ * If the string is being read by the user process, it is copied
376
+ * and a newline '\n' is added. It is truncated if the buffer is
377
+ * not large enough.
378
+ *
379
+ * Returns 0 on success.
380
+ */
381
+int proc_dostring(struct ctl_table *table, int write,
382
+ void *buffer, size_t *lenp, loff_t *ppos)
383
+{
384
+ if (write)
385
+ proc_first_pos_non_zero_ignore(ppos, table);
386
+
387
+ return _proc_do_string(table->data, table->maxlen, write, buffer, lenp,
388
+ ppos);
389
+}
390
+
391
+static void proc_skip_spaces(char **buf, size_t *size)
392
+{
393
+ while (*size) {
394
+ if (!isspace(**buf))
395
+ break;
396
+ (*size)--;
397
+ (*buf)++;
398
+ }
399
+}
400
+
401
+static void proc_skip_char(char **buf, size_t *size, const char v)
402
+{
403
+ while (*size) {
404
+ if (**buf != v)
405
+ break;
406
+ (*size)--;
407
+ (*buf)++;
408
+ }
409
+}
410
+
411
+/**
412
+ * strtoul_lenient - parse an ASCII formatted integer from a buffer and only
413
+ * fail on overflow
414
+ *
415
+ * @cp: kernel buffer containing the string to parse
416
+ * @endp: pointer to store the trailing characters
417
+ * @base: the base to use
418
+ * @res: where the parsed integer will be stored
419
+ *
420
+ * In case of success 0 is returned and @res will contain the parsed integer,
421
+ * @endp will hold any trailing characters.
422
+ * This function will fail the parse on overflow. If there wasn't an overflow
423
+ * the function will defer the decision what characters count as invalid to the
424
+ * caller.
425
+ */
426
+static int strtoul_lenient(const char *cp, char **endp, unsigned int base,
427
+ unsigned long *res)
428
+{
429
+ unsigned long long result;
430
+ unsigned int rv;
431
+
432
+ cp = _parse_integer_fixup_radix(cp, &base);
433
+ rv = _parse_integer(cp, base, &result);
434
+ if ((rv & KSTRTOX_OVERFLOW) || (result != (unsigned long)result))
435
+ return -ERANGE;
436
+
437
+ cp += rv;
438
+
439
+ if (endp)
440
+ *endp = (char *)cp;
441
+
442
+ *res = (unsigned long)result;
443
+ return 0;
444
+}
445
+
446
+#define TMPBUFLEN 22
447
+/**
448
+ * proc_get_long - reads an ASCII formatted integer from a user buffer
449
+ *
450
+ * @buf: a kernel buffer
451
+ * @size: size of the kernel buffer
452
+ * @val: this is where the number will be stored
453
+ * @neg: set to %TRUE if number is negative
454
+ * @perm_tr: a vector which contains the allowed trailers
455
+ * @perm_tr_len: size of the perm_tr vector
456
+ * @tr: pointer to store the trailer character
457
+ *
458
+ * In case of success %0 is returned and @buf and @size are updated with
459
+ * the amount of bytes read. If @tr is non-NULL and a trailing
460
+ * character exists (size is non-zero after returning from this
461
+ * function), @tr is updated with the trailing character.
462
+ */
463
+static int proc_get_long(char **buf, size_t *size,
464
+ unsigned long *val, bool *neg,
465
+ const char *perm_tr, unsigned perm_tr_len, char *tr)
466
+{
467
+ char *p, tmp[TMPBUFLEN];
468
+ ssize_t len = *size;
469
+
470
+ if (len <= 0)
471
+ return -EINVAL;
472
+
473
+ if (len > TMPBUFLEN - 1)
474
+ len = TMPBUFLEN - 1;
475
+
476
+ memcpy(tmp, *buf, len);
477
+
478
+ tmp[len] = 0;
479
+ p = tmp;
480
+ if (*p == '-' && *size > 1) {
481
+ *neg = true;
482
+ p++;
483
+ } else
484
+ *neg = false;
485
+ if (!isdigit(*p))
486
+ return -EINVAL;
487
+
488
+ if (strtoul_lenient(p, &p, 0, val))
489
+ return -EINVAL;
490
+
491
+ len = p - tmp;
492
+
493
+ /* We don't know if the next char is whitespace thus we may accept
494
+ * invalid integers (e.g. 1234...a) or two integers instead of one
495
+ * (e.g. 123...1). So lets not allow such large numbers. */
496
+ if (len == TMPBUFLEN - 1)
497
+ return -EINVAL;
498
+
499
+ if (len < *size && perm_tr_len && !memchr(perm_tr, *p, perm_tr_len))
500
+ return -EINVAL;
501
+
502
+ if (tr && (len < *size))
503
+ *tr = *p;
504
+
505
+ *buf += len;
506
+ *size -= len;
507
+
508
+ return 0;
509
+}
510
+
511
+/**
512
+ * proc_put_long - converts an integer to a decimal ASCII formatted string
513
+ *
514
+ * @buf: the user buffer
515
+ * @size: the size of the user buffer
516
+ * @val: the integer to be converted
517
+ * @neg: sign of the number, %TRUE for negative
518
+ *
519
+ * In case of success @buf and @size are updated with the amount of bytes
520
+ * written.
521
+ */
522
+static void proc_put_long(void **buf, size_t *size, unsigned long val, bool neg)
523
+{
524
+ int len;
525
+ char tmp[TMPBUFLEN], *p = tmp;
526
+
527
+ sprintf(p, "%s%lu", neg ? "-" : "", val);
528
+ len = strlen(tmp);
529
+ if (len > *size)
530
+ len = *size;
531
+ memcpy(*buf, tmp, len);
532
+ *size -= len;
533
+ *buf += len;
534
+}
535
+#undef TMPBUFLEN
536
+
537
+static void proc_put_char(void **buf, size_t *size, char c)
538
+{
539
+ if (*size) {
540
+ char **buffer = (char **)buf;
541
+ **buffer = c;
542
+
543
+ (*size)--;
544
+ (*buffer)++;
545
+ *buf = *buffer;
546
+ }
547
+}
548
+
549
+static int do_proc_dointvec_conv(bool *negp, unsigned long *lvalp,
550
+ int *valp,
551
+ int write, void *data)
552
+{
553
+ if (write) {
554
+ if (*negp) {
555
+ if (*lvalp > (unsigned long) INT_MAX + 1)
556
+ return -EINVAL;
557
+ WRITE_ONCE(*valp, -*lvalp);
558
+ } else {
559
+ if (*lvalp > (unsigned long) INT_MAX)
560
+ return -EINVAL;
561
+ WRITE_ONCE(*valp, *lvalp);
562
+ }
563
+ } else {
564
+ int val = READ_ONCE(*valp);
565
+ if (val < 0) {
566
+ *negp = true;
567
+ *lvalp = -(unsigned long)val;
568
+ } else {
569
+ *negp = false;
570
+ *lvalp = (unsigned long)val;
571
+ }
572
+ }
573
+ return 0;
574
+}
575
+
576
+static int do_proc_douintvec_conv(unsigned long *lvalp,
577
+ unsigned int *valp,
578
+ int write, void *data)
579
+{
580
+ if (write) {
581
+ if (*lvalp > UINT_MAX)
582
+ return -EINVAL;
583
+ WRITE_ONCE(*valp, *lvalp);
584
+ } else {
585
+ unsigned int val = READ_ONCE(*valp);
586
+ *lvalp = (unsigned long)val;
587
+ }
588
+ return 0;
589
+}
590
+
591
+static const char proc_wspace_sep[] = { ' ', '\t', '\n' };
592
+
593
+static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
594
+ int write, void *buffer,
595
+ size_t *lenp, loff_t *ppos,
596
+ int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
597
+ int write, void *data),
598
+ void *data)
599
+{
600
+ int *i, vleft, first = 1, err = 0;
601
+ size_t left;
602
+ char *p;
603
+
604
+ if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
605
+ *lenp = 0;
606
+ return 0;
607
+ }
608
+
609
+ i = (int *) tbl_data;
610
+ vleft = table->maxlen / sizeof(*i);
611
+ left = *lenp;
612
+
613
+ if (!conv)
614
+ conv = do_proc_dointvec_conv;
615
+
616
+ if (write) {
617
+ if (proc_first_pos_non_zero_ignore(ppos, table))
618
+ goto out;
619
+
620
+ if (left > PAGE_SIZE - 1)
621
+ left = PAGE_SIZE - 1;
622
+ p = buffer;
623
+ }
624
+
625
+ for (; left && vleft--; i++, first=0) {
626
+ unsigned long lval;
627
+ bool neg;
628
+
629
+ if (write) {
630
+ proc_skip_spaces(&p, &left);
631
+
632
+ if (!left)
633
+ break;
634
+ err = proc_get_long(&p, &left, &lval, &neg,
635
+ proc_wspace_sep,
636
+ sizeof(proc_wspace_sep), NULL);
637
+ if (err)
638
+ break;
639
+ if (conv(&neg, &lval, i, 1, data)) {
640
+ err = -EINVAL;
641
+ break;
642
+ }
643
+ } else {
644
+ if (conv(&neg, &lval, i, 0, data)) {
645
+ err = -EINVAL;
646
+ break;
647
+ }
648
+ if (!first)
649
+ proc_put_char(&buffer, &left, '\t');
650
+ proc_put_long(&buffer, &left, lval, neg);
651
+ }
652
+ }
653
+
654
+ if (!write && !first && left && !err)
655
+ proc_put_char(&buffer, &left, '\n');
656
+ if (write && !err && left)
657
+ proc_skip_spaces(&p, &left);
658
+ if (write && first)
659
+ return err ? : -EINVAL;
660
+ *lenp -= left;
661
+out:
662
+ *ppos += *lenp;
663
+ return err;
664
+}
665
+
666
+static int do_proc_dointvec(struct ctl_table *table, int write,
667
+ void *buffer, size_t *lenp, loff_t *ppos,
668
+ int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
669
+ int write, void *data),
670
+ void *data)
671
+{
672
+ return __do_proc_dointvec(table->data, table, write,
673
+ buffer, lenp, ppos, conv, data);
674
+}
675
+
676
+static int do_proc_douintvec_w(unsigned int *tbl_data,
677
+ struct ctl_table *table,
678
+ void *buffer,
679
+ size_t *lenp, loff_t *ppos,
680
+ int (*conv)(unsigned long *lvalp,
681
+ unsigned int *valp,
682
+ int write, void *data),
683
+ void *data)
684
+{
685
+ unsigned long lval;
686
+ int err = 0;
687
+ size_t left;
688
+ bool neg;
689
+ char *p = buffer;
690
+
691
+ left = *lenp;
692
+
693
+ if (proc_first_pos_non_zero_ignore(ppos, table))
694
+ goto bail_early;
695
+
696
+ if (left > PAGE_SIZE - 1)
697
+ left = PAGE_SIZE - 1;
698
+
699
+ proc_skip_spaces(&p, &left);
700
+ if (!left) {
701
+ err = -EINVAL;
702
+ goto out_free;
703
+ }
704
+
705
+ err = proc_get_long(&p, &left, &lval, &neg,
706
+ proc_wspace_sep,
707
+ sizeof(proc_wspace_sep), NULL);
708
+ if (err || neg) {
709
+ err = -EINVAL;
710
+ goto out_free;
711
+ }
712
+
713
+ if (conv(&lval, tbl_data, 1, data)) {
714
+ err = -EINVAL;
715
+ goto out_free;
716
+ }
717
+
718
+ if (!err && left)
719
+ proc_skip_spaces(&p, &left);
720
+
721
+out_free:
722
+ if (err)
723
+ return -EINVAL;
724
+
725
+ return 0;
726
+
727
+ /* This is in keeping with old __do_proc_dointvec() */
728
+bail_early:
729
+ *ppos += *lenp;
730
+ return err;
731
+}
732
+
733
+static int do_proc_douintvec_r(unsigned int *tbl_data, void *buffer,
734
+ size_t *lenp, loff_t *ppos,
735
+ int (*conv)(unsigned long *lvalp,
736
+ unsigned int *valp,
737
+ int write, void *data),
738
+ void *data)
739
+{
740
+ unsigned long lval;
741
+ int err = 0;
742
+ size_t left;
743
+
744
+ left = *lenp;
745
+
746
+ if (conv(&lval, tbl_data, 0, data)) {
747
+ err = -EINVAL;
748
+ goto out;
749
+ }
750
+
751
+ proc_put_long(&buffer, &left, lval, false);
752
+ if (!left)
753
+ goto out;
754
+
755
+ proc_put_char(&buffer, &left, '\n');
756
+
757
+out:
758
+ *lenp -= left;
759
+ *ppos += *lenp;
760
+
761
+ return err;
762
+}
763
+
764
+static int __do_proc_douintvec(void *tbl_data, struct ctl_table *table,
765
+ int write, void *buffer,
766
+ size_t *lenp, loff_t *ppos,
767
+ int (*conv)(unsigned long *lvalp,
768
+ unsigned int *valp,
769
+ int write, void *data),
770
+ void *data)
771
+{
772
+ unsigned int *i, vleft;
773
+
774
+ if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
775
+ *lenp = 0;
776
+ return 0;
777
+ }
778
+
779
+ i = (unsigned int *) tbl_data;
780
+ vleft = table->maxlen / sizeof(*i);
781
+
782
+ /*
783
+ * Arrays are not supported, keep this simple. *Do not* add
784
+ * support for them.
785
+ */
786
+ if (vleft != 1) {
787
+ *lenp = 0;
788
+ return -EINVAL;
789
+ }
790
+
791
+ if (!conv)
792
+ conv = do_proc_douintvec_conv;
793
+
794
+ if (write)
795
+ return do_proc_douintvec_w(i, table, buffer, lenp, ppos,
796
+ conv, data);
797
+ return do_proc_douintvec_r(i, buffer, lenp, ppos, conv, data);
798
+}
799
+
800
+static int do_proc_douintvec(struct ctl_table *table, int write,
801
+ void *buffer, size_t *lenp, loff_t *ppos,
802
+ int (*conv)(unsigned long *lvalp,
803
+ unsigned int *valp,
804
+ int write, void *data),
805
+ void *data)
806
+{
807
+ return __do_proc_douintvec(table->data, table, write,
808
+ buffer, lenp, ppos, conv, data);
809
+}
810
+
811
+/**
812
+ * proc_dointvec - read a vector of integers
813
+ * @table: the sysctl table
814
+ * @write: %TRUE if this is a write to the sysctl file
815
+ * @buffer: the user buffer
816
+ * @lenp: the size of the user buffer
817
+ * @ppos: file position
818
+ *
819
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
820
+ * values from/to the user buffer, treated as an ASCII string.
821
+ *
822
+ * Returns 0 on success.
823
+ */
824
+int proc_dointvec(struct ctl_table *table, int write, void *buffer,
825
+ size_t *lenp, loff_t *ppos)
826
+{
827
+ return do_proc_dointvec(table, write, buffer, lenp, ppos, NULL, NULL);
828
+}
829
+
830
+#ifdef CONFIG_COMPACTION
831
+static int proc_dointvec_minmax_warn_RT_change(struct ctl_table *table,
832
+ int write, void *buffer, size_t *lenp, loff_t *ppos)
833
+{
834
+ int ret, old;
835
+
836
+ if (!IS_ENABLED(CONFIG_PREEMPT_RT) || !write)
837
+ return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
838
+
839
+ old = *(int *)table->data;
840
+ ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
841
+ if (ret)
842
+ return ret;
843
+ if (old != *(int *)table->data)
844
+ pr_warn_once("sysctl attribute %s changed by %s[%d]\n",
845
+ table->procname, current->comm,
846
+ task_pid_nr(current));
847
+ return ret;
848
+}
849
+#endif
850
+
851
+/**
852
+ * proc_douintvec - read a vector of unsigned integers
853
+ * @table: the sysctl table
854
+ * @write: %TRUE if this is a write to the sysctl file
855
+ * @buffer: the user buffer
856
+ * @lenp: the size of the user buffer
857
+ * @ppos: file position
858
+ *
859
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
860
+ * values from/to the user buffer, treated as an ASCII string.
861
+ *
862
+ * Returns 0 on success.
863
+ */
864
+int proc_douintvec(struct ctl_table *table, int write, void *buffer,
865
+ size_t *lenp, loff_t *ppos)
866
+{
867
+ return do_proc_douintvec(table, write, buffer, lenp, ppos,
868
+ do_proc_douintvec_conv, NULL);
869
+}
870
+
871
+/*
872
+ * Taint values can only be increased
873
+ * This means we can safely use a temporary.
874
+ */
875
+static int proc_taint(struct ctl_table *table, int write,
876
+ void *buffer, size_t *lenp, loff_t *ppos)
877
+{
878
+ struct ctl_table t;
879
+ unsigned long tmptaint = get_taint();
880
+ int err;
881
+
882
+ if (write && !capable(CAP_SYS_ADMIN))
883
+ return -EPERM;
884
+
885
+ t = *table;
886
+ t.data = &tmptaint;
887
+ err = proc_doulongvec_minmax(&t, write, buffer, lenp, ppos);
888
+ if (err < 0)
889
+ return err;
890
+
891
+ if (write) {
892
+ int i;
893
+
894
+ /*
895
+ * If we are relying on panic_on_taint not producing
896
+ * false positives due to userspace input, bail out
897
+ * before setting the requested taint flags.
898
+ */
899
+ if (panic_on_taint_nousertaint && (tmptaint & panic_on_taint))
900
+ return -EINVAL;
901
+
902
+ /*
903
+ * Poor man's atomic or. Not worth adding a primitive
904
+ * to everyone's atomic.h for this
905
+ */
906
+ for (i = 0; i < TAINT_FLAGS_COUNT; i++)
907
+ if ((1UL << i) & tmptaint)
908
+ add_taint(i, LOCKDEP_STILL_OK);
909
+ }
910
+
911
+ return err;
912
+}
913
+
914
+#ifdef CONFIG_PRINTK
915
+static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
916
+ void *buffer, size_t *lenp, loff_t *ppos)
917
+{
918
+ if (write && !capable(CAP_SYS_ADMIN))
919
+ return -EPERM;
920
+
921
+ return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
922
+}
923
+#endif
924
+
925
+/**
926
+ * struct do_proc_dointvec_minmax_conv_param - proc_dointvec_minmax() range checking structure
927
+ * @min: pointer to minimum allowable value
928
+ * @max: pointer to maximum allowable value
929
+ *
930
+ * The do_proc_dointvec_minmax_conv_param structure provides the
931
+ * minimum and maximum values for doing range checking for those sysctl
932
+ * parameters that use the proc_dointvec_minmax() handler.
933
+ */
934
+struct do_proc_dointvec_minmax_conv_param {
935
+ int *min;
936
+ int *max;
937
+};
938
+
939
+static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp,
940
+ int *valp,
941
+ int write, void *data)
942
+{
943
+ int tmp, ret;
944
+ struct do_proc_dointvec_minmax_conv_param *param = data;
945
+ /*
946
+ * If writing, first do so via a temporary local int so we can
947
+ * bounds-check it before touching *valp.
948
+ */
949
+ int *ip = write ? &tmp : valp;
950
+
951
+ ret = do_proc_dointvec_conv(negp, lvalp, ip, write, data);
952
+ if (ret)
953
+ return ret;
954
+
955
+ if (write) {
956
+ if ((param->min && *param->min > tmp) ||
957
+ (param->max && *param->max < tmp))
958
+ return -EINVAL;
959
+ WRITE_ONCE(*valp, tmp);
960
+ }
961
+
962
+ return 0;
963
+}
964
+
965
+/**
966
+ * proc_dointvec_minmax - read a vector of integers with min/max values
967
+ * @table: the sysctl table
968
+ * @write: %TRUE if this is a write to the sysctl file
969
+ * @buffer: the user buffer
970
+ * @lenp: the size of the user buffer
971
+ * @ppos: file position
972
+ *
973
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
974
+ * values from/to the user buffer, treated as an ASCII string.
975
+ *
976
+ * This routine will ensure the values are within the range specified by
977
+ * table->extra1 (min) and table->extra2 (max).
978
+ *
979
+ * Returns 0 on success or -EINVAL on write when the range check fails.
980
+ */
981
+int proc_dointvec_minmax(struct ctl_table *table, int write,
982
+ void *buffer, size_t *lenp, loff_t *ppos)
983
+{
984
+ struct do_proc_dointvec_minmax_conv_param param = {
985
+ .min = (int *) table->extra1,
986
+ .max = (int *) table->extra2,
987
+ };
988
+ return do_proc_dointvec(table, write, buffer, lenp, ppos,
989
+ do_proc_dointvec_minmax_conv, &param);
990
+}
991
+
992
+/**
993
+ * struct do_proc_douintvec_minmax_conv_param - proc_douintvec_minmax() range checking structure
994
+ * @min: pointer to minimum allowable value
995
+ * @max: pointer to maximum allowable value
996
+ *
997
+ * The do_proc_douintvec_minmax_conv_param structure provides the
998
+ * minimum and maximum values for doing range checking for those sysctl
999
+ * parameters that use the proc_douintvec_minmax() handler.
1000
+ */
1001
+struct do_proc_douintvec_minmax_conv_param {
1002
+ unsigned int *min;
1003
+ unsigned int *max;
1004
+};
1005
+
1006
+static int do_proc_douintvec_minmax_conv(unsigned long *lvalp,
1007
+ unsigned int *valp,
1008
+ int write, void *data)
1009
+{
1010
+ int ret;
1011
+ unsigned int tmp;
1012
+ struct do_proc_douintvec_minmax_conv_param *param = data;
1013
+ /* write via temporary local uint for bounds-checking */
1014
+ unsigned int *up = write ? &tmp : valp;
1015
+
1016
+ ret = do_proc_douintvec_conv(lvalp, up, write, data);
1017
+ if (ret)
1018
+ return ret;
1019
+
1020
+ if (write) {
1021
+ if ((param->min && *param->min > tmp) ||
1022
+ (param->max && *param->max < tmp))
1023
+ return -ERANGE;
1024
+
1025
+ WRITE_ONCE(*valp, tmp);
1026
+ }
1027
+
1028
+ return 0;
1029
+}
1030
+
1031
+/**
1032
+ * proc_douintvec_minmax - read a vector of unsigned ints with min/max values
1033
+ * @table: the sysctl table
1034
+ * @write: %TRUE if this is a write to the sysctl file
1035
+ * @buffer: the user buffer
1036
+ * @lenp: the size of the user buffer
1037
+ * @ppos: file position
1038
+ *
1039
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
1040
+ * values from/to the user buffer, treated as an ASCII string. Negative
1041
+ * strings are not allowed.
1042
+ *
1043
+ * This routine will ensure the values are within the range specified by
1044
+ * table->extra1 (min) and table->extra2 (max). There is a final sanity
1045
+ * check for UINT_MAX to avoid having to support wrap around uses from
1046
+ * userspace.
1047
+ *
1048
+ * Returns 0 on success or -ERANGE on write when the range check fails.
1049
+ */
1050
+int proc_douintvec_minmax(struct ctl_table *table, int write,
1051
+ void *buffer, size_t *lenp, loff_t *ppos)
1052
+{
1053
+ struct do_proc_douintvec_minmax_conv_param param = {
1054
+ .min = (unsigned int *) table->extra1,
1055
+ .max = (unsigned int *) table->extra2,
1056
+ };
1057
+ return do_proc_douintvec(table, write, buffer, lenp, ppos,
1058
+ do_proc_douintvec_minmax_conv, &param);
1059
+}
1060
+
1061
+/**
1062
+ * proc_dou8vec_minmax - read a vector of unsigned chars with min/max values
1063
+ * @table: the sysctl table
1064
+ * @write: %TRUE if this is a write to the sysctl file
1065
+ * @buffer: the user buffer
1066
+ * @lenp: the size of the user buffer
1067
+ * @ppos: file position
1068
+ *
1069
+ * Reads/writes up to table->maxlen/sizeof(u8) unsigned chars
1070
+ * values from/to the user buffer, treated as an ASCII string. Negative
1071
+ * strings are not allowed.
1072
+ *
1073
+ * This routine will ensure the values are within the range specified by
1074
+ * table->extra1 (min) and table->extra2 (max).
1075
+ *
1076
+ * Returns 0 on success or an error on write when the range check fails.
1077
+ */
1078
+int proc_dou8vec_minmax(struct ctl_table *table, int write,
1079
+ void *buffer, size_t *lenp, loff_t *ppos)
1080
+{
1081
+ struct ctl_table tmp;
1082
+ unsigned int min = 0, max = 255U, val;
1083
+ u8 *data = table->data;
1084
+ struct do_proc_douintvec_minmax_conv_param param = {
1085
+ .min = &min,
1086
+ .max = &max,
1087
+ };
1088
+ int res;
1089
+
1090
+ /* Do not support arrays yet. */
1091
+ if (table->maxlen != sizeof(u8))
1092
+ return -EINVAL;
1093
+
1094
+ if (table->extra1) {
1095
+ min = *(unsigned int *) table->extra1;
1096
+ if (min > 255U)
1097
+ return -EINVAL;
1098
+ }
1099
+ if (table->extra2) {
1100
+ max = *(unsigned int *) table->extra2;
1101
+ if (max > 255U)
1102
+ return -EINVAL;
1103
+ }
1104
+
1105
+ tmp = *table;
1106
+
1107
+ tmp.maxlen = sizeof(val);
1108
+ tmp.data = &val;
1109
+ val = READ_ONCE(*data);
1110
+ res = do_proc_douintvec(&tmp, write, buffer, lenp, ppos,
1111
+ do_proc_douintvec_minmax_conv, &param);
1112
+ if (res)
1113
+ return res;
1114
+ if (write)
1115
+ WRITE_ONCE(*data, val);
1116
+ return 0;
1117
+}
1118
+EXPORT_SYMBOL_GPL(proc_dou8vec_minmax);
1119
+
1120
+static int do_proc_dopipe_max_size_conv(unsigned long *lvalp,
1121
+ unsigned int *valp,
1122
+ int write, void *data)
1123
+{
1124
+ if (write) {
1125
+ unsigned int val;
1126
+
1127
+ val = round_pipe_size(*lvalp);
1128
+ if (val == 0)
1129
+ return -EINVAL;
1130
+
1131
+ *valp = val;
1132
+ } else {
1133
+ unsigned int val = *valp;
1134
+ *lvalp = (unsigned long) val;
1135
+ }
1136
+
1137
+ return 0;
1138
+}
1139
+
1140
+static int proc_dopipe_max_size(struct ctl_table *table, int write,
1141
+ void *buffer, size_t *lenp, loff_t *ppos)
1142
+{
1143
+ return do_proc_douintvec(table, write, buffer, lenp, ppos,
1144
+ do_proc_dopipe_max_size_conv, NULL);
1145
+}
1146
+
1147
+static void validate_coredump_safety(void)
1148
+{
1149
+#ifdef CONFIG_COREDUMP
1150
+ if (suid_dumpable == SUID_DUMP_ROOT &&
1151
+ core_pattern[0] != '/' && core_pattern[0] != '|') {
1152
+ printk(KERN_WARNING
1153
+"Unsafe core_pattern used with fs.suid_dumpable=2.\n"
1154
+"Pipe handler or fully qualified core dump path required.\n"
1155
+"Set kernel.core_pattern before fs.suid_dumpable.\n"
1156
+ );
1157
+ }
1158
+#endif
1159
+}
1160
+
1161
+static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write,
1162
+ void *buffer, size_t *lenp, loff_t *ppos)
1163
+{
1164
+ int error = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
1165
+ if (!error)
1166
+ validate_coredump_safety();
1167
+ return error;
1168
+}
1169
+
1170
+#ifdef CONFIG_COREDUMP
1171
+static int proc_dostring_coredump(struct ctl_table *table, int write,
1172
+ void *buffer, size_t *lenp, loff_t *ppos)
1173
+{
1174
+ int error = proc_dostring(table, write, buffer, lenp, ppos);
1175
+ if (!error)
1176
+ validate_coredump_safety();
1177
+ return error;
1178
+}
1179
+#endif
1180
+
1181
+#ifdef CONFIG_MAGIC_SYSRQ
1182
+static int sysrq_sysctl_handler(struct ctl_table *table, int write,
1183
+ void *buffer, size_t *lenp, loff_t *ppos)
1184
+{
1185
+ int tmp, ret;
1186
+
1187
+ tmp = sysrq_mask();
1188
+
1189
+ ret = __do_proc_dointvec(&tmp, table, write, buffer,
1190
+ lenp, ppos, NULL, NULL);
1191
+ if (ret || !write)
1192
+ return ret;
1193
+
1194
+ if (write)
1195
+ sysrq_toggle_support(tmp);
1196
+
1197
+ return 0;
1198
+}
1199
+#endif
1200
+
1201
+static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table,
1202
+ int write, void *buffer, size_t *lenp, loff_t *ppos,
1203
+ unsigned long convmul, unsigned long convdiv)
1204
+{
1205
+ unsigned long *i, *min, *max;
1206
+ int vleft, first = 1, err = 0;
1207
+ size_t left;
1208
+ char *p;
1209
+
1210
+ if (!data || !table->maxlen || !*lenp || (*ppos && !write)) {
1211
+ *lenp = 0;
1212
+ return 0;
1213
+ }
1214
+
1215
+ i = (unsigned long *) data;
1216
+ min = (unsigned long *) table->extra1;
1217
+ max = (unsigned long *) table->extra2;
1218
+ vleft = table->maxlen / sizeof(unsigned long);
1219
+ left = *lenp;
1220
+
1221
+ if (write) {
1222
+ if (proc_first_pos_non_zero_ignore(ppos, table))
1223
+ goto out;
1224
+
1225
+ if (left > PAGE_SIZE - 1)
1226
+ left = PAGE_SIZE - 1;
1227
+ p = buffer;
1228
+ }
1229
+
1230
+ for (; left && vleft--; i++, first = 0) {
1231
+ unsigned long val;
1232
+
1233
+ if (write) {
1234
+ bool neg;
1235
+
1236
+ proc_skip_spaces(&p, &left);
1237
+ if (!left)
1238
+ break;
1239
+
1240
+ err = proc_get_long(&p, &left, &val, &neg,
1241
+ proc_wspace_sep,
1242
+ sizeof(proc_wspace_sep), NULL);
1243
+ if (err)
1244
+ break;
1245
+ if (neg)
1246
+ continue;
1247
+ val = convmul * val / convdiv;
1248
+ if ((min && val < *min) || (max && val > *max)) {
1249
+ err = -EINVAL;
1250
+ break;
1251
+ }
1252
+ WRITE_ONCE(*i, val);
1253
+ } else {
1254
+ val = convdiv * READ_ONCE(*i) / convmul;
1255
+ if (!first)
1256
+ proc_put_char(&buffer, &left, '\t');
1257
+ proc_put_long(&buffer, &left, val, false);
1258
+ }
1259
+ }
1260
+
1261
+ if (!write && !first && left && !err)
1262
+ proc_put_char(&buffer, &left, '\n');
1263
+ if (write && !err)
1264
+ proc_skip_spaces(&p, &left);
1265
+ if (write && first)
1266
+ return err ? : -EINVAL;
1267
+ *lenp -= left;
1268
+out:
1269
+ *ppos += *lenp;
1270
+ return err;
1271
+}
1272
+
1273
+static int do_proc_doulongvec_minmax(struct ctl_table *table, int write,
1274
+ void *buffer, size_t *lenp, loff_t *ppos, unsigned long convmul,
1275
+ unsigned long convdiv)
1276
+{
1277
+ return __do_proc_doulongvec_minmax(table->data, table, write,
1278
+ buffer, lenp, ppos, convmul, convdiv);
1279
+}
1280
+
1281
+/**
1282
+ * proc_doulongvec_minmax - read a vector of long integers with min/max values
1283
+ * @table: the sysctl table
1284
+ * @write: %TRUE if this is a write to the sysctl file
1285
+ * @buffer: the user buffer
1286
+ * @lenp: the size of the user buffer
1287
+ * @ppos: file position
1288
+ *
1289
+ * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
1290
+ * values from/to the user buffer, treated as an ASCII string.
1291
+ *
1292
+ * This routine will ensure the values are within the range specified by
1293
+ * table->extra1 (min) and table->extra2 (max).
1294
+ *
1295
+ * Returns 0 on success.
1296
+ */
1297
+int proc_doulongvec_minmax(struct ctl_table *table, int write,
1298
+ void *buffer, size_t *lenp, loff_t *ppos)
1299
+{
1300
+ return do_proc_doulongvec_minmax(table, write, buffer, lenp, ppos, 1l, 1l);
1301
+}
1302
+
1303
+/**
1304
+ * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values
1305
+ * @table: the sysctl table
1306
+ * @write: %TRUE if this is a write to the sysctl file
1307
+ * @buffer: the user buffer
1308
+ * @lenp: the size of the user buffer
1309
+ * @ppos: file position
1310
+ *
1311
+ * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
1312
+ * values from/to the user buffer, treated as an ASCII string. The values
1313
+ * are treated as milliseconds, and converted to jiffies when they are stored.
1314
+ *
1315
+ * This routine will ensure the values are within the range specified by
1316
+ * table->extra1 (min) and table->extra2 (max).
1317
+ *
1318
+ * Returns 0 on success.
1319
+ */
1320
+int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
1321
+ void *buffer, size_t *lenp, loff_t *ppos)
1322
+{
1323
+ return do_proc_doulongvec_minmax(table, write, buffer,
1324
+ lenp, ppos, HZ, 1000l);
1325
+}
1326
+
1327
+
1328
+static int do_proc_dointvec_jiffies_conv(bool *negp, unsigned long *lvalp,
1329
+ int *valp,
1330
+ int write, void *data)
1331
+{
1332
+ if (write) {
1333
+ if (*lvalp > INT_MAX / HZ)
1334
+ return 1;
1335
+ if (*negp)
1336
+ WRITE_ONCE(*valp, -*lvalp * HZ);
1337
+ else
1338
+ WRITE_ONCE(*valp, *lvalp * HZ);
1339
+ } else {
1340
+ int val = READ_ONCE(*valp);
1341
+ unsigned long lval;
1342
+ if (val < 0) {
1343
+ *negp = true;
1344
+ lval = -(unsigned long)val;
1345
+ } else {
1346
+ *negp = false;
1347
+ lval = (unsigned long)val;
1348
+ }
1349
+ *lvalp = lval / HZ;
1350
+ }
1351
+ return 0;
1352
+}
1353
+
1354
+static int do_proc_dointvec_userhz_jiffies_conv(bool *negp, unsigned long *lvalp,
1355
+ int *valp,
1356
+ int write, void *data)
1357
+{
1358
+ if (write) {
1359
+ if (USER_HZ < HZ && *lvalp > (LONG_MAX / HZ) * USER_HZ)
1360
+ return 1;
1361
+ *valp = clock_t_to_jiffies(*negp ? -*lvalp : *lvalp);
1362
+ } else {
1363
+ int val = *valp;
1364
+ unsigned long lval;
1365
+ if (val < 0) {
1366
+ *negp = true;
1367
+ lval = -(unsigned long)val;
1368
+ } else {
1369
+ *negp = false;
1370
+ lval = (unsigned long)val;
1371
+ }
1372
+ *lvalp = jiffies_to_clock_t(lval);
1373
+ }
1374
+ return 0;
1375
+}
1376
+
1377
+static int do_proc_dointvec_ms_jiffies_conv(bool *negp, unsigned long *lvalp,
1378
+ int *valp,
1379
+ int write, void *data)
1380
+{
1381
+ if (write) {
1382
+ unsigned long jif = msecs_to_jiffies(*negp ? -*lvalp : *lvalp);
1383
+
1384
+ if (jif > INT_MAX)
1385
+ return 1;
1386
+ WRITE_ONCE(*valp, (int)jif);
1387
+ } else {
1388
+ int val = READ_ONCE(*valp);
1389
+ unsigned long lval;
1390
+ if (val < 0) {
1391
+ *negp = true;
1392
+ lval = -(unsigned long)val;
1393
+ } else {
1394
+ *negp = false;
1395
+ lval = (unsigned long)val;
1396
+ }
1397
+ *lvalp = jiffies_to_msecs(lval);
1398
+ }
1399
+ return 0;
1400
+}
1401
+
1402
+/**
1403
+ * proc_dointvec_jiffies - read a vector of integers as seconds
1404
+ * @table: the sysctl table
1405
+ * @write: %TRUE if this is a write to the sysctl file
1406
+ * @buffer: the user buffer
1407
+ * @lenp: the size of the user buffer
1408
+ * @ppos: file position
1409
+ *
1410
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1411
+ * values from/to the user buffer, treated as an ASCII string.
1412
+ * The values read are assumed to be in seconds, and are converted into
1413
+ * jiffies.
1414
+ *
1415
+ * Returns 0 on success.
1416
+ */
1417
+int proc_dointvec_jiffies(struct ctl_table *table, int write,
1418
+ void *buffer, size_t *lenp, loff_t *ppos)
1419
+{
1420
+ return do_proc_dointvec(table,write,buffer,lenp,ppos,
1421
+ do_proc_dointvec_jiffies_conv,NULL);
1422
+}
1423
+
1424
+/**
1425
+ * proc_dointvec_userhz_jiffies - read a vector of integers as 1/USER_HZ seconds
1426
+ * @table: the sysctl table
1427
+ * @write: %TRUE if this is a write to the sysctl file
1428
+ * @buffer: the user buffer
1429
+ * @lenp: the size of the user buffer
1430
+ * @ppos: pointer to the file position
1431
+ *
1432
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1433
+ * values from/to the user buffer, treated as an ASCII string.
1434
+ * The values read are assumed to be in 1/USER_HZ seconds, and
1435
+ * are converted into jiffies.
1436
+ *
1437
+ * Returns 0 on success.
1438
+ */
1439
+int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
1440
+ void *buffer, size_t *lenp, loff_t *ppos)
1441
+{
1442
+ return do_proc_dointvec(table,write,buffer,lenp,ppos,
1443
+ do_proc_dointvec_userhz_jiffies_conv,NULL);
1444
+}
1445
+
1446
+/**
1447
+ * proc_dointvec_ms_jiffies - read a vector of integers as 1 milliseconds
1448
+ * @table: the sysctl table
1449
+ * @write: %TRUE if this is a write to the sysctl file
1450
+ * @buffer: the user buffer
1451
+ * @lenp: the size of the user buffer
1452
+ * @ppos: file position
1453
+ * @ppos: the current position in the file
1454
+ *
1455
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1456
+ * values from/to the user buffer, treated as an ASCII string.
1457
+ * The values read are assumed to be in 1/1000 seconds, and
1458
+ * are converted into jiffies.
1459
+ *
1460
+ * Returns 0 on success.
1461
+ */
1462
+int proc_dointvec_ms_jiffies(struct ctl_table *table, int write, void *buffer,
1463
+ size_t *lenp, loff_t *ppos)
1464
+{
1465
+ return do_proc_dointvec(table, write, buffer, lenp, ppos,
1466
+ do_proc_dointvec_ms_jiffies_conv, NULL);
1467
+}
1468
+
1469
+static int proc_do_cad_pid(struct ctl_table *table, int write, void *buffer,
1470
+ size_t *lenp, loff_t *ppos)
1471
+{
1472
+ struct pid *new_pid;
1473
+ pid_t tmp;
1474
+ int r;
1475
+
1476
+ tmp = pid_vnr(cad_pid);
1477
+
1478
+ r = __do_proc_dointvec(&tmp, table, write, buffer,
1479
+ lenp, ppos, NULL, NULL);
1480
+ if (r || !write)
1481
+ return r;
1482
+
1483
+ new_pid = find_get_pid(tmp);
1484
+ if (!new_pid)
1485
+ return -ESRCH;
1486
+
1487
+ put_pid(xchg(&cad_pid, new_pid));
1488
+ return 0;
1489
+}
1490
+
1491
+/**
1492
+ * proc_do_large_bitmap - read/write from/to a large bitmap
1493
+ * @table: the sysctl table
1494
+ * @write: %TRUE if this is a write to the sysctl file
1495
+ * @buffer: the user buffer
1496
+ * @lenp: the size of the user buffer
1497
+ * @ppos: file position
1498
+ *
1499
+ * The bitmap is stored at table->data and the bitmap length (in bits)
1500
+ * in table->maxlen.
1501
+ *
1502
+ * We use a range comma separated format (e.g. 1,3-4,10-10) so that
1503
+ * large bitmaps may be represented in a compact manner. Writing into
1504
+ * the file will clear the bitmap then update it with the given input.
1505
+ *
1506
+ * Returns 0 on success.
1507
+ */
1508
+int proc_do_large_bitmap(struct ctl_table *table, int write,
1509
+ void *buffer, size_t *lenp, loff_t *ppos)
1510
+{
1511
+ int err = 0;
1512
+ bool first = 1;
1513
+ size_t left = *lenp;
1514
+ unsigned long bitmap_len = table->maxlen;
1515
+ unsigned long *bitmap = *(unsigned long **) table->data;
1516
+ unsigned long *tmp_bitmap = NULL;
1517
+ char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
1518
+
1519
+ if (!bitmap || !bitmap_len || !left || (*ppos && !write)) {
1520
+ *lenp = 0;
1521
+ return 0;
1522
+ }
1523
+
1524
+ if (write) {
1525
+ char *p = buffer;
1526
+ size_t skipped = 0;
1527
+
1528
+ if (left > PAGE_SIZE - 1) {
1529
+ left = PAGE_SIZE - 1;
1530
+ /* How much of the buffer we'll skip this pass */
1531
+ skipped = *lenp - left;
1532
+ }
1533
+
1534
+ tmp_bitmap = bitmap_zalloc(bitmap_len, GFP_KERNEL);
1535
+ if (!tmp_bitmap)
1536
+ return -ENOMEM;
1537
+ proc_skip_char(&p, &left, '\n');
1538
+ while (!err && left) {
1539
+ unsigned long val_a, val_b;
1540
+ bool neg;
1541
+ size_t saved_left;
1542
+
1543
+ /* In case we stop parsing mid-number, we can reset */
1544
+ saved_left = left;
1545
+ err = proc_get_long(&p, &left, &val_a, &neg, tr_a,
1546
+ sizeof(tr_a), &c);
1547
+ /*
1548
+ * If we consumed the entirety of a truncated buffer or
1549
+ * only one char is left (may be a "-"), then stop here,
1550
+ * reset, & come back for more.
1551
+ */
1552
+ if ((left <= 1) && skipped) {
1553
+ left = saved_left;
1554
+ break;
1555
+ }
1556
+
1557
+ if (err)
1558
+ break;
1559
+ if (val_a >= bitmap_len || neg) {
1560
+ err = -EINVAL;
1561
+ break;
1562
+ }
1563
+
1564
+ val_b = val_a;
1565
+ if (left) {
1566
+ p++;
1567
+ left--;
1568
+ }
1569
+
1570
+ if (c == '-') {
1571
+ err = proc_get_long(&p, &left, &val_b,
1572
+ &neg, tr_b, sizeof(tr_b),
1573
+ &c);
1574
+ /*
1575
+ * If we consumed all of a truncated buffer or
1576
+ * then stop here, reset, & come back for more.
1577
+ */
1578
+ if (!left && skipped) {
1579
+ left = saved_left;
1580
+ break;
1581
+ }
1582
+
1583
+ if (err)
1584
+ break;
1585
+ if (val_b >= bitmap_len || neg ||
1586
+ val_a > val_b) {
1587
+ err = -EINVAL;
1588
+ break;
1589
+ }
1590
+ if (left) {
1591
+ p++;
1592
+ left--;
1593
+ }
1594
+ }
1595
+
1596
+ bitmap_set(tmp_bitmap, val_a, val_b - val_a + 1);
1597
+ first = 0;
1598
+ proc_skip_char(&p, &left, '\n');
1599
+ }
1600
+ left += skipped;
1601
+ } else {
1602
+ unsigned long bit_a, bit_b = 0;
1603
+
1604
+ while (left) {
1605
+ bit_a = find_next_bit(bitmap, bitmap_len, bit_b);
1606
+ if (bit_a >= bitmap_len)
1607
+ break;
1608
+ bit_b = find_next_zero_bit(bitmap, bitmap_len,
1609
+ bit_a + 1) - 1;
1610
+
1611
+ if (!first)
1612
+ proc_put_char(&buffer, &left, ',');
1613
+ proc_put_long(&buffer, &left, bit_a, false);
1614
+ if (bit_a != bit_b) {
1615
+ proc_put_char(&buffer, &left, '-');
1616
+ proc_put_long(&buffer, &left, bit_b, false);
1617
+ }
1618
+
1619
+ first = 0; bit_b++;
1620
+ }
1621
+ proc_put_char(&buffer, &left, '\n');
1622
+ }
1623
+
1624
+ if (!err) {
1625
+ if (write) {
1626
+ if (*ppos)
1627
+ bitmap_or(bitmap, bitmap, tmp_bitmap, bitmap_len);
1628
+ else
1629
+ bitmap_copy(bitmap, tmp_bitmap, bitmap_len);
1630
+ }
1631
+ *lenp -= left;
1632
+ *ppos += *lenp;
1633
+ }
1634
+
1635
+ bitmap_free(tmp_bitmap);
1636
+ return err;
1637
+}
1638
+
1639
+#else /* CONFIG_PROC_SYSCTL */
1640
+
1641
+int proc_dostring(struct ctl_table *table, int write,
1642
+ void *buffer, size_t *lenp, loff_t *ppos)
1643
+{
1644
+ return -ENOSYS;
1645
+}
1646
+
1647
+int proc_dointvec(struct ctl_table *table, int write,
1648
+ void *buffer, size_t *lenp, loff_t *ppos)
1649
+{
1650
+ return -ENOSYS;
1651
+}
1652
+
1653
+int proc_douintvec(struct ctl_table *table, int write,
1654
+ void *buffer, size_t *lenp, loff_t *ppos)
1655
+{
1656
+ return -ENOSYS;
1657
+}
1658
+
1659
+int proc_dointvec_minmax(struct ctl_table *table, int write,
1660
+ void *buffer, size_t *lenp, loff_t *ppos)
1661
+{
1662
+ return -ENOSYS;
1663
+}
1664
+
1665
+int proc_douintvec_minmax(struct ctl_table *table, int write,
1666
+ void *buffer, size_t *lenp, loff_t *ppos)
1667
+{
1668
+ return -ENOSYS;
1669
+}
1670
+
1671
+int proc_dou8vec_minmax(struct ctl_table *table, int write,
1672
+ void *buffer, size_t *lenp, loff_t *ppos)
1673
+{
1674
+ return -ENOSYS;
1675
+}
1676
+
1677
+int proc_dointvec_jiffies(struct ctl_table *table, int write,
1678
+ void *buffer, size_t *lenp, loff_t *ppos)
1679
+{
1680
+ return -ENOSYS;
1681
+}
1682
+
1683
+int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
1684
+ void *buffer, size_t *lenp, loff_t *ppos)
1685
+{
1686
+ return -ENOSYS;
1687
+}
1688
+
1689
+int proc_dointvec_ms_jiffies(struct ctl_table *table, int write,
1690
+ void *buffer, size_t *lenp, loff_t *ppos)
1691
+{
1692
+ return -ENOSYS;
1693
+}
1694
+
1695
+int proc_doulongvec_minmax(struct ctl_table *table, int write,
1696
+ void *buffer, size_t *lenp, loff_t *ppos)
1697
+{
1698
+ return -ENOSYS;
1699
+}
1700
+
1701
+int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
1702
+ void *buffer, size_t *lenp, loff_t *ppos)
1703
+{
1704
+ return -ENOSYS;
1705
+}
1706
+
1707
+int proc_do_large_bitmap(struct ctl_table *table, int write,
1708
+ void *buffer, size_t *lenp, loff_t *ppos)
1709
+{
1710
+ return -ENOSYS;
1711
+}
1712
+
1713
+#endif /* CONFIG_PROC_SYSCTL */
1714
+
1715
+#if defined(CONFIG_SYSCTL)
1716
+int proc_do_static_key(struct ctl_table *table, int write,
1717
+ void *buffer, size_t *lenp, loff_t *ppos)
1718
+{
1719
+ struct static_key *key = (struct static_key *)table->data;
1720
+ static DEFINE_MUTEX(static_key_mutex);
1721
+ int val, ret;
1722
+ struct ctl_table tmp = {
1723
+ .data = &val,
1724
+ .maxlen = sizeof(val),
1725
+ .mode = table->mode,
1726
+ .extra1 = SYSCTL_ZERO,
1727
+ .extra2 = SYSCTL_ONE,
1728
+ };
1729
+
1730
+ if (write && !capable(CAP_SYS_ADMIN))
1731
+ return -EPERM;
1732
+
1733
+ mutex_lock(&static_key_mutex);
1734
+ val = static_key_enabled(key);
1735
+ ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
1736
+ if (write && !ret) {
1737
+ if (val)
1738
+ static_key_enable(key);
1739
+ else
1740
+ static_key_disable(key);
1741
+ }
1742
+ mutex_unlock(&static_key_mutex);
1743
+ return ret;
1744
+}
1745
+
3411746 static struct ctl_table kern_table[] = {
3421747 {
3431748 .procname = "sched_child_runs_first",
....@@ -347,13 +1752,6 @@
3471752 .proc_handler = proc_dointvec,
3481753 },
3491754 #ifdef CONFIG_SCHED_DEBUG
350
- {
351
- .procname = "sched_cstate_aware",
352
- .data = &sysctl_sched_cstate_aware,
353
- .maxlen = sizeof(unsigned int),
354
- .mode = 0644,
355
- .proc_handler = proc_dointvec,
356
- },
3571755 {
3581756 .procname = "sched_min_granularity_ns",
3591757 .data = &sysctl_sched_min_granularity,
....@@ -373,13 +1771,6 @@
3731771 .extra2 = &max_sched_granularity_ns,
3741772 },
3751773 {
376
- .procname = "sched_sync_hint_enable",
377
- .data = &sysctl_sched_sync_hint_enable,
378
- .maxlen = sizeof(unsigned int),
379
- .mode = 0644,
380
- .proc_handler = proc_dointvec,
381
- },
382
- {
3831774 .procname = "sched_wakeup_granularity_ns",
3841775 .data = &sysctl_sched_wakeup_granularity,
3851776 .maxlen = sizeof(unsigned int),
....@@ -389,6 +1780,13 @@
3891780 .extra2 = &max_wakeup_granularity_ns,
3901781 },
3911782 #ifdef CONFIG_SMP
1783
+ {
1784
+ .procname = "sched_pelt_period",
1785
+ .data = &sysctl_sched_pelt_period,
1786
+ .maxlen = sizeof(int),
1787
+ .mode = 0644,
1788
+ .proc_handler = sched_pelt_period_update_handler,
1789
+ },
3921790 {
3931791 .procname = "sched_tunable_scaling",
3941792 .data = &sysctl_sched_tunable_scaling,
....@@ -419,8 +1817,8 @@
4191817 .maxlen = sizeof(unsigned int),
4201818 .mode = 0644,
4211819 .proc_handler = sysctl_schedstats,
422
- .extra1 = &zero,
423
- .extra2 = &one,
1820
+ .extra1 = SYSCTL_ZERO,
1821
+ .extra2 = SYSCTL_ONE,
4241822 },
4251823 #endif /* CONFIG_SCHEDSTATS */
4261824 #endif /* CONFIG_SMP */
....@@ -452,7 +1850,7 @@
4521850 .maxlen = sizeof(unsigned int),
4531851 .mode = 0644,
4541852 .proc_handler = proc_dointvec_minmax,
455
- .extra1 = &one,
1853
+ .extra1 = SYSCTL_ONE,
4561854 },
4571855 {
4581856 .procname = "numa_balancing",
....@@ -460,8 +1858,8 @@
4601858 .maxlen = sizeof(unsigned int),
4611859 .mode = 0644,
4621860 .proc_handler = sysctl_numa_balancing,
463
- .extra1 = &zero,
464
- .extra2 = &one,
1861
+ .extra1 = SYSCTL_ZERO,
1862
+ .extra2 = SYSCTL_ONE,
4651863 },
4661864 #endif /* CONFIG_NUMA_BALANCING */
4671865 #endif /* CONFIG_SCHED_DEBUG */
....@@ -480,12 +1878,35 @@
4801878 .proc_handler = sched_rt_handler,
4811879 },
4821880 {
1881
+ .procname = "sched_deadline_period_max_us",
1882
+ .data = &sysctl_sched_dl_period_max,
1883
+ .maxlen = sizeof(unsigned int),
1884
+ .mode = 0644,
1885
+ .proc_handler = proc_dointvec,
1886
+ },
1887
+ {
1888
+ .procname = "sched_deadline_period_min_us",
1889
+ .data = &sysctl_sched_dl_period_min,
1890
+ .maxlen = sizeof(unsigned int),
1891
+ .mode = 0644,
1892
+ .proc_handler = proc_dointvec,
1893
+ },
1894
+ {
4831895 .procname = "sched_rr_timeslice_ms",
4841896 .data = &sysctl_sched_rr_timeslice,
4851897 .maxlen = sizeof(int),
4861898 .mode = 0644,
4871899 .proc_handler = sched_rr_handler,
4881900 },
1901
+#ifdef CONFIG_SMP
1902
+ {
1903
+ .procname = "sched_pelt_multiplier",
1904
+ .data = &sysctl_sched_pelt_multiplier,
1905
+ .maxlen = sizeof(unsigned int),
1906
+ .mode = 0644,
1907
+ .proc_handler = sched_pelt_multiplier,
1908
+ },
1909
+#endif
4891910 #ifdef CONFIG_UCLAMP_TASK
4901911 {
4911912 .procname = "sched_util_clamp_min",
....@@ -501,6 +1922,13 @@
5011922 .mode = 0644,
5021923 .proc_handler = sysctl_sched_uclamp_handler,
5031924 },
1925
+ {
1926
+ .procname = "sched_util_clamp_min_rt_default",
1927
+ .data = &sysctl_sched_uclamp_util_min_rt_default,
1928
+ .maxlen = sizeof(unsigned int),
1929
+ .mode = 0644,
1930
+ .proc_handler = sysctl_sched_uclamp_handler,
1931
+ },
5041932 #endif
5051933 #ifdef CONFIG_SCHED_AUTOGROUP
5061934 {
....@@ -509,8 +1937,8 @@
5091937 .maxlen = sizeof(unsigned int),
5101938 .mode = 0644,
5111939 .proc_handler = proc_dointvec_minmax,
512
- .extra1 = &zero,
513
- .extra2 = &one,
1940
+ .extra1 = SYSCTL_ZERO,
1941
+ .extra2 = SYSCTL_ONE,
5141942 },
5151943 #endif
5161944 #ifdef CONFIG_CFS_BANDWIDTH
....@@ -520,16 +1948,7 @@
5201948 .maxlen = sizeof(unsigned int),
5211949 .mode = 0644,
5221950 .proc_handler = proc_dointvec_minmax,
523
- .extra1 = &one,
524
- },
525
-#endif
526
-#ifdef CONFIG_ROCKCHIP_SCHED_PERFORMANCE_BIAS
527
- {
528
- .procname = "sched_performance_bias",
529
- .data = &sysctl_sched_performance_bias,
530
- .maxlen = sizeof(unsigned int),
531
- .mode = 0644,
532
- .proc_handler = proc_dointvec,
1951
+ .extra1 = SYSCTL_ONE,
5331952 },
5341953 #endif
5351954 #if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL)
....@@ -539,8 +1958,8 @@
5391958 .maxlen = sizeof(unsigned int),
5401959 .mode = 0644,
5411960 .proc_handler = sched_energy_aware_handler,
542
- .extra1 = &zero,
543
- .extra2 = &one,
1961
+ .extra1 = SYSCTL_ZERO,
1962
+ .extra2 = SYSCTL_ONE,
5441963 },
5451964 #endif
5461965 #ifdef CONFIG_PROVE_LOCKING
....@@ -604,8 +2023,8 @@
6042023 .maxlen = sizeof(int),
6052024 .mode = 0644,
6062025 .proc_handler = proc_dointvec_minmax,
607
- .extra1 = &neg_one,
608
- .extra2 = &one,
2026
+ .extra1 = SYSCTL_NEG_ONE,
2027
+ .extra2 = SYSCTL_ONE,
6092028 },
6102029 #endif
6112030 #ifdef CONFIG_LATENCYTOP
....@@ -665,12 +2084,12 @@
6652084 .proc_handler = proc_dointvec,
6662085 },
6672086 #endif
668
-#ifdef __hppa__
2087
+#ifdef CONFIG_PARISC
6692088 {
6702089 .procname = "soft-power",
6712090 .data = &pwrsw_enabled,
6722091 .maxlen = sizeof (int),
673
- .mode = 0644,
2092
+ .mode = 0644,
6742093 .proc_handler = proc_dointvec,
6752094 },
6762095 #endif
....@@ -739,8 +2158,8 @@
7392158 .mode = 0644,
7402159 /* only handle a transition from default "0" to "1" */
7412160 .proc_handler = proc_dointvec_minmax,
742
- .extra1 = &one,
743
- .extra2 = &one,
2161
+ .extra1 = SYSCTL_ONE,
2162
+ .extra2 = SYSCTL_ONE,
7442163 },
7452164 #endif
7462165 #ifdef CONFIG_MODULES
....@@ -758,8 +2177,8 @@
7582177 .mode = 0644,
7592178 /* only handle a transition from default "0" to "1" */
7602179 .proc_handler = proc_dointvec_minmax,
761
- .extra1 = &one,
762
- .extra2 = &one,
2180
+ .extra1 = SYSCTL_ONE,
2181
+ .extra2 = SYSCTL_ONE,
7632182 },
7642183 #endif
7652184 #ifdef CONFIG_UEVENT_HELPER
....@@ -792,7 +2211,7 @@
7922211 #ifdef CONFIG_MAGIC_SYSRQ
7932212 {
7942213 .procname = "sysrq",
795
- .data = &__sysrq_enabled,
2214
+ .data = NULL,
7962215 .maxlen = sizeof (int),
7972216 .mode = 0644,
7982217 .proc_handler = sysrq_sysctl_handler,
....@@ -850,15 +2269,6 @@
8502269 .extra2 = &maxolduid,
8512270 },
8522271 #ifdef CONFIG_S390
853
-#ifdef CONFIG_MATHEMU
854
- {
855
- .procname = "ieee_emulation_warnings",
856
- .data = &sysctl_ieee_emulation_warnings,
857
- .maxlen = sizeof(int),
858
- .mode = 0644,
859
- .proc_handler = proc_dointvec,
860
- },
861
-#endif
8622272 {
8632273 .procname = "userprocess_debug",
8642274 .data = &show_unhandled_signals,
....@@ -882,6 +2292,13 @@
8822292 .maxlen = sizeof(int),
8832293 .mode = 0644,
8842294 .proc_handler = proc_dointvec,
2295
+ },
2296
+ {
2297
+ .procname = "panic_print",
2298
+ .data = &panic_print,
2299
+ .maxlen = sizeof(unsigned long),
2300
+ .mode = 0644,
2301
+ .proc_handler = proc_doulongvec_minmax,
8852302 },
8862303 #if defined CONFIG_PRINTK
8872304 {
....@@ -911,7 +2328,7 @@
9112328 .maxlen = sizeof(int),
9122329 .mode = 0644,
9132330 .proc_handler = proc_dointvec_minmax,
914
- .extra1 = &zero,
2331
+ .extra1 = SYSCTL_ZERO,
9152332 .extra2 = &ten_thousand,
9162333 },
9172334 {
....@@ -927,8 +2344,8 @@
9272344 .maxlen = sizeof(int),
9282345 .mode = 0644,
9292346 .proc_handler = proc_dointvec_minmax_sysadmin,
930
- .extra1 = &zero,
931
- .extra2 = &one,
2347
+ .extra1 = SYSCTL_ZERO,
2348
+ .extra2 = SYSCTL_ONE,
9322349 },
9332350 {
9342351 .procname = "kptr_restrict",
....@@ -936,8 +2353,8 @@
9362353 .maxlen = sizeof(int),
9372354 .mode = 0644,
9382355 .proc_handler = proc_dointvec_minmax_sysadmin,
939
- .extra1 = &zero,
940
- .extra2 = &two,
2356
+ .extra1 = SYSCTL_ZERO,
2357
+ .extra2 = SYSCTL_TWO,
9412358 },
9422359 #endif
9432360 {
....@@ -961,8 +2378,8 @@
9612378 .maxlen = sizeof(int),
9622379 .mode = 0644,
9632380 .proc_handler = proc_watchdog,
964
- .extra1 = &zero,
965
- .extra2 = &one,
2381
+ .extra1 = SYSCTL_ZERO,
2382
+ .extra2 = SYSCTL_ONE,
9662383 },
9672384 {
9682385 .procname = "watchdog_thresh",
....@@ -970,7 +2387,7 @@
9702387 .maxlen = sizeof(int),
9712388 .mode = 0644,
9722389 .proc_handler = proc_watchdog_thresh,
973
- .extra1 = &zero,
2390
+ .extra1 = SYSCTL_ZERO,
9742391 .extra2 = &sixty,
9752392 },
9762393 {
....@@ -979,8 +2396,8 @@
9792396 .maxlen = sizeof(int),
9802397 .mode = NMI_WATCHDOG_SYSCTL_PERM,
9812398 .proc_handler = proc_nmi_watchdog,
982
- .extra1 = &zero,
983
- .extra2 = &one,
2399
+ .extra1 = SYSCTL_ZERO,
2400
+ .extra2 = SYSCTL_ONE,
9842401 },
9852402 {
9862403 .procname = "watchdog_cpumask",
....@@ -996,8 +2413,8 @@
9962413 .maxlen = sizeof(int),
9972414 .mode = 0644,
9982415 .proc_handler = proc_soft_watchdog,
999
- .extra1 = &zero,
1000
- .extra2 = &one,
2416
+ .extra1 = SYSCTL_ZERO,
2417
+ .extra2 = SYSCTL_ONE,
10012418 },
10022419 {
10032420 .procname = "softlockup_panic",
....@@ -1005,8 +2422,8 @@
10052422 .maxlen = sizeof(int),
10062423 .mode = 0644,
10072424 .proc_handler = proc_dointvec_minmax,
1008
- .extra1 = &zero,
1009
- .extra2 = &one,
2425
+ .extra1 = SYSCTL_ZERO,
2426
+ .extra2 = SYSCTL_ONE,
10102427 },
10112428 #ifdef CONFIG_SMP
10122429 {
....@@ -1015,8 +2432,8 @@
10152432 .maxlen = sizeof(int),
10162433 .mode = 0644,
10172434 .proc_handler = proc_dointvec_minmax,
1018
- .extra1 = &zero,
1019
- .extra2 = &one,
2435
+ .extra1 = SYSCTL_ZERO,
2436
+ .extra2 = SYSCTL_ONE,
10202437 },
10212438 #endif /* CONFIG_SMP */
10222439 #endif
....@@ -1027,8 +2444,8 @@
10272444 .maxlen = sizeof(int),
10282445 .mode = 0644,
10292446 .proc_handler = proc_dointvec_minmax,
1030
- .extra1 = &zero,
1031
- .extra2 = &one,
2447
+ .extra1 = SYSCTL_ZERO,
2448
+ .extra2 = SYSCTL_ONE,
10322449 },
10332450 #ifdef CONFIG_SMP
10342451 {
....@@ -1037,8 +2454,8 @@
10372454 .maxlen = sizeof(int),
10382455 .mode = 0644,
10392456 .proc_handler = proc_dointvec_minmax,
1040
- .extra1 = &zero,
1041
- .extra2 = &one,
2457
+ .extra1 = SYSCTL_ZERO,
2458
+ .extra2 = SYSCTL_ONE,
10422459 },
10432460 #endif /* CONFIG_SMP */
10442461 #endif
....@@ -1051,6 +2468,17 @@
10512468 .maxlen = sizeof (int),
10522469 .mode = 0644,
10532470 .proc_handler = proc_dointvec,
2471
+ },
2472
+#endif
2473
+
2474
+#if (defined(CONFIG_X86_32) || defined(CONFIG_PARISC)) && \
2475
+ defined(CONFIG_DEBUG_STACKOVERFLOW)
2476
+ {
2477
+ .procname = "panic_on_stackoverflow",
2478
+ .data = &sysctl_panic_on_stackoverflow,
2479
+ .maxlen = sizeof(int),
2480
+ .mode = 0644,
2481
+ .proc_handler = proc_dointvec,
10542482 },
10552483 #endif
10562484 #if defined(CONFIG_X86)
....@@ -1068,15 +2496,6 @@
10682496 .mode = 0644,
10692497 .proc_handler = proc_dointvec,
10702498 },
1071
-#ifdef CONFIG_DEBUG_STACKOVERFLOW
1072
- {
1073
- .procname = "panic_on_stackoverflow",
1074
- .data = &sysctl_panic_on_stackoverflow,
1075
- .maxlen = sizeof(int),
1076
- .mode = 0644,
1077
- .proc_handler = proc_dointvec,
1078
- },
1079
-#endif
10802499 {
10812500 .procname = "bootloader_type",
10822501 .data = &bootloader_type,
....@@ -1131,7 +2550,7 @@
11312550 .procname = "ignore-unaligned-usertrap",
11322551 .data = &no_unaligned_warning,
11332552 .maxlen = sizeof (int),
1134
- .mode = 0644,
2553
+ .mode = 0644,
11352554 .proc_handler = proc_dointvec,
11362555 },
11372556 #endif
....@@ -1145,14 +2564,25 @@
11452564 },
11462565 #endif
11472566 #ifdef CONFIG_DETECT_HUNG_TASK
2567
+#ifdef CONFIG_SMP
2568
+ {
2569
+ .procname = "hung_task_all_cpu_backtrace",
2570
+ .data = &sysctl_hung_task_all_cpu_backtrace,
2571
+ .maxlen = sizeof(int),
2572
+ .mode = 0644,
2573
+ .proc_handler = proc_dointvec_minmax,
2574
+ .extra1 = SYSCTL_ZERO,
2575
+ .extra2 = SYSCTL_ONE,
2576
+ },
2577
+#endif /* CONFIG_SMP */
11482578 {
11492579 .procname = "hung_task_panic",
11502580 .data = &sysctl_hung_task_panic,
11512581 .maxlen = sizeof(int),
11522582 .mode = 0644,
11532583 .proc_handler = proc_dointvec_minmax,
1154
- .extra1 = &zero,
1155
- .extra2 = &one,
2584
+ .extra1 = SYSCTL_ZERO,
2585
+ .extra2 = SYSCTL_ONE,
11562586 },
11572587 {
11582588 .procname = "hung_task_check_count",
....@@ -1160,7 +2590,7 @@
11602590 .maxlen = sizeof(int),
11612591 .mode = 0644,
11622592 .proc_handler = proc_dointvec_minmax,
1163
- .extra1 = &zero,
2593
+ .extra1 = SYSCTL_ZERO,
11642594 },
11652595 {
11662596 .procname = "hung_task_timeout_secs",
....@@ -1184,7 +2614,7 @@
11842614 .maxlen = sizeof(int),
11852615 .mode = 0644,
11862616 .proc_handler = proc_dointvec_minmax,
1187
- .extra1 = &neg_one,
2617
+ .extra1 = SYSCTL_NEG_ONE,
11882618 },
11892619 #endif
11902620 #ifdef CONFIG_RT_MUTEXES
....@@ -1237,7 +2667,7 @@
12372667 .maxlen = sizeof(sysctl_perf_event_sample_rate),
12382668 .mode = 0644,
12392669 .proc_handler = perf_proc_update_handler,
1240
- .extra1 = &one,
2670
+ .extra1 = SYSCTL_ONE,
12412671 },
12422672 {
12432673 .procname = "perf_cpu_time_max_percent",
....@@ -1245,8 +2675,8 @@
12452675 .maxlen = sizeof(sysctl_perf_cpu_time_max_percent),
12462676 .mode = 0644,
12472677 .proc_handler = perf_cpu_time_max_percent_handler,
1248
- .extra1 = &zero,
1249
- .extra2 = &one_hundred,
2678
+ .extra1 = SYSCTL_ZERO,
2679
+ .extra2 = SYSCTL_ONE_HUNDRED,
12502680 },
12512681 {
12522682 .procname = "perf_event_max_stack",
....@@ -1254,7 +2684,7 @@
12542684 .maxlen = sizeof(sysctl_perf_event_max_stack),
12552685 .mode = 0644,
12562686 .proc_handler = perf_event_max_stack_handler,
1257
- .extra1 = &zero,
2687
+ .extra1 = SYSCTL_ZERO,
12582688 .extra2 = &six_hundred_forty_kb,
12592689 },
12602690 {
....@@ -1263,8 +2693,8 @@
12632693 .maxlen = sizeof(sysctl_perf_event_max_contexts_per_stack),
12642694 .mode = 0644,
12652695 .proc_handler = perf_event_max_stack_handler,
1266
- .extra1 = &zero,
1267
- .extra2 = &one_thousand,
2696
+ .extra1 = SYSCTL_ZERO,
2697
+ .extra2 = SYSCTL_ONE_THOUSAND,
12682698 },
12692699 #endif
12702700 {
....@@ -1273,8 +2703,8 @@
12732703 .maxlen = sizeof(int),
12742704 .mode = 0644,
12752705 .proc_handler = proc_dointvec_minmax,
1276
- .extra1 = &zero,
1277
- .extra2 = &one,
2706
+ .extra1 = SYSCTL_ZERO,
2707
+ .extra2 = SYSCTL_ONE,
12782708 },
12792709 #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
12802710 {
....@@ -1283,8 +2713,8 @@
12832713 .maxlen = sizeof(unsigned int),
12842714 .mode = 0644,
12852715 .proc_handler = timer_migration_handler,
1286
- .extra1 = &zero,
1287
- .extra2 = &one,
2716
+ .extra1 = SYSCTL_ZERO,
2717
+ .extra2 = SYSCTL_ONE,
12882718 },
12892719 #endif
12902720 #ifdef CONFIG_BPF_SYSCALL
....@@ -1294,19 +2724,37 @@
12942724 .maxlen = sizeof(sysctl_unprivileged_bpf_disabled),
12952725 .mode = 0644,
12962726 .proc_handler = bpf_unpriv_handler,
1297
- .extra1 = &zero,
1298
- .extra2 = &two,
2727
+ .extra1 = SYSCTL_ZERO,
2728
+ .extra2 = SYSCTL_TWO,
2729
+ },
2730
+ {
2731
+ .procname = "bpf_stats_enabled",
2732
+ .data = &bpf_stats_enabled_key.key,
2733
+ .maxlen = sizeof(bpf_stats_enabled_key),
2734
+ .mode = 0644,
2735
+ .proc_handler = bpf_stats_handler,
12992736 },
13002737 #endif
1301
-#if defined(CONFIG_TREE_RCU) || defined(CONFIG_PREEMPT_RCU)
2738
+#if defined(CONFIG_TREE_RCU)
13022739 {
13032740 .procname = "panic_on_rcu_stall",
13042741 .data = &sysctl_panic_on_rcu_stall,
13052742 .maxlen = sizeof(sysctl_panic_on_rcu_stall),
13062743 .mode = 0644,
13072744 .proc_handler = proc_dointvec_minmax,
1308
- .extra1 = &zero,
1309
- .extra2 = &one,
2745
+ .extra1 = SYSCTL_ZERO,
2746
+ .extra2 = SYSCTL_ONE,
2747
+ },
2748
+#endif
2749
+#ifdef CONFIG_STACKLEAK_RUNTIME_DISABLE
2750
+ {
2751
+ .procname = "stack_erasing",
2752
+ .data = NULL,
2753
+ .maxlen = sizeof(int),
2754
+ .mode = 0600,
2755
+ .proc_handler = stack_erasing_sysctl,
2756
+ .extra1 = SYSCTL_ZERO,
2757
+ .extra2 = SYSCTL_ONE,
13102758 },
13112759 #endif
13122760 { }
....@@ -1318,9 +2766,9 @@
13182766 .data = &sysctl_overcommit_memory,
13192767 .maxlen = sizeof(sysctl_overcommit_memory),
13202768 .mode = 0644,
1321
- .proc_handler = proc_dointvec_minmax,
1322
- .extra1 = &zero,
1323
- .extra2 = &two,
2769
+ .proc_handler = overcommit_policy_handler,
2770
+ .extra1 = SYSCTL_ZERO,
2771
+ .extra2 = SYSCTL_TWO,
13242772 },
13252773 {
13262774 .procname = "panic_on_oom",
....@@ -1328,8 +2776,8 @@
13282776 .maxlen = sizeof(sysctl_panic_on_oom),
13292777 .mode = 0644,
13302778 .proc_handler = proc_dointvec_minmax,
1331
- .extra1 = &zero,
1332
- .extra2 = &two,
2779
+ .extra1 = SYSCTL_ZERO,
2780
+ .extra2 = SYSCTL_TWO,
13332781 },
13342782 {
13352783 .procname = "oom_kill_allocating_task",
....@@ -1360,12 +2808,12 @@
13602808 .proc_handler = overcommit_kbytes_handler,
13612809 },
13622810 {
1363
- .procname = "page-cluster",
2811
+ .procname = "page-cluster",
13642812 .data = &page_cluster,
13652813 .maxlen = sizeof(int),
13662814 .mode = 0644,
13672815 .proc_handler = proc_dointvec_minmax,
1368
- .extra1 = &zero,
2816
+ .extra1 = SYSCTL_ZERO,
13692817 },
13702818 {
13712819 .procname = "dirty_background_ratio",
....@@ -1373,8 +2821,8 @@
13732821 .maxlen = sizeof(dirty_background_ratio),
13742822 .mode = 0644,
13752823 .proc_handler = dirty_background_ratio_handler,
1376
- .extra1 = &zero,
1377
- .extra2 = &one_hundred,
2824
+ .extra1 = SYSCTL_ZERO,
2825
+ .extra2 = SYSCTL_ONE_HUNDRED,
13782826 },
13792827 {
13802828 .procname = "dirty_background_bytes",
....@@ -1390,8 +2838,8 @@
13902838 .maxlen = sizeof(vm_dirty_ratio),
13912839 .mode = 0644,
13922840 .proc_handler = dirty_ratio_handler,
1393
- .extra1 = &zero,
1394
- .extra2 = &one_hundred,
2841
+ .extra1 = SYSCTL_ZERO,
2842
+ .extra2 = SYSCTL_ONE_HUNDRED,
13952843 },
13962844 {
13972845 .procname = "dirty_bytes",
....@@ -1414,7 +2862,7 @@
14142862 .maxlen = sizeof(dirty_expire_interval),
14152863 .mode = 0644,
14162864 .proc_handler = proc_dointvec_minmax,
1417
- .extra1 = &zero,
2865
+ .extra1 = SYSCTL_ZERO,
14182866 },
14192867 {
14202868 .procname = "dirtytime_expire_seconds",
....@@ -1422,7 +2870,7 @@
14222870 .maxlen = sizeof(dirtytime_expire_interval),
14232871 .mode = 0644,
14242872 .proc_handler = dirtytime_interval_handler,
1425
- .extra1 = &zero,
2873
+ .extra1 = SYSCTL_ZERO,
14262874 },
14272875 {
14282876 .procname = "swappiness",
....@@ -1430,9 +2878,20 @@
14302878 .maxlen = sizeof(vm_swappiness),
14312879 .mode = 0644,
14322880 .proc_handler = proc_dointvec_minmax,
1433
- .extra1 = &zero,
1434
- .extra2 = &one_hundred,
2881
+ .extra1 = SYSCTL_ZERO,
2882
+ .extra2 = SYSCTL_TWO_HUNDRED,
14352883 },
2884
+#ifdef CONFIG_NUMA
2885
+ {
2886
+ .procname = "numa_stat",
2887
+ .data = &sysctl_vm_numa_stat,
2888
+ .maxlen = sizeof(int),
2889
+ .mode = 0644,
2890
+ .proc_handler = sysctl_vm_numa_stat_handler,
2891
+ .extra1 = SYSCTL_ZERO,
2892
+ .extra2 = SYSCTL_ONE,
2893
+ },
2894
+#endif
14362895 #ifdef CONFIG_HUGETLB_PAGE
14372896 {
14382897 .procname = "nr_hugepages",
....@@ -1448,15 +2907,6 @@
14482907 .maxlen = sizeof(unsigned long),
14492908 .mode = 0644,
14502909 .proc_handler = &hugetlb_mempolicy_sysctl_handler,
1451
- },
1452
- {
1453
- .procname = "numa_stat",
1454
- .data = &sysctl_vm_numa_stat,
1455
- .maxlen = sizeof(int),
1456
- .mode = 0644,
1457
- .proc_handler = sysctl_vm_numa_stat_handler,
1458
- .extra1 = &zero,
1459
- .extra2 = &one,
14602910 },
14612911 #endif
14622912 {
....@@ -1487,8 +2937,8 @@
14872937 .maxlen = sizeof(int),
14882938 .mode = 0200,
14892939 .proc_handler = drop_caches_sysctl_handler,
1490
- .extra1 = &one,
1491
- .extra2 = &four,
2940
+ .extra1 = SYSCTL_ONE,
2941
+ .extra2 = SYSCTL_FOUR,
14922942 },
14932943 #ifdef CONFIG_COMPACTION
14942944 {
....@@ -1499,11 +2949,20 @@
14992949 .proc_handler = sysctl_compaction_handler,
15002950 },
15012951 {
2952
+ .procname = "compaction_proactiveness",
2953
+ .data = &sysctl_compaction_proactiveness,
2954
+ .maxlen = sizeof(sysctl_compaction_proactiveness),
2955
+ .mode = 0644,
2956
+ .proc_handler = compaction_proactiveness_sysctl_handler,
2957
+ .extra1 = SYSCTL_ZERO,
2958
+ .extra2 = SYSCTL_ONE_HUNDRED,
2959
+ },
2960
+ {
15022961 .procname = "extfrag_threshold",
15032962 .data = &sysctl_extfrag_threshold,
15042963 .maxlen = sizeof(int),
15052964 .mode = 0644,
1506
- .proc_handler = sysctl_extfrag_handler,
2965
+ .proc_handler = proc_dointvec_minmax,
15072966 .extra1 = &min_extfrag_threshold,
15082967 .extra2 = &max_extfrag_threshold,
15092968 },
....@@ -1512,9 +2971,9 @@
15122971 .data = &sysctl_compact_unevictable_allowed,
15132972 .maxlen = sizeof(int),
15142973 .mode = 0644,
1515
- .proc_handler = proc_dointvec,
1516
- .extra1 = &zero,
1517
- .extra2 = &one,
2974
+ .proc_handler = proc_dointvec_minmax_warn_RT_change,
2975
+ .extra1 = SYSCTL_ZERO,
2976
+ .extra2 = SYSCTL_ONE,
15182977 },
15192978
15202979 #endif /* CONFIG_COMPACTION */
....@@ -1524,7 +2983,15 @@
15242983 .maxlen = sizeof(min_free_kbytes),
15252984 .mode = 0644,
15262985 .proc_handler = min_free_kbytes_sysctl_handler,
1527
- .extra1 = &zero,
2986
+ .extra1 = SYSCTL_ZERO,
2987
+ },
2988
+ {
2989
+ .procname = "watermark_boost_factor",
2990
+ .data = &watermark_boost_factor,
2991
+ .maxlen = sizeof(watermark_boost_factor),
2992
+ .mode = 0644,
2993
+ .proc_handler = proc_dointvec_minmax,
2994
+ .extra1 = SYSCTL_ZERO,
15282995 },
15292996 {
15302997 .procname = "watermark_scale_factor",
....@@ -1532,8 +2999,8 @@
15322999 .maxlen = sizeof(watermark_scale_factor),
15333000 .mode = 0644,
15343001 .proc_handler = watermark_scale_factor_sysctl_handler,
1535
- .extra1 = &one,
1536
- .extra2 = &one_thousand,
3002
+ .extra1 = SYSCTL_ONE,
3003
+ .extra2 = SYSCTL_THREE_THOUSAND,
15373004 },
15383005 {
15393006 .procname = "extra_free_kbytes",
....@@ -1541,7 +3008,7 @@
15413008 .maxlen = sizeof(extra_free_kbytes),
15423009 .mode = 0644,
15433010 .proc_handler = min_free_kbytes_sysctl_handler,
1544
- .extra1 = &zero,
3011
+ .extra1 = SYSCTL_ZERO,
15453012 },
15463013 {
15473014 .procname = "percpu_pagelist_fraction",
....@@ -1549,7 +3016,15 @@
15493016 .maxlen = sizeof(percpu_pagelist_fraction),
15503017 .mode = 0644,
15513018 .proc_handler = percpu_pagelist_fraction_sysctl_handler,
1552
- .extra1 = &zero,
3019
+ .extra1 = SYSCTL_ZERO,
3020
+ },
3021
+ {
3022
+ .procname = "page_lock_unfairness",
3023
+ .data = &sysctl_page_lock_unfairness,
3024
+ .maxlen = sizeof(sysctl_page_lock_unfairness),
3025
+ .mode = 0644,
3026
+ .proc_handler = proc_dointvec_minmax,
3027
+ .extra1 = SYSCTL_ZERO,
15533028 },
15543029 #ifdef CONFIG_MMU
15553030 {
....@@ -1558,7 +3033,7 @@
15583033 .maxlen = sizeof(sysctl_max_map_count),
15593034 .mode = 0644,
15603035 .proc_handler = proc_dointvec_minmax,
1561
- .extra1 = &zero,
3036
+ .extra1 = SYSCTL_ZERO,
15623037 },
15633038 #else
15643039 {
....@@ -1567,7 +3042,7 @@
15673042 .maxlen = sizeof(sysctl_nr_trim_pages),
15683043 .mode = 0644,
15693044 .proc_handler = proc_dointvec_minmax,
1570
- .extra1 = &zero,
3045
+ .extra1 = SYSCTL_ZERO,
15713046 },
15723047 #endif
15733048 {
....@@ -1582,25 +3057,26 @@
15823057 .data = &block_dump,
15833058 .maxlen = sizeof(block_dump),
15843059 .mode = 0644,
1585
- .proc_handler = proc_dointvec,
1586
- .extra1 = &zero,
3060
+ .proc_handler = proc_dointvec_minmax,
3061
+ .extra1 = SYSCTL_ZERO,
15873062 },
15883063 {
15893064 .procname = "vfs_cache_pressure",
15903065 .data = &sysctl_vfs_cache_pressure,
15913066 .maxlen = sizeof(sysctl_vfs_cache_pressure),
15923067 .mode = 0644,
1593
- .proc_handler = proc_dointvec,
1594
- .extra1 = &zero,
3068
+ .proc_handler = proc_dointvec_minmax,
3069
+ .extra1 = SYSCTL_ZERO,
15953070 },
1596
-#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
3071
+#if defined(HAVE_ARCH_PICK_MMAP_LAYOUT) || \
3072
+ defined(CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT)
15973073 {
15983074 .procname = "legacy_va_layout",
15993075 .data = &sysctl_legacy_va_layout,
16003076 .maxlen = sizeof(sysctl_legacy_va_layout),
16013077 .mode = 0644,
1602
- .proc_handler = proc_dointvec,
1603
- .extra1 = &zero,
3078
+ .proc_handler = proc_dointvec_minmax,
3079
+ .extra1 = SYSCTL_ZERO,
16043080 },
16053081 #endif
16063082 #ifdef CONFIG_NUMA
....@@ -1609,8 +3085,8 @@
16093085 .data = &node_reclaim_mode,
16103086 .maxlen = sizeof(node_reclaim_mode),
16113087 .mode = 0644,
1612
- .proc_handler = proc_dointvec,
1613
- .extra1 = &zero,
3088
+ .proc_handler = proc_dointvec_minmax,
3089
+ .extra1 = SYSCTL_ZERO,
16143090 },
16153091 {
16163092 .procname = "min_unmapped_ratio",
....@@ -1618,8 +3094,8 @@
16183094 .maxlen = sizeof(sysctl_min_unmapped_ratio),
16193095 .mode = 0644,
16203096 .proc_handler = sysctl_min_unmapped_ratio_sysctl_handler,
1621
- .extra1 = &zero,
1622
- .extra2 = &one_hundred,
3097
+ .extra1 = SYSCTL_ZERO,
3098
+ .extra2 = SYSCTL_ONE_HUNDRED,
16233099 },
16243100 {
16253101 .procname = "min_slab_ratio",
....@@ -1627,8 +3103,8 @@
16273103 .maxlen = sizeof(sysctl_min_slab_ratio),
16283104 .mode = 0644,
16293105 .proc_handler = sysctl_min_slab_ratio_sysctl_handler,
1630
- .extra1 = &zero,
1631
- .extra2 = &one_hundred,
3106
+ .extra1 = SYSCTL_ZERO,
3107
+ .extra2 = SYSCTL_ONE_HUNDRED,
16323108 },
16333109 #endif
16343110 #ifdef CONFIG_SMP
....@@ -1678,7 +3154,7 @@
16783154 #endif
16793155 .mode = 0644,
16803156 .proc_handler = proc_dointvec,
1681
- .extra1 = &zero,
3157
+ .extra1 = SYSCTL_ZERO,
16823158 },
16833159 #endif
16843160 #ifdef CONFIG_HIGHMEM
....@@ -1688,8 +3164,8 @@
16883164 .maxlen = sizeof(vm_highmem_is_dirtyable),
16893165 .mode = 0644,
16903166 .proc_handler = proc_dointvec_minmax,
1691
- .extra1 = &zero,
1692
- .extra2 = &one,
3167
+ .extra1 = SYSCTL_ZERO,
3168
+ .extra2 = SYSCTL_ONE,
16933169 },
16943170 #endif
16953171 #ifdef CONFIG_MEMORY_FAILURE
....@@ -1699,8 +3175,8 @@
16993175 .maxlen = sizeof(sysctl_memory_failure_early_kill),
17003176 .mode = 0644,
17013177 .proc_handler = proc_dointvec_minmax,
1702
- .extra1 = &zero,
1703
- .extra2 = &one,
3178
+ .extra1 = SYSCTL_ZERO,
3179
+ .extra2 = SYSCTL_ONE,
17043180 },
17053181 {
17063182 .procname = "memory_failure_recovery",
....@@ -1708,8 +3184,8 @@
17083184 .maxlen = sizeof(sysctl_memory_failure_recovery),
17093185 .mode = 0644,
17103186 .proc_handler = proc_dointvec_minmax,
1711
- .extra1 = &zero,
1712
- .extra2 = &one,
3187
+ .extra1 = SYSCTL_ZERO,
3188
+ .extra2 = SYSCTL_ONE,
17133189 },
17143190 #endif
17153191 {
....@@ -1746,6 +3222,17 @@
17463222 .proc_handler = proc_dointvec_minmax,
17473223 .extra1 = (void *)&mmap_rnd_compat_bits_min,
17483224 .extra2 = (void *)&mmap_rnd_compat_bits_max,
3225
+ },
3226
+#endif
3227
+#ifdef CONFIG_USERFAULTFD
3228
+ {
3229
+ .procname = "unprivileged_userfaultfd",
3230
+ .data = &sysctl_unprivileged_userfaultfd,
3231
+ .maxlen = sizeof(sysctl_unprivileged_userfaultfd),
3232
+ .mode = 0644,
3233
+ .proc_handler = proc_dointvec_minmax,
3234
+ .extra1 = SYSCTL_ZERO,
3235
+ .extra2 = SYSCTL_ONE,
17493236 },
17503237 #endif
17513238 { }
....@@ -1881,8 +3368,8 @@
18813368 .maxlen = sizeof(int),
18823369 .mode = 0600,
18833370 .proc_handler = proc_dointvec_minmax,
1884
- .extra1 = &zero,
1885
- .extra2 = &one,
3371
+ .extra1 = SYSCTL_ZERO,
3372
+ .extra2 = SYSCTL_ONE,
18863373 },
18873374 {
18883375 .procname = "protected_hardlinks",
....@@ -1890,8 +3377,8 @@
18903377 .maxlen = sizeof(int),
18913378 .mode = 0600,
18923379 .proc_handler = proc_dointvec_minmax,
1893
- .extra1 = &zero,
1894
- .extra2 = &one,
3380
+ .extra1 = SYSCTL_ZERO,
3381
+ .extra2 = SYSCTL_ONE,
18953382 },
18963383 {
18973384 .procname = "protected_fifos",
....@@ -1899,8 +3386,8 @@
18993386 .maxlen = sizeof(int),
19003387 .mode = 0600,
19013388 .proc_handler = proc_dointvec_minmax,
1902
- .extra1 = &zero,
1903
- .extra2 = &two,
3389
+ .extra1 = SYSCTL_ZERO,
3390
+ .extra2 = SYSCTL_TWO,
19043391 },
19053392 {
19063393 .procname = "protected_regular",
....@@ -1908,8 +3395,8 @@
19083395 .maxlen = sizeof(int),
19093396 .mode = 0600,
19103397 .proc_handler = proc_dointvec_minmax,
1911
- .extra1 = &zero,
1912
- .extra2 = &two,
3398
+ .extra1 = SYSCTL_ZERO,
3399
+ .extra2 = SYSCTL_TWO,
19133400 },
19143401 {
19153402 .procname = "suid_dumpable",
....@@ -1917,8 +3404,8 @@
19173404 .maxlen = sizeof(int),
19183405 .mode = 0644,
19193406 .proc_handler = proc_dointvec_minmax_coredump,
1920
- .extra1 = &zero,
1921
- .extra2 = &two,
3407
+ .extra1 = SYSCTL_ZERO,
3408
+ .extra2 = SYSCTL_TWO,
19223409 },
19233410 #if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
19243411 {
....@@ -1954,7 +3441,7 @@
19543441 .maxlen = sizeof(unsigned int),
19553442 .mode = 0644,
19563443 .proc_handler = proc_dointvec_minmax,
1957
- .extra1 = &one,
3444
+ .extra1 = SYSCTL_ONE,
19583445 },
19593446 { }
19603447 };
....@@ -1976,14 +3463,43 @@
19763463 .maxlen = sizeof(int),
19773464 .mode = 0644,
19783465 .proc_handler = proc_kprobes_optimization_handler,
1979
- .extra1 = &zero,
1980
- .extra2 = &one,
3466
+ .extra1 = SYSCTL_ZERO,
3467
+ .extra2 = SYSCTL_ONE,
19813468 },
19823469 #endif
19833470 { }
19843471 };
19853472
19863473 static struct ctl_table dev_table[] = {
3474
+ { }
3475
+};
3476
+
3477
+static struct ctl_table sysctl_base_table[] = {
3478
+ {
3479
+ .procname = "kernel",
3480
+ .mode = 0555,
3481
+ .child = kern_table,
3482
+ },
3483
+ {
3484
+ .procname = "vm",
3485
+ .mode = 0555,
3486
+ .child = vm_table,
3487
+ },
3488
+ {
3489
+ .procname = "fs",
3490
+ .mode = 0555,
3491
+ .child = fs_table,
3492
+ },
3493
+ {
3494
+ .procname = "debug",
3495
+ .mode = 0555,
3496
+ .child = debug_table,
3497
+ },
3498
+ {
3499
+ .procname = "dev",
3500
+ .mode = 0555,
3501
+ .child = dev_table,
3502
+ },
19873503 { }
19883504 };
19893505
....@@ -1995,1377 +3511,7 @@
19953511 kmemleak_not_leak(hdr);
19963512 return 0;
19973513 }
1998
-
19993514 #endif /* CONFIG_SYSCTL */
2000
-
2001
-/*
2002
- * /proc/sys support
2003
- */
2004
-
2005
-#ifdef CONFIG_PROC_SYSCTL
2006
-
2007
-static int _proc_do_string(char *data, int maxlen, int write,
2008
- char __user *buffer,
2009
- size_t *lenp, loff_t *ppos)
2010
-{
2011
- size_t len;
2012
- char __user *p;
2013
- char c;
2014
-
2015
- if (!data || !maxlen || !*lenp) {
2016
- *lenp = 0;
2017
- return 0;
2018
- }
2019
-
2020
- if (write) {
2021
- if (sysctl_writes_strict == SYSCTL_WRITES_STRICT) {
2022
- /* Only continue writes not past the end of buffer. */
2023
- len = strlen(data);
2024
- if (len > maxlen - 1)
2025
- len = maxlen - 1;
2026
-
2027
- if (*ppos > len)
2028
- return 0;
2029
- len = *ppos;
2030
- } else {
2031
- /* Start writing from beginning of buffer. */
2032
- len = 0;
2033
- }
2034
-
2035
- *ppos += *lenp;
2036
- p = buffer;
2037
- while ((p - buffer) < *lenp && len < maxlen - 1) {
2038
- if (get_user(c, p++))
2039
- return -EFAULT;
2040
- if (c == 0 || c == '\n')
2041
- break;
2042
- data[len++] = c;
2043
- }
2044
- data[len] = 0;
2045
- } else {
2046
- len = strlen(data);
2047
- if (len > maxlen)
2048
- len = maxlen;
2049
-
2050
- if (*ppos > len) {
2051
- *lenp = 0;
2052
- return 0;
2053
- }
2054
-
2055
- data += *ppos;
2056
- len -= *ppos;
2057
-
2058
- if (len > *lenp)
2059
- len = *lenp;
2060
- if (len)
2061
- if (copy_to_user(buffer, data, len))
2062
- return -EFAULT;
2063
- if (len < *lenp) {
2064
- if (put_user('\n', buffer + len))
2065
- return -EFAULT;
2066
- len++;
2067
- }
2068
- *lenp = len;
2069
- *ppos += len;
2070
- }
2071
- return 0;
2072
-}
2073
-
2074
-static void warn_sysctl_write(struct ctl_table *table)
2075
-{
2076
- pr_warn_once("%s wrote to %s when file position was not 0!\n"
2077
- "This will not be supported in the future. To silence this\n"
2078
- "warning, set kernel.sysctl_writes_strict = -1\n",
2079
- current->comm, table->procname);
2080
-}
2081
-
2082
-/**
2083
- * proc_first_pos_non_zero_ignore - check if first position is allowed
2084
- * @ppos: file position
2085
- * @table: the sysctl table
2086
- *
2087
- * Returns true if the first position is non-zero and the sysctl_writes_strict
2088
- * mode indicates this is not allowed for numeric input types. String proc
2089
- * handlers can ignore the return value.
2090
- */
2091
-static bool proc_first_pos_non_zero_ignore(loff_t *ppos,
2092
- struct ctl_table *table)
2093
-{
2094
- if (!*ppos)
2095
- return false;
2096
-
2097
- switch (sysctl_writes_strict) {
2098
- case SYSCTL_WRITES_STRICT:
2099
- return true;
2100
- case SYSCTL_WRITES_WARN:
2101
- warn_sysctl_write(table);
2102
- return false;
2103
- default:
2104
- return false;
2105
- }
2106
-}
2107
-
2108
-/**
2109
- * proc_dostring - read a string sysctl
2110
- * @table: the sysctl table
2111
- * @write: %TRUE if this is a write to the sysctl file
2112
- * @buffer: the user buffer
2113
- * @lenp: the size of the user buffer
2114
- * @ppos: file position
2115
- *
2116
- * Reads/writes a string from/to the user buffer. If the kernel
2117
- * buffer provided is not large enough to hold the string, the
2118
- * string is truncated. The copied string is %NULL-terminated.
2119
- * If the string is being read by the user process, it is copied
2120
- * and a newline '\n' is added. It is truncated if the buffer is
2121
- * not large enough.
2122
- *
2123
- * Returns 0 on success.
2124
- */
2125
-int proc_dostring(struct ctl_table *table, int write,
2126
- void __user *buffer, size_t *lenp, loff_t *ppos)
2127
-{
2128
- if (write)
2129
- proc_first_pos_non_zero_ignore(ppos, table);
2130
-
2131
- return _proc_do_string((char *)(table->data), table->maxlen, write,
2132
- (char __user *)buffer, lenp, ppos);
2133
-}
2134
-
2135
-static size_t proc_skip_spaces(char **buf)
2136
-{
2137
- size_t ret;
2138
- char *tmp = skip_spaces(*buf);
2139
- ret = tmp - *buf;
2140
- *buf = tmp;
2141
- return ret;
2142
-}
2143
-
2144
-static void proc_skip_char(char **buf, size_t *size, const char v)
2145
-{
2146
- while (*size) {
2147
- if (**buf != v)
2148
- break;
2149
- (*size)--;
2150
- (*buf)++;
2151
- }
2152
-}
2153
-
2154
-/**
2155
- * strtoul_lenient - parse an ASCII formatted integer from a buffer and only
2156
- * fail on overflow
2157
- *
2158
- * @cp: kernel buffer containing the string to parse
2159
- * @endp: pointer to store the trailing characters
2160
- * @base: the base to use
2161
- * @res: where the parsed integer will be stored
2162
- *
2163
- * In case of success 0 is returned and @res will contain the parsed integer,
2164
- * @endp will hold any trailing characters.
2165
- * This function will fail the parse on overflow. If there wasn't an overflow
2166
- * the function will defer the decision what characters count as invalid to the
2167
- * caller.
2168
- */
2169
-static int strtoul_lenient(const char *cp, char **endp, unsigned int base,
2170
- unsigned long *res)
2171
-{
2172
- unsigned long long result;
2173
- unsigned int rv;
2174
-
2175
- cp = _parse_integer_fixup_radix(cp, &base);
2176
- rv = _parse_integer(cp, base, &result);
2177
- if ((rv & KSTRTOX_OVERFLOW) || (result != (unsigned long)result))
2178
- return -ERANGE;
2179
-
2180
- cp += rv;
2181
-
2182
- if (endp)
2183
- *endp = (char *)cp;
2184
-
2185
- *res = (unsigned long)result;
2186
- return 0;
2187
-}
2188
-
2189
-#define TMPBUFLEN 22
2190
-/**
2191
- * proc_get_long - reads an ASCII formatted integer from a user buffer
2192
- *
2193
- * @buf: a kernel buffer
2194
- * @size: size of the kernel buffer
2195
- * @val: this is where the number will be stored
2196
- * @neg: set to %TRUE if number is negative
2197
- * @perm_tr: a vector which contains the allowed trailers
2198
- * @perm_tr_len: size of the perm_tr vector
2199
- * @tr: pointer to store the trailer character
2200
- *
2201
- * In case of success %0 is returned and @buf and @size are updated with
2202
- * the amount of bytes read. If @tr is non-NULL and a trailing
2203
- * character exists (size is non-zero after returning from this
2204
- * function), @tr is updated with the trailing character.
2205
- */
2206
-static int proc_get_long(char **buf, size_t *size,
2207
- unsigned long *val, bool *neg,
2208
- const char *perm_tr, unsigned perm_tr_len, char *tr)
2209
-{
2210
- int len;
2211
- char *p, tmp[TMPBUFLEN];
2212
-
2213
- if (!*size)
2214
- return -EINVAL;
2215
-
2216
- len = *size;
2217
- if (len > TMPBUFLEN - 1)
2218
- len = TMPBUFLEN - 1;
2219
-
2220
- memcpy(tmp, *buf, len);
2221
-
2222
- tmp[len] = 0;
2223
- p = tmp;
2224
- if (*p == '-' && *size > 1) {
2225
- *neg = true;
2226
- p++;
2227
- } else
2228
- *neg = false;
2229
- if (!isdigit(*p))
2230
- return -EINVAL;
2231
-
2232
- if (strtoul_lenient(p, &p, 0, val))
2233
- return -EINVAL;
2234
-
2235
- len = p - tmp;
2236
-
2237
- /* We don't know if the next char is whitespace thus we may accept
2238
- * invalid integers (e.g. 1234...a) or two integers instead of one
2239
- * (e.g. 123...1). So lets not allow such large numbers. */
2240
- if (len == TMPBUFLEN - 1)
2241
- return -EINVAL;
2242
-
2243
- if (len < *size && perm_tr_len && !memchr(perm_tr, *p, perm_tr_len))
2244
- return -EINVAL;
2245
-
2246
- if (tr && (len < *size))
2247
- *tr = *p;
2248
-
2249
- *buf += len;
2250
- *size -= len;
2251
-
2252
- return 0;
2253
-}
2254
-
2255
-/**
2256
- * proc_put_long - converts an integer to a decimal ASCII formatted string
2257
- *
2258
- * @buf: the user buffer
2259
- * @size: the size of the user buffer
2260
- * @val: the integer to be converted
2261
- * @neg: sign of the number, %TRUE for negative
2262
- *
2263
- * In case of success %0 is returned and @buf and @size are updated with
2264
- * the amount of bytes written.
2265
- */
2266
-static int proc_put_long(void __user **buf, size_t *size, unsigned long val,
2267
- bool neg)
2268
-{
2269
- int len;
2270
- char tmp[TMPBUFLEN], *p = tmp;
2271
-
2272
- sprintf(p, "%s%lu", neg ? "-" : "", val);
2273
- len = strlen(tmp);
2274
- if (len > *size)
2275
- len = *size;
2276
- if (copy_to_user(*buf, tmp, len))
2277
- return -EFAULT;
2278
- *size -= len;
2279
- *buf += len;
2280
- return 0;
2281
-}
2282
-#undef TMPBUFLEN
2283
-
2284
-static int proc_put_char(void __user **buf, size_t *size, char c)
2285
-{
2286
- if (*size) {
2287
- char __user **buffer = (char __user **)buf;
2288
- if (put_user(c, *buffer))
2289
- return -EFAULT;
2290
- (*size)--, (*buffer)++;
2291
- *buf = *buffer;
2292
- }
2293
- return 0;
2294
-}
2295
-
2296
-static int do_proc_dointvec_conv(bool *negp, unsigned long *lvalp,
2297
- int *valp,
2298
- int write, void *data)
2299
-{
2300
- if (write) {
2301
- if (*negp) {
2302
- if (*lvalp > (unsigned long) INT_MAX + 1)
2303
- return -EINVAL;
2304
- *valp = -*lvalp;
2305
- } else {
2306
- if (*lvalp > (unsigned long) INT_MAX)
2307
- return -EINVAL;
2308
- *valp = *lvalp;
2309
- }
2310
- } else {
2311
- int val = *valp;
2312
- if (val < 0) {
2313
- *negp = true;
2314
- *lvalp = -(unsigned long)val;
2315
- } else {
2316
- *negp = false;
2317
- *lvalp = (unsigned long)val;
2318
- }
2319
- }
2320
- return 0;
2321
-}
2322
-
2323
-static int do_proc_douintvec_conv(unsigned long *lvalp,
2324
- unsigned int *valp,
2325
- int write, void *data)
2326
-{
2327
- if (write) {
2328
- if (*lvalp > UINT_MAX)
2329
- return -EINVAL;
2330
- *valp = *lvalp;
2331
- } else {
2332
- unsigned int val = *valp;
2333
- *lvalp = (unsigned long)val;
2334
- }
2335
- return 0;
2336
-}
2337
-
2338
-static const char proc_wspace_sep[] = { ' ', '\t', '\n' };
2339
-
2340
-static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
2341
- int write, void __user *buffer,
2342
- size_t *lenp, loff_t *ppos,
2343
- int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
2344
- int write, void *data),
2345
- void *data)
2346
-{
2347
- int *i, vleft, first = 1, err = 0;
2348
- size_t left;
2349
- char *kbuf = NULL, *p;
2350
-
2351
- if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
2352
- *lenp = 0;
2353
- return 0;
2354
- }
2355
-
2356
- i = (int *) tbl_data;
2357
- vleft = table->maxlen / sizeof(*i);
2358
- left = *lenp;
2359
-
2360
- if (!conv)
2361
- conv = do_proc_dointvec_conv;
2362
-
2363
- if (write) {
2364
- if (proc_first_pos_non_zero_ignore(ppos, table))
2365
- goto out;
2366
-
2367
- if (left > PAGE_SIZE - 1)
2368
- left = PAGE_SIZE - 1;
2369
- p = kbuf = memdup_user_nul(buffer, left);
2370
- if (IS_ERR(kbuf))
2371
- return PTR_ERR(kbuf);
2372
- }
2373
-
2374
- for (; left && vleft--; i++, first=0) {
2375
- unsigned long lval;
2376
- bool neg;
2377
-
2378
- if (write) {
2379
- left -= proc_skip_spaces(&p);
2380
-
2381
- if (!left)
2382
- break;
2383
- err = proc_get_long(&p, &left, &lval, &neg,
2384
- proc_wspace_sep,
2385
- sizeof(proc_wspace_sep), NULL);
2386
- if (err)
2387
- break;
2388
- if (conv(&neg, &lval, i, 1, data)) {
2389
- err = -EINVAL;
2390
- break;
2391
- }
2392
- } else {
2393
- if (conv(&neg, &lval, i, 0, data)) {
2394
- err = -EINVAL;
2395
- break;
2396
- }
2397
- if (!first)
2398
- err = proc_put_char(&buffer, &left, '\t');
2399
- if (err)
2400
- break;
2401
- err = proc_put_long(&buffer, &left, lval, neg);
2402
- if (err)
2403
- break;
2404
- }
2405
- }
2406
-
2407
- if (!write && !first && left && !err)
2408
- err = proc_put_char(&buffer, &left, '\n');
2409
- if (write && !err && left)
2410
- left -= proc_skip_spaces(&p);
2411
- if (write) {
2412
- kfree(kbuf);
2413
- if (first)
2414
- return err ? : -EINVAL;
2415
- }
2416
- *lenp -= left;
2417
-out:
2418
- *ppos += *lenp;
2419
- return err;
2420
-}
2421
-
2422
-static int do_proc_dointvec(struct ctl_table *table, int write,
2423
- void __user *buffer, size_t *lenp, loff_t *ppos,
2424
- int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
2425
- int write, void *data),
2426
- void *data)
2427
-{
2428
- return __do_proc_dointvec(table->data, table, write,
2429
- buffer, lenp, ppos, conv, data);
2430
-}
2431
-
2432
-static int do_proc_douintvec_w(unsigned int *tbl_data,
2433
- struct ctl_table *table,
2434
- void __user *buffer,
2435
- size_t *lenp, loff_t *ppos,
2436
- int (*conv)(unsigned long *lvalp,
2437
- unsigned int *valp,
2438
- int write, void *data),
2439
- void *data)
2440
-{
2441
- unsigned long lval;
2442
- int err = 0;
2443
- size_t left;
2444
- bool neg;
2445
- char *kbuf = NULL, *p;
2446
-
2447
- left = *lenp;
2448
-
2449
- if (proc_first_pos_non_zero_ignore(ppos, table))
2450
- goto bail_early;
2451
-
2452
- if (left > PAGE_SIZE - 1)
2453
- left = PAGE_SIZE - 1;
2454
-
2455
- p = kbuf = memdup_user_nul(buffer, left);
2456
- if (IS_ERR(kbuf))
2457
- return -EINVAL;
2458
-
2459
- left -= proc_skip_spaces(&p);
2460
- if (!left) {
2461
- err = -EINVAL;
2462
- goto out_free;
2463
- }
2464
-
2465
- err = proc_get_long(&p, &left, &lval, &neg,
2466
- proc_wspace_sep,
2467
- sizeof(proc_wspace_sep), NULL);
2468
- if (err || neg) {
2469
- err = -EINVAL;
2470
- goto out_free;
2471
- }
2472
-
2473
- if (conv(&lval, tbl_data, 1, data)) {
2474
- err = -EINVAL;
2475
- goto out_free;
2476
- }
2477
-
2478
- if (!err && left)
2479
- left -= proc_skip_spaces(&p);
2480
-
2481
-out_free:
2482
- kfree(kbuf);
2483
- if (err)
2484
- return -EINVAL;
2485
-
2486
- return 0;
2487
-
2488
- /* This is in keeping with old __do_proc_dointvec() */
2489
-bail_early:
2490
- *ppos += *lenp;
2491
- return err;
2492
-}
2493
-
2494
-static int do_proc_douintvec_r(unsigned int *tbl_data, void __user *buffer,
2495
- size_t *lenp, loff_t *ppos,
2496
- int (*conv)(unsigned long *lvalp,
2497
- unsigned int *valp,
2498
- int write, void *data),
2499
- void *data)
2500
-{
2501
- unsigned long lval;
2502
- int err = 0;
2503
- size_t left;
2504
-
2505
- left = *lenp;
2506
-
2507
- if (conv(&lval, tbl_data, 0, data)) {
2508
- err = -EINVAL;
2509
- goto out;
2510
- }
2511
-
2512
- err = proc_put_long(&buffer, &left, lval, false);
2513
- if (err || !left)
2514
- goto out;
2515
-
2516
- err = proc_put_char(&buffer, &left, '\n');
2517
-
2518
-out:
2519
- *lenp -= left;
2520
- *ppos += *lenp;
2521
-
2522
- return err;
2523
-}
2524
-
2525
-static int __do_proc_douintvec(void *tbl_data, struct ctl_table *table,
2526
- int write, void __user *buffer,
2527
- size_t *lenp, loff_t *ppos,
2528
- int (*conv)(unsigned long *lvalp,
2529
- unsigned int *valp,
2530
- int write, void *data),
2531
- void *data)
2532
-{
2533
- unsigned int *i, vleft;
2534
-
2535
- if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
2536
- *lenp = 0;
2537
- return 0;
2538
- }
2539
-
2540
- i = (unsigned int *) tbl_data;
2541
- vleft = table->maxlen / sizeof(*i);
2542
-
2543
- /*
2544
- * Arrays are not supported, keep this simple. *Do not* add
2545
- * support for them.
2546
- */
2547
- if (vleft != 1) {
2548
- *lenp = 0;
2549
- return -EINVAL;
2550
- }
2551
-
2552
- if (!conv)
2553
- conv = do_proc_douintvec_conv;
2554
-
2555
- if (write)
2556
- return do_proc_douintvec_w(i, table, buffer, lenp, ppos,
2557
- conv, data);
2558
- return do_proc_douintvec_r(i, buffer, lenp, ppos, conv, data);
2559
-}
2560
-
2561
-static int do_proc_douintvec(struct ctl_table *table, int write,
2562
- void __user *buffer, size_t *lenp, loff_t *ppos,
2563
- int (*conv)(unsigned long *lvalp,
2564
- unsigned int *valp,
2565
- int write, void *data),
2566
- void *data)
2567
-{
2568
- return __do_proc_douintvec(table->data, table, write,
2569
- buffer, lenp, ppos, conv, data);
2570
-}
2571
-
2572
-/**
2573
- * proc_dointvec - read a vector of integers
2574
- * @table: the sysctl table
2575
- * @write: %TRUE if this is a write to the sysctl file
2576
- * @buffer: the user buffer
2577
- * @lenp: the size of the user buffer
2578
- * @ppos: file position
2579
- *
2580
- * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
2581
- * values from/to the user buffer, treated as an ASCII string.
2582
- *
2583
- * Returns 0 on success.
2584
- */
2585
-int proc_dointvec(struct ctl_table *table, int write,
2586
- void __user *buffer, size_t *lenp, loff_t *ppos)
2587
-{
2588
- return do_proc_dointvec(table, write, buffer, lenp, ppos, NULL, NULL);
2589
-}
2590
-
2591
-/**
2592
- * proc_douintvec - read a vector of unsigned integers
2593
- * @table: the sysctl table
2594
- * @write: %TRUE if this is a write to the sysctl file
2595
- * @buffer: the user buffer
2596
- * @lenp: the size of the user buffer
2597
- * @ppos: file position
2598
- *
2599
- * Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
2600
- * values from/to the user buffer, treated as an ASCII string.
2601
- *
2602
- * Returns 0 on success.
2603
- */
2604
-int proc_douintvec(struct ctl_table *table, int write,
2605
- void __user *buffer, size_t *lenp, loff_t *ppos)
2606
-{
2607
- return do_proc_douintvec(table, write, buffer, lenp, ppos,
2608
- do_proc_douintvec_conv, NULL);
2609
-}
2610
-
2611
-/*
2612
- * Taint values can only be increased
2613
- * This means we can safely use a temporary.
2614
- */
2615
-static int proc_taint(struct ctl_table *table, int write,
2616
- void __user *buffer, size_t *lenp, loff_t *ppos)
2617
-{
2618
- struct ctl_table t;
2619
- unsigned long tmptaint = get_taint();
2620
- int err;
2621
-
2622
- if (write && !capable(CAP_SYS_ADMIN))
2623
- return -EPERM;
2624
-
2625
- t = *table;
2626
- t.data = &tmptaint;
2627
- err = proc_doulongvec_minmax(&t, write, buffer, lenp, ppos);
2628
- if (err < 0)
2629
- return err;
2630
-
2631
- if (write) {
2632
- /*
2633
- * Poor man's atomic or. Not worth adding a primitive
2634
- * to everyone's atomic.h for this
2635
- */
2636
- int i;
2637
- for (i = 0; i < BITS_PER_LONG && tmptaint >> i; i++) {
2638
- if ((tmptaint >> i) & 1)
2639
- add_taint(i, LOCKDEP_STILL_OK);
2640
- }
2641
- }
2642
-
2643
- return err;
2644
-}
2645
-
2646
-#ifdef CONFIG_PRINTK
2647
-static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
2648
- void __user *buffer, size_t *lenp, loff_t *ppos)
2649
-{
2650
- if (write && !capable(CAP_SYS_ADMIN))
2651
- return -EPERM;
2652
-
2653
- return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
2654
-}
2655
-#endif
2656
-
2657
-/**
2658
- * struct do_proc_dointvec_minmax_conv_param - proc_dointvec_minmax() range checking structure
2659
- * @min: pointer to minimum allowable value
2660
- * @max: pointer to maximum allowable value
2661
- *
2662
- * The do_proc_dointvec_minmax_conv_param structure provides the
2663
- * minimum and maximum values for doing range checking for those sysctl
2664
- * parameters that use the proc_dointvec_minmax() handler.
2665
- */
2666
-struct do_proc_dointvec_minmax_conv_param {
2667
- int *min;
2668
- int *max;
2669
-};
2670
-
2671
-static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp,
2672
- int *valp,
2673
- int write, void *data)
2674
-{
2675
- struct do_proc_dointvec_minmax_conv_param *param = data;
2676
- if (write) {
2677
- int val;
2678
- if (*negp) {
2679
- if (*lvalp > (unsigned long) INT_MAX + 1)
2680
- return -EINVAL;
2681
- val = -*lvalp;
2682
- } else {
2683
- if (*lvalp > (unsigned long) INT_MAX)
2684
- return -EINVAL;
2685
- val = *lvalp;
2686
- }
2687
- if ((param->min && *param->min > val) ||
2688
- (param->max && *param->max < val))
2689
- return -EINVAL;
2690
- *valp = val;
2691
- } else {
2692
- int val = *valp;
2693
- if (val < 0) {
2694
- *negp = true;
2695
- *lvalp = -(unsigned long)val;
2696
- } else {
2697
- *negp = false;
2698
- *lvalp = (unsigned long)val;
2699
- }
2700
- }
2701
- return 0;
2702
-}
2703
-
2704
-/**
2705
- * proc_dointvec_minmax - read a vector of integers with min/max values
2706
- * @table: the sysctl table
2707
- * @write: %TRUE if this is a write to the sysctl file
2708
- * @buffer: the user buffer
2709
- * @lenp: the size of the user buffer
2710
- * @ppos: file position
2711
- *
2712
- * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
2713
- * values from/to the user buffer, treated as an ASCII string.
2714
- *
2715
- * This routine will ensure the values are within the range specified by
2716
- * table->extra1 (min) and table->extra2 (max).
2717
- *
2718
- * Returns 0 on success or -EINVAL on write when the range check fails.
2719
- */
2720
-int proc_dointvec_minmax(struct ctl_table *table, int write,
2721
- void __user *buffer, size_t *lenp, loff_t *ppos)
2722
-{
2723
- struct do_proc_dointvec_minmax_conv_param param = {
2724
- .min = (int *) table->extra1,
2725
- .max = (int *) table->extra2,
2726
- };
2727
- return do_proc_dointvec(table, write, buffer, lenp, ppos,
2728
- do_proc_dointvec_minmax_conv, &param);
2729
-}
2730
-
2731
-/**
2732
- * struct do_proc_douintvec_minmax_conv_param - proc_douintvec_minmax() range checking structure
2733
- * @min: pointer to minimum allowable value
2734
- * @max: pointer to maximum allowable value
2735
- *
2736
- * The do_proc_douintvec_minmax_conv_param structure provides the
2737
- * minimum and maximum values for doing range checking for those sysctl
2738
- * parameters that use the proc_douintvec_minmax() handler.
2739
- */
2740
-struct do_proc_douintvec_minmax_conv_param {
2741
- unsigned int *min;
2742
- unsigned int *max;
2743
-};
2744
-
2745
-static int do_proc_douintvec_minmax_conv(unsigned long *lvalp,
2746
- unsigned int *valp,
2747
- int write, void *data)
2748
-{
2749
- struct do_proc_douintvec_minmax_conv_param *param = data;
2750
-
2751
- if (write) {
2752
- unsigned int val = *lvalp;
2753
-
2754
- if (*lvalp > UINT_MAX)
2755
- return -EINVAL;
2756
-
2757
- if ((param->min && *param->min > val) ||
2758
- (param->max && *param->max < val))
2759
- return -ERANGE;
2760
-
2761
- *valp = val;
2762
- } else {
2763
- unsigned int val = *valp;
2764
- *lvalp = (unsigned long) val;
2765
- }
2766
-
2767
- return 0;
2768
-}
2769
-
2770
-/**
2771
- * proc_douintvec_minmax - read a vector of unsigned ints with min/max values
2772
- * @table: the sysctl table
2773
- * @write: %TRUE if this is a write to the sysctl file
2774
- * @buffer: the user buffer
2775
- * @lenp: the size of the user buffer
2776
- * @ppos: file position
2777
- *
2778
- * Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
2779
- * values from/to the user buffer, treated as an ASCII string. Negative
2780
- * strings are not allowed.
2781
- *
2782
- * This routine will ensure the values are within the range specified by
2783
- * table->extra1 (min) and table->extra2 (max). There is a final sanity
2784
- * check for UINT_MAX to avoid having to support wrap around uses from
2785
- * userspace.
2786
- *
2787
- * Returns 0 on success or -ERANGE on write when the range check fails.
2788
- */
2789
-int proc_douintvec_minmax(struct ctl_table *table, int write,
2790
- void __user *buffer, size_t *lenp, loff_t *ppos)
2791
-{
2792
- struct do_proc_douintvec_minmax_conv_param param = {
2793
- .min = (unsigned int *) table->extra1,
2794
- .max = (unsigned int *) table->extra2,
2795
- };
2796
- return do_proc_douintvec(table, write, buffer, lenp, ppos,
2797
- do_proc_douintvec_minmax_conv, &param);
2798
-}
2799
-
2800
-static int do_proc_dopipe_max_size_conv(unsigned long *lvalp,
2801
- unsigned int *valp,
2802
- int write, void *data)
2803
-{
2804
- if (write) {
2805
- unsigned int val;
2806
-
2807
- val = round_pipe_size(*lvalp);
2808
- if (val == 0)
2809
- return -EINVAL;
2810
-
2811
- *valp = val;
2812
- } else {
2813
- unsigned int val = *valp;
2814
- *lvalp = (unsigned long) val;
2815
- }
2816
-
2817
- return 0;
2818
-}
2819
-
2820
-static int proc_dopipe_max_size(struct ctl_table *table, int write,
2821
- void __user *buffer, size_t *lenp, loff_t *ppos)
2822
-{
2823
- return do_proc_douintvec(table, write, buffer, lenp, ppos,
2824
- do_proc_dopipe_max_size_conv, NULL);
2825
-}
2826
-
2827
-static void validate_coredump_safety(void)
2828
-{
2829
-#ifdef CONFIG_COREDUMP
2830
- if (suid_dumpable == SUID_DUMP_ROOT &&
2831
- core_pattern[0] != '/' && core_pattern[0] != '|') {
2832
- printk(KERN_WARNING
2833
-"Unsafe core_pattern used with fs.suid_dumpable=2.\n"
2834
-"Pipe handler or fully qualified core dump path required.\n"
2835
-"Set kernel.core_pattern before fs.suid_dumpable.\n"
2836
- );
2837
- }
2838
-#endif
2839
-}
2840
-
2841
-static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write,
2842
- void __user *buffer, size_t *lenp, loff_t *ppos)
2843
-{
2844
- int error = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
2845
- if (!error)
2846
- validate_coredump_safety();
2847
- return error;
2848
-}
2849
-
2850
-#ifdef CONFIG_COREDUMP
2851
-static int proc_dostring_coredump(struct ctl_table *table, int write,
2852
- void __user *buffer, size_t *lenp, loff_t *ppos)
2853
-{
2854
- int error = proc_dostring(table, write, buffer, lenp, ppos);
2855
- if (!error)
2856
- validate_coredump_safety();
2857
- return error;
2858
-}
2859
-#endif
2860
-
2861
-static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int write,
2862
- void __user *buffer,
2863
- size_t *lenp, loff_t *ppos,
2864
- unsigned long convmul,
2865
- unsigned long convdiv)
2866
-{
2867
- unsigned long *i, *min, *max;
2868
- int vleft, first = 1, err = 0;
2869
- size_t left;
2870
- char *kbuf = NULL, *p;
2871
-
2872
- if (!data || !table->maxlen || !*lenp || (*ppos && !write)) {
2873
- *lenp = 0;
2874
- return 0;
2875
- }
2876
-
2877
- i = (unsigned long *) data;
2878
- min = (unsigned long *) table->extra1;
2879
- max = (unsigned long *) table->extra2;
2880
- vleft = table->maxlen / sizeof(unsigned long);
2881
- left = *lenp;
2882
-
2883
- if (write) {
2884
- if (proc_first_pos_non_zero_ignore(ppos, table))
2885
- goto out;
2886
-
2887
- if (left > PAGE_SIZE - 1)
2888
- left = PAGE_SIZE - 1;
2889
- p = kbuf = memdup_user_nul(buffer, left);
2890
- if (IS_ERR(kbuf))
2891
- return PTR_ERR(kbuf);
2892
- }
2893
-
2894
- for (; left && vleft--; i++, first = 0) {
2895
- unsigned long val;
2896
-
2897
- if (write) {
2898
- bool neg;
2899
-
2900
- left -= proc_skip_spaces(&p);
2901
- if (!left)
2902
- break;
2903
-
2904
- err = proc_get_long(&p, &left, &val, &neg,
2905
- proc_wspace_sep,
2906
- sizeof(proc_wspace_sep), NULL);
2907
- if (err)
2908
- break;
2909
- if (neg)
2910
- continue;
2911
- val = convmul * val / convdiv;
2912
- if ((min && val < *min) || (max && val > *max)) {
2913
- err = -EINVAL;
2914
- break;
2915
- }
2916
- *i = val;
2917
- } else {
2918
- val = convdiv * (*i) / convmul;
2919
- if (!first) {
2920
- err = proc_put_char(&buffer, &left, '\t');
2921
- if (err)
2922
- break;
2923
- }
2924
- err = proc_put_long(&buffer, &left, val, false);
2925
- if (err)
2926
- break;
2927
- }
2928
- }
2929
-
2930
- if (!write && !first && left && !err)
2931
- err = proc_put_char(&buffer, &left, '\n');
2932
- if (write && !err)
2933
- left -= proc_skip_spaces(&p);
2934
- if (write) {
2935
- kfree(kbuf);
2936
- if (first)
2937
- return err ? : -EINVAL;
2938
- }
2939
- *lenp -= left;
2940
-out:
2941
- *ppos += *lenp;
2942
- return err;
2943
-}
2944
-
2945
-static int do_proc_doulongvec_minmax(struct ctl_table *table, int write,
2946
- void __user *buffer,
2947
- size_t *lenp, loff_t *ppos,
2948
- unsigned long convmul,
2949
- unsigned long convdiv)
2950
-{
2951
- return __do_proc_doulongvec_minmax(table->data, table, write,
2952
- buffer, lenp, ppos, convmul, convdiv);
2953
-}
2954
-
2955
-/**
2956
- * proc_doulongvec_minmax - read a vector of long integers with min/max values
2957
- * @table: the sysctl table
2958
- * @write: %TRUE if this is a write to the sysctl file
2959
- * @buffer: the user buffer
2960
- * @lenp: the size of the user buffer
2961
- * @ppos: file position
2962
- *
2963
- * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
2964
- * values from/to the user buffer, treated as an ASCII string.
2965
- *
2966
- * This routine will ensure the values are within the range specified by
2967
- * table->extra1 (min) and table->extra2 (max).
2968
- *
2969
- * Returns 0 on success.
2970
- */
2971
-int proc_doulongvec_minmax(struct ctl_table *table, int write,
2972
- void __user *buffer, size_t *lenp, loff_t *ppos)
2973
-{
2974
- return do_proc_doulongvec_minmax(table, write, buffer, lenp, ppos, 1l, 1l);
2975
-}
2976
-
2977
-/**
2978
- * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values
2979
- * @table: the sysctl table
2980
- * @write: %TRUE if this is a write to the sysctl file
2981
- * @buffer: the user buffer
2982
- * @lenp: the size of the user buffer
2983
- * @ppos: file position
2984
- *
2985
- * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
2986
- * values from/to the user buffer, treated as an ASCII string. The values
2987
- * are treated as milliseconds, and converted to jiffies when they are stored.
2988
- *
2989
- * This routine will ensure the values are within the range specified by
2990
- * table->extra1 (min) and table->extra2 (max).
2991
- *
2992
- * Returns 0 on success.
2993
- */
2994
-int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
2995
- void __user *buffer,
2996
- size_t *lenp, loff_t *ppos)
2997
-{
2998
- return do_proc_doulongvec_minmax(table, write, buffer,
2999
- lenp, ppos, HZ, 1000l);
3000
-}
3001
-
3002
-
3003
-static int do_proc_dointvec_jiffies_conv(bool *negp, unsigned long *lvalp,
3004
- int *valp,
3005
- int write, void *data)
3006
-{
3007
- if (write) {
3008
- if (*lvalp > INT_MAX / HZ)
3009
- return 1;
3010
- *valp = *negp ? -(*lvalp*HZ) : (*lvalp*HZ);
3011
- } else {
3012
- int val = *valp;
3013
- unsigned long lval;
3014
- if (val < 0) {
3015
- *negp = true;
3016
- lval = -(unsigned long)val;
3017
- } else {
3018
- *negp = false;
3019
- lval = (unsigned long)val;
3020
- }
3021
- *lvalp = lval / HZ;
3022
- }
3023
- return 0;
3024
-}
3025
-
3026
-static int do_proc_dointvec_userhz_jiffies_conv(bool *negp, unsigned long *lvalp,
3027
- int *valp,
3028
- int write, void *data)
3029
-{
3030
- if (write) {
3031
- if (USER_HZ < HZ && *lvalp > (LONG_MAX / HZ) * USER_HZ)
3032
- return 1;
3033
- *valp = clock_t_to_jiffies(*negp ? -*lvalp : *lvalp);
3034
- } else {
3035
- int val = *valp;
3036
- unsigned long lval;
3037
- if (val < 0) {
3038
- *negp = true;
3039
- lval = -(unsigned long)val;
3040
- } else {
3041
- *negp = false;
3042
- lval = (unsigned long)val;
3043
- }
3044
- *lvalp = jiffies_to_clock_t(lval);
3045
- }
3046
- return 0;
3047
-}
3048
-
3049
-static int do_proc_dointvec_ms_jiffies_conv(bool *negp, unsigned long *lvalp,
3050
- int *valp,
3051
- int write, void *data)
3052
-{
3053
- if (write) {
3054
- unsigned long jif = msecs_to_jiffies(*negp ? -*lvalp : *lvalp);
3055
-
3056
- if (jif > INT_MAX)
3057
- return 1;
3058
- *valp = (int)jif;
3059
- } else {
3060
- int val = *valp;
3061
- unsigned long lval;
3062
- if (val < 0) {
3063
- *negp = true;
3064
- lval = -(unsigned long)val;
3065
- } else {
3066
- *negp = false;
3067
- lval = (unsigned long)val;
3068
- }
3069
- *lvalp = jiffies_to_msecs(lval);
3070
- }
3071
- return 0;
3072
-}
3073
-
3074
-/**
3075
- * proc_dointvec_jiffies - read a vector of integers as seconds
3076
- * @table: the sysctl table
3077
- * @write: %TRUE if this is a write to the sysctl file
3078
- * @buffer: the user buffer
3079
- * @lenp: the size of the user buffer
3080
- * @ppos: file position
3081
- *
3082
- * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
3083
- * values from/to the user buffer, treated as an ASCII string.
3084
- * The values read are assumed to be in seconds, and are converted into
3085
- * jiffies.
3086
- *
3087
- * Returns 0 on success.
3088
- */
3089
-int proc_dointvec_jiffies(struct ctl_table *table, int write,
3090
- void __user *buffer, size_t *lenp, loff_t *ppos)
3091
-{
3092
- return do_proc_dointvec(table,write,buffer,lenp,ppos,
3093
- do_proc_dointvec_jiffies_conv,NULL);
3094
-}
3095
-
3096
-/**
3097
- * proc_dointvec_userhz_jiffies - read a vector of integers as 1/USER_HZ seconds
3098
- * @table: the sysctl table
3099
- * @write: %TRUE if this is a write to the sysctl file
3100
- * @buffer: the user buffer
3101
- * @lenp: the size of the user buffer
3102
- * @ppos: pointer to the file position
3103
- *
3104
- * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
3105
- * values from/to the user buffer, treated as an ASCII string.
3106
- * The values read are assumed to be in 1/USER_HZ seconds, and
3107
- * are converted into jiffies.
3108
- *
3109
- * Returns 0 on success.
3110
- */
3111
-int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
3112
- void __user *buffer, size_t *lenp, loff_t *ppos)
3113
-{
3114
- return do_proc_dointvec(table,write,buffer,lenp,ppos,
3115
- do_proc_dointvec_userhz_jiffies_conv,NULL);
3116
-}
3117
-
3118
-/**
3119
- * proc_dointvec_ms_jiffies - read a vector of integers as 1 milliseconds
3120
- * @table: the sysctl table
3121
- * @write: %TRUE if this is a write to the sysctl file
3122
- * @buffer: the user buffer
3123
- * @lenp: the size of the user buffer
3124
- * @ppos: file position
3125
- * @ppos: the current position in the file
3126
- *
3127
- * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
3128
- * values from/to the user buffer, treated as an ASCII string.
3129
- * The values read are assumed to be in 1/1000 seconds, and
3130
- * are converted into jiffies.
3131
- *
3132
- * Returns 0 on success.
3133
- */
3134
-int proc_dointvec_ms_jiffies(struct ctl_table *table, int write,
3135
- void __user *buffer, size_t *lenp, loff_t *ppos)
3136
-{
3137
- return do_proc_dointvec(table, write, buffer, lenp, ppos,
3138
- do_proc_dointvec_ms_jiffies_conv, NULL);
3139
-}
3140
-
3141
-static int proc_do_cad_pid(struct ctl_table *table, int write,
3142
- void __user *buffer, size_t *lenp, loff_t *ppos)
3143
-{
3144
- struct pid *new_pid;
3145
- pid_t tmp;
3146
- int r;
3147
-
3148
- tmp = pid_vnr(cad_pid);
3149
-
3150
- r = __do_proc_dointvec(&tmp, table, write, buffer,
3151
- lenp, ppos, NULL, NULL);
3152
- if (r || !write)
3153
- return r;
3154
-
3155
- new_pid = find_get_pid(tmp);
3156
- if (!new_pid)
3157
- return -ESRCH;
3158
-
3159
- put_pid(xchg(&cad_pid, new_pid));
3160
- return 0;
3161
-}
3162
-
3163
-/**
3164
- * proc_do_large_bitmap - read/write from/to a large bitmap
3165
- * @table: the sysctl table
3166
- * @write: %TRUE if this is a write to the sysctl file
3167
- * @buffer: the user buffer
3168
- * @lenp: the size of the user buffer
3169
- * @ppos: file position
3170
- *
3171
- * The bitmap is stored at table->data and the bitmap length (in bits)
3172
- * in table->maxlen.
3173
- *
3174
- * We use a range comma separated format (e.g. 1,3-4,10-10) so that
3175
- * large bitmaps may be represented in a compact manner. Writing into
3176
- * the file will clear the bitmap then update it with the given input.
3177
- *
3178
- * Returns 0 on success.
3179
- */
3180
-int proc_do_large_bitmap(struct ctl_table *table, int write,
3181
- void __user *buffer, size_t *lenp, loff_t *ppos)
3182
-{
3183
- int err = 0;
3184
- bool first = 1;
3185
- size_t left = *lenp;
3186
- unsigned long bitmap_len = table->maxlen;
3187
- unsigned long *bitmap = *(unsigned long **) table->data;
3188
- unsigned long *tmp_bitmap = NULL;
3189
- char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
3190
-
3191
- if (!bitmap || !bitmap_len || !left || (*ppos && !write)) {
3192
- *lenp = 0;
3193
- return 0;
3194
- }
3195
-
3196
- if (write) {
3197
- char *kbuf, *p;
3198
-
3199
- if (left > PAGE_SIZE - 1)
3200
- left = PAGE_SIZE - 1;
3201
-
3202
- p = kbuf = memdup_user_nul(buffer, left);
3203
- if (IS_ERR(kbuf))
3204
- return PTR_ERR(kbuf);
3205
-
3206
- tmp_bitmap = kcalloc(BITS_TO_LONGS(bitmap_len),
3207
- sizeof(unsigned long),
3208
- GFP_KERNEL);
3209
- if (!tmp_bitmap) {
3210
- kfree(kbuf);
3211
- return -ENOMEM;
3212
- }
3213
- proc_skip_char(&p, &left, '\n');
3214
- while (!err && left) {
3215
- unsigned long val_a, val_b;
3216
- bool neg;
3217
-
3218
- err = proc_get_long(&p, &left, &val_a, &neg, tr_a,
3219
- sizeof(tr_a), &c);
3220
- if (err)
3221
- break;
3222
- if (val_a >= bitmap_len || neg) {
3223
- err = -EINVAL;
3224
- break;
3225
- }
3226
-
3227
- val_b = val_a;
3228
- if (left) {
3229
- p++;
3230
- left--;
3231
- }
3232
-
3233
- if (c == '-') {
3234
- err = proc_get_long(&p, &left, &val_b,
3235
- &neg, tr_b, sizeof(tr_b),
3236
- &c);
3237
- if (err)
3238
- break;
3239
- if (val_b >= bitmap_len || neg ||
3240
- val_a > val_b) {
3241
- err = -EINVAL;
3242
- break;
3243
- }
3244
- if (left) {
3245
- p++;
3246
- left--;
3247
- }
3248
- }
3249
-
3250
- bitmap_set(tmp_bitmap, val_a, val_b - val_a + 1);
3251
- first = 0;
3252
- proc_skip_char(&p, &left, '\n');
3253
- }
3254
- kfree(kbuf);
3255
- } else {
3256
- unsigned long bit_a, bit_b = 0;
3257
-
3258
- while (left) {
3259
- bit_a = find_next_bit(bitmap, bitmap_len, bit_b);
3260
- if (bit_a >= bitmap_len)
3261
- break;
3262
- bit_b = find_next_zero_bit(bitmap, bitmap_len,
3263
- bit_a + 1) - 1;
3264
-
3265
- if (!first) {
3266
- err = proc_put_char(&buffer, &left, ',');
3267
- if (err)
3268
- break;
3269
- }
3270
- err = proc_put_long(&buffer, &left, bit_a, false);
3271
- if (err)
3272
- break;
3273
- if (bit_a != bit_b) {
3274
- err = proc_put_char(&buffer, &left, '-');
3275
- if (err)
3276
- break;
3277
- err = proc_put_long(&buffer, &left, bit_b, false);
3278
- if (err)
3279
- break;
3280
- }
3281
-
3282
- first = 0; bit_b++;
3283
- }
3284
- if (!err)
3285
- err = proc_put_char(&buffer, &left, '\n');
3286
- }
3287
-
3288
- if (!err) {
3289
- if (write) {
3290
- if (*ppos)
3291
- bitmap_or(bitmap, bitmap, tmp_bitmap, bitmap_len);
3292
- else
3293
- bitmap_copy(bitmap, tmp_bitmap, bitmap_len);
3294
- }
3295
- *lenp -= left;
3296
- *ppos += *lenp;
3297
- }
3298
-
3299
- kfree(tmp_bitmap);
3300
- return err;
3301
-}
3302
-
3303
-#else /* CONFIG_PROC_SYSCTL */
3304
-
3305
-int proc_dostring(struct ctl_table *table, int write,
3306
- void __user *buffer, size_t *lenp, loff_t *ppos)
3307
-{
3308
- return -ENOSYS;
3309
-}
3310
-
3311
-int proc_dointvec(struct ctl_table *table, int write,
3312
- void __user *buffer, size_t *lenp, loff_t *ppos)
3313
-{
3314
- return -ENOSYS;
3315
-}
3316
-
3317
-int proc_douintvec(struct ctl_table *table, int write,
3318
- void __user *buffer, size_t *lenp, loff_t *ppos)
3319
-{
3320
- return -ENOSYS;
3321
-}
3322
-
3323
-int proc_dointvec_minmax(struct ctl_table *table, int write,
3324
- void __user *buffer, size_t *lenp, loff_t *ppos)
3325
-{
3326
- return -ENOSYS;
3327
-}
3328
-
3329
-int proc_douintvec_minmax(struct ctl_table *table, int write,
3330
- void __user *buffer, size_t *lenp, loff_t *ppos)
3331
-{
3332
- return -ENOSYS;
3333
-}
3334
-
3335
-int proc_dointvec_jiffies(struct ctl_table *table, int write,
3336
- void __user *buffer, size_t *lenp, loff_t *ppos)
3337
-{
3338
- return -ENOSYS;
3339
-}
3340
-
3341
-int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
3342
- void __user *buffer, size_t *lenp, loff_t *ppos)
3343
-{
3344
- return -ENOSYS;
3345
-}
3346
-
3347
-int proc_dointvec_ms_jiffies(struct ctl_table *table, int write,
3348
- void __user *buffer, size_t *lenp, loff_t *ppos)
3349
-{
3350
- return -ENOSYS;
3351
-}
3352
-
3353
-int proc_doulongvec_minmax(struct ctl_table *table, int write,
3354
- void __user *buffer, size_t *lenp, loff_t *ppos)
3355
-{
3356
- return -ENOSYS;
3357
-}
3358
-
3359
-int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
3360
- void __user *buffer,
3361
- size_t *lenp, loff_t *ppos)
3362
-{
3363
- return -ENOSYS;
3364
-}
3365
-
3366
-
3367
-#endif /* CONFIG_PROC_SYSCTL */
3368
-
33693515 /*
33703516 * No sense putting this after each symbol definition, twice,
33713517 * exception granted :-)
....@@ -3380,3 +3526,4 @@
33803526 EXPORT_SYMBOL(proc_dostring);
33813527 EXPORT_SYMBOL(proc_doulongvec_minmax);
33823528 EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
3529
+EXPORT_SYMBOL(proc_do_large_bitmap);