hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
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,21 +107,7 @@
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
....@@ -123,15 +115,13 @@
123115 #endif
124116
125117 static int __maybe_unused neg_one = -1;
126
-
127
-static int zero;
128
-static int __maybe_unused one = 1;
129118 static int __maybe_unused two = 2;
130119 static int __maybe_unused four = 4;
131120 static unsigned long zero_ul;
132121 static unsigned long one_ul = 1;
133122 static unsigned long long_max = LONG_MAX;
134123 static int one_hundred = 100;
124
+static int two_hundred = 200;
135125 static int one_thousand = 1000;
136126 #ifdef CONFIG_PRINTK
137127 static int ten_thousand = 10000;
....@@ -161,24 +151,6 @@
161151 #ifdef CONFIG_INOTIFY_USER
162152 #include <linux/inotify.h>
163153 #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
182154
183155 #ifdef CONFIG_PROC_SYSCTL
184156
....@@ -186,17 +158,17 @@
186158 * enum sysctl_writes_mode - supported sysctl write modes
187159 *
188160 * @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.
161
+ * to be written, and multiple writes on the same sysctl file descriptor
162
+ * will rewrite the sysctl value, regardless of file position. No warning
163
+ * is issued when the initial position is not 0.
192164 * @SYSCTL_WRITES_WARN: same as above but warn when the initial file position is
193
- * not 0.
165
+ * not 0.
194166 * @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.
167
+ * file position 0 and the value must be fully contained in the buffer
168
+ * sent to the write syscall. If dealing with strings respect the file
169
+ * position, but restrict this to the max length of the buffer, anything
170
+ * passed the max length will be ignored. Multiple writes will append
171
+ * to the buffer.
200172 *
201173 * These write modes control how current file position affects the behavior of
202174 * updating sysctl values through the proc interface on each write.
....@@ -208,119 +180,12 @@
208180 };
209181
210182 static enum sysctl_writes_mode sysctl_writes_strict = SYSCTL_WRITES_STRICT;
183
+#endif /* CONFIG_PROC_SYSCTL */
211184
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
185
+#if defined(HAVE_ARCH_PICK_MMAP_LAYOUT) || \
186
+ defined(CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT)
291187 int sysctl_legacy_va_layout;
292188 #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
-};
324189
325190 #ifdef CONFIG_SCHED_DEBUG
326191 static int min_sched_granularity_ns = 100000; /* 100 usecs */
....@@ -338,6 +203,1487 @@
338203 static int max_extfrag_threshold = 1000;
339204 #endif
340205
206
+#endif /* CONFIG_SYSCTL */
207
+
208
+#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_SYSCTL)
209
+static int bpf_stats_handler(struct ctl_table *table, int write,
210
+ void *buffer, size_t *lenp, loff_t *ppos)
211
+{
212
+ struct static_key *key = (struct static_key *)table->data;
213
+ static int saved_val;
214
+ int val, ret;
215
+ struct ctl_table tmp = {
216
+ .data = &val,
217
+ .maxlen = sizeof(val),
218
+ .mode = table->mode,
219
+ .extra1 = SYSCTL_ZERO,
220
+ .extra2 = SYSCTL_ONE,
221
+ };
222
+
223
+ if (write && !capable(CAP_SYS_ADMIN))
224
+ return -EPERM;
225
+
226
+ mutex_lock(&bpf_stats_enabled_mutex);
227
+ val = saved_val;
228
+ ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
229
+ if (write && !ret && val != saved_val) {
230
+ if (val)
231
+ static_key_slow_inc(key);
232
+ else
233
+ static_key_slow_dec(key);
234
+ saved_val = val;
235
+ }
236
+ mutex_unlock(&bpf_stats_enabled_mutex);
237
+ return ret;
238
+}
239
+
240
+void __weak unpriv_ebpf_notify(int new_state)
241
+{
242
+}
243
+
244
+static int bpf_unpriv_handler(struct ctl_table *table, int write,
245
+ void *buffer, size_t *lenp, loff_t *ppos)
246
+{
247
+ int ret, unpriv_enable = *(int *)table->data;
248
+ bool locked_state = unpriv_enable == 1;
249
+ struct ctl_table tmp = *table;
250
+
251
+ if (write && !capable(CAP_SYS_ADMIN))
252
+ return -EPERM;
253
+
254
+ tmp.data = &unpriv_enable;
255
+ ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
256
+ if (write && !ret) {
257
+ if (locked_state && unpriv_enable != 1)
258
+ return -EPERM;
259
+ *(int *)table->data = unpriv_enable;
260
+ }
261
+
262
+ unpriv_ebpf_notify(unpriv_enable);
263
+
264
+ return ret;
265
+}
266
+#endif /* CONFIG_BPF_SYSCALL && CONFIG_SYSCTL */
267
+
268
+/*
269
+ * /proc/sys support
270
+ */
271
+
272
+#ifdef CONFIG_PROC_SYSCTL
273
+
274
+static int _proc_do_string(char *data, int maxlen, int write,
275
+ char *buffer, size_t *lenp, loff_t *ppos)
276
+{
277
+ size_t len;
278
+ char c, *p;
279
+
280
+ if (!data || !maxlen || !*lenp) {
281
+ *lenp = 0;
282
+ return 0;
283
+ }
284
+
285
+ if (write) {
286
+ if (sysctl_writes_strict == SYSCTL_WRITES_STRICT) {
287
+ /* Only continue writes not past the end of buffer. */
288
+ len = strlen(data);
289
+ if (len > maxlen - 1)
290
+ len = maxlen - 1;
291
+
292
+ if (*ppos > len)
293
+ return 0;
294
+ len = *ppos;
295
+ } else {
296
+ /* Start writing from beginning of buffer. */
297
+ len = 0;
298
+ }
299
+
300
+ *ppos += *lenp;
301
+ p = buffer;
302
+ while ((p - buffer) < *lenp && len < maxlen - 1) {
303
+ c = *(p++);
304
+ if (c == 0 || c == '\n')
305
+ break;
306
+ data[len++] = c;
307
+ }
308
+ data[len] = 0;
309
+ } else {
310
+ len = strlen(data);
311
+ if (len > maxlen)
312
+ len = maxlen;
313
+
314
+ if (*ppos > len) {
315
+ *lenp = 0;
316
+ return 0;
317
+ }
318
+
319
+ data += *ppos;
320
+ len -= *ppos;
321
+
322
+ if (len > *lenp)
323
+ len = *lenp;
324
+ if (len)
325
+ memcpy(buffer, data, len);
326
+ if (len < *lenp) {
327
+ buffer[len] = '\n';
328
+ len++;
329
+ }
330
+ *lenp = len;
331
+ *ppos += len;
332
+ }
333
+ return 0;
334
+}
335
+
336
+static void warn_sysctl_write(struct ctl_table *table)
337
+{
338
+ pr_warn_once("%s wrote to %s when file position was not 0!\n"
339
+ "This will not be supported in the future. To silence this\n"
340
+ "warning, set kernel.sysctl_writes_strict = -1\n",
341
+ current->comm, table->procname);
342
+}
343
+
344
+/**
345
+ * proc_first_pos_non_zero_ignore - check if first position is allowed
346
+ * @ppos: file position
347
+ * @table: the sysctl table
348
+ *
349
+ * Returns true if the first position is non-zero and the sysctl_writes_strict
350
+ * mode indicates this is not allowed for numeric input types. String proc
351
+ * handlers can ignore the return value.
352
+ */
353
+static bool proc_first_pos_non_zero_ignore(loff_t *ppos,
354
+ struct ctl_table *table)
355
+{
356
+ if (!*ppos)
357
+ return false;
358
+
359
+ switch (sysctl_writes_strict) {
360
+ case SYSCTL_WRITES_STRICT:
361
+ return true;
362
+ case SYSCTL_WRITES_WARN:
363
+ warn_sysctl_write(table);
364
+ return false;
365
+ default:
366
+ return false;
367
+ }
368
+}
369
+
370
+/**
371
+ * proc_dostring - read a string sysctl
372
+ * @table: the sysctl table
373
+ * @write: %TRUE if this is a write to the sysctl file
374
+ * @buffer: the user buffer
375
+ * @lenp: the size of the user buffer
376
+ * @ppos: file position
377
+ *
378
+ * Reads/writes a string from/to the user buffer. If the kernel
379
+ * buffer provided is not large enough to hold the string, the
380
+ * string is truncated. The copied string is %NULL-terminated.
381
+ * If the string is being read by the user process, it is copied
382
+ * and a newline '\n' is added. It is truncated if the buffer is
383
+ * not large enough.
384
+ *
385
+ * Returns 0 on success.
386
+ */
387
+int proc_dostring(struct ctl_table *table, int write,
388
+ void *buffer, size_t *lenp, loff_t *ppos)
389
+{
390
+ if (write)
391
+ proc_first_pos_non_zero_ignore(ppos, table);
392
+
393
+ return _proc_do_string(table->data, table->maxlen, write, buffer, lenp,
394
+ ppos);
395
+}
396
+
397
+static void proc_skip_spaces(char **buf, size_t *size)
398
+{
399
+ while (*size) {
400
+ if (!isspace(**buf))
401
+ break;
402
+ (*size)--;
403
+ (*buf)++;
404
+ }
405
+}
406
+
407
+static void proc_skip_char(char **buf, size_t *size, const char v)
408
+{
409
+ while (*size) {
410
+ if (**buf != v)
411
+ break;
412
+ (*size)--;
413
+ (*buf)++;
414
+ }
415
+}
416
+
417
+/**
418
+ * strtoul_lenient - parse an ASCII formatted integer from a buffer and only
419
+ * fail on overflow
420
+ *
421
+ * @cp: kernel buffer containing the string to parse
422
+ * @endp: pointer to store the trailing characters
423
+ * @base: the base to use
424
+ * @res: where the parsed integer will be stored
425
+ *
426
+ * In case of success 0 is returned and @res will contain the parsed integer,
427
+ * @endp will hold any trailing characters.
428
+ * This function will fail the parse on overflow. If there wasn't an overflow
429
+ * the function will defer the decision what characters count as invalid to the
430
+ * caller.
431
+ */
432
+static int strtoul_lenient(const char *cp, char **endp, unsigned int base,
433
+ unsigned long *res)
434
+{
435
+ unsigned long long result;
436
+ unsigned int rv;
437
+
438
+ cp = _parse_integer_fixup_radix(cp, &base);
439
+ rv = _parse_integer(cp, base, &result);
440
+ if ((rv & KSTRTOX_OVERFLOW) || (result != (unsigned long)result))
441
+ return -ERANGE;
442
+
443
+ cp += rv;
444
+
445
+ if (endp)
446
+ *endp = (char *)cp;
447
+
448
+ *res = (unsigned long)result;
449
+ return 0;
450
+}
451
+
452
+#define TMPBUFLEN 22
453
+/**
454
+ * proc_get_long - reads an ASCII formatted integer from a user buffer
455
+ *
456
+ * @buf: a kernel buffer
457
+ * @size: size of the kernel buffer
458
+ * @val: this is where the number will be stored
459
+ * @neg: set to %TRUE if number is negative
460
+ * @perm_tr: a vector which contains the allowed trailers
461
+ * @perm_tr_len: size of the perm_tr vector
462
+ * @tr: pointer to store the trailer character
463
+ *
464
+ * In case of success %0 is returned and @buf and @size are updated with
465
+ * the amount of bytes read. If @tr is non-NULL and a trailing
466
+ * character exists (size is non-zero after returning from this
467
+ * function), @tr is updated with the trailing character.
468
+ */
469
+static int proc_get_long(char **buf, size_t *size,
470
+ unsigned long *val, bool *neg,
471
+ const char *perm_tr, unsigned perm_tr_len, char *tr)
472
+{
473
+ char *p, tmp[TMPBUFLEN];
474
+ ssize_t len = *size;
475
+
476
+ if (len <= 0)
477
+ return -EINVAL;
478
+
479
+ if (len > TMPBUFLEN - 1)
480
+ len = TMPBUFLEN - 1;
481
+
482
+ memcpy(tmp, *buf, len);
483
+
484
+ tmp[len] = 0;
485
+ p = tmp;
486
+ if (*p == '-' && *size > 1) {
487
+ *neg = true;
488
+ p++;
489
+ } else
490
+ *neg = false;
491
+ if (!isdigit(*p))
492
+ return -EINVAL;
493
+
494
+ if (strtoul_lenient(p, &p, 0, val))
495
+ return -EINVAL;
496
+
497
+ len = p - tmp;
498
+
499
+ /* We don't know if the next char is whitespace thus we may accept
500
+ * invalid integers (e.g. 1234...a) or two integers instead of one
501
+ * (e.g. 123...1). So lets not allow such large numbers. */
502
+ if (len == TMPBUFLEN - 1)
503
+ return -EINVAL;
504
+
505
+ if (len < *size && perm_tr_len && !memchr(perm_tr, *p, perm_tr_len))
506
+ return -EINVAL;
507
+
508
+ if (tr && (len < *size))
509
+ *tr = *p;
510
+
511
+ *buf += len;
512
+ *size -= len;
513
+
514
+ return 0;
515
+}
516
+
517
+/**
518
+ * proc_put_long - converts an integer to a decimal ASCII formatted string
519
+ *
520
+ * @buf: the user buffer
521
+ * @size: the size of the user buffer
522
+ * @val: the integer to be converted
523
+ * @neg: sign of the number, %TRUE for negative
524
+ *
525
+ * In case of success @buf and @size are updated with the amount of bytes
526
+ * written.
527
+ */
528
+static void proc_put_long(void **buf, size_t *size, unsigned long val, bool neg)
529
+{
530
+ int len;
531
+ char tmp[TMPBUFLEN], *p = tmp;
532
+
533
+ sprintf(p, "%s%lu", neg ? "-" : "", val);
534
+ len = strlen(tmp);
535
+ if (len > *size)
536
+ len = *size;
537
+ memcpy(*buf, tmp, len);
538
+ *size -= len;
539
+ *buf += len;
540
+}
541
+#undef TMPBUFLEN
542
+
543
+static void proc_put_char(void **buf, size_t *size, char c)
544
+{
545
+ if (*size) {
546
+ char **buffer = (char **)buf;
547
+ **buffer = c;
548
+
549
+ (*size)--;
550
+ (*buffer)++;
551
+ *buf = *buffer;
552
+ }
553
+}
554
+
555
+static int do_proc_dointvec_conv(bool *negp, unsigned long *lvalp,
556
+ int *valp,
557
+ int write, void *data)
558
+{
559
+ if (write) {
560
+ if (*negp) {
561
+ if (*lvalp > (unsigned long) INT_MAX + 1)
562
+ return -EINVAL;
563
+ WRITE_ONCE(*valp, -*lvalp);
564
+ } else {
565
+ if (*lvalp > (unsigned long) INT_MAX)
566
+ return -EINVAL;
567
+ WRITE_ONCE(*valp, *lvalp);
568
+ }
569
+ } else {
570
+ int val = READ_ONCE(*valp);
571
+ if (val < 0) {
572
+ *negp = true;
573
+ *lvalp = -(unsigned long)val;
574
+ } else {
575
+ *negp = false;
576
+ *lvalp = (unsigned long)val;
577
+ }
578
+ }
579
+ return 0;
580
+}
581
+
582
+static int do_proc_douintvec_conv(unsigned long *lvalp,
583
+ unsigned int *valp,
584
+ int write, void *data)
585
+{
586
+ if (write) {
587
+ if (*lvalp > UINT_MAX)
588
+ return -EINVAL;
589
+ WRITE_ONCE(*valp, *lvalp);
590
+ } else {
591
+ unsigned int val = READ_ONCE(*valp);
592
+ *lvalp = (unsigned long)val;
593
+ }
594
+ return 0;
595
+}
596
+
597
+static const char proc_wspace_sep[] = { ' ', '\t', '\n' };
598
+
599
+static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
600
+ int write, void *buffer,
601
+ size_t *lenp, loff_t *ppos,
602
+ int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
603
+ int write, void *data),
604
+ void *data)
605
+{
606
+ int *i, vleft, first = 1, err = 0;
607
+ size_t left;
608
+ char *p;
609
+
610
+ if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
611
+ *lenp = 0;
612
+ return 0;
613
+ }
614
+
615
+ i = (int *) tbl_data;
616
+ vleft = table->maxlen / sizeof(*i);
617
+ left = *lenp;
618
+
619
+ if (!conv)
620
+ conv = do_proc_dointvec_conv;
621
+
622
+ if (write) {
623
+ if (proc_first_pos_non_zero_ignore(ppos, table))
624
+ goto out;
625
+
626
+ if (left > PAGE_SIZE - 1)
627
+ left = PAGE_SIZE - 1;
628
+ p = buffer;
629
+ }
630
+
631
+ for (; left && vleft--; i++, first=0) {
632
+ unsigned long lval;
633
+ bool neg;
634
+
635
+ if (write) {
636
+ proc_skip_spaces(&p, &left);
637
+
638
+ if (!left)
639
+ break;
640
+ err = proc_get_long(&p, &left, &lval, &neg,
641
+ proc_wspace_sep,
642
+ sizeof(proc_wspace_sep), NULL);
643
+ if (err)
644
+ break;
645
+ if (conv(&neg, &lval, i, 1, data)) {
646
+ err = -EINVAL;
647
+ break;
648
+ }
649
+ } else {
650
+ if (conv(&neg, &lval, i, 0, data)) {
651
+ err = -EINVAL;
652
+ break;
653
+ }
654
+ if (!first)
655
+ proc_put_char(&buffer, &left, '\t');
656
+ proc_put_long(&buffer, &left, lval, neg);
657
+ }
658
+ }
659
+
660
+ if (!write && !first && left && !err)
661
+ proc_put_char(&buffer, &left, '\n');
662
+ if (write && !err && left)
663
+ proc_skip_spaces(&p, &left);
664
+ if (write && first)
665
+ return err ? : -EINVAL;
666
+ *lenp -= left;
667
+out:
668
+ *ppos += *lenp;
669
+ return err;
670
+}
671
+
672
+static int do_proc_dointvec(struct ctl_table *table, int write,
673
+ void *buffer, size_t *lenp, loff_t *ppos,
674
+ int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
675
+ int write, void *data),
676
+ void *data)
677
+{
678
+ return __do_proc_dointvec(table->data, table, write,
679
+ buffer, lenp, ppos, conv, data);
680
+}
681
+
682
+static int do_proc_douintvec_w(unsigned int *tbl_data,
683
+ struct ctl_table *table,
684
+ void *buffer,
685
+ size_t *lenp, loff_t *ppos,
686
+ int (*conv)(unsigned long *lvalp,
687
+ unsigned int *valp,
688
+ int write, void *data),
689
+ void *data)
690
+{
691
+ unsigned long lval;
692
+ int err = 0;
693
+ size_t left;
694
+ bool neg;
695
+ char *p = buffer;
696
+
697
+ left = *lenp;
698
+
699
+ if (proc_first_pos_non_zero_ignore(ppos, table))
700
+ goto bail_early;
701
+
702
+ if (left > PAGE_SIZE - 1)
703
+ left = PAGE_SIZE - 1;
704
+
705
+ proc_skip_spaces(&p, &left);
706
+ if (!left) {
707
+ err = -EINVAL;
708
+ goto out_free;
709
+ }
710
+
711
+ err = proc_get_long(&p, &left, &lval, &neg,
712
+ proc_wspace_sep,
713
+ sizeof(proc_wspace_sep), NULL);
714
+ if (err || neg) {
715
+ err = -EINVAL;
716
+ goto out_free;
717
+ }
718
+
719
+ if (conv(&lval, tbl_data, 1, data)) {
720
+ err = -EINVAL;
721
+ goto out_free;
722
+ }
723
+
724
+ if (!err && left)
725
+ proc_skip_spaces(&p, &left);
726
+
727
+out_free:
728
+ if (err)
729
+ return -EINVAL;
730
+
731
+ return 0;
732
+
733
+ /* This is in keeping with old __do_proc_dointvec() */
734
+bail_early:
735
+ *ppos += *lenp;
736
+ return err;
737
+}
738
+
739
+static int do_proc_douintvec_r(unsigned int *tbl_data, void *buffer,
740
+ size_t *lenp, loff_t *ppos,
741
+ int (*conv)(unsigned long *lvalp,
742
+ unsigned int *valp,
743
+ int write, void *data),
744
+ void *data)
745
+{
746
+ unsigned long lval;
747
+ int err = 0;
748
+ size_t left;
749
+
750
+ left = *lenp;
751
+
752
+ if (conv(&lval, tbl_data, 0, data)) {
753
+ err = -EINVAL;
754
+ goto out;
755
+ }
756
+
757
+ proc_put_long(&buffer, &left, lval, false);
758
+ if (!left)
759
+ goto out;
760
+
761
+ proc_put_char(&buffer, &left, '\n');
762
+
763
+out:
764
+ *lenp -= left;
765
+ *ppos += *lenp;
766
+
767
+ return err;
768
+}
769
+
770
+static int __do_proc_douintvec(void *tbl_data, struct ctl_table *table,
771
+ int write, void *buffer,
772
+ size_t *lenp, loff_t *ppos,
773
+ int (*conv)(unsigned long *lvalp,
774
+ unsigned int *valp,
775
+ int write, void *data),
776
+ void *data)
777
+{
778
+ unsigned int *i, vleft;
779
+
780
+ if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
781
+ *lenp = 0;
782
+ return 0;
783
+ }
784
+
785
+ i = (unsigned int *) tbl_data;
786
+ vleft = table->maxlen / sizeof(*i);
787
+
788
+ /*
789
+ * Arrays are not supported, keep this simple. *Do not* add
790
+ * support for them.
791
+ */
792
+ if (vleft != 1) {
793
+ *lenp = 0;
794
+ return -EINVAL;
795
+ }
796
+
797
+ if (!conv)
798
+ conv = do_proc_douintvec_conv;
799
+
800
+ if (write)
801
+ return do_proc_douintvec_w(i, table, buffer, lenp, ppos,
802
+ conv, data);
803
+ return do_proc_douintvec_r(i, buffer, lenp, ppos, conv, data);
804
+}
805
+
806
+static int do_proc_douintvec(struct ctl_table *table, int write,
807
+ void *buffer, size_t *lenp, loff_t *ppos,
808
+ int (*conv)(unsigned long *lvalp,
809
+ unsigned int *valp,
810
+ int write, void *data),
811
+ void *data)
812
+{
813
+ return __do_proc_douintvec(table->data, table, write,
814
+ buffer, lenp, ppos, conv, data);
815
+}
816
+
817
+/**
818
+ * proc_dointvec - read a vector of integers
819
+ * @table: the sysctl table
820
+ * @write: %TRUE if this is a write to the sysctl file
821
+ * @buffer: the user buffer
822
+ * @lenp: the size of the user buffer
823
+ * @ppos: file position
824
+ *
825
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
826
+ * values from/to the user buffer, treated as an ASCII string.
827
+ *
828
+ * Returns 0 on success.
829
+ */
830
+int proc_dointvec(struct ctl_table *table, int write, void *buffer,
831
+ size_t *lenp, loff_t *ppos)
832
+{
833
+ return do_proc_dointvec(table, write, buffer, lenp, ppos, NULL, NULL);
834
+}
835
+
836
+#ifdef CONFIG_COMPACTION
837
+static int proc_dointvec_minmax_warn_RT_change(struct ctl_table *table,
838
+ int write, void *buffer, size_t *lenp, loff_t *ppos)
839
+{
840
+ int ret, old;
841
+
842
+ if (!IS_ENABLED(CONFIG_PREEMPT_RT) || !write)
843
+ return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
844
+
845
+ old = *(int *)table->data;
846
+ ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
847
+ if (ret)
848
+ return ret;
849
+ if (old != *(int *)table->data)
850
+ pr_warn_once("sysctl attribute %s changed by %s[%d]\n",
851
+ table->procname, current->comm,
852
+ task_pid_nr(current));
853
+ return ret;
854
+}
855
+#endif
856
+
857
+/**
858
+ * proc_douintvec - read a vector of unsigned integers
859
+ * @table: the sysctl table
860
+ * @write: %TRUE if this is a write to the sysctl file
861
+ * @buffer: the user buffer
862
+ * @lenp: the size of the user buffer
863
+ * @ppos: file position
864
+ *
865
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
866
+ * values from/to the user buffer, treated as an ASCII string.
867
+ *
868
+ * Returns 0 on success.
869
+ */
870
+int proc_douintvec(struct ctl_table *table, int write, void *buffer,
871
+ size_t *lenp, loff_t *ppos)
872
+{
873
+ return do_proc_douintvec(table, write, buffer, lenp, ppos,
874
+ do_proc_douintvec_conv, NULL);
875
+}
876
+
877
+/*
878
+ * Taint values can only be increased
879
+ * This means we can safely use a temporary.
880
+ */
881
+static int proc_taint(struct ctl_table *table, int write,
882
+ void *buffer, size_t *lenp, loff_t *ppos)
883
+{
884
+ struct ctl_table t;
885
+ unsigned long tmptaint = get_taint();
886
+ int err;
887
+
888
+ if (write && !capable(CAP_SYS_ADMIN))
889
+ return -EPERM;
890
+
891
+ t = *table;
892
+ t.data = &tmptaint;
893
+ err = proc_doulongvec_minmax(&t, write, buffer, lenp, ppos);
894
+ if (err < 0)
895
+ return err;
896
+
897
+ if (write) {
898
+ int i;
899
+
900
+ /*
901
+ * If we are relying on panic_on_taint not producing
902
+ * false positives due to userspace input, bail out
903
+ * before setting the requested taint flags.
904
+ */
905
+ if (panic_on_taint_nousertaint && (tmptaint & panic_on_taint))
906
+ return -EINVAL;
907
+
908
+ /*
909
+ * Poor man's atomic or. Not worth adding a primitive
910
+ * to everyone's atomic.h for this
911
+ */
912
+ for (i = 0; i < TAINT_FLAGS_COUNT; i++)
913
+ if ((1UL << i) & tmptaint)
914
+ add_taint(i, LOCKDEP_STILL_OK);
915
+ }
916
+
917
+ return err;
918
+}
919
+
920
+#ifdef CONFIG_PRINTK
921
+static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
922
+ void *buffer, size_t *lenp, loff_t *ppos)
923
+{
924
+ if (write && !capable(CAP_SYS_ADMIN))
925
+ return -EPERM;
926
+
927
+ return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
928
+}
929
+#endif
930
+
931
+/**
932
+ * struct do_proc_dointvec_minmax_conv_param - proc_dointvec_minmax() range checking structure
933
+ * @min: pointer to minimum allowable value
934
+ * @max: pointer to maximum allowable value
935
+ *
936
+ * The do_proc_dointvec_minmax_conv_param structure provides the
937
+ * minimum and maximum values for doing range checking for those sysctl
938
+ * parameters that use the proc_dointvec_minmax() handler.
939
+ */
940
+struct do_proc_dointvec_minmax_conv_param {
941
+ int *min;
942
+ int *max;
943
+};
944
+
945
+static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp,
946
+ int *valp,
947
+ int write, void *data)
948
+{
949
+ int tmp, ret;
950
+ struct do_proc_dointvec_minmax_conv_param *param = data;
951
+ /*
952
+ * If writing, first do so via a temporary local int so we can
953
+ * bounds-check it before touching *valp.
954
+ */
955
+ int *ip = write ? &tmp : valp;
956
+
957
+ ret = do_proc_dointvec_conv(negp, lvalp, ip, write, data);
958
+ if (ret)
959
+ return ret;
960
+
961
+ if (write) {
962
+ if ((param->min && *param->min > tmp) ||
963
+ (param->max && *param->max < tmp))
964
+ return -EINVAL;
965
+ WRITE_ONCE(*valp, tmp);
966
+ }
967
+
968
+ return 0;
969
+}
970
+
971
+/**
972
+ * proc_dointvec_minmax - read a vector of integers with min/max values
973
+ * @table: the sysctl table
974
+ * @write: %TRUE if this is a write to the sysctl file
975
+ * @buffer: the user buffer
976
+ * @lenp: the size of the user buffer
977
+ * @ppos: file position
978
+ *
979
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
980
+ * values from/to the user buffer, treated as an ASCII string.
981
+ *
982
+ * This routine will ensure the values are within the range specified by
983
+ * table->extra1 (min) and table->extra2 (max).
984
+ *
985
+ * Returns 0 on success or -EINVAL on write when the range check fails.
986
+ */
987
+int proc_dointvec_minmax(struct ctl_table *table, int write,
988
+ void *buffer, size_t *lenp, loff_t *ppos)
989
+{
990
+ struct do_proc_dointvec_minmax_conv_param param = {
991
+ .min = (int *) table->extra1,
992
+ .max = (int *) table->extra2,
993
+ };
994
+ return do_proc_dointvec(table, write, buffer, lenp, ppos,
995
+ do_proc_dointvec_minmax_conv, &param);
996
+}
997
+
998
+/**
999
+ * struct do_proc_douintvec_minmax_conv_param - proc_douintvec_minmax() range checking structure
1000
+ * @min: pointer to minimum allowable value
1001
+ * @max: pointer to maximum allowable value
1002
+ *
1003
+ * The do_proc_douintvec_minmax_conv_param structure provides the
1004
+ * minimum and maximum values for doing range checking for those sysctl
1005
+ * parameters that use the proc_douintvec_minmax() handler.
1006
+ */
1007
+struct do_proc_douintvec_minmax_conv_param {
1008
+ unsigned int *min;
1009
+ unsigned int *max;
1010
+};
1011
+
1012
+static int do_proc_douintvec_minmax_conv(unsigned long *lvalp,
1013
+ unsigned int *valp,
1014
+ int write, void *data)
1015
+{
1016
+ int ret;
1017
+ unsigned int tmp;
1018
+ struct do_proc_douintvec_minmax_conv_param *param = data;
1019
+ /* write via temporary local uint for bounds-checking */
1020
+ unsigned int *up = write ? &tmp : valp;
1021
+
1022
+ ret = do_proc_douintvec_conv(lvalp, up, write, data);
1023
+ if (ret)
1024
+ return ret;
1025
+
1026
+ if (write) {
1027
+ if ((param->min && *param->min > tmp) ||
1028
+ (param->max && *param->max < tmp))
1029
+ return -ERANGE;
1030
+
1031
+ WRITE_ONCE(*valp, tmp);
1032
+ }
1033
+
1034
+ return 0;
1035
+}
1036
+
1037
+/**
1038
+ * proc_douintvec_minmax - read a vector of unsigned ints with min/max values
1039
+ * @table: the sysctl table
1040
+ * @write: %TRUE if this is a write to the sysctl file
1041
+ * @buffer: the user buffer
1042
+ * @lenp: the size of the user buffer
1043
+ * @ppos: file position
1044
+ *
1045
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
1046
+ * values from/to the user buffer, treated as an ASCII string. Negative
1047
+ * strings are not allowed.
1048
+ *
1049
+ * This routine will ensure the values are within the range specified by
1050
+ * table->extra1 (min) and table->extra2 (max). There is a final sanity
1051
+ * check for UINT_MAX to avoid having to support wrap around uses from
1052
+ * userspace.
1053
+ *
1054
+ * Returns 0 on success or -ERANGE on write when the range check fails.
1055
+ */
1056
+int proc_douintvec_minmax(struct ctl_table *table, int write,
1057
+ void *buffer, size_t *lenp, loff_t *ppos)
1058
+{
1059
+ struct do_proc_douintvec_minmax_conv_param param = {
1060
+ .min = (unsigned int *) table->extra1,
1061
+ .max = (unsigned int *) table->extra2,
1062
+ };
1063
+ return do_proc_douintvec(table, write, buffer, lenp, ppos,
1064
+ do_proc_douintvec_minmax_conv, &param);
1065
+}
1066
+
1067
+static int do_proc_dopipe_max_size_conv(unsigned long *lvalp,
1068
+ unsigned int *valp,
1069
+ int write, void *data)
1070
+{
1071
+ if (write) {
1072
+ unsigned int val;
1073
+
1074
+ val = round_pipe_size(*lvalp);
1075
+ if (val == 0)
1076
+ return -EINVAL;
1077
+
1078
+ *valp = val;
1079
+ } else {
1080
+ unsigned int val = *valp;
1081
+ *lvalp = (unsigned long) val;
1082
+ }
1083
+
1084
+ return 0;
1085
+}
1086
+
1087
+static int proc_dopipe_max_size(struct ctl_table *table, int write,
1088
+ void *buffer, size_t *lenp, loff_t *ppos)
1089
+{
1090
+ return do_proc_douintvec(table, write, buffer, lenp, ppos,
1091
+ do_proc_dopipe_max_size_conv, NULL);
1092
+}
1093
+
1094
+static void validate_coredump_safety(void)
1095
+{
1096
+#ifdef CONFIG_COREDUMP
1097
+ if (suid_dumpable == SUID_DUMP_ROOT &&
1098
+ core_pattern[0] != '/' && core_pattern[0] != '|') {
1099
+ printk(KERN_WARNING
1100
+"Unsafe core_pattern used with fs.suid_dumpable=2.\n"
1101
+"Pipe handler or fully qualified core dump path required.\n"
1102
+"Set kernel.core_pattern before fs.suid_dumpable.\n"
1103
+ );
1104
+ }
1105
+#endif
1106
+}
1107
+
1108
+static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write,
1109
+ void *buffer, size_t *lenp, loff_t *ppos)
1110
+{
1111
+ int error = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
1112
+ if (!error)
1113
+ validate_coredump_safety();
1114
+ return error;
1115
+}
1116
+
1117
+#ifdef CONFIG_COREDUMP
1118
+static int proc_dostring_coredump(struct ctl_table *table, int write,
1119
+ void *buffer, size_t *lenp, loff_t *ppos)
1120
+{
1121
+ int error = proc_dostring(table, write, buffer, lenp, ppos);
1122
+ if (!error)
1123
+ validate_coredump_safety();
1124
+ return error;
1125
+}
1126
+#endif
1127
+
1128
+#ifdef CONFIG_MAGIC_SYSRQ
1129
+static int sysrq_sysctl_handler(struct ctl_table *table, int write,
1130
+ void *buffer, size_t *lenp, loff_t *ppos)
1131
+{
1132
+ int tmp, ret;
1133
+
1134
+ tmp = sysrq_mask();
1135
+
1136
+ ret = __do_proc_dointvec(&tmp, table, write, buffer,
1137
+ lenp, ppos, NULL, NULL);
1138
+ if (ret || !write)
1139
+ return ret;
1140
+
1141
+ if (write)
1142
+ sysrq_toggle_support(tmp);
1143
+
1144
+ return 0;
1145
+}
1146
+#endif
1147
+
1148
+static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table,
1149
+ int write, void *buffer, size_t *lenp, loff_t *ppos,
1150
+ unsigned long convmul, unsigned long convdiv)
1151
+{
1152
+ unsigned long *i, *min, *max;
1153
+ int vleft, first = 1, err = 0;
1154
+ size_t left;
1155
+ char *p;
1156
+
1157
+ if (!data || !table->maxlen || !*lenp || (*ppos && !write)) {
1158
+ *lenp = 0;
1159
+ return 0;
1160
+ }
1161
+
1162
+ i = (unsigned long *) data;
1163
+ min = (unsigned long *) table->extra1;
1164
+ max = (unsigned long *) table->extra2;
1165
+ vleft = table->maxlen / sizeof(unsigned long);
1166
+ left = *lenp;
1167
+
1168
+ if (write) {
1169
+ if (proc_first_pos_non_zero_ignore(ppos, table))
1170
+ goto out;
1171
+
1172
+ if (left > PAGE_SIZE - 1)
1173
+ left = PAGE_SIZE - 1;
1174
+ p = buffer;
1175
+ }
1176
+
1177
+ for (; left && vleft--; i++, first = 0) {
1178
+ unsigned long val;
1179
+
1180
+ if (write) {
1181
+ bool neg;
1182
+
1183
+ proc_skip_spaces(&p, &left);
1184
+ if (!left)
1185
+ break;
1186
+
1187
+ err = proc_get_long(&p, &left, &val, &neg,
1188
+ proc_wspace_sep,
1189
+ sizeof(proc_wspace_sep), NULL);
1190
+ if (err)
1191
+ break;
1192
+ if (neg)
1193
+ continue;
1194
+ val = convmul * val / convdiv;
1195
+ if ((min && val < *min) || (max && val > *max)) {
1196
+ err = -EINVAL;
1197
+ break;
1198
+ }
1199
+ WRITE_ONCE(*i, val);
1200
+ } else {
1201
+ val = convdiv * READ_ONCE(*i) / convmul;
1202
+ if (!first)
1203
+ proc_put_char(&buffer, &left, '\t');
1204
+ proc_put_long(&buffer, &left, val, false);
1205
+ }
1206
+ }
1207
+
1208
+ if (!write && !first && left && !err)
1209
+ proc_put_char(&buffer, &left, '\n');
1210
+ if (write && !err)
1211
+ proc_skip_spaces(&p, &left);
1212
+ if (write && first)
1213
+ return err ? : -EINVAL;
1214
+ *lenp -= left;
1215
+out:
1216
+ *ppos += *lenp;
1217
+ return err;
1218
+}
1219
+
1220
+static int do_proc_doulongvec_minmax(struct ctl_table *table, int write,
1221
+ void *buffer, size_t *lenp, loff_t *ppos, unsigned long convmul,
1222
+ unsigned long convdiv)
1223
+{
1224
+ return __do_proc_doulongvec_minmax(table->data, table, write,
1225
+ buffer, lenp, ppos, convmul, convdiv);
1226
+}
1227
+
1228
+/**
1229
+ * proc_doulongvec_minmax - read a vector of long integers with min/max values
1230
+ * @table: the sysctl table
1231
+ * @write: %TRUE if this is a write to the sysctl file
1232
+ * @buffer: the user buffer
1233
+ * @lenp: the size of the user buffer
1234
+ * @ppos: file position
1235
+ *
1236
+ * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
1237
+ * values from/to the user buffer, treated as an ASCII string.
1238
+ *
1239
+ * This routine will ensure the values are within the range specified by
1240
+ * table->extra1 (min) and table->extra2 (max).
1241
+ *
1242
+ * Returns 0 on success.
1243
+ */
1244
+int proc_doulongvec_minmax(struct ctl_table *table, int write,
1245
+ void *buffer, size_t *lenp, loff_t *ppos)
1246
+{
1247
+ return do_proc_doulongvec_minmax(table, write, buffer, lenp, ppos, 1l, 1l);
1248
+}
1249
+
1250
+/**
1251
+ * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values
1252
+ * @table: the sysctl table
1253
+ * @write: %TRUE if this is a write to the sysctl file
1254
+ * @buffer: the user buffer
1255
+ * @lenp: the size of the user buffer
1256
+ * @ppos: file position
1257
+ *
1258
+ * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
1259
+ * values from/to the user buffer, treated as an ASCII string. The values
1260
+ * are treated as milliseconds, and converted to jiffies when they are stored.
1261
+ *
1262
+ * This routine will ensure the values are within the range specified by
1263
+ * table->extra1 (min) and table->extra2 (max).
1264
+ *
1265
+ * Returns 0 on success.
1266
+ */
1267
+int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
1268
+ void *buffer, size_t *lenp, loff_t *ppos)
1269
+{
1270
+ return do_proc_doulongvec_minmax(table, write, buffer,
1271
+ lenp, ppos, HZ, 1000l);
1272
+}
1273
+
1274
+
1275
+static int do_proc_dointvec_jiffies_conv(bool *negp, unsigned long *lvalp,
1276
+ int *valp,
1277
+ int write, void *data)
1278
+{
1279
+ if (write) {
1280
+ if (*lvalp > INT_MAX / HZ)
1281
+ return 1;
1282
+ if (*negp)
1283
+ WRITE_ONCE(*valp, -*lvalp * HZ);
1284
+ else
1285
+ WRITE_ONCE(*valp, *lvalp * HZ);
1286
+ } else {
1287
+ int val = READ_ONCE(*valp);
1288
+ unsigned long lval;
1289
+ if (val < 0) {
1290
+ *negp = true;
1291
+ lval = -(unsigned long)val;
1292
+ } else {
1293
+ *negp = false;
1294
+ lval = (unsigned long)val;
1295
+ }
1296
+ *lvalp = lval / HZ;
1297
+ }
1298
+ return 0;
1299
+}
1300
+
1301
+static int do_proc_dointvec_userhz_jiffies_conv(bool *negp, unsigned long *lvalp,
1302
+ int *valp,
1303
+ int write, void *data)
1304
+{
1305
+ if (write) {
1306
+ if (USER_HZ < HZ && *lvalp > (LONG_MAX / HZ) * USER_HZ)
1307
+ return 1;
1308
+ *valp = clock_t_to_jiffies(*negp ? -*lvalp : *lvalp);
1309
+ } else {
1310
+ int val = *valp;
1311
+ unsigned long lval;
1312
+ if (val < 0) {
1313
+ *negp = true;
1314
+ lval = -(unsigned long)val;
1315
+ } else {
1316
+ *negp = false;
1317
+ lval = (unsigned long)val;
1318
+ }
1319
+ *lvalp = jiffies_to_clock_t(lval);
1320
+ }
1321
+ return 0;
1322
+}
1323
+
1324
+static int do_proc_dointvec_ms_jiffies_conv(bool *negp, unsigned long *lvalp,
1325
+ int *valp,
1326
+ int write, void *data)
1327
+{
1328
+ if (write) {
1329
+ unsigned long jif = msecs_to_jiffies(*negp ? -*lvalp : *lvalp);
1330
+
1331
+ if (jif > INT_MAX)
1332
+ return 1;
1333
+ WRITE_ONCE(*valp, (int)jif);
1334
+ } else {
1335
+ int val = READ_ONCE(*valp);
1336
+ unsigned long lval;
1337
+ if (val < 0) {
1338
+ *negp = true;
1339
+ lval = -(unsigned long)val;
1340
+ } else {
1341
+ *negp = false;
1342
+ lval = (unsigned long)val;
1343
+ }
1344
+ *lvalp = jiffies_to_msecs(lval);
1345
+ }
1346
+ return 0;
1347
+}
1348
+
1349
+/**
1350
+ * proc_dointvec_jiffies - read a vector of integers as seconds
1351
+ * @table: the sysctl table
1352
+ * @write: %TRUE if this is a write to the sysctl file
1353
+ * @buffer: the user buffer
1354
+ * @lenp: the size of the user buffer
1355
+ * @ppos: file position
1356
+ *
1357
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1358
+ * values from/to the user buffer, treated as an ASCII string.
1359
+ * The values read are assumed to be in seconds, and are converted into
1360
+ * jiffies.
1361
+ *
1362
+ * Returns 0 on success.
1363
+ */
1364
+int proc_dointvec_jiffies(struct ctl_table *table, int write,
1365
+ void *buffer, size_t *lenp, loff_t *ppos)
1366
+{
1367
+ return do_proc_dointvec(table,write,buffer,lenp,ppos,
1368
+ do_proc_dointvec_jiffies_conv,NULL);
1369
+}
1370
+
1371
+/**
1372
+ * proc_dointvec_userhz_jiffies - read a vector of integers as 1/USER_HZ seconds
1373
+ * @table: the sysctl table
1374
+ * @write: %TRUE if this is a write to the sysctl file
1375
+ * @buffer: the user buffer
1376
+ * @lenp: the size of the user buffer
1377
+ * @ppos: pointer to the file position
1378
+ *
1379
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1380
+ * values from/to the user buffer, treated as an ASCII string.
1381
+ * The values read are assumed to be in 1/USER_HZ seconds, and
1382
+ * are converted into jiffies.
1383
+ *
1384
+ * Returns 0 on success.
1385
+ */
1386
+int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
1387
+ void *buffer, size_t *lenp, loff_t *ppos)
1388
+{
1389
+ return do_proc_dointvec(table,write,buffer,lenp,ppos,
1390
+ do_proc_dointvec_userhz_jiffies_conv,NULL);
1391
+}
1392
+
1393
+/**
1394
+ * proc_dointvec_ms_jiffies - read a vector of integers as 1 milliseconds
1395
+ * @table: the sysctl table
1396
+ * @write: %TRUE if this is a write to the sysctl file
1397
+ * @buffer: the user buffer
1398
+ * @lenp: the size of the user buffer
1399
+ * @ppos: file position
1400
+ * @ppos: the current position in the file
1401
+ *
1402
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1403
+ * values from/to the user buffer, treated as an ASCII string.
1404
+ * The values read are assumed to be in 1/1000 seconds, and
1405
+ * are converted into jiffies.
1406
+ *
1407
+ * Returns 0 on success.
1408
+ */
1409
+int proc_dointvec_ms_jiffies(struct ctl_table *table, int write, void *buffer,
1410
+ size_t *lenp, loff_t *ppos)
1411
+{
1412
+ return do_proc_dointvec(table, write, buffer, lenp, ppos,
1413
+ do_proc_dointvec_ms_jiffies_conv, NULL);
1414
+}
1415
+
1416
+static int proc_do_cad_pid(struct ctl_table *table, int write, void *buffer,
1417
+ size_t *lenp, loff_t *ppos)
1418
+{
1419
+ struct pid *new_pid;
1420
+ pid_t tmp;
1421
+ int r;
1422
+
1423
+ tmp = pid_vnr(cad_pid);
1424
+
1425
+ r = __do_proc_dointvec(&tmp, table, write, buffer,
1426
+ lenp, ppos, NULL, NULL);
1427
+ if (r || !write)
1428
+ return r;
1429
+
1430
+ new_pid = find_get_pid(tmp);
1431
+ if (!new_pid)
1432
+ return -ESRCH;
1433
+
1434
+ put_pid(xchg(&cad_pid, new_pid));
1435
+ return 0;
1436
+}
1437
+
1438
+/**
1439
+ * proc_do_large_bitmap - read/write from/to a large bitmap
1440
+ * @table: the sysctl table
1441
+ * @write: %TRUE if this is a write to the sysctl file
1442
+ * @buffer: the user buffer
1443
+ * @lenp: the size of the user buffer
1444
+ * @ppos: file position
1445
+ *
1446
+ * The bitmap is stored at table->data and the bitmap length (in bits)
1447
+ * in table->maxlen.
1448
+ *
1449
+ * We use a range comma separated format (e.g. 1,3-4,10-10) so that
1450
+ * large bitmaps may be represented in a compact manner. Writing into
1451
+ * the file will clear the bitmap then update it with the given input.
1452
+ *
1453
+ * Returns 0 on success.
1454
+ */
1455
+int proc_do_large_bitmap(struct ctl_table *table, int write,
1456
+ void *buffer, size_t *lenp, loff_t *ppos)
1457
+{
1458
+ int err = 0;
1459
+ bool first = 1;
1460
+ size_t left = *lenp;
1461
+ unsigned long bitmap_len = table->maxlen;
1462
+ unsigned long *bitmap = *(unsigned long **) table->data;
1463
+ unsigned long *tmp_bitmap = NULL;
1464
+ char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
1465
+
1466
+ if (!bitmap || !bitmap_len || !left || (*ppos && !write)) {
1467
+ *lenp = 0;
1468
+ return 0;
1469
+ }
1470
+
1471
+ if (write) {
1472
+ char *p = buffer;
1473
+ size_t skipped = 0;
1474
+
1475
+ if (left > PAGE_SIZE - 1) {
1476
+ left = PAGE_SIZE - 1;
1477
+ /* How much of the buffer we'll skip this pass */
1478
+ skipped = *lenp - left;
1479
+ }
1480
+
1481
+ tmp_bitmap = bitmap_zalloc(bitmap_len, GFP_KERNEL);
1482
+ if (!tmp_bitmap)
1483
+ return -ENOMEM;
1484
+ proc_skip_char(&p, &left, '\n');
1485
+ while (!err && left) {
1486
+ unsigned long val_a, val_b;
1487
+ bool neg;
1488
+ size_t saved_left;
1489
+
1490
+ /* In case we stop parsing mid-number, we can reset */
1491
+ saved_left = left;
1492
+ err = proc_get_long(&p, &left, &val_a, &neg, tr_a,
1493
+ sizeof(tr_a), &c);
1494
+ /*
1495
+ * If we consumed the entirety of a truncated buffer or
1496
+ * only one char is left (may be a "-"), then stop here,
1497
+ * reset, & come back for more.
1498
+ */
1499
+ if ((left <= 1) && skipped) {
1500
+ left = saved_left;
1501
+ break;
1502
+ }
1503
+
1504
+ if (err)
1505
+ break;
1506
+ if (val_a >= bitmap_len || neg) {
1507
+ err = -EINVAL;
1508
+ break;
1509
+ }
1510
+
1511
+ val_b = val_a;
1512
+ if (left) {
1513
+ p++;
1514
+ left--;
1515
+ }
1516
+
1517
+ if (c == '-') {
1518
+ err = proc_get_long(&p, &left, &val_b,
1519
+ &neg, tr_b, sizeof(tr_b),
1520
+ &c);
1521
+ /*
1522
+ * If we consumed all of a truncated buffer or
1523
+ * then stop here, reset, & come back for more.
1524
+ */
1525
+ if (!left && skipped) {
1526
+ left = saved_left;
1527
+ break;
1528
+ }
1529
+
1530
+ if (err)
1531
+ break;
1532
+ if (val_b >= bitmap_len || neg ||
1533
+ val_a > val_b) {
1534
+ err = -EINVAL;
1535
+ break;
1536
+ }
1537
+ if (left) {
1538
+ p++;
1539
+ left--;
1540
+ }
1541
+ }
1542
+
1543
+ bitmap_set(tmp_bitmap, val_a, val_b - val_a + 1);
1544
+ first = 0;
1545
+ proc_skip_char(&p, &left, '\n');
1546
+ }
1547
+ left += skipped;
1548
+ } else {
1549
+ unsigned long bit_a, bit_b = 0;
1550
+
1551
+ while (left) {
1552
+ bit_a = find_next_bit(bitmap, bitmap_len, bit_b);
1553
+ if (bit_a >= bitmap_len)
1554
+ break;
1555
+ bit_b = find_next_zero_bit(bitmap, bitmap_len,
1556
+ bit_a + 1) - 1;
1557
+
1558
+ if (!first)
1559
+ proc_put_char(&buffer, &left, ',');
1560
+ proc_put_long(&buffer, &left, bit_a, false);
1561
+ if (bit_a != bit_b) {
1562
+ proc_put_char(&buffer, &left, '-');
1563
+ proc_put_long(&buffer, &left, bit_b, false);
1564
+ }
1565
+
1566
+ first = 0; bit_b++;
1567
+ }
1568
+ proc_put_char(&buffer, &left, '\n');
1569
+ }
1570
+
1571
+ if (!err) {
1572
+ if (write) {
1573
+ if (*ppos)
1574
+ bitmap_or(bitmap, bitmap, tmp_bitmap, bitmap_len);
1575
+ else
1576
+ bitmap_copy(bitmap, tmp_bitmap, bitmap_len);
1577
+ }
1578
+ *lenp -= left;
1579
+ *ppos += *lenp;
1580
+ }
1581
+
1582
+ bitmap_free(tmp_bitmap);
1583
+ return err;
1584
+}
1585
+
1586
+#else /* CONFIG_PROC_SYSCTL */
1587
+
1588
+int proc_dostring(struct ctl_table *table, int write,
1589
+ void *buffer, size_t *lenp, loff_t *ppos)
1590
+{
1591
+ return -ENOSYS;
1592
+}
1593
+
1594
+int proc_dointvec(struct ctl_table *table, int write,
1595
+ void *buffer, size_t *lenp, loff_t *ppos)
1596
+{
1597
+ return -ENOSYS;
1598
+}
1599
+
1600
+int proc_douintvec(struct ctl_table *table, int write,
1601
+ void *buffer, size_t *lenp, loff_t *ppos)
1602
+{
1603
+ return -ENOSYS;
1604
+}
1605
+
1606
+int proc_dointvec_minmax(struct ctl_table *table, int write,
1607
+ void *buffer, size_t *lenp, loff_t *ppos)
1608
+{
1609
+ return -ENOSYS;
1610
+}
1611
+
1612
+int proc_douintvec_minmax(struct ctl_table *table, int write,
1613
+ void *buffer, size_t *lenp, loff_t *ppos)
1614
+{
1615
+ return -ENOSYS;
1616
+}
1617
+
1618
+int proc_dointvec_jiffies(struct ctl_table *table, int write,
1619
+ void *buffer, size_t *lenp, loff_t *ppos)
1620
+{
1621
+ return -ENOSYS;
1622
+}
1623
+
1624
+int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
1625
+ void *buffer, size_t *lenp, loff_t *ppos)
1626
+{
1627
+ return -ENOSYS;
1628
+}
1629
+
1630
+int proc_dointvec_ms_jiffies(struct ctl_table *table, int write,
1631
+ void *buffer, size_t *lenp, loff_t *ppos)
1632
+{
1633
+ return -ENOSYS;
1634
+}
1635
+
1636
+int proc_doulongvec_minmax(struct ctl_table *table, int write,
1637
+ void *buffer, size_t *lenp, loff_t *ppos)
1638
+{
1639
+ return -ENOSYS;
1640
+}
1641
+
1642
+int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
1643
+ void *buffer, size_t *lenp, loff_t *ppos)
1644
+{
1645
+ return -ENOSYS;
1646
+}
1647
+
1648
+int proc_do_large_bitmap(struct ctl_table *table, int write,
1649
+ void *buffer, size_t *lenp, loff_t *ppos)
1650
+{
1651
+ return -ENOSYS;
1652
+}
1653
+
1654
+#endif /* CONFIG_PROC_SYSCTL */
1655
+
1656
+#if defined(CONFIG_SYSCTL)
1657
+int proc_do_static_key(struct ctl_table *table, int write,
1658
+ void *buffer, size_t *lenp, loff_t *ppos)
1659
+{
1660
+ struct static_key *key = (struct static_key *)table->data;
1661
+ static DEFINE_MUTEX(static_key_mutex);
1662
+ int val, ret;
1663
+ struct ctl_table tmp = {
1664
+ .data = &val,
1665
+ .maxlen = sizeof(val),
1666
+ .mode = table->mode,
1667
+ .extra1 = SYSCTL_ZERO,
1668
+ .extra2 = SYSCTL_ONE,
1669
+ };
1670
+
1671
+ if (write && !capable(CAP_SYS_ADMIN))
1672
+ return -EPERM;
1673
+
1674
+ mutex_lock(&static_key_mutex);
1675
+ val = static_key_enabled(key);
1676
+ ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
1677
+ if (write && !ret) {
1678
+ if (val)
1679
+ static_key_enable(key);
1680
+ else
1681
+ static_key_disable(key);
1682
+ }
1683
+ mutex_unlock(&static_key_mutex);
1684
+ return ret;
1685
+}
1686
+
3411687 static struct ctl_table kern_table[] = {
3421688 {
3431689 .procname = "sched_child_runs_first",
....@@ -347,13 +1693,6 @@
3471693 .proc_handler = proc_dointvec,
3481694 },
3491695 #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
- },
3571696 {
3581697 .procname = "sched_min_granularity_ns",
3591698 .data = &sysctl_sched_min_granularity,
....@@ -373,13 +1712,6 @@
3731712 .extra2 = &max_sched_granularity_ns,
3741713 },
3751714 {
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
- {
3831715 .procname = "sched_wakeup_granularity_ns",
3841716 .data = &sysctl_sched_wakeup_granularity,
3851717 .maxlen = sizeof(unsigned int),
....@@ -389,6 +1721,13 @@
3891721 .extra2 = &max_wakeup_granularity_ns,
3901722 },
3911723 #ifdef CONFIG_SMP
1724
+ {
1725
+ .procname = "sched_pelt_period",
1726
+ .data = &sysctl_sched_pelt_period,
1727
+ .maxlen = sizeof(int),
1728
+ .mode = 0644,
1729
+ .proc_handler = sched_pelt_period_update_handler,
1730
+ },
3921731 {
3931732 .procname = "sched_tunable_scaling",
3941733 .data = &sysctl_sched_tunable_scaling,
....@@ -419,8 +1758,8 @@
4191758 .maxlen = sizeof(unsigned int),
4201759 .mode = 0644,
4211760 .proc_handler = sysctl_schedstats,
422
- .extra1 = &zero,
423
- .extra2 = &one,
1761
+ .extra1 = SYSCTL_ZERO,
1762
+ .extra2 = SYSCTL_ONE,
4241763 },
4251764 #endif /* CONFIG_SCHEDSTATS */
4261765 #endif /* CONFIG_SMP */
....@@ -452,7 +1791,7 @@
4521791 .maxlen = sizeof(unsigned int),
4531792 .mode = 0644,
4541793 .proc_handler = proc_dointvec_minmax,
455
- .extra1 = &one,
1794
+ .extra1 = SYSCTL_ONE,
4561795 },
4571796 {
4581797 .procname = "numa_balancing",
....@@ -460,8 +1799,8 @@
4601799 .maxlen = sizeof(unsigned int),
4611800 .mode = 0644,
4621801 .proc_handler = sysctl_numa_balancing,
463
- .extra1 = &zero,
464
- .extra2 = &one,
1802
+ .extra1 = SYSCTL_ZERO,
1803
+ .extra2 = SYSCTL_ONE,
4651804 },
4661805 #endif /* CONFIG_NUMA_BALANCING */
4671806 #endif /* CONFIG_SCHED_DEBUG */
....@@ -480,12 +1819,35 @@
4801819 .proc_handler = sched_rt_handler,
4811820 },
4821821 {
1822
+ .procname = "sched_deadline_period_max_us",
1823
+ .data = &sysctl_sched_dl_period_max,
1824
+ .maxlen = sizeof(unsigned int),
1825
+ .mode = 0644,
1826
+ .proc_handler = proc_dointvec,
1827
+ },
1828
+ {
1829
+ .procname = "sched_deadline_period_min_us",
1830
+ .data = &sysctl_sched_dl_period_min,
1831
+ .maxlen = sizeof(unsigned int),
1832
+ .mode = 0644,
1833
+ .proc_handler = proc_dointvec,
1834
+ },
1835
+ {
4831836 .procname = "sched_rr_timeslice_ms",
4841837 .data = &sysctl_sched_rr_timeslice,
4851838 .maxlen = sizeof(int),
4861839 .mode = 0644,
4871840 .proc_handler = sched_rr_handler,
4881841 },
1842
+#ifdef CONFIG_SMP
1843
+ {
1844
+ .procname = "sched_pelt_multiplier",
1845
+ .data = &sysctl_sched_pelt_multiplier,
1846
+ .maxlen = sizeof(unsigned int),
1847
+ .mode = 0644,
1848
+ .proc_handler = sched_pelt_multiplier,
1849
+ },
1850
+#endif
4891851 #ifdef CONFIG_UCLAMP_TASK
4901852 {
4911853 .procname = "sched_util_clamp_min",
....@@ -501,6 +1863,13 @@
5011863 .mode = 0644,
5021864 .proc_handler = sysctl_sched_uclamp_handler,
5031865 },
1866
+ {
1867
+ .procname = "sched_util_clamp_min_rt_default",
1868
+ .data = &sysctl_sched_uclamp_util_min_rt_default,
1869
+ .maxlen = sizeof(unsigned int),
1870
+ .mode = 0644,
1871
+ .proc_handler = sysctl_sched_uclamp_handler,
1872
+ },
5041873 #endif
5051874 #ifdef CONFIG_SCHED_AUTOGROUP
5061875 {
....@@ -509,8 +1878,8 @@
5091878 .maxlen = sizeof(unsigned int),
5101879 .mode = 0644,
5111880 .proc_handler = proc_dointvec_minmax,
512
- .extra1 = &zero,
513
- .extra2 = &one,
1881
+ .extra1 = SYSCTL_ZERO,
1882
+ .extra2 = SYSCTL_ONE,
5141883 },
5151884 #endif
5161885 #ifdef CONFIG_CFS_BANDWIDTH
....@@ -520,16 +1889,7 @@
5201889 .maxlen = sizeof(unsigned int),
5211890 .mode = 0644,
5221891 .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,
1892
+ .extra1 = SYSCTL_ONE,
5331893 },
5341894 #endif
5351895 #if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL)
....@@ -539,8 +1899,8 @@
5391899 .maxlen = sizeof(unsigned int),
5401900 .mode = 0644,
5411901 .proc_handler = sched_energy_aware_handler,
542
- .extra1 = &zero,
543
- .extra2 = &one,
1902
+ .extra1 = SYSCTL_ZERO,
1903
+ .extra2 = SYSCTL_ONE,
5441904 },
5451905 #endif
5461906 #ifdef CONFIG_PROVE_LOCKING
....@@ -605,7 +1965,7 @@
6051965 .mode = 0644,
6061966 .proc_handler = proc_dointvec_minmax,
6071967 .extra1 = &neg_one,
608
- .extra2 = &one,
1968
+ .extra2 = SYSCTL_ONE,
6091969 },
6101970 #endif
6111971 #ifdef CONFIG_LATENCYTOP
....@@ -665,12 +2025,12 @@
6652025 .proc_handler = proc_dointvec,
6662026 },
6672027 #endif
668
-#ifdef __hppa__
2028
+#ifdef CONFIG_PARISC
6692029 {
6702030 .procname = "soft-power",
6712031 .data = &pwrsw_enabled,
6722032 .maxlen = sizeof (int),
673
- .mode = 0644,
2033
+ .mode = 0644,
6742034 .proc_handler = proc_dointvec,
6752035 },
6762036 #endif
....@@ -739,8 +2099,8 @@
7392099 .mode = 0644,
7402100 /* only handle a transition from default "0" to "1" */
7412101 .proc_handler = proc_dointvec_minmax,
742
- .extra1 = &one,
743
- .extra2 = &one,
2102
+ .extra1 = SYSCTL_ONE,
2103
+ .extra2 = SYSCTL_ONE,
7442104 },
7452105 #endif
7462106 #ifdef CONFIG_MODULES
....@@ -758,8 +2118,8 @@
7582118 .mode = 0644,
7592119 /* only handle a transition from default "0" to "1" */
7602120 .proc_handler = proc_dointvec_minmax,
761
- .extra1 = &one,
762
- .extra2 = &one,
2121
+ .extra1 = SYSCTL_ONE,
2122
+ .extra2 = SYSCTL_ONE,
7632123 },
7642124 #endif
7652125 #ifdef CONFIG_UEVENT_HELPER
....@@ -792,7 +2152,7 @@
7922152 #ifdef CONFIG_MAGIC_SYSRQ
7932153 {
7942154 .procname = "sysrq",
795
- .data = &__sysrq_enabled,
2155
+ .data = NULL,
7962156 .maxlen = sizeof (int),
7972157 .mode = 0644,
7982158 .proc_handler = sysrq_sysctl_handler,
....@@ -850,15 +2210,6 @@
8502210 .extra2 = &maxolduid,
8512211 },
8522212 #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
8622213 {
8632214 .procname = "userprocess_debug",
8642215 .data = &show_unhandled_signals,
....@@ -867,6 +2218,17 @@
8672218 .proc_handler = proc_dointvec,
8682219 },
8692220 #endif
2221
+#ifdef CONFIG_SMP
2222
+ {
2223
+ .procname = "oops_all_cpu_backtrace",
2224
+ .data = &sysctl_oops_all_cpu_backtrace,
2225
+ .maxlen = sizeof(int),
2226
+ .mode = 0644,
2227
+ .proc_handler = proc_dointvec_minmax,
2228
+ .extra1 = SYSCTL_ZERO,
2229
+ .extra2 = SYSCTL_ONE,
2230
+ },
2231
+#endif /* CONFIG_SMP */
8702232 {
8712233 .procname = "pid_max",
8722234 .data = &pid_max,
....@@ -882,6 +2244,13 @@
8822244 .maxlen = sizeof(int),
8832245 .mode = 0644,
8842246 .proc_handler = proc_dointvec,
2247
+ },
2248
+ {
2249
+ .procname = "panic_print",
2250
+ .data = &panic_print,
2251
+ .maxlen = sizeof(unsigned long),
2252
+ .mode = 0644,
2253
+ .proc_handler = proc_doulongvec_minmax,
8852254 },
8862255 #if defined CONFIG_PRINTK
8872256 {
....@@ -911,7 +2280,7 @@
9112280 .maxlen = sizeof(int),
9122281 .mode = 0644,
9132282 .proc_handler = proc_dointvec_minmax,
914
- .extra1 = &zero,
2283
+ .extra1 = SYSCTL_ZERO,
9152284 .extra2 = &ten_thousand,
9162285 },
9172286 {
....@@ -927,8 +2296,8 @@
9272296 .maxlen = sizeof(int),
9282297 .mode = 0644,
9292298 .proc_handler = proc_dointvec_minmax_sysadmin,
930
- .extra1 = &zero,
931
- .extra2 = &one,
2299
+ .extra1 = SYSCTL_ZERO,
2300
+ .extra2 = SYSCTL_ONE,
9322301 },
9332302 {
9342303 .procname = "kptr_restrict",
....@@ -936,7 +2305,7 @@
9362305 .maxlen = sizeof(int),
9372306 .mode = 0644,
9382307 .proc_handler = proc_dointvec_minmax_sysadmin,
939
- .extra1 = &zero,
2308
+ .extra1 = SYSCTL_ZERO,
9402309 .extra2 = &two,
9412310 },
9422311 #endif
....@@ -961,8 +2330,8 @@
9612330 .maxlen = sizeof(int),
9622331 .mode = 0644,
9632332 .proc_handler = proc_watchdog,
964
- .extra1 = &zero,
965
- .extra2 = &one,
2333
+ .extra1 = SYSCTL_ZERO,
2334
+ .extra2 = SYSCTL_ONE,
9662335 },
9672336 {
9682337 .procname = "watchdog_thresh",
....@@ -970,7 +2339,7 @@
9702339 .maxlen = sizeof(int),
9712340 .mode = 0644,
9722341 .proc_handler = proc_watchdog_thresh,
973
- .extra1 = &zero,
2342
+ .extra1 = SYSCTL_ZERO,
9742343 .extra2 = &sixty,
9752344 },
9762345 {
....@@ -979,8 +2348,8 @@
9792348 .maxlen = sizeof(int),
9802349 .mode = NMI_WATCHDOG_SYSCTL_PERM,
9812350 .proc_handler = proc_nmi_watchdog,
982
- .extra1 = &zero,
983
- .extra2 = &one,
2351
+ .extra1 = SYSCTL_ZERO,
2352
+ .extra2 = SYSCTL_ONE,
9842353 },
9852354 {
9862355 .procname = "watchdog_cpumask",
....@@ -996,8 +2365,8 @@
9962365 .maxlen = sizeof(int),
9972366 .mode = 0644,
9982367 .proc_handler = proc_soft_watchdog,
999
- .extra1 = &zero,
1000
- .extra2 = &one,
2368
+ .extra1 = SYSCTL_ZERO,
2369
+ .extra2 = SYSCTL_ONE,
10012370 },
10022371 {
10032372 .procname = "softlockup_panic",
....@@ -1005,8 +2374,8 @@
10052374 .maxlen = sizeof(int),
10062375 .mode = 0644,
10072376 .proc_handler = proc_dointvec_minmax,
1008
- .extra1 = &zero,
1009
- .extra2 = &one,
2377
+ .extra1 = SYSCTL_ZERO,
2378
+ .extra2 = SYSCTL_ONE,
10102379 },
10112380 #ifdef CONFIG_SMP
10122381 {
....@@ -1015,8 +2384,8 @@
10152384 .maxlen = sizeof(int),
10162385 .mode = 0644,
10172386 .proc_handler = proc_dointvec_minmax,
1018
- .extra1 = &zero,
1019
- .extra2 = &one,
2387
+ .extra1 = SYSCTL_ZERO,
2388
+ .extra2 = SYSCTL_ONE,
10202389 },
10212390 #endif /* CONFIG_SMP */
10222391 #endif
....@@ -1027,8 +2396,8 @@
10272396 .maxlen = sizeof(int),
10282397 .mode = 0644,
10292398 .proc_handler = proc_dointvec_minmax,
1030
- .extra1 = &zero,
1031
- .extra2 = &one,
2399
+ .extra1 = SYSCTL_ZERO,
2400
+ .extra2 = SYSCTL_ONE,
10322401 },
10332402 #ifdef CONFIG_SMP
10342403 {
....@@ -1037,8 +2406,8 @@
10372406 .maxlen = sizeof(int),
10382407 .mode = 0644,
10392408 .proc_handler = proc_dointvec_minmax,
1040
- .extra1 = &zero,
1041
- .extra2 = &one,
2409
+ .extra1 = SYSCTL_ZERO,
2410
+ .extra2 = SYSCTL_ONE,
10422411 },
10432412 #endif /* CONFIG_SMP */
10442413 #endif
....@@ -1051,6 +2420,17 @@
10512420 .maxlen = sizeof (int),
10522421 .mode = 0644,
10532422 .proc_handler = proc_dointvec,
2423
+ },
2424
+#endif
2425
+
2426
+#if (defined(CONFIG_X86_32) || defined(CONFIG_PARISC)) && \
2427
+ defined(CONFIG_DEBUG_STACKOVERFLOW)
2428
+ {
2429
+ .procname = "panic_on_stackoverflow",
2430
+ .data = &sysctl_panic_on_stackoverflow,
2431
+ .maxlen = sizeof(int),
2432
+ .mode = 0644,
2433
+ .proc_handler = proc_dointvec,
10542434 },
10552435 #endif
10562436 #if defined(CONFIG_X86)
....@@ -1068,15 +2448,6 @@
10682448 .mode = 0644,
10692449 .proc_handler = proc_dointvec,
10702450 },
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
10802451 {
10812452 .procname = "bootloader_type",
10822453 .data = &bootloader_type,
....@@ -1131,7 +2502,7 @@
11312502 .procname = "ignore-unaligned-usertrap",
11322503 .data = &no_unaligned_warning,
11332504 .maxlen = sizeof (int),
1134
- .mode = 0644,
2505
+ .mode = 0644,
11352506 .proc_handler = proc_dointvec,
11362507 },
11372508 #endif
....@@ -1145,14 +2516,25 @@
11452516 },
11462517 #endif
11472518 #ifdef CONFIG_DETECT_HUNG_TASK
2519
+#ifdef CONFIG_SMP
2520
+ {
2521
+ .procname = "hung_task_all_cpu_backtrace",
2522
+ .data = &sysctl_hung_task_all_cpu_backtrace,
2523
+ .maxlen = sizeof(int),
2524
+ .mode = 0644,
2525
+ .proc_handler = proc_dointvec_minmax,
2526
+ .extra1 = SYSCTL_ZERO,
2527
+ .extra2 = SYSCTL_ONE,
2528
+ },
2529
+#endif /* CONFIG_SMP */
11482530 {
11492531 .procname = "hung_task_panic",
11502532 .data = &sysctl_hung_task_panic,
11512533 .maxlen = sizeof(int),
11522534 .mode = 0644,
11532535 .proc_handler = proc_dointvec_minmax,
1154
- .extra1 = &zero,
1155
- .extra2 = &one,
2536
+ .extra1 = SYSCTL_ZERO,
2537
+ .extra2 = SYSCTL_ONE,
11562538 },
11572539 {
11582540 .procname = "hung_task_check_count",
....@@ -1160,7 +2542,7 @@
11602542 .maxlen = sizeof(int),
11612543 .mode = 0644,
11622544 .proc_handler = proc_dointvec_minmax,
1163
- .extra1 = &zero,
2545
+ .extra1 = SYSCTL_ZERO,
11642546 },
11652547 {
11662548 .procname = "hung_task_timeout_secs",
....@@ -1237,7 +2619,7 @@
12372619 .maxlen = sizeof(sysctl_perf_event_sample_rate),
12382620 .mode = 0644,
12392621 .proc_handler = perf_proc_update_handler,
1240
- .extra1 = &one,
2622
+ .extra1 = SYSCTL_ONE,
12412623 },
12422624 {
12432625 .procname = "perf_cpu_time_max_percent",
....@@ -1245,7 +2627,7 @@
12452627 .maxlen = sizeof(sysctl_perf_cpu_time_max_percent),
12462628 .mode = 0644,
12472629 .proc_handler = perf_cpu_time_max_percent_handler,
1248
- .extra1 = &zero,
2630
+ .extra1 = SYSCTL_ZERO,
12492631 .extra2 = &one_hundred,
12502632 },
12512633 {
....@@ -1254,7 +2636,7 @@
12542636 .maxlen = sizeof(sysctl_perf_event_max_stack),
12552637 .mode = 0644,
12562638 .proc_handler = perf_event_max_stack_handler,
1257
- .extra1 = &zero,
2639
+ .extra1 = SYSCTL_ZERO,
12582640 .extra2 = &six_hundred_forty_kb,
12592641 },
12602642 {
....@@ -1263,7 +2645,7 @@
12632645 .maxlen = sizeof(sysctl_perf_event_max_contexts_per_stack),
12642646 .mode = 0644,
12652647 .proc_handler = perf_event_max_stack_handler,
1266
- .extra1 = &zero,
2648
+ .extra1 = SYSCTL_ZERO,
12672649 .extra2 = &one_thousand,
12682650 },
12692651 #endif
....@@ -1273,8 +2655,8 @@
12732655 .maxlen = sizeof(int),
12742656 .mode = 0644,
12752657 .proc_handler = proc_dointvec_minmax,
1276
- .extra1 = &zero,
1277
- .extra2 = &one,
2658
+ .extra1 = SYSCTL_ZERO,
2659
+ .extra2 = SYSCTL_ONE,
12782660 },
12792661 #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
12802662 {
....@@ -1283,8 +2665,8 @@
12832665 .maxlen = sizeof(unsigned int),
12842666 .mode = 0644,
12852667 .proc_handler = timer_migration_handler,
1286
- .extra1 = &zero,
1287
- .extra2 = &one,
2668
+ .extra1 = SYSCTL_ZERO,
2669
+ .extra2 = SYSCTL_ONE,
12882670 },
12892671 #endif
12902672 #ifdef CONFIG_BPF_SYSCALL
....@@ -1294,19 +2676,37 @@
12942676 .maxlen = sizeof(sysctl_unprivileged_bpf_disabled),
12952677 .mode = 0644,
12962678 .proc_handler = bpf_unpriv_handler,
1297
- .extra1 = &zero,
2679
+ .extra1 = SYSCTL_ZERO,
12982680 .extra2 = &two,
12992681 },
2682
+ {
2683
+ .procname = "bpf_stats_enabled",
2684
+ .data = &bpf_stats_enabled_key.key,
2685
+ .maxlen = sizeof(bpf_stats_enabled_key),
2686
+ .mode = 0644,
2687
+ .proc_handler = bpf_stats_handler,
2688
+ },
13002689 #endif
1301
-#if defined(CONFIG_TREE_RCU) || defined(CONFIG_PREEMPT_RCU)
2690
+#if defined(CONFIG_TREE_RCU)
13022691 {
13032692 .procname = "panic_on_rcu_stall",
13042693 .data = &sysctl_panic_on_rcu_stall,
13052694 .maxlen = sizeof(sysctl_panic_on_rcu_stall),
13062695 .mode = 0644,
13072696 .proc_handler = proc_dointvec_minmax,
1308
- .extra1 = &zero,
1309
- .extra2 = &one,
2697
+ .extra1 = SYSCTL_ZERO,
2698
+ .extra2 = SYSCTL_ONE,
2699
+ },
2700
+#endif
2701
+#ifdef CONFIG_STACKLEAK_RUNTIME_DISABLE
2702
+ {
2703
+ .procname = "stack_erasing",
2704
+ .data = NULL,
2705
+ .maxlen = sizeof(int),
2706
+ .mode = 0600,
2707
+ .proc_handler = stack_erasing_sysctl,
2708
+ .extra1 = SYSCTL_ZERO,
2709
+ .extra2 = SYSCTL_ONE,
13102710 },
13112711 #endif
13122712 { }
....@@ -1318,8 +2718,8 @@
13182718 .data = &sysctl_overcommit_memory,
13192719 .maxlen = sizeof(sysctl_overcommit_memory),
13202720 .mode = 0644,
1321
- .proc_handler = proc_dointvec_minmax,
1322
- .extra1 = &zero,
2721
+ .proc_handler = overcommit_policy_handler,
2722
+ .extra1 = SYSCTL_ZERO,
13232723 .extra2 = &two,
13242724 },
13252725 {
....@@ -1328,7 +2728,7 @@
13282728 .maxlen = sizeof(sysctl_panic_on_oom),
13292729 .mode = 0644,
13302730 .proc_handler = proc_dointvec_minmax,
1331
- .extra1 = &zero,
2731
+ .extra1 = SYSCTL_ZERO,
13322732 .extra2 = &two,
13332733 },
13342734 {
....@@ -1360,12 +2760,12 @@
13602760 .proc_handler = overcommit_kbytes_handler,
13612761 },
13622762 {
1363
- .procname = "page-cluster",
2763
+ .procname = "page-cluster",
13642764 .data = &page_cluster,
13652765 .maxlen = sizeof(int),
13662766 .mode = 0644,
13672767 .proc_handler = proc_dointvec_minmax,
1368
- .extra1 = &zero,
2768
+ .extra1 = SYSCTL_ZERO,
13692769 },
13702770 {
13712771 .procname = "dirty_background_ratio",
....@@ -1373,7 +2773,7 @@
13732773 .maxlen = sizeof(dirty_background_ratio),
13742774 .mode = 0644,
13752775 .proc_handler = dirty_background_ratio_handler,
1376
- .extra1 = &zero,
2776
+ .extra1 = SYSCTL_ZERO,
13772777 .extra2 = &one_hundred,
13782778 },
13792779 {
....@@ -1390,7 +2790,7 @@
13902790 .maxlen = sizeof(vm_dirty_ratio),
13912791 .mode = 0644,
13922792 .proc_handler = dirty_ratio_handler,
1393
- .extra1 = &zero,
2793
+ .extra1 = SYSCTL_ZERO,
13942794 .extra2 = &one_hundred,
13952795 },
13962796 {
....@@ -1414,7 +2814,7 @@
14142814 .maxlen = sizeof(dirty_expire_interval),
14152815 .mode = 0644,
14162816 .proc_handler = proc_dointvec_minmax,
1417
- .extra1 = &zero,
2817
+ .extra1 = SYSCTL_ZERO,
14182818 },
14192819 {
14202820 .procname = "dirtytime_expire_seconds",
....@@ -1422,7 +2822,7 @@
14222822 .maxlen = sizeof(dirtytime_expire_interval),
14232823 .mode = 0644,
14242824 .proc_handler = dirtytime_interval_handler,
1425
- .extra1 = &zero,
2825
+ .extra1 = SYSCTL_ZERO,
14262826 },
14272827 {
14282828 .procname = "swappiness",
....@@ -1430,9 +2830,20 @@
14302830 .maxlen = sizeof(vm_swappiness),
14312831 .mode = 0644,
14322832 .proc_handler = proc_dointvec_minmax,
1433
- .extra1 = &zero,
1434
- .extra2 = &one_hundred,
2833
+ .extra1 = SYSCTL_ZERO,
2834
+ .extra2 = &two_hundred,
14352835 },
2836
+#ifdef CONFIG_NUMA
2837
+ {
2838
+ .procname = "numa_stat",
2839
+ .data = &sysctl_vm_numa_stat,
2840
+ .maxlen = sizeof(int),
2841
+ .mode = 0644,
2842
+ .proc_handler = sysctl_vm_numa_stat_handler,
2843
+ .extra1 = SYSCTL_ZERO,
2844
+ .extra2 = SYSCTL_ONE,
2845
+ },
2846
+#endif
14362847 #ifdef CONFIG_HUGETLB_PAGE
14372848 {
14382849 .procname = "nr_hugepages",
....@@ -1448,15 +2859,6 @@
14482859 .maxlen = sizeof(unsigned long),
14492860 .mode = 0644,
14502861 .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,
14602862 },
14612863 #endif
14622864 {
....@@ -1487,7 +2889,7 @@
14872889 .maxlen = sizeof(int),
14882890 .mode = 0200,
14892891 .proc_handler = drop_caches_sysctl_handler,
1490
- .extra1 = &one,
2892
+ .extra1 = SYSCTL_ONE,
14912893 .extra2 = &four,
14922894 },
14932895 #ifdef CONFIG_COMPACTION
....@@ -1499,11 +2901,20 @@
14992901 .proc_handler = sysctl_compaction_handler,
15002902 },
15012903 {
2904
+ .procname = "compaction_proactiveness",
2905
+ .data = &sysctl_compaction_proactiveness,
2906
+ .maxlen = sizeof(sysctl_compaction_proactiveness),
2907
+ .mode = 0644,
2908
+ .proc_handler = compaction_proactiveness_sysctl_handler,
2909
+ .extra1 = SYSCTL_ZERO,
2910
+ .extra2 = &one_hundred,
2911
+ },
2912
+ {
15022913 .procname = "extfrag_threshold",
15032914 .data = &sysctl_extfrag_threshold,
15042915 .maxlen = sizeof(int),
15052916 .mode = 0644,
1506
- .proc_handler = sysctl_extfrag_handler,
2917
+ .proc_handler = proc_dointvec_minmax,
15072918 .extra1 = &min_extfrag_threshold,
15082919 .extra2 = &max_extfrag_threshold,
15092920 },
....@@ -1512,9 +2923,9 @@
15122923 .data = &sysctl_compact_unevictable_allowed,
15132924 .maxlen = sizeof(int),
15142925 .mode = 0644,
1515
- .proc_handler = proc_dointvec,
1516
- .extra1 = &zero,
1517
- .extra2 = &one,
2926
+ .proc_handler = proc_dointvec_minmax_warn_RT_change,
2927
+ .extra1 = SYSCTL_ZERO,
2928
+ .extra2 = SYSCTL_ONE,
15182929 },
15192930
15202931 #endif /* CONFIG_COMPACTION */
....@@ -1524,7 +2935,15 @@
15242935 .maxlen = sizeof(min_free_kbytes),
15252936 .mode = 0644,
15262937 .proc_handler = min_free_kbytes_sysctl_handler,
1527
- .extra1 = &zero,
2938
+ .extra1 = SYSCTL_ZERO,
2939
+ },
2940
+ {
2941
+ .procname = "watermark_boost_factor",
2942
+ .data = &watermark_boost_factor,
2943
+ .maxlen = sizeof(watermark_boost_factor),
2944
+ .mode = 0644,
2945
+ .proc_handler = proc_dointvec_minmax,
2946
+ .extra1 = SYSCTL_ZERO,
15282947 },
15292948 {
15302949 .procname = "watermark_scale_factor",
....@@ -1532,7 +2951,7 @@
15322951 .maxlen = sizeof(watermark_scale_factor),
15332952 .mode = 0644,
15342953 .proc_handler = watermark_scale_factor_sysctl_handler,
1535
- .extra1 = &one,
2954
+ .extra1 = SYSCTL_ONE,
15362955 .extra2 = &one_thousand,
15372956 },
15382957 {
....@@ -1541,7 +2960,7 @@
15412960 .maxlen = sizeof(extra_free_kbytes),
15422961 .mode = 0644,
15432962 .proc_handler = min_free_kbytes_sysctl_handler,
1544
- .extra1 = &zero,
2963
+ .extra1 = SYSCTL_ZERO,
15452964 },
15462965 {
15472966 .procname = "percpu_pagelist_fraction",
....@@ -1549,7 +2968,15 @@
15492968 .maxlen = sizeof(percpu_pagelist_fraction),
15502969 .mode = 0644,
15512970 .proc_handler = percpu_pagelist_fraction_sysctl_handler,
1552
- .extra1 = &zero,
2971
+ .extra1 = SYSCTL_ZERO,
2972
+ },
2973
+ {
2974
+ .procname = "page_lock_unfairness",
2975
+ .data = &sysctl_page_lock_unfairness,
2976
+ .maxlen = sizeof(sysctl_page_lock_unfairness),
2977
+ .mode = 0644,
2978
+ .proc_handler = proc_dointvec_minmax,
2979
+ .extra1 = SYSCTL_ZERO,
15532980 },
15542981 #ifdef CONFIG_MMU
15552982 {
....@@ -1558,7 +2985,7 @@
15582985 .maxlen = sizeof(sysctl_max_map_count),
15592986 .mode = 0644,
15602987 .proc_handler = proc_dointvec_minmax,
1561
- .extra1 = &zero,
2988
+ .extra1 = SYSCTL_ZERO,
15622989 },
15632990 #else
15642991 {
....@@ -1567,7 +2994,7 @@
15672994 .maxlen = sizeof(sysctl_nr_trim_pages),
15682995 .mode = 0644,
15692996 .proc_handler = proc_dointvec_minmax,
1570
- .extra1 = &zero,
2997
+ .extra1 = SYSCTL_ZERO,
15712998 },
15722999 #endif
15733000 {
....@@ -1582,25 +3009,26 @@
15823009 .data = &block_dump,
15833010 .maxlen = sizeof(block_dump),
15843011 .mode = 0644,
1585
- .proc_handler = proc_dointvec,
1586
- .extra1 = &zero,
3012
+ .proc_handler = proc_dointvec_minmax,
3013
+ .extra1 = SYSCTL_ZERO,
15873014 },
15883015 {
15893016 .procname = "vfs_cache_pressure",
15903017 .data = &sysctl_vfs_cache_pressure,
15913018 .maxlen = sizeof(sysctl_vfs_cache_pressure),
15923019 .mode = 0644,
1593
- .proc_handler = proc_dointvec,
1594
- .extra1 = &zero,
3020
+ .proc_handler = proc_dointvec_minmax,
3021
+ .extra1 = SYSCTL_ZERO,
15953022 },
1596
-#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
3023
+#if defined(HAVE_ARCH_PICK_MMAP_LAYOUT) || \
3024
+ defined(CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT)
15973025 {
15983026 .procname = "legacy_va_layout",
15993027 .data = &sysctl_legacy_va_layout,
16003028 .maxlen = sizeof(sysctl_legacy_va_layout),
16013029 .mode = 0644,
1602
- .proc_handler = proc_dointvec,
1603
- .extra1 = &zero,
3030
+ .proc_handler = proc_dointvec_minmax,
3031
+ .extra1 = SYSCTL_ZERO,
16043032 },
16053033 #endif
16063034 #ifdef CONFIG_NUMA
....@@ -1609,8 +3037,8 @@
16093037 .data = &node_reclaim_mode,
16103038 .maxlen = sizeof(node_reclaim_mode),
16113039 .mode = 0644,
1612
- .proc_handler = proc_dointvec,
1613
- .extra1 = &zero,
3040
+ .proc_handler = proc_dointvec_minmax,
3041
+ .extra1 = SYSCTL_ZERO,
16143042 },
16153043 {
16163044 .procname = "min_unmapped_ratio",
....@@ -1618,7 +3046,7 @@
16183046 .maxlen = sizeof(sysctl_min_unmapped_ratio),
16193047 .mode = 0644,
16203048 .proc_handler = sysctl_min_unmapped_ratio_sysctl_handler,
1621
- .extra1 = &zero,
3049
+ .extra1 = SYSCTL_ZERO,
16223050 .extra2 = &one_hundred,
16233051 },
16243052 {
....@@ -1627,7 +3055,7 @@
16273055 .maxlen = sizeof(sysctl_min_slab_ratio),
16283056 .mode = 0644,
16293057 .proc_handler = sysctl_min_slab_ratio_sysctl_handler,
1630
- .extra1 = &zero,
3058
+ .extra1 = SYSCTL_ZERO,
16313059 .extra2 = &one_hundred,
16323060 },
16333061 #endif
....@@ -1678,7 +3106,7 @@
16783106 #endif
16793107 .mode = 0644,
16803108 .proc_handler = proc_dointvec,
1681
- .extra1 = &zero,
3109
+ .extra1 = SYSCTL_ZERO,
16823110 },
16833111 #endif
16843112 #ifdef CONFIG_HIGHMEM
....@@ -1688,8 +3116,8 @@
16883116 .maxlen = sizeof(vm_highmem_is_dirtyable),
16893117 .mode = 0644,
16903118 .proc_handler = proc_dointvec_minmax,
1691
- .extra1 = &zero,
1692
- .extra2 = &one,
3119
+ .extra1 = SYSCTL_ZERO,
3120
+ .extra2 = SYSCTL_ONE,
16933121 },
16943122 #endif
16953123 #ifdef CONFIG_MEMORY_FAILURE
....@@ -1699,8 +3127,8 @@
16993127 .maxlen = sizeof(sysctl_memory_failure_early_kill),
17003128 .mode = 0644,
17013129 .proc_handler = proc_dointvec_minmax,
1702
- .extra1 = &zero,
1703
- .extra2 = &one,
3130
+ .extra1 = SYSCTL_ZERO,
3131
+ .extra2 = SYSCTL_ONE,
17043132 },
17053133 {
17063134 .procname = "memory_failure_recovery",
....@@ -1708,8 +3136,8 @@
17083136 .maxlen = sizeof(sysctl_memory_failure_recovery),
17093137 .mode = 0644,
17103138 .proc_handler = proc_dointvec_minmax,
1711
- .extra1 = &zero,
1712
- .extra2 = &one,
3139
+ .extra1 = SYSCTL_ZERO,
3140
+ .extra2 = SYSCTL_ONE,
17133141 },
17143142 #endif
17153143 {
....@@ -1746,6 +3174,17 @@
17463174 .proc_handler = proc_dointvec_minmax,
17473175 .extra1 = (void *)&mmap_rnd_compat_bits_min,
17483176 .extra2 = (void *)&mmap_rnd_compat_bits_max,
3177
+ },
3178
+#endif
3179
+#ifdef CONFIG_USERFAULTFD
3180
+ {
3181
+ .procname = "unprivileged_userfaultfd",
3182
+ .data = &sysctl_unprivileged_userfaultfd,
3183
+ .maxlen = sizeof(sysctl_unprivileged_userfaultfd),
3184
+ .mode = 0644,
3185
+ .proc_handler = proc_dointvec_minmax,
3186
+ .extra1 = SYSCTL_ZERO,
3187
+ .extra2 = SYSCTL_ONE,
17493188 },
17503189 #endif
17513190 { }
....@@ -1881,8 +3320,8 @@
18813320 .maxlen = sizeof(int),
18823321 .mode = 0600,
18833322 .proc_handler = proc_dointvec_minmax,
1884
- .extra1 = &zero,
1885
- .extra2 = &one,
3323
+ .extra1 = SYSCTL_ZERO,
3324
+ .extra2 = SYSCTL_ONE,
18863325 },
18873326 {
18883327 .procname = "protected_hardlinks",
....@@ -1890,8 +3329,8 @@
18903329 .maxlen = sizeof(int),
18913330 .mode = 0600,
18923331 .proc_handler = proc_dointvec_minmax,
1893
- .extra1 = &zero,
1894
- .extra2 = &one,
3332
+ .extra1 = SYSCTL_ZERO,
3333
+ .extra2 = SYSCTL_ONE,
18953334 },
18963335 {
18973336 .procname = "protected_fifos",
....@@ -1899,7 +3338,7 @@
18993338 .maxlen = sizeof(int),
19003339 .mode = 0600,
19013340 .proc_handler = proc_dointvec_minmax,
1902
- .extra1 = &zero,
3341
+ .extra1 = SYSCTL_ZERO,
19033342 .extra2 = &two,
19043343 },
19053344 {
....@@ -1908,7 +3347,7 @@
19083347 .maxlen = sizeof(int),
19093348 .mode = 0600,
19103349 .proc_handler = proc_dointvec_minmax,
1911
- .extra1 = &zero,
3350
+ .extra1 = SYSCTL_ZERO,
19123351 .extra2 = &two,
19133352 },
19143353 {
....@@ -1917,7 +3356,7 @@
19173356 .maxlen = sizeof(int),
19183357 .mode = 0644,
19193358 .proc_handler = proc_dointvec_minmax_coredump,
1920
- .extra1 = &zero,
3359
+ .extra1 = SYSCTL_ZERO,
19213360 .extra2 = &two,
19223361 },
19233362 #if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
....@@ -1954,7 +3393,7 @@
19543393 .maxlen = sizeof(unsigned int),
19553394 .mode = 0644,
19563395 .proc_handler = proc_dointvec_minmax,
1957
- .extra1 = &one,
3396
+ .extra1 = SYSCTL_ONE,
19583397 },
19593398 { }
19603399 };
....@@ -1976,14 +3415,43 @@
19763415 .maxlen = sizeof(int),
19773416 .mode = 0644,
19783417 .proc_handler = proc_kprobes_optimization_handler,
1979
- .extra1 = &zero,
1980
- .extra2 = &one,
3418
+ .extra1 = SYSCTL_ZERO,
3419
+ .extra2 = SYSCTL_ONE,
19813420 },
19823421 #endif
19833422 { }
19843423 };
19853424
19863425 static struct ctl_table dev_table[] = {
3426
+ { }
3427
+};
3428
+
3429
+static struct ctl_table sysctl_base_table[] = {
3430
+ {
3431
+ .procname = "kernel",
3432
+ .mode = 0555,
3433
+ .child = kern_table,
3434
+ },
3435
+ {
3436
+ .procname = "vm",
3437
+ .mode = 0555,
3438
+ .child = vm_table,
3439
+ },
3440
+ {
3441
+ .procname = "fs",
3442
+ .mode = 0555,
3443
+ .child = fs_table,
3444
+ },
3445
+ {
3446
+ .procname = "debug",
3447
+ .mode = 0555,
3448
+ .child = debug_table,
3449
+ },
3450
+ {
3451
+ .procname = "dev",
3452
+ .mode = 0555,
3453
+ .child = dev_table,
3454
+ },
19873455 { }
19883456 };
19893457
....@@ -1995,1377 +3463,7 @@
19953463 kmemleak_not_leak(hdr);
19963464 return 0;
19973465 }
1998
-
19993466 #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
-
33693467 /*
33703468 * No sense putting this after each symbol definition, twice,
33713469 * exception granted :-)
....@@ -3380,3 +3478,4 @@
33803478 EXPORT_SYMBOL(proc_dostring);
33813479 EXPORT_SYMBOL(proc_doulongvec_minmax);
33823480 EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
3481
+EXPORT_SYMBOL(proc_do_large_bitmap);