blob: 5ae443b2882e2f4698a4a71a44be462613967308 [file] [log] [blame]
Thomas Gleixner457c8992019-05-19 13:08:55 +01001// SPDX-License-Identifier: GPL-2.0-only
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * sysctl.c: General linux system control interface
4 *
5 * Begun 24 March 1995, Stephen Tweedie
6 * Added /proc support, Dec 1995
7 * Added bdflush entry and intvec min/max checking, 2/23/96, Tom Dyas.
8 * Added hooks for /proc/sys/net (minor, minor patch), 96/4/1, Mike Shaver.
9 * Added kernel/java-{interpreter,appletviewer}, 96/5/10, Mike Shaver.
10 * Dynamic registration fixes, Stephen Tweedie.
11 * Added kswapd-interval, ctrl-alt-del, printk stuff, 1/8/97, Chris Horn.
12 * Made sysctl support optional via CONFIG_SYSCTL, 1/10/97, Chris
13 * Horn.
14 * Added proc_doulongvec_ms_jiffies_minmax, 09/08/99, Carlos H. Bauer.
15 * Added proc_doulongvec_minmax, 09/08/99, Carlos H. Bauer.
16 * Changed linked lists to use list.h instead of lists.h, 02/24/00, Bill
17 * Wendling.
18 * The list_for_each() macro wasn't appropriate for the sysctl loop.
19 * Removed it and replaced it with older style, 03/23/00, Bill Wendling
20 */
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/module.h>
23#include <linux/mm.h>
24#include <linux/swap.h>
25#include <linux/slab.h>
26#include <linux/sysctl.h>
Akinobu Mita5a04cca2012-03-28 14:42:50 -070027#include <linux/bitmap.h>
Dave Youngd33ed522010-03-10 15:23:59 -080028#include <linux/signal.h>
Andy Shevchenkof39650d2021-06-30 18:54:59 -070029#include <linux/panic.h>
Dan Rosenberg455cd5a2011-01-12 16:59:41 -080030#include <linux/printk.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/proc_fs.h>
Andrew Morgan72c2d582007-10-18 03:05:59 -070032#include <linux/security.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/ctype.h>
Steven Rostedtfd4b6162012-07-30 14:42:48 -070034#include <linux/kmemleak.h>
Jakub Kicinskib6459412021-12-28 16:49:13 -080035#include <linux/filter.h>
Adrian Bunk62239ac2007-07-17 04:03:45 -070036#include <linux/fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/init.h>
38#include <linux/kernel.h>
Kay Sievers0296b222005-11-11 05:33:52 +010039#include <linux/kobject.h>
Arnaldo Carvalho de Melo20380732005-08-16 02:18:02 -030040#include <linux/net.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/sysrq.h>
42#include <linux/highuid.h>
43#include <linux/writeback.h>
Ingo Molnar3fff4c42009-09-22 16:18:09 +020044#include <linux/ratelimit.h>
Mel Gorman76ab0f52010-05-24 14:32:28 -070045#include <linux/compaction.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#include <linux/hugetlb.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <linux/initrd.h>
David Howells0b77f5b2008-04-29 01:01:32 -070048#include <linux/key.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/times.h>
50#include <linux/limits.h>
51#include <linux/dcache.h>
52#include <linux/syscalls.h>
Adrian Bunkc748e132008-07-23 21:27:03 -070053#include <linux/vmstat.h>
Pavel Machekc255d842006-02-20 18:27:58 -080054#include <linux/nfs_fs.h>
55#include <linux/acpi.h>
Jeremy Fitzhardinge10a0a8d2007-07-17 18:37:02 -070056#include <linux/reboot.h>
Steven Rostedtb0fc4942008-05-12 21:20:43 +020057#include <linux/ftrace.h>
Ingo Molnarcdd6c482009-09-21 12:02:48 +020058#include <linux/perf_event.h>
David Rientjes8e4228e2010-08-09 17:18:56 -070059#include <linux/oom.h>
Eric Paris17f60a72011-04-01 17:07:50 -040060#include <linux/kmod.h>
Dan Ballard73efc032011-10-31 17:11:20 -070061#include <linux/capability.h>
Al Viro40401532012-02-13 03:58:52 +000062#include <linux/binfmts.h>
Clark Williamscf4aebc22013-02-07 09:46:59 -060063#include <linux/sched/sysctl.h>
Kees Cook79847542014-01-23 15:55:59 -080064#include <linux/kexec.h>
Alexei Starovoitov1be7f752015-10-07 22:23:21 -070065#include <linux/bpf.h>
Eric W. Biedermand2921682016-09-28 00:27:17 -050066#include <linux/mount.h>
Peter Xucefdca02019-05-13 17:16:41 -070067#include <linux/userfaultfd_k.h>
Christoph Hellwig2374c092020-04-24 08:43:36 +020068#include <linux/latencytop.h>
69#include <linux/pid.h>
Peter Zijlstra0cd7c742021-05-10 14:01:00 +020070#include <linux/delayacct.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070071
Christian Brauner7f2923c2019-03-07 16:29:40 -080072#include "../lib/kstrtox.h"
73
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080074#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070075#include <asm/processor.h>
76
Andi Kleen29cbc782006-09-30 01:47:55 +020077#ifdef CONFIG_X86
78#include <asm/nmi.h>
Chuck Ebbert0741f4d2006-12-07 02:14:11 +010079#include <asm/stacktrace.h>
Ingo Molnar6e7c4022008-01-30 13:30:05 +010080#include <asm/io.h>
Andi Kleen29cbc782006-09-30 01:47:55 +020081#endif
David Howellsd550bbd2012-03-28 18:30:03 +010082#ifdef CONFIG_SPARC
83#include <asm/setup.h>
84#endif
Dave Youngc55b7c32010-03-10 15:24:08 -080085#ifdef CONFIG_BSD_PROCESS_ACCT
86#include <linux/acct.h>
87#endif
Dave Young4f0e0562010-03-10 15:24:09 -080088#ifdef CONFIG_RT_MUTEXES
89#include <linux/rtmutex.h>
90#endif
Dave Young2edf5e42010-03-10 15:24:10 -080091#if defined(CONFIG_PROVE_LOCKING) || defined(CONFIG_LOCK_STAT)
92#include <linux/lockdep.h>
93#endif
Don Zickus504d7cf2010-02-12 17:19:19 -050094
Linus Torvalds1da177e2005-04-16 15:20:36 -070095#if defined(CONFIG_SYSCTL)
96
Ravikiran G Thirumalaic4f3b632007-10-16 23:26:09 -070097/* Constants used for minimum and maximum */
Ravikiran G Thirumalaic4f3b632007-10-16 23:26:09 -070098
Arnaldo Carvalho de Meloc5dfd782016-04-21 12:28:50 -030099#ifdef CONFIG_PERF_EVENTS
Xiaoming Nid73840e2022-01-21 22:11:14 -0800100static const int six_hundred_forty_kb = 640 * 1024;
Arnaldo Carvalho de Meloc5dfd782016-04-21 12:28:50 -0300101#endif
Ravikiran G Thirumalaic4f3b632007-10-16 23:26:09 -0700102
Andrea Righi9e4a5bd2009-04-30 15:08:57 -0700103/* this is needed for the proc_doulongvec_minmax of vm_dirty_bytes */
Xiaoming Nid73840e2022-01-21 22:11:14 -0800104static const unsigned long dirty_bytes_min = 2 * PAGE_SIZE;
Andrea Righi9e4a5bd2009-04-30 15:08:57 -0700105
Stephen Kittf6288672022-01-21 22:11:09 -0800106static const int ngroups_max = NGROUPS_MAX;
Dan Ballard73efc032011-10-31 17:11:20 -0700107static const int cap_last_cap = CAP_LAST_CAP;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
Randy Dunlapd6f8ff72006-10-19 23:28:34 -0700109#ifdef CONFIG_PROC_SYSCTL
Kees Cookf4aacea2014-06-06 14:37:19 -0700110
Luis R. Rodrigueza19ac332017-07-12 14:33:30 -0700111/**
112 * enum sysctl_writes_mode - supported sysctl write modes
113 *
114 * @SYSCTL_WRITES_LEGACY: each write syscall must fully contain the sysctl value
Weitao Hou65f50f22019-07-16 16:26:54 -0700115 * to be written, and multiple writes on the same sysctl file descriptor
116 * will rewrite the sysctl value, regardless of file position. No warning
117 * is issued when the initial position is not 0.
Luis R. Rodrigueza19ac332017-07-12 14:33:30 -0700118 * @SYSCTL_WRITES_WARN: same as above but warn when the initial file position is
Weitao Hou65f50f22019-07-16 16:26:54 -0700119 * not 0.
Luis R. Rodrigueza19ac332017-07-12 14:33:30 -0700120 * @SYSCTL_WRITES_STRICT: writes to numeric sysctl entries must always be at
Weitao Hou65f50f22019-07-16 16:26:54 -0700121 * file position 0 and the value must be fully contained in the buffer
122 * sent to the write syscall. If dealing with strings respect the file
123 * position, but restrict this to the max length of the buffer, anything
124 * passed the max length will be ignored. Multiple writes will append
125 * to the buffer.
Luis R. Rodrigueza19ac332017-07-12 14:33:30 -0700126 *
127 * These write modes control how current file position affects the behavior of
128 * updating sysctl values through the proc interface on each write.
129 */
130enum sysctl_writes_mode {
131 SYSCTL_WRITES_LEGACY = -1,
132 SYSCTL_WRITES_WARN = 0,
133 SYSCTL_WRITES_STRICT = 1,
134};
Kees Cookf4aacea2014-06-06 14:37:19 -0700135
Luis R. Rodrigueza19ac332017-07-12 14:33:30 -0700136static enum sysctl_writes_mode sysctl_writes_strict = SYSCTL_WRITES_STRICT;
Christoph Hellwigf461d2d2020-04-24 08:43:37 +0200137#endif /* CONFIG_PROC_SYSCTL */
Luis R. Rodriguezceb18132018-03-10 06:14:51 -0800138
Alexandre Ghiti67f39772019-09-23 15:38:47 -0700139#if defined(HAVE_ARCH_PICK_MMAP_LAYOUT) || \
140 defined(CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141int sysctl_legacy_va_layout;
142#endif
143
Mel Gorman5e771902010-05-24 14:32:31 -0700144#ifdef CONFIG_COMPACTION
Xiaoming Ni2452dcb2022-01-21 22:11:19 -0800145/* min_extfrag_threshold is SYSCTL_ZERO */;
Xiaoming Nid73840e2022-01-21 22:11:14 -0800146static const int max_extfrag_threshold = 1000;
Mel Gorman5e771902010-05-24 14:32:31 -0700147#endif
148
Eric W. Biedermanb89a8172006-09-27 01:51:04 -0700149#endif /* CONFIG_SYSCTL */
150
Arnd Bergmann5447e8e2020-05-05 16:07:12 +0200151#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_SYSCTL)
Song Liud46edd62020-04-30 00:15:04 -0700152static int bpf_stats_handler(struct ctl_table *table, int write,
Tobias Klauser7787b6f2020-08-24 16:20:47 +0200153 void *buffer, size_t *lenp, loff_t *ppos)
Song Liud46edd62020-04-30 00:15:04 -0700154{
155 struct static_key *key = (struct static_key *)table->data;
156 static int saved_val;
157 int val, ret;
158 struct ctl_table tmp = {
159 .data = &val,
160 .maxlen = sizeof(val),
161 .mode = table->mode,
162 .extra1 = SYSCTL_ZERO,
163 .extra2 = SYSCTL_ONE,
164 };
165
166 if (write && !capable(CAP_SYS_ADMIN))
167 return -EPERM;
168
169 mutex_lock(&bpf_stats_enabled_mutex);
170 val = saved_val;
171 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
172 if (write && !ret && val != saved_val) {
173 if (val)
174 static_key_slow_inc(key);
175 else
176 static_key_slow_dec(key);
177 saved_val = val;
178 }
179 mutex_unlock(&bpf_stats_enabled_mutex);
180 return ret;
181}
Daniel Borkmann08389d82021-05-11 22:35:17 +0200182
183static int bpf_unpriv_handler(struct ctl_table *table, int write,
184 void *buffer, size_t *lenp, loff_t *ppos)
185{
186 int ret, unpriv_enable = *(int *)table->data;
187 bool locked_state = unpriv_enable == 1;
188 struct ctl_table tmp = *table;
189
190 if (write && !capable(CAP_SYS_ADMIN))
191 return -EPERM;
192
193 tmp.data = &unpriv_enable;
194 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
195 if (write && !ret) {
196 if (locked_state && unpriv_enable != 1)
197 return -EPERM;
198 *(int *)table->data = unpriv_enable;
199 }
200 return ret;
201}
202#endif /* CONFIG_BPF_SYSCALL && CONFIG_SYSCTL */
Song Liud46edd62020-04-30 00:15:04 -0700203
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204/*
205 * /proc/sys support
206 */
207
Eric W. Biedermanb89a8172006-09-27 01:51:04 -0700208#ifdef CONFIG_PROC_SYSCTL
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209
Kees Cookf8808302014-06-06 14:37:17 -0700210static int _proc_do_string(char *data, int maxlen, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +0200211 char *buffer, size_t *lenp, loff_t *ppos)
Sam Vilainf5dd3d62006-10-02 02:18:04 -0700212{
213 size_t len;
Christoph Hellwig32927392020-04-24 08:43:38 +0200214 char c, *p;
Oleg Nesterov8d060872007-02-10 01:46:38 -0800215
216 if (!data || !maxlen || !*lenp) {
Sam Vilainf5dd3d62006-10-02 02:18:04 -0700217 *lenp = 0;
218 return 0;
219 }
Oleg Nesterov8d060872007-02-10 01:46:38 -0800220
Sam Vilainf5dd3d62006-10-02 02:18:04 -0700221 if (write) {
Kees Cookf4aacea2014-06-06 14:37:19 -0700222 if (sysctl_writes_strict == SYSCTL_WRITES_STRICT) {
223 /* Only continue writes not past the end of buffer. */
224 len = strlen(data);
225 if (len > maxlen - 1)
226 len = maxlen - 1;
227
228 if (*ppos > len)
229 return 0;
230 len = *ppos;
231 } else {
232 /* Start writing from beginning of buffer. */
233 len = 0;
234 }
235
Kees Cook2ca9bb42014-06-06 14:37:18 -0700236 *ppos += *lenp;
Sam Vilainf5dd3d62006-10-02 02:18:04 -0700237 p = buffer;
Kees Cook2ca9bb42014-06-06 14:37:18 -0700238 while ((p - buffer) < *lenp && len < maxlen - 1) {
Christoph Hellwig32927392020-04-24 08:43:38 +0200239 c = *(p++);
Sam Vilainf5dd3d62006-10-02 02:18:04 -0700240 if (c == 0 || c == '\n')
241 break;
Kees Cook2ca9bb42014-06-06 14:37:18 -0700242 data[len++] = c;
Sam Vilainf5dd3d62006-10-02 02:18:04 -0700243 }
Kees Cookf8808302014-06-06 14:37:17 -0700244 data[len] = 0;
Sam Vilainf5dd3d62006-10-02 02:18:04 -0700245 } else {
246 len = strlen(data);
247 if (len > maxlen)
248 len = maxlen;
Oleg Nesterov8d060872007-02-10 01:46:38 -0800249
250 if (*ppos > len) {
251 *lenp = 0;
252 return 0;
253 }
254
255 data += *ppos;
256 len -= *ppos;
257
Sam Vilainf5dd3d62006-10-02 02:18:04 -0700258 if (len > *lenp)
259 len = *lenp;
260 if (len)
Christoph Hellwig32927392020-04-24 08:43:38 +0200261 memcpy(buffer, data, len);
Sam Vilainf5dd3d62006-10-02 02:18:04 -0700262 if (len < *lenp) {
Christoph Hellwig32927392020-04-24 08:43:38 +0200263 buffer[len] = '\n';
Sam Vilainf5dd3d62006-10-02 02:18:04 -0700264 len++;
265 }
266 *lenp = len;
267 *ppos += len;
268 }
269 return 0;
270}
271
Kees Cookf4aacea2014-06-06 14:37:19 -0700272static void warn_sysctl_write(struct ctl_table *table)
273{
274 pr_warn_once("%s wrote to %s when file position was not 0!\n"
275 "This will not be supported in the future. To silence this\n"
276 "warning, set kernel.sysctl_writes_strict = -1\n",
277 current->comm, table->procname);
278}
279
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280/**
Randy Dunlap5f733e82018-08-21 22:01:06 -0700281 * proc_first_pos_non_zero_ignore - check if first position is allowed
Luis R. Rodriguezd383d482017-07-12 14:33:33 -0700282 * @ppos: file position
283 * @table: the sysctl table
284 *
285 * Returns true if the first position is non-zero and the sysctl_writes_strict
286 * mode indicates this is not allowed for numeric input types. String proc
Randy Dunlap5f733e82018-08-21 22:01:06 -0700287 * handlers can ignore the return value.
Luis R. Rodriguezd383d482017-07-12 14:33:33 -0700288 */
289static bool proc_first_pos_non_zero_ignore(loff_t *ppos,
290 struct ctl_table *table)
291{
292 if (!*ppos)
293 return false;
294
295 switch (sysctl_writes_strict) {
296 case SYSCTL_WRITES_STRICT:
297 return true;
298 case SYSCTL_WRITES_WARN:
299 warn_sysctl_write(table);
300 return false;
301 default:
302 return false;
303 }
304}
305
306/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 * proc_dostring - read a string sysctl
308 * @table: the sysctl table
309 * @write: %TRUE if this is a write to the sysctl file
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 * @buffer: the user buffer
311 * @lenp: the size of the user buffer
312 * @ppos: file position
313 *
314 * Reads/writes a string from/to the user buffer. If the kernel
315 * buffer provided is not large enough to hold the string, the
316 * string is truncated. The copied string is %NULL-terminated.
317 * If the string is being read by the user process, it is copied
318 * and a newline '\n' is added. It is truncated if the buffer is
319 * not large enough.
320 *
321 * Returns 0 on success.
322 */
Alexey Dobriyan8d65af72009-09-23 15:57:19 -0700323int proc_dostring(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +0200324 void *buffer, size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325{
Luis R. Rodriguezd383d482017-07-12 14:33:33 -0700326 if (write)
327 proc_first_pos_non_zero_ignore(ppos, table);
Kees Cookf4aacea2014-06-06 14:37:19 -0700328
Christoph Hellwig32927392020-04-24 08:43:38 +0200329 return _proc_do_string(table->data, table->maxlen, write, buffer, lenp,
330 ppos);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331}
332
Amerigo Wang00b7c332010-05-05 00:26:45 +0000333static size_t proc_skip_spaces(char **buf)
334{
335 size_t ret;
336 char *tmp = skip_spaces(*buf);
337 ret = tmp - *buf;
338 *buf = tmp;
339 return ret;
340}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341
Octavian Purdila9f977fb2010-05-05 00:26:55 +0000342static void proc_skip_char(char **buf, size_t *size, const char v)
343{
344 while (*size) {
345 if (**buf != v)
346 break;
347 (*size)--;
348 (*buf)++;
349 }
350}
351
Christian Brauner7f2923c2019-03-07 16:29:40 -0800352/**
353 * strtoul_lenient - parse an ASCII formatted integer from a buffer and only
354 * fail on overflow
355 *
356 * @cp: kernel buffer containing the string to parse
357 * @endp: pointer to store the trailing characters
358 * @base: the base to use
359 * @res: where the parsed integer will be stored
360 *
361 * In case of success 0 is returned and @res will contain the parsed integer,
362 * @endp will hold any trailing characters.
363 * This function will fail the parse on overflow. If there wasn't an overflow
364 * the function will defer the decision what characters count as invalid to the
365 * caller.
366 */
367static int strtoul_lenient(const char *cp, char **endp, unsigned int base,
368 unsigned long *res)
369{
370 unsigned long long result;
371 unsigned int rv;
372
373 cp = _parse_integer_fixup_radix(cp, &base);
374 rv = _parse_integer(cp, base, &result);
375 if ((rv & KSTRTOX_OVERFLOW) || (result != (unsigned long)result))
376 return -ERANGE;
377
378 cp += rv;
379
380 if (endp)
381 *endp = (char *)cp;
382
383 *res = (unsigned long)result;
384 return 0;
385}
386
Amerigo Wang00b7c332010-05-05 00:26:45 +0000387#define TMPBUFLEN 22
388/**
Randy Dunlap0fc377b2010-05-21 11:29:53 -0700389 * proc_get_long - reads an ASCII formatted integer from a user buffer
Amerigo Wang00b7c332010-05-05 00:26:45 +0000390 *
Randy Dunlap0fc377b2010-05-21 11:29:53 -0700391 * @buf: a kernel buffer
392 * @size: size of the kernel buffer
393 * @val: this is where the number will be stored
394 * @neg: set to %TRUE if number is negative
395 * @perm_tr: a vector which contains the allowed trailers
396 * @perm_tr_len: size of the perm_tr vector
397 * @tr: pointer to store the trailer character
Amerigo Wang00b7c332010-05-05 00:26:45 +0000398 *
Randy Dunlap0fc377b2010-05-21 11:29:53 -0700399 * In case of success %0 is returned and @buf and @size are updated with
400 * the amount of bytes read. If @tr is non-NULL and a trailing
401 * character exists (size is non-zero after returning from this
402 * function), @tr is updated with the trailing character.
Amerigo Wang00b7c332010-05-05 00:26:45 +0000403 */
404static int proc_get_long(char **buf, size_t *size,
405 unsigned long *val, bool *neg,
406 const char *perm_tr, unsigned perm_tr_len, char *tr)
407{
408 int len;
409 char *p, tmp[TMPBUFLEN];
410
411 if (!*size)
412 return -EINVAL;
413
414 len = *size;
415 if (len > TMPBUFLEN - 1)
416 len = TMPBUFLEN - 1;
417
418 memcpy(tmp, *buf, len);
419
420 tmp[len] = 0;
421 p = tmp;
422 if (*p == '-' && *size > 1) {
423 *neg = true;
424 p++;
425 } else
426 *neg = false;
427 if (!isdigit(*p))
428 return -EINVAL;
429
Christian Brauner7f2923c2019-03-07 16:29:40 -0800430 if (strtoul_lenient(p, &p, 0, val))
431 return -EINVAL;
Amerigo Wang00b7c332010-05-05 00:26:45 +0000432
433 len = p - tmp;
434
435 /* We don't know if the next char is whitespace thus we may accept
436 * invalid integers (e.g. 1234...a) or two integers instead of one
437 * (e.g. 123...1). So lets not allow such large numbers. */
438 if (len == TMPBUFLEN - 1)
439 return -EINVAL;
440
441 if (len < *size && perm_tr_len && !memchr(perm_tr, *p, perm_tr_len))
442 return -EINVAL;
443
444 if (tr && (len < *size))
445 *tr = *p;
446
447 *buf += len;
448 *size -= len;
449
450 return 0;
451}
452
453/**
Randy Dunlap0fc377b2010-05-21 11:29:53 -0700454 * proc_put_long - converts an integer to a decimal ASCII formatted string
Amerigo Wang00b7c332010-05-05 00:26:45 +0000455 *
Randy Dunlap0fc377b2010-05-21 11:29:53 -0700456 * @buf: the user buffer
457 * @size: the size of the user buffer
458 * @val: the integer to be converted
459 * @neg: sign of the number, %TRUE for negative
Amerigo Wang00b7c332010-05-05 00:26:45 +0000460 *
Christoph Hellwig32927392020-04-24 08:43:38 +0200461 * In case of success @buf and @size are updated with the amount of bytes
462 * written.
Amerigo Wang00b7c332010-05-05 00:26:45 +0000463 */
Christoph Hellwig32927392020-04-24 08:43:38 +0200464static void proc_put_long(void **buf, size_t *size, unsigned long val, bool neg)
Amerigo Wang00b7c332010-05-05 00:26:45 +0000465{
466 int len;
467 char tmp[TMPBUFLEN], *p = tmp;
468
469 sprintf(p, "%s%lu", neg ? "-" : "", val);
470 len = strlen(tmp);
471 if (len > *size)
472 len = *size;
Christoph Hellwig32927392020-04-24 08:43:38 +0200473 memcpy(*buf, tmp, len);
Amerigo Wang00b7c332010-05-05 00:26:45 +0000474 *size -= len;
475 *buf += len;
Amerigo Wang00b7c332010-05-05 00:26:45 +0000476}
477#undef TMPBUFLEN
478
Christoph Hellwig32927392020-04-24 08:43:38 +0200479static void proc_put_char(void **buf, size_t *size, char c)
Amerigo Wang00b7c332010-05-05 00:26:45 +0000480{
481 if (*size) {
Christoph Hellwig32927392020-04-24 08:43:38 +0200482 char **buffer = (char **)buf;
483 **buffer = c;
484
485 (*size)--;
486 (*buffer)++;
Amerigo Wang00b7c332010-05-05 00:26:45 +0000487 *buf = *buffer;
488 }
Amerigo Wang00b7c332010-05-05 00:26:45 +0000489}
490
Jia Hea2071572021-08-03 12:59:36 +0200491static int do_proc_dobool_conv(bool *negp, unsigned long *lvalp,
492 int *valp,
493 int write, void *data)
494{
495 if (write) {
496 *(bool *)valp = *lvalp;
497 } else {
498 int val = *(bool *)valp;
499
500 *lvalp = (unsigned long)val;
501 *negp = false;
502 }
503 return 0;
504}
505
Amerigo Wang00b7c332010-05-05 00:26:45 +0000506static int do_proc_dointvec_conv(bool *negp, unsigned long *lvalp,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 int *valp,
508 int write, void *data)
509{
510 if (write) {
Heinrich Schuchardt230633d2015-04-16 12:48:07 -0700511 if (*negp) {
512 if (*lvalp > (unsigned long) INT_MAX + 1)
513 return -EINVAL;
514 *valp = -*lvalp;
515 } else {
516 if (*lvalp > (unsigned long) INT_MAX)
517 return -EINVAL;
518 *valp = *lvalp;
519 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 } else {
521 int val = *valp;
522 if (val < 0) {
Amerigo Wang00b7c332010-05-05 00:26:45 +0000523 *negp = true;
Ilya Dryomov9a5bc722015-09-09 15:39:06 -0700524 *lvalp = -(unsigned long)val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 } else {
Amerigo Wang00b7c332010-05-05 00:26:45 +0000526 *negp = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 *lvalp = (unsigned long)val;
528 }
529 }
530 return 0;
531}
532
Luis R. Rodriguez4f2fec02017-07-12 14:33:36 -0700533static int do_proc_douintvec_conv(unsigned long *lvalp,
534 unsigned int *valp,
535 int write, void *data)
Subash Abhinov Kasiviswanathane7d316a2016-08-25 15:16:51 -0700536{
537 if (write) {
Luis R. Rodriguez4f2fec02017-07-12 14:33:36 -0700538 if (*lvalp > UINT_MAX)
Subash Abhinov Kasiviswanathane7d316a2016-08-25 15:16:51 -0700539 return -EINVAL;
540 *valp = *lvalp;
541 } else {
542 unsigned int val = *valp;
543 *lvalp = (unsigned long)val;
544 }
545 return 0;
546}
547
Amerigo Wang00b7c332010-05-05 00:26:45 +0000548static const char proc_wspace_sep[] = { ' ', '\t', '\n' };
549
Eric W. Biedermand8217f02007-10-18 03:05:22 -0700550static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
Christoph Hellwig32927392020-04-24 08:43:38 +0200551 int write, void *buffer,
Kirill Korotaevfcfbd542006-10-02 02:18:23 -0700552 size_t *lenp, loff_t *ppos,
Amerigo Wang00b7c332010-05-05 00:26:45 +0000553 int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 int write, void *data),
555 void *data)
556{
Amerigo Wang00b7c332010-05-05 00:26:45 +0000557 int *i, vleft, first = 1, err = 0;
Amerigo Wang00b7c332010-05-05 00:26:45 +0000558 size_t left;
Christoph Hellwig32927392020-04-24 08:43:38 +0200559 char *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560
Amerigo Wang00b7c332010-05-05 00:26:45 +0000561 if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 *lenp = 0;
563 return 0;
564 }
565
Kirill Korotaevfcfbd542006-10-02 02:18:23 -0700566 i = (int *) tbl_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 vleft = table->maxlen / sizeof(*i);
568 left = *lenp;
569
570 if (!conv)
571 conv = do_proc_dointvec_conv;
572
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 if (write) {
Luis R. Rodriguezd383d482017-07-12 14:33:33 -0700574 if (proc_first_pos_non_zero_ignore(ppos, table))
575 goto out;
Kees Cookf4aacea2014-06-06 14:37:19 -0700576
Amerigo Wang00b7c332010-05-05 00:26:45 +0000577 if (left > PAGE_SIZE - 1)
578 left = PAGE_SIZE - 1;
Christoph Hellwig32927392020-04-24 08:43:38 +0200579 p = buffer;
Amerigo Wang00b7c332010-05-05 00:26:45 +0000580 }
581
582 for (; left && vleft--; i++, first=0) {
583 unsigned long lval;
584 bool neg;
585
586 if (write) {
Al Viro70f6cbb2015-12-24 00:13:10 -0500587 left -= proc_skip_spaces(&p);
Amerigo Wang00b7c332010-05-05 00:26:45 +0000588
J. R. Okajima563b0462010-05-25 16:10:14 -0700589 if (!left)
590 break;
Al Viro70f6cbb2015-12-24 00:13:10 -0500591 err = proc_get_long(&p, &left, &lval, &neg,
Amerigo Wang00b7c332010-05-05 00:26:45 +0000592 proc_wspace_sep,
593 sizeof(proc_wspace_sep), NULL);
594 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 break;
Amerigo Wang00b7c332010-05-05 00:26:45 +0000596 if (conv(&neg, &lval, i, 1, data)) {
597 err = -EINVAL;
598 break;
599 }
600 } else {
601 if (conv(&neg, &lval, i, 0, data)) {
602 err = -EINVAL;
603 break;
604 }
605 if (!first)
Christoph Hellwig32927392020-04-24 08:43:38 +0200606 proc_put_char(&buffer, &left, '\t');
607 proc_put_long(&buffer, &left, lval, neg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 }
609 }
Amerigo Wang00b7c332010-05-05 00:26:45 +0000610
611 if (!write && !first && left && !err)
Christoph Hellwig32927392020-04-24 08:43:38 +0200612 proc_put_char(&buffer, &left, '\n');
J. R. Okajima563b0462010-05-25 16:10:14 -0700613 if (write && !err && left)
Al Viro70f6cbb2015-12-24 00:13:10 -0500614 left -= proc_skip_spaces(&p);
Christoph Hellwig32927392020-04-24 08:43:38 +0200615 if (write && first)
616 return err ? : -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 *lenp -= left;
Kees Cookf4aacea2014-06-06 14:37:19 -0700618out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 *ppos += *lenp;
Amerigo Wang00b7c332010-05-05 00:26:45 +0000620 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621}
622
Alexey Dobriyan8d65af72009-09-23 15:57:19 -0700623static int do_proc_dointvec(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +0200624 void *buffer, size_t *lenp, loff_t *ppos,
Amerigo Wang00b7c332010-05-05 00:26:45 +0000625 int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
Kirill Korotaevfcfbd542006-10-02 02:18:23 -0700626 int write, void *data),
627 void *data)
628{
Alexey Dobriyan8d65af72009-09-23 15:57:19 -0700629 return __do_proc_dointvec(table->data, table, write,
Kirill Korotaevfcfbd542006-10-02 02:18:23 -0700630 buffer, lenp, ppos, conv, data);
631}
632
Luis R. Rodriguez4f2fec02017-07-12 14:33:36 -0700633static int do_proc_douintvec_w(unsigned int *tbl_data,
634 struct ctl_table *table,
Christoph Hellwig32927392020-04-24 08:43:38 +0200635 void *buffer,
Luis R. Rodriguez4f2fec02017-07-12 14:33:36 -0700636 size_t *lenp, loff_t *ppos,
637 int (*conv)(unsigned long *lvalp,
638 unsigned int *valp,
639 int write, void *data),
640 void *data)
641{
642 unsigned long lval;
643 int err = 0;
644 size_t left;
645 bool neg;
Christoph Hellwig32927392020-04-24 08:43:38 +0200646 char *p = buffer;
Luis R. Rodriguez4f2fec02017-07-12 14:33:36 -0700647
648 left = *lenp;
649
650 if (proc_first_pos_non_zero_ignore(ppos, table))
651 goto bail_early;
652
653 if (left > PAGE_SIZE - 1)
654 left = PAGE_SIZE - 1;
655
Luis R. Rodriguez4f2fec02017-07-12 14:33:36 -0700656 left -= proc_skip_spaces(&p);
657 if (!left) {
658 err = -EINVAL;
659 goto out_free;
660 }
661
662 err = proc_get_long(&p, &left, &lval, &neg,
663 proc_wspace_sep,
664 sizeof(proc_wspace_sep), NULL);
665 if (err || neg) {
666 err = -EINVAL;
667 goto out_free;
668 }
669
670 if (conv(&lval, tbl_data, 1, data)) {
671 err = -EINVAL;
672 goto out_free;
673 }
674
675 if (!err && left)
676 left -= proc_skip_spaces(&p);
677
678out_free:
Luis R. Rodriguez4f2fec02017-07-12 14:33:36 -0700679 if (err)
680 return -EINVAL;
681
682 return 0;
683
684 /* This is in keeping with old __do_proc_dointvec() */
685bail_early:
686 *ppos += *lenp;
687 return err;
688}
689
Christoph Hellwig32927392020-04-24 08:43:38 +0200690static int do_proc_douintvec_r(unsigned int *tbl_data, void *buffer,
Luis R. Rodriguez4f2fec02017-07-12 14:33:36 -0700691 size_t *lenp, loff_t *ppos,
692 int (*conv)(unsigned long *lvalp,
693 unsigned int *valp,
694 int write, void *data),
695 void *data)
696{
697 unsigned long lval;
698 int err = 0;
699 size_t left;
700
701 left = *lenp;
702
703 if (conv(&lval, tbl_data, 0, data)) {
704 err = -EINVAL;
705 goto out;
706 }
707
Christoph Hellwig32927392020-04-24 08:43:38 +0200708 proc_put_long(&buffer, &left, lval, false);
709 if (!left)
Luis R. Rodriguez4f2fec02017-07-12 14:33:36 -0700710 goto out;
711
Christoph Hellwig32927392020-04-24 08:43:38 +0200712 proc_put_char(&buffer, &left, '\n');
Luis R. Rodriguez4f2fec02017-07-12 14:33:36 -0700713
714out:
715 *lenp -= left;
716 *ppos += *lenp;
717
718 return err;
719}
720
721static int __do_proc_douintvec(void *tbl_data, struct ctl_table *table,
Christoph Hellwig32927392020-04-24 08:43:38 +0200722 int write, void *buffer,
Luis R. Rodriguez4f2fec02017-07-12 14:33:36 -0700723 size_t *lenp, loff_t *ppos,
724 int (*conv)(unsigned long *lvalp,
725 unsigned int *valp,
726 int write, void *data),
727 void *data)
728{
729 unsigned int *i, vleft;
730
731 if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
732 *lenp = 0;
733 return 0;
734 }
735
736 i = (unsigned int *) tbl_data;
737 vleft = table->maxlen / sizeof(*i);
738
739 /*
740 * Arrays are not supported, keep this simple. *Do not* add
741 * support for them.
742 */
743 if (vleft != 1) {
744 *lenp = 0;
745 return -EINVAL;
746 }
747
748 if (!conv)
749 conv = do_proc_douintvec_conv;
750
751 if (write)
752 return do_proc_douintvec_w(i, table, buffer, lenp, ppos,
753 conv, data);
754 return do_proc_douintvec_r(i, buffer, lenp, ppos, conv, data);
755}
756
Luis Chamberlain1998f192022-01-21 22:13:20 -0800757int do_proc_douintvec(struct ctl_table *table, int write,
758 void *buffer, size_t *lenp, loff_t *ppos,
759 int (*conv)(unsigned long *lvalp,
760 unsigned int *valp,
761 int write, void *data),
762 void *data)
Luis R. Rodriguez4f2fec02017-07-12 14:33:36 -0700763{
764 return __do_proc_douintvec(table->data, table, write,
765 buffer, lenp, ppos, conv, data);
766}
767
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768/**
Jia Hea2071572021-08-03 12:59:36 +0200769 * proc_dobool - read/write a bool
770 * @table: the sysctl table
771 * @write: %TRUE if this is a write to the sysctl file
772 * @buffer: the user buffer
773 * @lenp: the size of the user buffer
774 * @ppos: file position
775 *
776 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
777 * values from/to the user buffer, treated as an ASCII string.
778 *
779 * Returns 0 on success.
780 */
781int proc_dobool(struct ctl_table *table, int write, void *buffer,
782 size_t *lenp, loff_t *ppos)
783{
784 return do_proc_dointvec(table, write, buffer, lenp, ppos,
785 do_proc_dobool_conv, NULL);
786}
787
788/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 * proc_dointvec - read a vector of integers
790 * @table: the sysctl table
791 * @write: %TRUE if this is a write to the sysctl file
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 * @buffer: the user buffer
793 * @lenp: the size of the user buffer
794 * @ppos: file position
795 *
796 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
797 * values from/to the user buffer, treated as an ASCII string.
798 *
799 * Returns 0 on success.
800 */
Christoph Hellwig32927392020-04-24 08:43:38 +0200801int proc_dointvec(struct ctl_table *table, int write, void *buffer,
802 size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803{
Subash Abhinov Kasiviswanathane7d316a2016-08-25 15:16:51 -0700804 return do_proc_dointvec(table, write, buffer, lenp, ppos, NULL, NULL);
805}
806
Sebastian Andrzej Siewior6923aa02020-04-01 21:10:42 -0700807#ifdef CONFIG_COMPACTION
808static int proc_dointvec_minmax_warn_RT_change(struct ctl_table *table,
Christoph Hellwig32927392020-04-24 08:43:38 +0200809 int write, void *buffer, size_t *lenp, loff_t *ppos)
Sebastian Andrzej Siewior6923aa02020-04-01 21:10:42 -0700810{
811 int ret, old;
812
813 if (!IS_ENABLED(CONFIG_PREEMPT_RT) || !write)
814 return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
815
816 old = *(int *)table->data;
817 ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
818 if (ret)
819 return ret;
820 if (old != *(int *)table->data)
821 pr_warn_once("sysctl attribute %s changed by %s[%d]\n",
822 table->procname, current->comm,
823 task_pid_nr(current));
824 return ret;
825}
826#endif
827
Subash Abhinov Kasiviswanathane7d316a2016-08-25 15:16:51 -0700828/**
829 * proc_douintvec - read a vector of unsigned integers
830 * @table: the sysctl table
831 * @write: %TRUE if this is a write to the sysctl file
832 * @buffer: the user buffer
833 * @lenp: the size of the user buffer
834 * @ppos: file position
835 *
836 * Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
837 * values from/to the user buffer, treated as an ASCII string.
838 *
839 * Returns 0 on success.
840 */
Christoph Hellwig32927392020-04-24 08:43:38 +0200841int proc_douintvec(struct ctl_table *table, int write, void *buffer,
842 size_t *lenp, loff_t *ppos)
Subash Abhinov Kasiviswanathane7d316a2016-08-25 15:16:51 -0700843{
Luis R. Rodriguez4f2fec02017-07-12 14:33:36 -0700844 return do_proc_douintvec(table, write, buffer, lenp, ppos,
845 do_proc_douintvec_conv, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846}
847
Theodore Ts'o34f5a392007-02-10 01:45:24 -0800848/*
Andi Kleen25ddbb12008-10-15 22:01:41 -0700849 * Taint values can only be increased
850 * This means we can safely use a temporary.
Theodore Ts'o34f5a392007-02-10 01:45:24 -0800851 */
Alexey Dobriyan8d65af72009-09-23 15:57:19 -0700852static int proc_taint(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +0200853 void *buffer, size_t *lenp, loff_t *ppos)
Theodore Ts'o34f5a392007-02-10 01:45:24 -0800854{
Andi Kleen25ddbb12008-10-15 22:01:41 -0700855 struct ctl_table t;
856 unsigned long tmptaint = get_taint();
857 int err;
Theodore Ts'o34f5a392007-02-10 01:45:24 -0800858
Bastian Blank91fcd412007-04-23 14:41:14 -0700859 if (write && !capable(CAP_SYS_ADMIN))
Theodore Ts'o34f5a392007-02-10 01:45:24 -0800860 return -EPERM;
861
Andi Kleen25ddbb12008-10-15 22:01:41 -0700862 t = *table;
863 t.data = &tmptaint;
Alexey Dobriyan8d65af72009-09-23 15:57:19 -0700864 err = proc_doulongvec_minmax(&t, write, buffer, lenp, ppos);
Andi Kleen25ddbb12008-10-15 22:01:41 -0700865 if (err < 0)
866 return err;
867
868 if (write) {
Rafael Aquinidb38d5c2020-06-07 21:40:17 -0700869 int i;
870
871 /*
872 * If we are relying on panic_on_taint not producing
873 * false positives due to userspace input, bail out
874 * before setting the requested taint flags.
875 */
876 if (panic_on_taint_nousertaint && (tmptaint & panic_on_taint))
877 return -EINVAL;
878
Andi Kleen25ddbb12008-10-15 22:01:41 -0700879 /*
880 * Poor man's atomic or. Not worth adding a primitive
881 * to everyone's atomic.h for this
882 */
Rafael Aquinie77132e2020-06-07 21:40:51 -0700883 for (i = 0; i < TAINT_FLAGS_COUNT; i++)
884 if ((1UL << i) & tmptaint)
Rusty Russell373d4d02013-01-21 17:17:39 +1030885 add_taint(i, LOCKDEP_STILL_OK);
Andi Kleen25ddbb12008-10-15 22:01:41 -0700886 }
887
888 return err;
Theodore Ts'o34f5a392007-02-10 01:45:24 -0800889}
890
Waiman Long24704f32018-04-10 16:35:38 -0700891/**
892 * struct do_proc_dointvec_minmax_conv_param - proc_dointvec_minmax() range checking structure
893 * @min: pointer to minimum allowable value
894 * @max: pointer to maximum allowable value
895 *
896 * The do_proc_dointvec_minmax_conv_param structure provides the
897 * minimum and maximum values for doing range checking for those sysctl
898 * parameters that use the proc_dointvec_minmax() handler.
899 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900struct do_proc_dointvec_minmax_conv_param {
901 int *min;
902 int *max;
903};
904
Amerigo Wang00b7c332010-05-05 00:26:45 +0000905static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp,
906 int *valp,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 int write, void *data)
908{
Zev Weiss2bc4fc62019-03-11 23:28:06 -0700909 int tmp, ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 struct do_proc_dointvec_minmax_conv_param *param = data;
Zev Weiss2bc4fc62019-03-11 23:28:06 -0700911 /*
912 * If writing, first do so via a temporary local int so we can
913 * bounds-check it before touching *valp.
914 */
915 int *ip = write ? &tmp : valp;
916
917 ret = do_proc_dointvec_conv(negp, lvalp, ip, write, data);
918 if (ret)
919 return ret;
920
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 if (write) {
Zev Weiss2bc4fc62019-03-11 23:28:06 -0700922 if ((param->min && *param->min > tmp) ||
923 (param->max && *param->max < tmp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 return -EINVAL;
Zev Weiss2bc4fc62019-03-11 23:28:06 -0700925 *valp = tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 }
Zev Weiss2bc4fc62019-03-11 23:28:06 -0700927
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 return 0;
929}
930
931/**
932 * proc_dointvec_minmax - read a vector of integers with min/max values
933 * @table: the sysctl table
934 * @write: %TRUE if this is a write to the sysctl file
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 * @buffer: the user buffer
936 * @lenp: the size of the user buffer
937 * @ppos: file position
938 *
939 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
940 * values from/to the user buffer, treated as an ASCII string.
941 *
942 * This routine will ensure the values are within the range specified by
943 * table->extra1 (min) and table->extra2 (max).
944 *
Waiman Long24704f32018-04-10 16:35:38 -0700945 * Returns 0 on success or -EINVAL on write when the range check fails.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 */
Alexey Dobriyan8d65af72009-09-23 15:57:19 -0700947int proc_dointvec_minmax(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +0200948 void *buffer, size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949{
950 struct do_proc_dointvec_minmax_conv_param param = {
951 .min = (int *) table->extra1,
952 .max = (int *) table->extra2,
953 };
Alexey Dobriyan8d65af72009-09-23 15:57:19 -0700954 return do_proc_dointvec(table, write, buffer, lenp, ppos,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 do_proc_dointvec_minmax_conv, &param);
956}
957
Waiman Long24704f32018-04-10 16:35:38 -0700958/**
959 * struct do_proc_douintvec_minmax_conv_param - proc_douintvec_minmax() range checking structure
960 * @min: pointer to minimum allowable value
961 * @max: pointer to maximum allowable value
962 *
963 * The do_proc_douintvec_minmax_conv_param structure provides the
964 * minimum and maximum values for doing range checking for those sysctl
965 * parameters that use the proc_douintvec_minmax() handler.
966 */
Luis R. Rodriguez61d9b562017-07-12 14:33:40 -0700967struct do_proc_douintvec_minmax_conv_param {
968 unsigned int *min;
969 unsigned int *max;
970};
971
972static int do_proc_douintvec_minmax_conv(unsigned long *lvalp,
973 unsigned int *valp,
974 int write, void *data)
975{
Zev Weiss2bc4fc62019-03-11 23:28:06 -0700976 int ret;
977 unsigned int tmp;
Luis R. Rodriguez61d9b562017-07-12 14:33:40 -0700978 struct do_proc_douintvec_minmax_conv_param *param = data;
Zev Weiss2bc4fc62019-03-11 23:28:06 -0700979 /* write via temporary local uint for bounds-checking */
980 unsigned int *up = write ? &tmp : valp;
981
982 ret = do_proc_douintvec_conv(lvalp, up, write, data);
983 if (ret)
984 return ret;
Luis R. Rodriguez61d9b562017-07-12 14:33:40 -0700985
986 if (write) {
Zev Weiss2bc4fc62019-03-11 23:28:06 -0700987 if ((param->min && *param->min > tmp) ||
988 (param->max && *param->max < tmp))
Luis R. Rodriguez61d9b562017-07-12 14:33:40 -0700989 return -ERANGE;
990
Zev Weiss2bc4fc62019-03-11 23:28:06 -0700991 *valp = tmp;
Luis R. Rodriguez61d9b562017-07-12 14:33:40 -0700992 }
993
994 return 0;
995}
996
997/**
998 * proc_douintvec_minmax - read a vector of unsigned ints with min/max values
999 * @table: the sysctl table
1000 * @write: %TRUE if this is a write to the sysctl file
1001 * @buffer: the user buffer
1002 * @lenp: the size of the user buffer
1003 * @ppos: file position
1004 *
1005 * Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
1006 * values from/to the user buffer, treated as an ASCII string. Negative
1007 * strings are not allowed.
1008 *
1009 * This routine will ensure the values are within the range specified by
1010 * table->extra1 (min) and table->extra2 (max). There is a final sanity
1011 * check for UINT_MAX to avoid having to support wrap around uses from
1012 * userspace.
1013 *
Waiman Long24704f32018-04-10 16:35:38 -07001014 * Returns 0 on success or -ERANGE on write when the range check fails.
Luis R. Rodriguez61d9b562017-07-12 14:33:40 -07001015 */
1016int proc_douintvec_minmax(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001017 void *buffer, size_t *lenp, loff_t *ppos)
Luis R. Rodriguez61d9b562017-07-12 14:33:40 -07001018{
1019 struct do_proc_douintvec_minmax_conv_param param = {
1020 .min = (unsigned int *) table->extra1,
1021 .max = (unsigned int *) table->extra2,
1022 };
1023 return do_proc_douintvec(table, write, buffer, lenp, ppos,
1024 do_proc_douintvec_minmax_conv, &param);
1025}
1026
Eric Dumazetcb944412021-03-25 11:08:13 -07001027/**
1028 * proc_dou8vec_minmax - read a vector of unsigned chars with min/max values
1029 * @table: the sysctl table
1030 * @write: %TRUE if this is a write to the sysctl file
1031 * @buffer: the user buffer
1032 * @lenp: the size of the user buffer
1033 * @ppos: file position
1034 *
1035 * Reads/writes up to table->maxlen/sizeof(u8) unsigned chars
1036 * values from/to the user buffer, treated as an ASCII string. Negative
1037 * strings are not allowed.
1038 *
1039 * This routine will ensure the values are within the range specified by
1040 * table->extra1 (min) and table->extra2 (max).
1041 *
1042 * Returns 0 on success or an error on write when the range check fails.
1043 */
1044int proc_dou8vec_minmax(struct ctl_table *table, int write,
1045 void *buffer, size_t *lenp, loff_t *ppos)
1046{
1047 struct ctl_table tmp;
1048 unsigned int min = 0, max = 255U, val;
1049 u8 *data = table->data;
1050 struct do_proc_douintvec_minmax_conv_param param = {
1051 .min = &min,
1052 .max = &max,
1053 };
1054 int res;
1055
1056 /* Do not support arrays yet. */
1057 if (table->maxlen != sizeof(u8))
1058 return -EINVAL;
1059
1060 if (table->extra1) {
1061 min = *(unsigned int *) table->extra1;
1062 if (min > 255U)
1063 return -EINVAL;
1064 }
1065 if (table->extra2) {
1066 max = *(unsigned int *) table->extra2;
1067 if (max > 255U)
1068 return -EINVAL;
1069 }
1070
1071 tmp = *table;
1072
1073 tmp.maxlen = sizeof(val);
1074 tmp.data = &val;
1075 val = *data;
1076 res = do_proc_douintvec(&tmp, write, buffer, lenp, ppos,
1077 do_proc_douintvec_minmax_conv, &param);
1078 if (res)
1079 return res;
1080 if (write)
1081 *data = val;
1082 return 0;
1083}
1084EXPORT_SYMBOL_GPL(proc_dou8vec_minmax);
1085
Dmitry Safonoveaee4172020-03-02 17:51:34 +00001086#ifdef CONFIG_MAGIC_SYSRQ
1087static int sysrq_sysctl_handler(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001088 void *buffer, size_t *lenp, loff_t *ppos)
Dmitry Safonoveaee4172020-03-02 17:51:34 +00001089{
1090 int tmp, ret;
1091
1092 tmp = sysrq_mask();
1093
1094 ret = __do_proc_dointvec(&tmp, table, write, buffer,
1095 lenp, ppos, NULL, NULL);
1096 if (ret || !write)
1097 return ret;
1098
1099 if (write)
1100 sysrq_toggle_support(tmp);
1101
1102 return 0;
1103}
1104#endif
1105
Christoph Hellwig32927392020-04-24 08:43:38 +02001106static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table,
1107 int write, void *buffer, size_t *lenp, loff_t *ppos,
1108 unsigned long convmul, unsigned long convdiv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109{
Amerigo Wang00b7c332010-05-05 00:26:45 +00001110 unsigned long *i, *min, *max;
1111 int vleft, first = 1, err = 0;
Amerigo Wang00b7c332010-05-05 00:26:45 +00001112 size_t left;
Christoph Hellwig32927392020-04-24 08:43:38 +02001113 char *p;
Amerigo Wang00b7c332010-05-05 00:26:45 +00001114
1115 if (!data || !table->maxlen || !*lenp || (*ppos && !write)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 *lenp = 0;
1117 return 0;
1118 }
Amerigo Wang00b7c332010-05-05 00:26:45 +00001119
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07001120 i = (unsigned long *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 min = (unsigned long *) table->extra1;
1122 max = (unsigned long *) table->extra2;
1123 vleft = table->maxlen / sizeof(unsigned long);
1124 left = *lenp;
Amerigo Wang00b7c332010-05-05 00:26:45 +00001125
1126 if (write) {
Luis R. Rodriguezd383d482017-07-12 14:33:33 -07001127 if (proc_first_pos_non_zero_ignore(ppos, table))
1128 goto out;
Kees Cookf4aacea2014-06-06 14:37:19 -07001129
Amerigo Wang00b7c332010-05-05 00:26:45 +00001130 if (left > PAGE_SIZE - 1)
1131 left = PAGE_SIZE - 1;
Christoph Hellwig32927392020-04-24 08:43:38 +02001132 p = buffer;
Amerigo Wang00b7c332010-05-05 00:26:45 +00001133 }
1134
Eric Dumazet27b3d802010-10-07 12:59:29 -07001135 for (; left && vleft--; i++, first = 0) {
Amerigo Wang00b7c332010-05-05 00:26:45 +00001136 unsigned long val;
1137
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 if (write) {
Amerigo Wang00b7c332010-05-05 00:26:45 +00001139 bool neg;
1140
Al Viro70f6cbb2015-12-24 00:13:10 -05001141 left -= proc_skip_spaces(&p);
Cheng Lin09be1782019-01-03 15:26:13 -08001142 if (!left)
1143 break;
Amerigo Wang00b7c332010-05-05 00:26:45 +00001144
Al Viro70f6cbb2015-12-24 00:13:10 -05001145 err = proc_get_long(&p, &left, &val, &neg,
Amerigo Wang00b7c332010-05-05 00:26:45 +00001146 proc_wspace_sep,
1147 sizeof(proc_wspace_sep), NULL);
Baokun Li1622ed72022-01-21 22:13:48 -08001148 if (err || neg) {
1149 err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 break;
Baokun Li1622ed72022-01-21 22:13:48 -08001151 }
1152
Eric Dumazetff9f8a72017-01-25 18:20:55 -08001153 val = convmul * val / convdiv;
Christian Braunere260ad02019-05-14 15:44:55 -07001154 if ((min && val < *min) || (max && val > *max)) {
1155 err = -EINVAL;
1156 break;
1157 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 *i = val;
1159 } else {
Amerigo Wang00b7c332010-05-05 00:26:45 +00001160 val = convdiv * (*i) / convmul;
Christoph Hellwig32927392020-04-24 08:43:38 +02001161 if (!first)
1162 proc_put_char(&buffer, &left, '\t');
1163 proc_put_long(&buffer, &left, val, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 }
1165 }
1166
Amerigo Wang00b7c332010-05-05 00:26:45 +00001167 if (!write && !first && left && !err)
Christoph Hellwig32927392020-04-24 08:43:38 +02001168 proc_put_char(&buffer, &left, '\n');
Amerigo Wang00b7c332010-05-05 00:26:45 +00001169 if (write && !err)
Al Viro70f6cbb2015-12-24 00:13:10 -05001170 left -= proc_skip_spaces(&p);
Christoph Hellwig32927392020-04-24 08:43:38 +02001171 if (write && first)
1172 return err ? : -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 *lenp -= left;
Kees Cookf4aacea2014-06-06 14:37:19 -07001174out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 *ppos += *lenp;
Amerigo Wang00b7c332010-05-05 00:26:45 +00001176 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177}
1178
Eric W. Biedermand8217f02007-10-18 03:05:22 -07001179static int do_proc_doulongvec_minmax(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001180 void *buffer, size_t *lenp, loff_t *ppos, unsigned long convmul,
1181 unsigned long convdiv)
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07001182{
1183 return __do_proc_doulongvec_minmax(table->data, table, write,
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07001184 buffer, lenp, ppos, convmul, convdiv);
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07001185}
1186
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187/**
1188 * proc_doulongvec_minmax - read a vector of long integers with min/max values
1189 * @table: the sysctl table
1190 * @write: %TRUE if this is a write to the sysctl file
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 * @buffer: the user buffer
1192 * @lenp: the size of the user buffer
1193 * @ppos: file position
1194 *
1195 * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
1196 * values from/to the user buffer, treated as an ASCII string.
1197 *
1198 * This routine will ensure the values are within the range specified by
1199 * table->extra1 (min) and table->extra2 (max).
1200 *
1201 * Returns 0 on success.
1202 */
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07001203int proc_doulongvec_minmax(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001204 void *buffer, size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205{
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07001206 return do_proc_doulongvec_minmax(table, write, buffer, lenp, ppos, 1l, 1l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207}
1208
1209/**
1210 * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values
1211 * @table: the sysctl table
1212 * @write: %TRUE if this is a write to the sysctl file
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 * @buffer: the user buffer
1214 * @lenp: the size of the user buffer
1215 * @ppos: file position
1216 *
1217 * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
1218 * values from/to the user buffer, treated as an ASCII string. The values
1219 * are treated as milliseconds, and converted to jiffies when they are stored.
1220 *
1221 * This routine will ensure the values are within the range specified by
1222 * table->extra1 (min) and table->extra2 (max).
1223 *
1224 * Returns 0 on success.
1225 */
Eric W. Biedermand8217f02007-10-18 03:05:22 -07001226int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001227 void *buffer, size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228{
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07001229 return do_proc_doulongvec_minmax(table, write, buffer,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 lenp, ppos, HZ, 1000l);
1231}
1232
1233
Amerigo Wang00b7c332010-05-05 00:26:45 +00001234static int do_proc_dointvec_jiffies_conv(bool *negp, unsigned long *lvalp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 int *valp,
1236 int write, void *data)
1237{
1238 if (write) {
Gao Feng63259452017-05-08 15:54:58 -07001239 if (*lvalp > INT_MAX / HZ)
Bart Samwelcba9f332006-03-24 03:15:50 -08001240 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241 *valp = *negp ? -(*lvalp*HZ) : (*lvalp*HZ);
1242 } else {
1243 int val = *valp;
1244 unsigned long lval;
1245 if (val < 0) {
Amerigo Wang00b7c332010-05-05 00:26:45 +00001246 *negp = true;
Ilya Dryomov9a5bc722015-09-09 15:39:06 -07001247 lval = -(unsigned long)val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 } else {
Amerigo Wang00b7c332010-05-05 00:26:45 +00001249 *negp = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 lval = (unsigned long)val;
1251 }
1252 *lvalp = lval / HZ;
1253 }
1254 return 0;
1255}
1256
Amerigo Wang00b7c332010-05-05 00:26:45 +00001257static int do_proc_dointvec_userhz_jiffies_conv(bool *negp, unsigned long *lvalp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 int *valp,
1259 int write, void *data)
1260{
1261 if (write) {
Bart Samwelcba9f332006-03-24 03:15:50 -08001262 if (USER_HZ < HZ && *lvalp > (LONG_MAX / HZ) * USER_HZ)
1263 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 *valp = clock_t_to_jiffies(*negp ? -*lvalp : *lvalp);
1265 } else {
1266 int val = *valp;
1267 unsigned long lval;
1268 if (val < 0) {
Amerigo Wang00b7c332010-05-05 00:26:45 +00001269 *negp = true;
Ilya Dryomov9a5bc722015-09-09 15:39:06 -07001270 lval = -(unsigned long)val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 } else {
Amerigo Wang00b7c332010-05-05 00:26:45 +00001272 *negp = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 lval = (unsigned long)val;
1274 }
1275 *lvalp = jiffies_to_clock_t(lval);
1276 }
1277 return 0;
1278}
1279
Amerigo Wang00b7c332010-05-05 00:26:45 +00001280static int do_proc_dointvec_ms_jiffies_conv(bool *negp, unsigned long *lvalp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 int *valp,
1282 int write, void *data)
1283{
1284 if (write) {
Francesco Fuscod738ce82013-07-24 10:39:07 +02001285 unsigned long jif = msecs_to_jiffies(*negp ? -*lvalp : *lvalp);
1286
1287 if (jif > INT_MAX)
1288 return 1;
1289 *valp = (int)jif;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 } else {
1291 int val = *valp;
1292 unsigned long lval;
1293 if (val < 0) {
Amerigo Wang00b7c332010-05-05 00:26:45 +00001294 *negp = true;
Ilya Dryomov9a5bc722015-09-09 15:39:06 -07001295 lval = -(unsigned long)val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 } else {
Amerigo Wang00b7c332010-05-05 00:26:45 +00001297 *negp = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 lval = (unsigned long)val;
1299 }
1300 *lvalp = jiffies_to_msecs(lval);
1301 }
1302 return 0;
1303}
1304
1305/**
1306 * proc_dointvec_jiffies - read a vector of integers as seconds
1307 * @table: the sysctl table
1308 * @write: %TRUE if this is a write to the sysctl file
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 * @buffer: the user buffer
1310 * @lenp: the size of the user buffer
1311 * @ppos: file position
1312 *
1313 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1314 * values from/to the user buffer, treated as an ASCII string.
1315 * The values read are assumed to be in seconds, and are converted into
1316 * jiffies.
1317 *
1318 * Returns 0 on success.
1319 */
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07001320int proc_dointvec_jiffies(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001321 void *buffer, size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322{
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07001323 return do_proc_dointvec(table,write,buffer,lenp,ppos,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 do_proc_dointvec_jiffies_conv,NULL);
1325}
1326
1327/**
1328 * proc_dointvec_userhz_jiffies - read a vector of integers as 1/USER_HZ seconds
1329 * @table: the sysctl table
1330 * @write: %TRUE if this is a write to the sysctl file
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 * @buffer: the user buffer
1332 * @lenp: the size of the user buffer
Randy Dunlap1e5d5332005-11-07 01:01:06 -08001333 * @ppos: pointer to the file position
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 *
1335 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1336 * values from/to the user buffer, treated as an ASCII string.
1337 * The values read are assumed to be in 1/USER_HZ seconds, and
1338 * are converted into jiffies.
1339 *
1340 * Returns 0 on success.
1341 */
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07001342int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001343 void *buffer, size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344{
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07001345 return do_proc_dointvec(table,write,buffer,lenp,ppos,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 do_proc_dointvec_userhz_jiffies_conv,NULL);
1347}
1348
1349/**
1350 * proc_dointvec_ms_jiffies - read a vector of integers as 1 milliseconds
1351 * @table: the sysctl table
1352 * @write: %TRUE if this is a write to the sysctl file
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 * @buffer: the user buffer
1354 * @lenp: the size of the user buffer
Martin Waitz67be2dd2005-05-01 08:59:26 -07001355 * @ppos: file position
1356 * @ppos: the current position in the file
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 *
1358 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1359 * values from/to the user buffer, treated as an ASCII string.
1360 * The values read are assumed to be in 1/1000 seconds, and
1361 * are converted into jiffies.
1362 *
1363 * Returns 0 on success.
1364 */
Christoph Hellwig32927392020-04-24 08:43:38 +02001365int proc_dointvec_ms_jiffies(struct ctl_table *table, int write, void *buffer,
1366 size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367{
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07001368 return do_proc_dointvec(table, write, buffer, lenp, ppos,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 do_proc_dointvec_ms_jiffies_conv, NULL);
1370}
1371
Christoph Hellwig32927392020-04-24 08:43:38 +02001372static int proc_do_cad_pid(struct ctl_table *table, int write, void *buffer,
1373 size_t *lenp, loff_t *ppos)
Cedric Le Goater9ec52092006-10-02 02:19:00 -07001374{
1375 struct pid *new_pid;
1376 pid_t tmp;
1377 int r;
1378
Pavel Emelyanov6c5f3e72008-02-08 04:19:20 -08001379 tmp = pid_vnr(cad_pid);
Cedric Le Goater9ec52092006-10-02 02:19:00 -07001380
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07001381 r = __do_proc_dointvec(&tmp, table, write, buffer,
Cedric Le Goater9ec52092006-10-02 02:19:00 -07001382 lenp, ppos, NULL, NULL);
1383 if (r || !write)
1384 return r;
1385
1386 new_pid = find_get_pid(tmp);
1387 if (!new_pid)
1388 return -ESRCH;
1389
1390 put_pid(xchg(&cad_pid, new_pid));
1391 return 0;
1392}
1393
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001394/**
1395 * proc_do_large_bitmap - read/write from/to a large bitmap
1396 * @table: the sysctl table
1397 * @write: %TRUE if this is a write to the sysctl file
1398 * @buffer: the user buffer
1399 * @lenp: the size of the user buffer
1400 * @ppos: file position
1401 *
1402 * The bitmap is stored at table->data and the bitmap length (in bits)
1403 * in table->maxlen.
1404 *
1405 * We use a range comma separated format (e.g. 1,3-4,10-10) so that
1406 * large bitmaps may be represented in a compact manner. Writing into
1407 * the file will clear the bitmap then update it with the given input.
1408 *
1409 * Returns 0 on success.
1410 */
1411int proc_do_large_bitmap(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001412 void *buffer, size_t *lenp, loff_t *ppos)
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001413{
1414 int err = 0;
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001415 size_t left = *lenp;
1416 unsigned long bitmap_len = table->maxlen;
WANG Cong122ff242014-05-12 16:04:53 -07001417 unsigned long *bitmap = *(unsigned long **) table->data;
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001418 unsigned long *tmp_bitmap = NULL;
1419 char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
1420
WANG Cong122ff242014-05-12 16:04:53 -07001421 if (!bitmap || !bitmap_len || !left || (*ppos && !write)) {
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001422 *lenp = 0;
1423 return 0;
1424 }
1425
1426 if (write) {
Christoph Hellwig32927392020-04-24 08:43:38 +02001427 char *p = buffer;
Eric Sandeen3116ad32019-05-14 15:45:13 -07001428 size_t skipped = 0;
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001429
Eric Sandeen3116ad32019-05-14 15:45:13 -07001430 if (left > PAGE_SIZE - 1) {
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001431 left = PAGE_SIZE - 1;
Eric Sandeen3116ad32019-05-14 15:45:13 -07001432 /* How much of the buffer we'll skip this pass */
1433 skipped = *lenp - left;
1434 }
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001435
Andy Shevchenko475dae32019-05-14 15:44:52 -07001436 tmp_bitmap = bitmap_zalloc(bitmap_len, GFP_KERNEL);
Christoph Hellwig32927392020-04-24 08:43:38 +02001437 if (!tmp_bitmap)
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001438 return -ENOMEM;
Al Viro70f6cbb2015-12-24 00:13:10 -05001439 proc_skip_char(&p, &left, '\n');
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001440 while (!err && left) {
1441 unsigned long val_a, val_b;
1442 bool neg;
Eric Sandeen3116ad32019-05-14 15:45:13 -07001443 size_t saved_left;
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001444
Eric Sandeen3116ad32019-05-14 15:45:13 -07001445 /* In case we stop parsing mid-number, we can reset */
1446 saved_left = left;
Al Viro70f6cbb2015-12-24 00:13:10 -05001447 err = proc_get_long(&p, &left, &val_a, &neg, tr_a,
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001448 sizeof(tr_a), &c);
Eric Sandeen3116ad32019-05-14 15:45:13 -07001449 /*
1450 * If we consumed the entirety of a truncated buffer or
1451 * only one char is left (may be a "-"), then stop here,
1452 * reset, & come back for more.
1453 */
1454 if ((left <= 1) && skipped) {
1455 left = saved_left;
1456 break;
1457 }
1458
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001459 if (err)
1460 break;
1461 if (val_a >= bitmap_len || neg) {
1462 err = -EINVAL;
1463 break;
1464 }
1465
1466 val_b = val_a;
1467 if (left) {
Al Viro70f6cbb2015-12-24 00:13:10 -05001468 p++;
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001469 left--;
1470 }
1471
1472 if (c == '-') {
Al Viro70f6cbb2015-12-24 00:13:10 -05001473 err = proc_get_long(&p, &left, &val_b,
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001474 &neg, tr_b, sizeof(tr_b),
1475 &c);
Eric Sandeen3116ad32019-05-14 15:45:13 -07001476 /*
1477 * If we consumed all of a truncated buffer or
1478 * then stop here, reset, & come back for more.
1479 */
1480 if (!left && skipped) {
1481 left = saved_left;
1482 break;
1483 }
1484
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001485 if (err)
1486 break;
1487 if (val_b >= bitmap_len || neg ||
1488 val_a > val_b) {
1489 err = -EINVAL;
1490 break;
1491 }
1492 if (left) {
Al Viro70f6cbb2015-12-24 00:13:10 -05001493 p++;
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001494 left--;
1495 }
1496 }
1497
Akinobu Mita5a04cca2012-03-28 14:42:50 -07001498 bitmap_set(tmp_bitmap, val_a, val_b - val_a + 1);
Al Viro70f6cbb2015-12-24 00:13:10 -05001499 proc_skip_char(&p, &left, '\n');
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001500 }
Eric Sandeen3116ad32019-05-14 15:45:13 -07001501 left += skipped;
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001502 } else {
1503 unsigned long bit_a, bit_b = 0;
Jiapeng Chong9a52c5f2021-06-30 18:54:53 -07001504 bool first = 1;
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001505
1506 while (left) {
1507 bit_a = find_next_bit(bitmap, bitmap_len, bit_b);
1508 if (bit_a >= bitmap_len)
1509 break;
1510 bit_b = find_next_zero_bit(bitmap, bitmap_len,
1511 bit_a + 1) - 1;
1512
Christoph Hellwig32927392020-04-24 08:43:38 +02001513 if (!first)
1514 proc_put_char(&buffer, &left, ',');
1515 proc_put_long(&buffer, &left, bit_a, false);
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001516 if (bit_a != bit_b) {
Christoph Hellwig32927392020-04-24 08:43:38 +02001517 proc_put_char(&buffer, &left, '-');
1518 proc_put_long(&buffer, &left, bit_b, false);
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001519 }
1520
1521 first = 0; bit_b++;
1522 }
Christoph Hellwig32927392020-04-24 08:43:38 +02001523 proc_put_char(&buffer, &left, '\n');
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001524 }
1525
1526 if (!err) {
1527 if (write) {
1528 if (*ppos)
1529 bitmap_or(bitmap, bitmap, tmp_bitmap, bitmap_len);
1530 else
Akinobu Mita5a04cca2012-03-28 14:42:50 -07001531 bitmap_copy(bitmap, tmp_bitmap, bitmap_len);
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001532 }
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001533 *lenp -= left;
1534 *ppos += *lenp;
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001535 }
Ola N. Kaldestadf9eb2fd2017-11-17 15:30:26 -08001536
Andy Shevchenko475dae32019-05-14 15:44:52 -07001537 bitmap_free(tmp_bitmap);
Ola N. Kaldestadf9eb2fd2017-11-17 15:30:26 -08001538 return err;
Octavian Purdila9f977fb2010-05-05 00:26:55 +00001539}
1540
Jovi Zhang55610502011-01-12 17:00:45 -08001541#else /* CONFIG_PROC_SYSCTL */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07001543int proc_dostring(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001544 void *buffer, size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545{
1546 return -ENOSYS;
1547}
1548
Jia Hea2071572021-08-03 12:59:36 +02001549int proc_dobool(struct ctl_table *table, int write,
1550 void *buffer, size_t *lenp, loff_t *ppos)
1551{
1552 return -ENOSYS;
1553}
1554
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07001555int proc_dointvec(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001556 void *buffer, size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557{
1558 return -ENOSYS;
1559}
1560
Subash Abhinov Kasiviswanathane7d316a2016-08-25 15:16:51 -07001561int proc_douintvec(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001562 void *buffer, size_t *lenp, loff_t *ppos)
Subash Abhinov Kasiviswanathane7d316a2016-08-25 15:16:51 -07001563{
1564 return -ENOSYS;
1565}
1566
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07001567int proc_dointvec_minmax(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001568 void *buffer, size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569{
1570 return -ENOSYS;
1571}
1572
Luis R. Rodriguez61d9b562017-07-12 14:33:40 -07001573int proc_douintvec_minmax(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001574 void *buffer, size_t *lenp, loff_t *ppos)
Luis R. Rodriguez61d9b562017-07-12 14:33:40 -07001575{
1576 return -ENOSYS;
1577}
1578
Eric Dumazetcb944412021-03-25 11:08:13 -07001579int proc_dou8vec_minmax(struct ctl_table *table, int write,
1580 void *buffer, size_t *lenp, loff_t *ppos)
1581{
1582 return -ENOSYS;
1583}
1584
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07001585int proc_dointvec_jiffies(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001586 void *buffer, size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587{
1588 return -ENOSYS;
1589}
1590
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07001591int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001592 void *buffer, size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593{
1594 return -ENOSYS;
1595}
1596
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07001597int proc_dointvec_ms_jiffies(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001598 void *buffer, size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599{
1600 return -ENOSYS;
1601}
1602
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07001603int proc_doulongvec_minmax(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001604 void *buffer, size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605{
1606 return -ENOSYS;
1607}
1608
Eric W. Biedermand8217f02007-10-18 03:05:22 -07001609int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001610 void *buffer, size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611{
Christoph Hellwig32927392020-04-24 08:43:38 +02001612 return -ENOSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613}
1614
Stephen Suryaputra0bc19982019-04-17 16:35:49 -04001615int proc_do_large_bitmap(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001616 void *buffer, size_t *lenp, loff_t *ppos)
Stephen Suryaputra0bc19982019-04-17 16:35:49 -04001617{
1618 return -ENOSYS;
1619}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620
Jovi Zhang55610502011-01-12 17:00:45 -08001621#endif /* CONFIG_PROC_SYSCTL */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622
Eric Dumazeta8e11e52019-06-14 16:22:18 -07001623#if defined(CONFIG_SYSCTL)
1624int proc_do_static_key(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +02001625 void *buffer, size_t *lenp, loff_t *ppos)
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001626{
Eric Dumazeta8e11e52019-06-14 16:22:18 -07001627 struct static_key *key = (struct static_key *)table->data;
1628 static DEFINE_MUTEX(static_key_mutex);
1629 int val, ret;
1630 struct ctl_table tmp = {
1631 .data = &val,
1632 .maxlen = sizeof(val),
1633 .mode = table->mode,
Matteo Croceeec48442019-07-18 15:58:50 -07001634 .extra1 = SYSCTL_ZERO,
1635 .extra2 = SYSCTL_ONE,
Eric Dumazeta8e11e52019-06-14 16:22:18 -07001636 };
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001637
1638 if (write && !capable(CAP_SYS_ADMIN))
1639 return -EPERM;
1640
Eric Dumazeta8e11e52019-06-14 16:22:18 -07001641 mutex_lock(&static_key_mutex);
1642 val = static_key_enabled(key);
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001643 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
1644 if (write && !ret) {
Eric Dumazeta8e11e52019-06-14 16:22:18 -07001645 if (val)
1646 static_key_enable(key);
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001647 else
Eric Dumazeta8e11e52019-06-14 16:22:18 -07001648 static_key_disable(key);
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001649 }
Eric Dumazeta8e11e52019-06-14 16:22:18 -07001650 mutex_unlock(&static_key_mutex);
Alexei Starovoitov492ecee2019-02-25 14:28:39 -08001651 return ret;
1652}
Christoph Hellwigf461d2d2020-04-24 08:43:37 +02001653
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654static struct ctl_table kern_table[] = {
1655 {
1656 .procname = "sched_child_runs_first",
1657 .data = &sysctl_sched_child_runs_first,
1658 .maxlen = sizeof(unsigned int),
1659 .mode = 0644,
1660 .proc_handler = proc_dointvec,
1661 },
Peter Zijlstra1d1c2502021-03-24 19:47:43 +01001662#ifdef CONFIG_SCHEDSTATS
1663 {
1664 .procname = "sched_schedstats",
1665 .data = NULL,
1666 .maxlen = sizeof(unsigned int),
1667 .mode = 0644,
1668 .proc_handler = sysctl_schedstats,
1669 .extra1 = SYSCTL_ZERO,
1670 .extra2 = SYSCTL_ONE,
1671 },
1672#endif /* CONFIG_SCHEDSTATS */
Peter Zijlstra0cd7c742021-05-10 14:01:00 +02001673#ifdef CONFIG_TASK_DELAY_ACCT
1674 {
1675 .procname = "task_delayacct",
1676 .data = NULL,
1677 .maxlen = sizeof(unsigned int),
1678 .mode = 0644,
1679 .proc_handler = sysctl_delayacct,
1680 .extra1 = SYSCTL_ZERO,
1681 .extra2 = SYSCTL_ONE,
1682 },
1683#endif /* CONFIG_TASK_DELAY_ACCT */
Mel Gormanb7cc6ec2021-03-24 13:39:16 +00001684#ifdef CONFIG_NUMA_BALANCING
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 {
1686 .procname = "numa_balancing",
1687 .data = NULL, /* filled in by handler */
1688 .maxlen = sizeof(unsigned int),
1689 .mode = 0644,
1690 .proc_handler = sysctl_numa_balancing,
1691 .extra1 = SYSCTL_ZERO,
1692 .extra2 = SYSCTL_ONE,
1693 },
1694#endif /* CONFIG_NUMA_BALANCING */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 {
1696 .procname = "sched_rt_period_us",
1697 .data = &sysctl_sched_rt_period,
1698 .maxlen = sizeof(unsigned int),
1699 .mode = 0644,
1700 .proc_handler = sched_rt_handler,
1701 },
1702 {
1703 .procname = "sched_rt_runtime_us",
1704 .data = &sysctl_sched_rt_runtime,
1705 .maxlen = sizeof(int),
1706 .mode = 0644,
1707 .proc_handler = sched_rt_handler,
1708 },
1709 {
Peter Zijlstrab4098bf2019-07-26 16:54:10 +02001710 .procname = "sched_deadline_period_max_us",
1711 .data = &sysctl_sched_dl_period_max,
1712 .maxlen = sizeof(unsigned int),
1713 .mode = 0644,
1714 .proc_handler = proc_dointvec,
1715 },
1716 {
1717 .procname = "sched_deadline_period_min_us",
1718 .data = &sysctl_sched_dl_period_min,
1719 .maxlen = sizeof(unsigned int),
1720 .mode = 0644,
1721 .proc_handler = proc_dointvec,
1722 },
1723 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724 .procname = "sched_rr_timeslice_ms",
1725 .data = &sysctl_sched_rr_timeslice,
1726 .maxlen = sizeof(int),
1727 .mode = 0644,
1728 .proc_handler = sched_rr_handler,
1729 },
1730#ifdef CONFIG_UCLAMP_TASK
1731 {
1732 .procname = "sched_util_clamp_min",
1733 .data = &sysctl_sched_uclamp_util_min,
1734 .maxlen = sizeof(unsigned int),
1735 .mode = 0644,
1736 .proc_handler = sysctl_sched_uclamp_handler,
1737 },
1738 {
1739 .procname = "sched_util_clamp_max",
1740 .data = &sysctl_sched_uclamp_util_max,
1741 .maxlen = sizeof(unsigned int),
1742 .mode = 0644,
1743 .proc_handler = sysctl_sched_uclamp_handler,
1744 },
Qais Yousef13685c42020-07-16 12:03:45 +01001745 {
1746 .procname = "sched_util_clamp_min_rt_default",
1747 .data = &sysctl_sched_uclamp_util_min_rt_default,
1748 .maxlen = sizeof(unsigned int),
1749 .mode = 0644,
1750 .proc_handler = sysctl_sched_uclamp_handler,
1751 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752#endif
1753#ifdef CONFIG_SCHED_AUTOGROUP
1754 {
1755 .procname = "sched_autogroup_enabled",
1756 .data = &sysctl_sched_autogroup_enabled,
1757 .maxlen = sizeof(unsigned int),
1758 .mode = 0644,
1759 .proc_handler = proc_dointvec_minmax,
1760 .extra1 = SYSCTL_ZERO,
1761 .extra2 = SYSCTL_ONE,
1762 },
1763#endif
1764#ifdef CONFIG_CFS_BANDWIDTH
1765 {
1766 .procname = "sched_cfs_bandwidth_slice_us",
1767 .data = &sysctl_sched_cfs_bandwidth_slice,
1768 .maxlen = sizeof(unsigned int),
1769 .mode = 0644,
1770 .proc_handler = proc_dointvec_minmax,
1771 .extra1 = SYSCTL_ONE,
1772 },
1773#endif
1774#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL)
1775 {
1776 .procname = "sched_energy_aware",
1777 .data = &sysctl_sched_energy_aware,
1778 .maxlen = sizeof(unsigned int),
1779 .mode = 0644,
1780 .proc_handler = sched_energy_aware_handler,
1781 .extra1 = SYSCTL_ZERO,
1782 .extra2 = SYSCTL_ONE,
1783 },
1784#endif
1785#ifdef CONFIG_PROVE_LOCKING
1786 {
1787 .procname = "prove_locking",
1788 .data = &prove_locking,
1789 .maxlen = sizeof(int),
1790 .mode = 0644,
1791 .proc_handler = proc_dointvec,
1792 },
1793#endif
1794#ifdef CONFIG_LOCK_STAT
1795 {
1796 .procname = "lock_stat",
1797 .data = &lock_stat,
1798 .maxlen = sizeof(int),
1799 .mode = 0644,
1800 .proc_handler = proc_dointvec,
1801 },
1802#endif
1803 {
1804 .procname = "panic",
1805 .data = &panic_timeout,
1806 .maxlen = sizeof(int),
1807 .mode = 0644,
1808 .proc_handler = proc_dointvec,
1809 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810#ifdef CONFIG_PROC_SYSCTL
1811 {
1812 .procname = "tainted",
1813 .maxlen = sizeof(long),
1814 .mode = 0644,
1815 .proc_handler = proc_taint,
1816 },
1817 {
1818 .procname = "sysctl_writes_strict",
1819 .data = &sysctl_writes_strict,
1820 .maxlen = sizeof(int),
1821 .mode = 0644,
1822 .proc_handler = proc_dointvec_minmax,
Xiaoming Ni78e36f32022-01-21 22:10:55 -08001823 .extra1 = SYSCTL_NEG_ONE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 .extra2 = SYSCTL_ONE,
1825 },
1826#endif
1827#ifdef CONFIG_LATENCYTOP
1828 {
1829 .procname = "latencytop",
1830 .data = &latencytop_enabled,
1831 .maxlen = sizeof(int),
1832 .mode = 0644,
1833 .proc_handler = sysctl_latencytop,
1834 },
1835#endif
1836#ifdef CONFIG_BLK_DEV_INITRD
1837 {
1838 .procname = "real-root-dev",
1839 .data = &real_root_dev,
1840 .maxlen = sizeof(int),
1841 .mode = 0644,
1842 .proc_handler = proc_dointvec,
1843 },
1844#endif
1845 {
1846 .procname = "print-fatal-signals",
1847 .data = &print_fatal_signals,
1848 .maxlen = sizeof(int),
1849 .mode = 0644,
1850 .proc_handler = proc_dointvec,
1851 },
1852#ifdef CONFIG_SPARC
1853 {
1854 .procname = "reboot-cmd",
1855 .data = reboot_command,
1856 .maxlen = 256,
1857 .mode = 0644,
1858 .proc_handler = proc_dostring,
1859 },
1860 {
1861 .procname = "stop-a",
1862 .data = &stop_a_enabled,
1863 .maxlen = sizeof (int),
1864 .mode = 0644,
1865 .proc_handler = proc_dointvec,
1866 },
1867 {
1868 .procname = "scons-poweroff",
1869 .data = &scons_pwroff,
1870 .maxlen = sizeof (int),
1871 .mode = 0644,
1872 .proc_handler = proc_dointvec,
1873 },
1874#endif
1875#ifdef CONFIG_SPARC64
1876 {
1877 .procname = "tsb-ratio",
1878 .data = &sysctl_tsb_ratio,
1879 .maxlen = sizeof (int),
1880 .mode = 0644,
1881 .proc_handler = proc_dointvec,
1882 },
1883#endif
1884#ifdef CONFIG_PARISC
1885 {
1886 .procname = "soft-power",
1887 .data = &pwrsw_enabled,
1888 .maxlen = sizeof (int),
Christoph Hellwigf461d2d2020-04-24 08:43:37 +02001889 .mode = 0644,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 .proc_handler = proc_dointvec,
1891 },
1892#endif
1893#ifdef CONFIG_SYSCTL_ARCH_UNALIGN_ALLOW
1894 {
1895 .procname = "unaligned-trap",
1896 .data = &unaligned_enabled,
1897 .maxlen = sizeof (int),
1898 .mode = 0644,
1899 .proc_handler = proc_dointvec,
1900 },
1901#endif
1902 {
1903 .procname = "ctrl-alt-del",
1904 .data = &C_A_D,
1905 .maxlen = sizeof(int),
1906 .mode = 0644,
1907 .proc_handler = proc_dointvec,
1908 },
1909#ifdef CONFIG_FUNCTION_TRACER
1910 {
1911 .procname = "ftrace_enabled",
1912 .data = &ftrace_enabled,
1913 .maxlen = sizeof(int),
1914 .mode = 0644,
1915 .proc_handler = ftrace_enable_sysctl,
1916 },
1917#endif
1918#ifdef CONFIG_STACK_TRACER
1919 {
1920 .procname = "stack_tracer_enabled",
1921 .data = &stack_tracer_enabled,
1922 .maxlen = sizeof(int),
1923 .mode = 0644,
1924 .proc_handler = stack_trace_sysctl,
1925 },
1926#endif
1927#ifdef CONFIG_TRACING
1928 {
1929 .procname = "ftrace_dump_on_oops",
1930 .data = &ftrace_dump_on_oops,
1931 .maxlen = sizeof(int),
1932 .mode = 0644,
1933 .proc_handler = proc_dointvec,
1934 },
1935 {
1936 .procname = "traceoff_on_warning",
1937 .data = &__disable_trace_on_warning,
1938 .maxlen = sizeof(__disable_trace_on_warning),
1939 .mode = 0644,
1940 .proc_handler = proc_dointvec,
1941 },
1942 {
1943 .procname = "tracepoint_printk",
1944 .data = &tracepoint_printk,
1945 .maxlen = sizeof(tracepoint_printk),
1946 .mode = 0644,
1947 .proc_handler = tracepoint_printk_sysctl,
1948 },
1949#endif
1950#ifdef CONFIG_KEXEC_CORE
1951 {
1952 .procname = "kexec_load_disabled",
1953 .data = &kexec_load_disabled,
1954 .maxlen = sizeof(int),
1955 .mode = 0644,
1956 /* only handle a transition from default "0" to "1" */
1957 .proc_handler = proc_dointvec_minmax,
1958 .extra1 = SYSCTL_ONE,
1959 .extra2 = SYSCTL_ONE,
1960 },
1961#endif
1962#ifdef CONFIG_MODULES
1963 {
1964 .procname = "modprobe",
1965 .data = &modprobe_path,
1966 .maxlen = KMOD_PATH_LEN,
1967 .mode = 0644,
1968 .proc_handler = proc_dostring,
1969 },
1970 {
1971 .procname = "modules_disabled",
1972 .data = &modules_disabled,
1973 .maxlen = sizeof(int),
1974 .mode = 0644,
1975 /* only handle a transition from default "0" to "1" */
1976 .proc_handler = proc_dointvec_minmax,
1977 .extra1 = SYSCTL_ONE,
1978 .extra2 = SYSCTL_ONE,
1979 },
1980#endif
1981#ifdef CONFIG_UEVENT_HELPER
1982 {
1983 .procname = "hotplug",
1984 .data = &uevent_helper,
1985 .maxlen = UEVENT_HELPER_PATH_LEN,
1986 .mode = 0644,
1987 .proc_handler = proc_dostring,
1988 },
1989#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990#ifdef CONFIG_BSD_PROCESS_ACCT
1991 {
1992 .procname = "acct",
1993 .data = &acct_parm,
1994 .maxlen = 3*sizeof(int),
1995 .mode = 0644,
1996 .proc_handler = proc_dointvec,
1997 },
1998#endif
1999#ifdef CONFIG_MAGIC_SYSRQ
2000 {
2001 .procname = "sysrq",
2002 .data = NULL,
2003 .maxlen = sizeof (int),
2004 .mode = 0644,
2005 .proc_handler = sysrq_sysctl_handler,
2006 },
2007#endif
2008#ifdef CONFIG_PROC_SYSCTL
2009 {
2010 .procname = "cad_pid",
2011 .data = NULL,
2012 .maxlen = sizeof (int),
2013 .mode = 0600,
2014 .proc_handler = proc_do_cad_pid,
2015 },
2016#endif
2017 {
2018 .procname = "threads-max",
2019 .data = NULL,
2020 .maxlen = sizeof(int),
2021 .mode = 0644,
2022 .proc_handler = sysctl_max_threads,
2023 },
2024 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 .procname = "usermodehelper",
2026 .mode = 0555,
2027 .child = usermodehelper_table,
2028 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029 {
2030 .procname = "overflowuid",
2031 .data = &overflowuid,
2032 .maxlen = sizeof(int),
2033 .mode = 0644,
2034 .proc_handler = proc_dointvec_minmax,
Xiaoming Ni2452dcb2022-01-21 22:11:19 -08002035 .extra1 = SYSCTL_ZERO,
Luis Chamberlain54771612022-01-21 22:13:03 -08002036 .extra2 = SYSCTL_MAXOLDUID,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 },
2038 {
2039 .procname = "overflowgid",
2040 .data = &overflowgid,
2041 .maxlen = sizeof(int),
2042 .mode = 0644,
2043 .proc_handler = proc_dointvec_minmax,
Xiaoming Ni2452dcb2022-01-21 22:11:19 -08002044 .extra1 = SYSCTL_ZERO,
Luis Chamberlain54771612022-01-21 22:13:03 -08002045 .extra2 = SYSCTL_MAXOLDUID,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 },
2047#ifdef CONFIG_S390
2048 {
2049 .procname = "userprocess_debug",
2050 .data = &show_unhandled_signals,
2051 .maxlen = sizeof(int),
2052 .mode = 0644,
2053 .proc_handler = proc_dointvec,
2054 },
2055#endif
Guilherme G. Piccoli60c958d2020-06-07 21:40:48 -07002056#ifdef CONFIG_SMP
2057 {
2058 .procname = "oops_all_cpu_backtrace",
2059 .data = &sysctl_oops_all_cpu_backtrace,
2060 .maxlen = sizeof(int),
2061 .mode = 0644,
2062 .proc_handler = proc_dointvec_minmax,
2063 .extra1 = SYSCTL_ZERO,
2064 .extra2 = SYSCTL_ONE,
2065 },
2066#endif /* CONFIG_SMP */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067 {
2068 .procname = "pid_max",
2069 .data = &pid_max,
2070 .maxlen = sizeof (int),
2071 .mode = 0644,
2072 .proc_handler = proc_dointvec_minmax,
2073 .extra1 = &pid_max_min,
2074 .extra2 = &pid_max_max,
2075 },
2076 {
2077 .procname = "panic_on_oops",
2078 .data = &panic_on_oops,
2079 .maxlen = sizeof(int),
2080 .mode = 0644,
2081 .proc_handler = proc_dointvec,
2082 },
2083 {
2084 .procname = "panic_print",
2085 .data = &panic_print,
2086 .maxlen = sizeof(unsigned long),
2087 .mode = 0644,
2088 .proc_handler = proc_doulongvec_minmax,
2089 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 {
2091 .procname = "ngroups_max",
Stephen Kittf6288672022-01-21 22:11:09 -08002092 .data = (void *)&ngroups_max,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 .maxlen = sizeof (int),
2094 .mode = 0444,
2095 .proc_handler = proc_dointvec,
2096 },
2097 {
2098 .procname = "cap_last_cap",
2099 .data = (void *)&cap_last_cap,
2100 .maxlen = sizeof(int),
2101 .mode = 0444,
2102 .proc_handler = proc_dointvec,
2103 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
2105 {
2106 .procname = "unknown_nmi_panic",
2107 .data = &unknown_nmi_panic,
2108 .maxlen = sizeof (int),
2109 .mode = 0644,
2110 .proc_handler = proc_dointvec,
2111 },
2112#endif
Xiaoming Nib6522fa2020-04-11 21:06:19 +08002113
2114#if (defined(CONFIG_X86_32) || defined(CONFIG_PARISC)) && \
2115 defined(CONFIG_DEBUG_STACKOVERFLOW)
2116 {
2117 .procname = "panic_on_stackoverflow",
2118 .data = &sysctl_panic_on_stackoverflow,
2119 .maxlen = sizeof(int),
2120 .mode = 0644,
2121 .proc_handler = proc_dointvec,
2122 },
2123#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124#if defined(CONFIG_X86)
2125 {
2126 .procname = "panic_on_unrecovered_nmi",
2127 .data = &panic_on_unrecovered_nmi,
2128 .maxlen = sizeof(int),
2129 .mode = 0644,
2130 .proc_handler = proc_dointvec,
2131 },
2132 {
2133 .procname = "panic_on_io_nmi",
2134 .data = &panic_on_io_nmi,
2135 .maxlen = sizeof(int),
2136 .mode = 0644,
2137 .proc_handler = proc_dointvec,
2138 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 {
2140 .procname = "bootloader_type",
2141 .data = &bootloader_type,
2142 .maxlen = sizeof (int),
2143 .mode = 0444,
2144 .proc_handler = proc_dointvec,
2145 },
2146 {
2147 .procname = "bootloader_version",
2148 .data = &bootloader_version,
2149 .maxlen = sizeof (int),
2150 .mode = 0444,
2151 .proc_handler = proc_dointvec,
2152 },
2153 {
2154 .procname = "io_delay_type",
2155 .data = &io_delay_type,
2156 .maxlen = sizeof(int),
2157 .mode = 0644,
2158 .proc_handler = proc_dointvec,
2159 },
2160#endif
2161#if defined(CONFIG_MMU)
2162 {
2163 .procname = "randomize_va_space",
2164 .data = &randomize_va_space,
2165 .maxlen = sizeof(int),
2166 .mode = 0644,
2167 .proc_handler = proc_dointvec,
2168 },
2169#endif
2170#if defined(CONFIG_S390) && defined(CONFIG_SMP)
2171 {
2172 .procname = "spin_retry",
2173 .data = &spin_retry,
2174 .maxlen = sizeof (int),
2175 .mode = 0644,
2176 .proc_handler = proc_dointvec,
2177 },
2178#endif
2179#if defined(CONFIG_ACPI_SLEEP) && defined(CONFIG_X86)
2180 {
2181 .procname = "acpi_video_flags",
2182 .data = &acpi_realmode_flags,
2183 .maxlen = sizeof (unsigned long),
2184 .mode = 0644,
2185 .proc_handler = proc_doulongvec_minmax,
2186 },
2187#endif
2188#ifdef CONFIG_SYSCTL_ARCH_UNALIGN_NO_WARN
2189 {
2190 .procname = "ignore-unaligned-usertrap",
2191 .data = &no_unaligned_warning,
2192 .maxlen = sizeof (int),
Christoph Hellwigf461d2d2020-04-24 08:43:37 +02002193 .mode = 0644,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 .proc_handler = proc_dointvec,
2195 },
2196#endif
2197#ifdef CONFIG_IA64
2198 {
2199 .procname = "unaligned-dump-stack",
2200 .data = &unaligned_dump_stack,
2201 .maxlen = sizeof (int),
2202 .mode = 0644,
2203 .proc_handler = proc_dointvec,
2204 },
2205#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206#ifdef CONFIG_RT_MUTEXES
2207 {
2208 .procname = "max_lock_depth",
2209 .data = &max_lock_depth,
2210 .maxlen = sizeof(int),
2211 .mode = 0644,
2212 .proc_handler = proc_dointvec,
2213 },
2214#endif
2215 {
2216 .procname = "poweroff_cmd",
2217 .data = &poweroff_cmd,
2218 .maxlen = POWEROFF_CMD_PATH_LEN,
2219 .mode = 0644,
2220 .proc_handler = proc_dostring,
2221 },
2222#ifdef CONFIG_KEYS
2223 {
2224 .procname = "keys",
2225 .mode = 0555,
2226 .child = key_sysctls,
2227 },
2228#endif
2229#ifdef CONFIG_PERF_EVENTS
2230 /*
2231 * User-space scripts rely on the existence of this file
2232 * as a feature check for perf_events being enabled.
2233 *
2234 * So it's an ABI, do not remove!
2235 */
2236 {
2237 .procname = "perf_event_paranoid",
2238 .data = &sysctl_perf_event_paranoid,
2239 .maxlen = sizeof(sysctl_perf_event_paranoid),
2240 .mode = 0644,
2241 .proc_handler = proc_dointvec,
2242 },
2243 {
2244 .procname = "perf_event_mlock_kb",
2245 .data = &sysctl_perf_event_mlock,
2246 .maxlen = sizeof(sysctl_perf_event_mlock),
2247 .mode = 0644,
2248 .proc_handler = proc_dointvec,
2249 },
2250 {
2251 .procname = "perf_event_max_sample_rate",
2252 .data = &sysctl_perf_event_sample_rate,
2253 .maxlen = sizeof(sysctl_perf_event_sample_rate),
2254 .mode = 0644,
2255 .proc_handler = perf_proc_update_handler,
2256 .extra1 = SYSCTL_ONE,
2257 },
2258 {
2259 .procname = "perf_cpu_time_max_percent",
2260 .data = &sysctl_perf_cpu_time_max_percent,
2261 .maxlen = sizeof(sysctl_perf_cpu_time_max_percent),
2262 .mode = 0644,
2263 .proc_handler = perf_cpu_time_max_percent_handler,
2264 .extra1 = SYSCTL_ZERO,
Xiaoming Ni78e36f32022-01-21 22:10:55 -08002265 .extra2 = SYSCTL_ONE_HUNDRED,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 },
2267 {
2268 .procname = "perf_event_max_stack",
2269 .data = &sysctl_perf_event_max_stack,
2270 .maxlen = sizeof(sysctl_perf_event_max_stack),
2271 .mode = 0644,
2272 .proc_handler = perf_event_max_stack_handler,
2273 .extra1 = SYSCTL_ZERO,
Xiaoming Nid73840e2022-01-21 22:11:14 -08002274 .extra2 = (void *)&six_hundred_forty_kb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 },
2276 {
2277 .procname = "perf_event_max_contexts_per_stack",
2278 .data = &sysctl_perf_event_max_contexts_per_stack,
2279 .maxlen = sizeof(sysctl_perf_event_max_contexts_per_stack),
2280 .mode = 0644,
2281 .proc_handler = perf_event_max_stack_handler,
2282 .extra1 = SYSCTL_ZERO,
Xiaoming Ni78e36f32022-01-21 22:10:55 -08002283 .extra2 = SYSCTL_ONE_THOUSAND,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 },
2285#endif
2286 {
2287 .procname = "panic_on_warn",
2288 .data = &panic_on_warn,
2289 .maxlen = sizeof(int),
2290 .mode = 0644,
2291 .proc_handler = proc_dointvec_minmax,
2292 .extra1 = SYSCTL_ZERO,
2293 .extra2 = SYSCTL_ONE,
2294 },
2295#if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
2296 {
2297 .procname = "timer_migration",
2298 .data = &sysctl_timer_migration,
2299 .maxlen = sizeof(unsigned int),
2300 .mode = 0644,
2301 .proc_handler = timer_migration_handler,
2302 .extra1 = SYSCTL_ZERO,
2303 .extra2 = SYSCTL_ONE,
2304 },
2305#endif
2306#ifdef CONFIG_BPF_SYSCALL
2307 {
2308 .procname = "unprivileged_bpf_disabled",
2309 .data = &sysctl_unprivileged_bpf_disabled,
2310 .maxlen = sizeof(sysctl_unprivileged_bpf_disabled),
2311 .mode = 0644,
Daniel Borkmann08389d82021-05-11 22:35:17 +02002312 .proc_handler = bpf_unpriv_handler,
2313 .extra1 = SYSCTL_ZERO,
Xiaoming Ni78e36f32022-01-21 22:10:55 -08002314 .extra2 = SYSCTL_TWO,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 },
2316 {
2317 .procname = "bpf_stats_enabled",
2318 .data = &bpf_stats_enabled_key.key,
2319 .maxlen = sizeof(bpf_stats_enabled_key),
2320 .mode = 0644,
Song Liud46edd62020-04-30 00:15:04 -07002321 .proc_handler = bpf_stats_handler,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 },
2323#endif
2324#if defined(CONFIG_TREE_RCU)
2325 {
2326 .procname = "panic_on_rcu_stall",
2327 .data = &sysctl_panic_on_rcu_stall,
2328 .maxlen = sizeof(sysctl_panic_on_rcu_stall),
2329 .mode = 0644,
2330 .proc_handler = proc_dointvec_minmax,
2331 .extra1 = SYSCTL_ZERO,
2332 .extra2 = SYSCTL_ONE,
2333 },
2334#endif
chaodfe56402020-08-30 23:41:17 -07002335#if defined(CONFIG_TREE_RCU)
2336 {
2337 .procname = "max_rcu_stall_to_panic",
2338 .data = &sysctl_max_rcu_stall_to_panic,
2339 .maxlen = sizeof(sysctl_max_rcu_stall_to_panic),
2340 .mode = 0644,
2341 .proc_handler = proc_dointvec_minmax,
2342 .extra1 = SYSCTL_ONE,
2343 .extra2 = SYSCTL_INT_MAX,
2344 },
2345#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346 { }
2347};
2348
2349static struct ctl_table vm_table[] = {
2350 {
2351 .procname = "overcommit_memory",
2352 .data = &sysctl_overcommit_memory,
2353 .maxlen = sizeof(sysctl_overcommit_memory),
2354 .mode = 0644,
Feng Tang56f35472020-08-06 23:23:15 -07002355 .proc_handler = overcommit_policy_handler,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 .extra1 = SYSCTL_ZERO,
Xiaoming Ni78e36f32022-01-21 22:10:55 -08002357 .extra2 = SYSCTL_TWO,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 },
2359 {
2360 .procname = "panic_on_oom",
2361 .data = &sysctl_panic_on_oom,
2362 .maxlen = sizeof(sysctl_panic_on_oom),
2363 .mode = 0644,
2364 .proc_handler = proc_dointvec_minmax,
2365 .extra1 = SYSCTL_ZERO,
Xiaoming Ni78e36f32022-01-21 22:10:55 -08002366 .extra2 = SYSCTL_TWO,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367 },
2368 {
2369 .procname = "oom_kill_allocating_task",
2370 .data = &sysctl_oom_kill_allocating_task,
2371 .maxlen = sizeof(sysctl_oom_kill_allocating_task),
2372 .mode = 0644,
2373 .proc_handler = proc_dointvec,
2374 },
2375 {
2376 .procname = "oom_dump_tasks",
2377 .data = &sysctl_oom_dump_tasks,
2378 .maxlen = sizeof(sysctl_oom_dump_tasks),
2379 .mode = 0644,
2380 .proc_handler = proc_dointvec,
2381 },
2382 {
2383 .procname = "overcommit_ratio",
2384 .data = &sysctl_overcommit_ratio,
2385 .maxlen = sizeof(sysctl_overcommit_ratio),
2386 .mode = 0644,
2387 .proc_handler = overcommit_ratio_handler,
2388 },
2389 {
2390 .procname = "overcommit_kbytes",
2391 .data = &sysctl_overcommit_kbytes,
2392 .maxlen = sizeof(sysctl_overcommit_kbytes),
2393 .mode = 0644,
2394 .proc_handler = overcommit_kbytes_handler,
2395 },
2396 {
Christoph Hellwigf461d2d2020-04-24 08:43:37 +02002397 .procname = "page-cluster",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 .data = &page_cluster,
2399 .maxlen = sizeof(int),
2400 .mode = 0644,
2401 .proc_handler = proc_dointvec_minmax,
2402 .extra1 = SYSCTL_ZERO,
2403 },
2404 {
2405 .procname = "dirty_background_ratio",
2406 .data = &dirty_background_ratio,
2407 .maxlen = sizeof(dirty_background_ratio),
2408 .mode = 0644,
2409 .proc_handler = dirty_background_ratio_handler,
2410 .extra1 = SYSCTL_ZERO,
Xiaoming Ni78e36f32022-01-21 22:10:55 -08002411 .extra2 = SYSCTL_ONE_HUNDRED,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 },
2413 {
2414 .procname = "dirty_background_bytes",
2415 .data = &dirty_background_bytes,
2416 .maxlen = sizeof(dirty_background_bytes),
2417 .mode = 0644,
2418 .proc_handler = dirty_background_bytes_handler,
Luis Chamberlainb1f2aff2022-01-21 22:12:48 -08002419 .extra1 = SYSCTL_LONG_ONE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420 },
2421 {
2422 .procname = "dirty_ratio",
2423 .data = &vm_dirty_ratio,
2424 .maxlen = sizeof(vm_dirty_ratio),
2425 .mode = 0644,
2426 .proc_handler = dirty_ratio_handler,
2427 .extra1 = SYSCTL_ZERO,
Xiaoming Ni78e36f32022-01-21 22:10:55 -08002428 .extra2 = SYSCTL_ONE_HUNDRED,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 },
2430 {
2431 .procname = "dirty_bytes",
2432 .data = &vm_dirty_bytes,
2433 .maxlen = sizeof(vm_dirty_bytes),
2434 .mode = 0644,
2435 .proc_handler = dirty_bytes_handler,
Xiaoming Nid73840e2022-01-21 22:11:14 -08002436 .extra1 = (void *)&dirty_bytes_min,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 },
2438 {
2439 .procname = "dirty_writeback_centisecs",
2440 .data = &dirty_writeback_interval,
2441 .maxlen = sizeof(dirty_writeback_interval),
2442 .mode = 0644,
2443 .proc_handler = dirty_writeback_centisecs_handler,
2444 },
2445 {
2446 .procname = "dirty_expire_centisecs",
2447 .data = &dirty_expire_interval,
2448 .maxlen = sizeof(dirty_expire_interval),
2449 .mode = 0644,
2450 .proc_handler = proc_dointvec_minmax,
2451 .extra1 = SYSCTL_ZERO,
2452 },
2453 {
2454 .procname = "dirtytime_expire_seconds",
2455 .data = &dirtytime_expire_interval,
2456 .maxlen = sizeof(dirtytime_expire_interval),
2457 .mode = 0644,
2458 .proc_handler = dirtytime_interval_handler,
2459 .extra1 = SYSCTL_ZERO,
2460 },
2461 {
2462 .procname = "swappiness",
2463 .data = &vm_swappiness,
2464 .maxlen = sizeof(vm_swappiness),
2465 .mode = 0644,
2466 .proc_handler = proc_dointvec_minmax,
2467 .extra1 = SYSCTL_ZERO,
Xiaoming Ni78e36f32022-01-21 22:10:55 -08002468 .extra2 = SYSCTL_TWO_HUNDRED,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 },
2470#ifdef CONFIG_HUGETLB_PAGE
2471 {
2472 .procname = "nr_hugepages",
2473 .data = NULL,
2474 .maxlen = sizeof(unsigned long),
2475 .mode = 0644,
2476 .proc_handler = hugetlb_sysctl_handler,
2477 },
2478#ifdef CONFIG_NUMA
2479 {
2480 .procname = "nr_hugepages_mempolicy",
2481 .data = NULL,
2482 .maxlen = sizeof(unsigned long),
2483 .mode = 0644,
2484 .proc_handler = &hugetlb_mempolicy_sysctl_handler,
2485 },
2486 {
2487 .procname = "numa_stat",
2488 .data = &sysctl_vm_numa_stat,
2489 .maxlen = sizeof(int),
2490 .mode = 0644,
2491 .proc_handler = sysctl_vm_numa_stat_handler,
2492 .extra1 = SYSCTL_ZERO,
2493 .extra2 = SYSCTL_ONE,
2494 },
2495#endif
2496 {
2497 .procname = "hugetlb_shm_group",
2498 .data = &sysctl_hugetlb_shm_group,
2499 .maxlen = sizeof(gid_t),
2500 .mode = 0644,
2501 .proc_handler = proc_dointvec,
2502 },
2503 {
2504 .procname = "nr_overcommit_hugepages",
2505 .data = NULL,
2506 .maxlen = sizeof(unsigned long),
2507 .mode = 0644,
2508 .proc_handler = hugetlb_overcommit_handler,
2509 },
2510#endif
2511 {
2512 .procname = "lowmem_reserve_ratio",
2513 .data = &sysctl_lowmem_reserve_ratio,
2514 .maxlen = sizeof(sysctl_lowmem_reserve_ratio),
2515 .mode = 0644,
2516 .proc_handler = lowmem_reserve_ratio_sysctl_handler,
2517 },
2518 {
2519 .procname = "drop_caches",
2520 .data = &sysctl_drop_caches,
2521 .maxlen = sizeof(int),
2522 .mode = 0200,
2523 .proc_handler = drop_caches_sysctl_handler,
2524 .extra1 = SYSCTL_ONE,
Xiaoming Ni78e36f32022-01-21 22:10:55 -08002525 .extra2 = SYSCTL_FOUR,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526 },
2527#ifdef CONFIG_COMPACTION
2528 {
2529 .procname = "compact_memory",
Pintu Kumaref498432021-05-04 18:36:48 -07002530 .data = NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531 .maxlen = sizeof(int),
2532 .mode = 0200,
2533 .proc_handler = sysctl_compaction_handler,
2534 },
2535 {
Nitin Guptafacdaa92020-08-11 18:31:00 -07002536 .procname = "compaction_proactiveness",
2537 .data = &sysctl_compaction_proactiveness,
Nitin Guptad34c0a72020-08-11 18:31:07 -07002538 .maxlen = sizeof(sysctl_compaction_proactiveness),
Nitin Guptafacdaa92020-08-11 18:31:00 -07002539 .mode = 0644,
Charan Teja Reddy65d759c2021-09-02 14:59:59 -07002540 .proc_handler = compaction_proactiveness_sysctl_handler,
Nitin Guptafacdaa92020-08-11 18:31:00 -07002541 .extra1 = SYSCTL_ZERO,
Xiaoming Ni78e36f32022-01-21 22:10:55 -08002542 .extra2 = SYSCTL_ONE_HUNDRED,
Nitin Guptafacdaa92020-08-11 18:31:00 -07002543 },
2544 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 .procname = "extfrag_threshold",
2546 .data = &sysctl_extfrag_threshold,
2547 .maxlen = sizeof(int),
2548 .mode = 0644,
2549 .proc_handler = proc_dointvec_minmax,
Xiaoming Ni2452dcb2022-01-21 22:11:19 -08002550 .extra1 = SYSCTL_ZERO,
Xiaoming Nid73840e2022-01-21 22:11:14 -08002551 .extra2 = (void *)&max_extfrag_threshold,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552 },
2553 {
2554 .procname = "compact_unevictable_allowed",
2555 .data = &sysctl_compact_unevictable_allowed,
2556 .maxlen = sizeof(int),
2557 .mode = 0644,
2558 .proc_handler = proc_dointvec_minmax_warn_RT_change,
2559 .extra1 = SYSCTL_ZERO,
2560 .extra2 = SYSCTL_ONE,
2561 },
2562
2563#endif /* CONFIG_COMPACTION */
2564 {
2565 .procname = "min_free_kbytes",
2566 .data = &min_free_kbytes,
2567 .maxlen = sizeof(min_free_kbytes),
2568 .mode = 0644,
2569 .proc_handler = min_free_kbytes_sysctl_handler,
2570 .extra1 = SYSCTL_ZERO,
2571 },
2572 {
2573 .procname = "watermark_boost_factor",
2574 .data = &watermark_boost_factor,
2575 .maxlen = sizeof(watermark_boost_factor),
2576 .mode = 0644,
Christoph Hellwigf461d2d2020-04-24 08:43:37 +02002577 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 .extra1 = SYSCTL_ZERO,
2579 },
2580 {
2581 .procname = "watermark_scale_factor",
2582 .data = &watermark_scale_factor,
2583 .maxlen = sizeof(watermark_scale_factor),
2584 .mode = 0644,
2585 .proc_handler = watermark_scale_factor_sysctl_handler,
2586 .extra1 = SYSCTL_ONE,
Xiaoming Ni78e36f32022-01-21 22:10:55 -08002587 .extra2 = SYSCTL_THREE_THOUSAND,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588 },
2589 {
Mel Gorman74f44822021-06-28 19:42:24 -07002590 .procname = "percpu_pagelist_high_fraction",
2591 .data = &percpu_pagelist_high_fraction,
2592 .maxlen = sizeof(percpu_pagelist_high_fraction),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593 .mode = 0644,
Mel Gorman74f44822021-06-28 19:42:24 -07002594 .proc_handler = percpu_pagelist_high_fraction_sysctl_handler,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595 .extra1 = SYSCTL_ZERO,
2596 },
Linus Torvalds5ef64cc2020-09-13 14:05:35 -07002597 {
2598 .procname = "page_lock_unfairness",
2599 .data = &sysctl_page_lock_unfairness,
2600 .maxlen = sizeof(sysctl_page_lock_unfairness),
2601 .mode = 0644,
2602 .proc_handler = proc_dointvec_minmax,
2603 .extra1 = SYSCTL_ZERO,
2604 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605#ifdef CONFIG_MMU
2606 {
2607 .procname = "max_map_count",
2608 .data = &sysctl_max_map_count,
2609 .maxlen = sizeof(sysctl_max_map_count),
2610 .mode = 0644,
2611 .proc_handler = proc_dointvec_minmax,
2612 .extra1 = SYSCTL_ZERO,
2613 },
2614#else
2615 {
2616 .procname = "nr_trim_pages",
2617 .data = &sysctl_nr_trim_pages,
2618 .maxlen = sizeof(sysctl_nr_trim_pages),
2619 .mode = 0644,
2620 .proc_handler = proc_dointvec_minmax,
2621 .extra1 = SYSCTL_ZERO,
2622 },
2623#endif
2624 {
2625 .procname = "laptop_mode",
2626 .data = &laptop_mode,
2627 .maxlen = sizeof(laptop_mode),
2628 .mode = 0644,
2629 .proc_handler = proc_dointvec_jiffies,
2630 },
2631 {
2632 .procname = "vfs_cache_pressure",
2633 .data = &sysctl_vfs_cache_pressure,
2634 .maxlen = sizeof(sysctl_vfs_cache_pressure),
2635 .mode = 0644,
Lin Feng3b3376f2021-02-25 17:20:53 -08002636 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 .extra1 = SYSCTL_ZERO,
2638 },
2639#if defined(HAVE_ARCH_PICK_MMAP_LAYOUT) || \
2640 defined(CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT)
2641 {
2642 .procname = "legacy_va_layout",
2643 .data = &sysctl_legacy_va_layout,
2644 .maxlen = sizeof(sysctl_legacy_va_layout),
2645 .mode = 0644,
Lin Feng3b3376f2021-02-25 17:20:53 -08002646 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647 .extra1 = SYSCTL_ZERO,
2648 },
2649#endif
2650#ifdef CONFIG_NUMA
2651 {
2652 .procname = "zone_reclaim_mode",
2653 .data = &node_reclaim_mode,
2654 .maxlen = sizeof(node_reclaim_mode),
2655 .mode = 0644,
Lin Feng3b3376f2021-02-25 17:20:53 -08002656 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657 .extra1 = SYSCTL_ZERO,
2658 },
2659 {
2660 .procname = "min_unmapped_ratio",
2661 .data = &sysctl_min_unmapped_ratio,
2662 .maxlen = sizeof(sysctl_min_unmapped_ratio),
2663 .mode = 0644,
2664 .proc_handler = sysctl_min_unmapped_ratio_sysctl_handler,
2665 .extra1 = SYSCTL_ZERO,
Xiaoming Ni78e36f32022-01-21 22:10:55 -08002666 .extra2 = SYSCTL_ONE_HUNDRED,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667 },
2668 {
2669 .procname = "min_slab_ratio",
2670 .data = &sysctl_min_slab_ratio,
2671 .maxlen = sizeof(sysctl_min_slab_ratio),
2672 .mode = 0644,
2673 .proc_handler = sysctl_min_slab_ratio_sysctl_handler,
2674 .extra1 = SYSCTL_ZERO,
Xiaoming Ni78e36f32022-01-21 22:10:55 -08002675 .extra2 = SYSCTL_ONE_HUNDRED,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676 },
2677#endif
2678#ifdef CONFIG_SMP
2679 {
2680 .procname = "stat_interval",
2681 .data = &sysctl_stat_interval,
2682 .maxlen = sizeof(sysctl_stat_interval),
2683 .mode = 0644,
2684 .proc_handler = proc_dointvec_jiffies,
2685 },
2686 {
2687 .procname = "stat_refresh",
2688 .data = NULL,
2689 .maxlen = 0,
2690 .mode = 0600,
2691 .proc_handler = vmstat_refresh,
2692 },
2693#endif
2694#ifdef CONFIG_MMU
2695 {
2696 .procname = "mmap_min_addr",
2697 .data = &dac_mmap_min_addr,
2698 .maxlen = sizeof(unsigned long),
2699 .mode = 0644,
2700 .proc_handler = mmap_min_addr_handler,
2701 },
2702#endif
2703#ifdef CONFIG_NUMA
2704 {
2705 .procname = "numa_zonelist_order",
2706 .data = &numa_zonelist_order,
2707 .maxlen = NUMA_ZONELIST_ORDER_LEN,
2708 .mode = 0644,
2709 .proc_handler = numa_zonelist_order_handler,
2710 },
2711#endif
2712#if (defined(CONFIG_X86_32) && !defined(CONFIG_UML))|| \
2713 (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL))
2714 {
2715 .procname = "vdso_enabled",
2716#ifdef CONFIG_X86_32
2717 .data = &vdso32_enabled,
2718 .maxlen = sizeof(vdso32_enabled),
2719#else
2720 .data = &vdso_enabled,
2721 .maxlen = sizeof(vdso_enabled),
2722#endif
2723 .mode = 0644,
2724 .proc_handler = proc_dointvec,
2725 .extra1 = SYSCTL_ZERO,
2726 },
2727#endif
2728#ifdef CONFIG_HIGHMEM
2729 {
2730 .procname = "highmem_is_dirtyable",
2731 .data = &vm_highmem_is_dirtyable,
2732 .maxlen = sizeof(vm_highmem_is_dirtyable),
2733 .mode = 0644,
2734 .proc_handler = proc_dointvec_minmax,
2735 .extra1 = SYSCTL_ZERO,
2736 .extra2 = SYSCTL_ONE,
2737 },
2738#endif
2739#ifdef CONFIG_MEMORY_FAILURE
2740 {
2741 .procname = "memory_failure_early_kill",
2742 .data = &sysctl_memory_failure_early_kill,
2743 .maxlen = sizeof(sysctl_memory_failure_early_kill),
2744 .mode = 0644,
2745 .proc_handler = proc_dointvec_minmax,
2746 .extra1 = SYSCTL_ZERO,
2747 .extra2 = SYSCTL_ONE,
2748 },
2749 {
2750 .procname = "memory_failure_recovery",
2751 .data = &sysctl_memory_failure_recovery,
2752 .maxlen = sizeof(sysctl_memory_failure_recovery),
2753 .mode = 0644,
2754 .proc_handler = proc_dointvec_minmax,
2755 .extra1 = SYSCTL_ZERO,
2756 .extra2 = SYSCTL_ONE,
2757 },
2758#endif
2759 {
2760 .procname = "user_reserve_kbytes",
2761 .data = &sysctl_user_reserve_kbytes,
2762 .maxlen = sizeof(sysctl_user_reserve_kbytes),
2763 .mode = 0644,
2764 .proc_handler = proc_doulongvec_minmax,
2765 },
2766 {
2767 .procname = "admin_reserve_kbytes",
2768 .data = &sysctl_admin_reserve_kbytes,
2769 .maxlen = sizeof(sysctl_admin_reserve_kbytes),
2770 .mode = 0644,
2771 .proc_handler = proc_doulongvec_minmax,
2772 },
2773#ifdef CONFIG_HAVE_ARCH_MMAP_RND_BITS
2774 {
2775 .procname = "mmap_rnd_bits",
2776 .data = &mmap_rnd_bits,
2777 .maxlen = sizeof(mmap_rnd_bits),
2778 .mode = 0600,
2779 .proc_handler = proc_dointvec_minmax,
2780 .extra1 = (void *)&mmap_rnd_bits_min,
2781 .extra2 = (void *)&mmap_rnd_bits_max,
2782 },
2783#endif
2784#ifdef CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS
2785 {
2786 .procname = "mmap_rnd_compat_bits",
2787 .data = &mmap_rnd_compat_bits,
2788 .maxlen = sizeof(mmap_rnd_compat_bits),
2789 .mode = 0600,
2790 .proc_handler = proc_dointvec_minmax,
2791 .extra1 = (void *)&mmap_rnd_compat_bits_min,
2792 .extra2 = (void *)&mmap_rnd_compat_bits_max,
2793 },
2794#endif
2795#ifdef CONFIG_USERFAULTFD
2796 {
2797 .procname = "unprivileged_userfaultfd",
2798 .data = &sysctl_unprivileged_userfaultfd,
2799 .maxlen = sizeof(sysctl_unprivileged_userfaultfd),
2800 .mode = 0644,
2801 .proc_handler = proc_dointvec_minmax,
2802 .extra1 = SYSCTL_ZERO,
2803 .extra2 = SYSCTL_ONE,
2804 },
2805#endif
2806 { }
2807};
2808
Linus Torvalds1da177e2005-04-16 15:20:36 -07002809static struct ctl_table debug_table[] = {
2810#ifdef CONFIG_SYSCTL_EXCEPTION_TRACE
2811 {
2812 .procname = "exception-trace",
2813 .data = &show_unhandled_signals,
2814 .maxlen = sizeof(int),
2815 .mode = 0644,
2816 .proc_handler = proc_dointvec
2817 },
2818#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 { }
2820};
2821
2822static struct ctl_table dev_table[] = {
2823 { }
2824};
2825
Luis Chamberlain51cb8df2022-01-21 22:13:24 -08002826DECLARE_SYSCTL_BASE(kernel, kern_table);
2827DECLARE_SYSCTL_BASE(vm, vm_table);
Luis Chamberlain51cb8df2022-01-21 22:13:24 -08002828DECLARE_SYSCTL_BASE(debug, debug_table);
2829DECLARE_SYSCTL_BASE(dev, dev_table);
Christoph Hellwigf461d2d2020-04-24 08:43:37 +02002830
Luis Chamberlaind8c04182022-01-21 22:13:31 -08002831int __init sysctl_init_bases(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832{
Luis Chamberlain51cb8df2022-01-21 22:13:24 -08002833 register_sysctl_base(kernel);
2834 register_sysctl_base(vm);
Luis Chamberlain51cb8df2022-01-21 22:13:24 -08002835 register_sysctl_base(debug);
2836 register_sysctl_base(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838 return 0;
2839}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840#endif /* CONFIG_SYSCTL */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841/*
2842 * No sense putting this after each symbol definition, twice,
2843 * exception granted :-)
2844 */
Jia Hea2071572021-08-03 12:59:36 +02002845EXPORT_SYMBOL(proc_dobool);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846EXPORT_SYMBOL(proc_dointvec);
Subash Abhinov Kasiviswanathane7d316a2016-08-25 15:16:51 -07002847EXPORT_SYMBOL(proc_douintvec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848EXPORT_SYMBOL(proc_dointvec_jiffies);
2849EXPORT_SYMBOL(proc_dointvec_minmax);
Luis R. Rodriguez61d9b562017-07-12 14:33:40 -07002850EXPORT_SYMBOL_GPL(proc_douintvec_minmax);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
2852EXPORT_SYMBOL(proc_dointvec_ms_jiffies);
2853EXPORT_SYMBOL(proc_dostring);
2854EXPORT_SYMBOL(proc_doulongvec_minmax);
2855EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
Stephen Suryaputra0bc19982019-04-17 16:35:49 -04002856EXPORT_SYMBOL(proc_do_large_bitmap);