sysctl.c 81.2 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-only
Linus Torvalds's avatar
Linus Torvalds committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * sysctl.c: General linux system control interface
 *
 * Begun 24 March 1995, Stephen Tweedie
 * Added /proc support, Dec 1995
 * Added bdflush entry and intvec min/max checking, 2/23/96, Tom Dyas.
 * Added hooks for /proc/sys/net (minor, minor patch), 96/4/1, Mike Shaver.
 * Added kernel/java-{interpreter,appletviewer}, 96/5/10, Mike Shaver.
 * Dynamic registration fixes, Stephen Tweedie.
 * Added kswapd-interval, ctrl-alt-del, printk stuff, 1/8/97, Chris Horn.
 * Made sysctl support optional via CONFIG_SYSCTL, 1/10/97, Chris
 *  Horn.
 * Added proc_doulongvec_ms_jiffies_minmax, 09/08/99, Carlos H. Bauer.
 * Added proc_doulongvec_minmax, 09/08/99, Carlos H. Bauer.
 * Changed linked lists to use list.h instead of lists.h, 02/24/00, Bill
 *  Wendling.
 * The list_for_each() macro wasn't appropriate for the sysctl loop.
 *  Removed it and replaced it with older style, 03/23/00, Bill Wendling
 */

#include <linux/module.h>
23
#include <linux/aio.h>
Linus Torvalds's avatar
Linus Torvalds committed
24 25 26 27
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/slab.h>
#include <linux/sysctl.h>
28
#include <linux/bitmap.h>
Dave Young's avatar
Dave Young committed
29
#include <linux/signal.h>
30
#include <linux/printk.h>
Linus Torvalds's avatar
Linus Torvalds committed
31
#include <linux/proc_fs.h>
32
#include <linux/security.h>
Linus Torvalds's avatar
Linus Torvalds committed
33
#include <linux/ctype.h>
34
#include <linux/kmemleak.h>
35
#include <linux/fs.h>
Linus Torvalds's avatar
Linus Torvalds committed
36 37
#include <linux/init.h>
#include <linux/kernel.h>
38
#include <linux/kobject.h>
39
#include <linux/net.h>
Linus Torvalds's avatar
Linus Torvalds committed
40 41 42
#include <linux/sysrq.h>
#include <linux/highuid.h>
#include <linux/writeback.h>
43
#include <linux/ratelimit.h>
44
#include <linux/compaction.h>
Linus Torvalds's avatar
Linus Torvalds committed
45 46
#include <linux/hugetlb.h>
#include <linux/initrd.h>
47
#include <linux/key.h>
Linus Torvalds's avatar
Linus Torvalds committed
48 49 50
#include <linux/times.h>
#include <linux/limits.h>
#include <linux/dcache.h>
51
#include <linux/dnotify.h>
Linus Torvalds's avatar
Linus Torvalds committed
52
#include <linux/syscalls.h>
Adrian Bunk's avatar
Adrian Bunk committed
53
#include <linux/vmstat.h>
54 55
#include <linux/nfs_fs.h>
#include <linux/acpi.h>
56
#include <linux/reboot.h>
57
#include <linux/ftrace.h>
58
#include <linux/perf_event.h>
59
#include <linux/kprobes.h>
60
#include <linux/pipe_fs_i.h>
61
#include <linux/oom.h>
62
#include <linux/kmod.h>
63
#include <linux/capability.h>
Al Viro's avatar
Al Viro committed
64
#include <linux/binfmts.h>
65
#include <linux/sched/sysctl.h>
66
#include <linux/sched/coredump.h>
67
#include <linux/kexec.h>
68
#include <linux/bpf.h>
69
#include <linux/mount.h>
70
#include <linux/userfaultfd_k.h>
Linus Torvalds's avatar
Linus Torvalds committed
71

72 73
#include "../lib/kstrtox.h"

74
#include <linux/uaccess.h>
Linus Torvalds's avatar
Linus Torvalds committed
75 76
#include <asm/processor.h>

77 78
#ifdef CONFIG_X86
#include <asm/nmi.h>
79
#include <asm/stacktrace.h>
80
#include <asm/io.h>
81
#endif
82 83 84
#ifdef CONFIG_SPARC
#include <asm/setup.h>
#endif
Dave Young's avatar
Dave Young committed
85 86 87
#ifdef CONFIG_BSD_PROCESS_ACCT
#include <linux/acct.h>
#endif
Dave Young's avatar
Dave Young committed
88 89 90
#ifdef CONFIG_RT_MUTEXES
#include <linux/rtmutex.h>
#endif
Dave Young's avatar
Dave Young committed
91 92 93
#if defined(CONFIG_PROVE_LOCKING) || defined(CONFIG_LOCK_STAT)
#include <linux/lockdep.h>
#endif
Dave Young's avatar
Dave Young committed
94 95 96
#ifdef CONFIG_CHR_DEV_SG
#include <scsi/sg.h>
#endif
97 98 99
#ifdef CONFIG_STACKLEAK_RUNTIME_DISABLE
#include <linux/stackleak.h>
#endif
100
#ifdef CONFIG_LOCKUP_DETECTOR
101 102 103
#include <linux/nmi.h>
#endif

Linus Torvalds's avatar
Linus Torvalds committed
104 105 106
#if defined(CONFIG_SYSCTL)

/* External variables not in a header file. */
Alan Cox's avatar
Alan Cox committed
107
extern int suid_dumpable;
108 109
#ifdef CONFIG_COREDUMP
extern int core_uses_pid;
Linus Torvalds's avatar
Linus Torvalds committed
110
extern char core_pattern[];
111
extern unsigned int core_pipe_limit;
112
#endif
Linus Torvalds's avatar
Linus Torvalds committed
113 114
extern int pid_max;
extern int pid_max_min, pid_max_max;
115
extern int percpu_pagelist_fraction;
Arjan van de Ven's avatar
Arjan van de Ven committed
116
extern int latencytop_enabled;
117
extern unsigned int sysctl_nr_open_min, sysctl_nr_open_max;
118 119 120
#ifndef CONFIG_MMU
extern int sysctl_nr_trim_pages;
#endif
Linus Torvalds's avatar
Linus Torvalds committed
121

122
/* Constants used for minimum and  maximum */
123
#ifdef CONFIG_LOCKUP_DETECTOR
124 125 126
static int sixty = 60;
#endif

127
static int __maybe_unused neg_one = -1;
128
static int __maybe_unused two = 2;
129
static int __maybe_unused four = 4;
130
static unsigned long zero_ul;
131
static unsigned long one_ul = 1;
132
static unsigned long long_max = LONG_MAX;
133
static int one_hundred = 100;
134
static int one_thousand = 1000;
135 136 137
#ifdef CONFIG_PRINTK
static int ten_thousand = 10000;
#endif
138 139 140
#ifdef CONFIG_PERF_EVENTS
static int six_hundred_forty_kb = 640 * 1024;
#endif
141

142 143 144
/* this is needed for the proc_doulongvec_minmax of vm_dirty_bytes */
static unsigned long dirty_bytes_min = 2 * PAGE_SIZE;

Linus Torvalds's avatar
Linus Torvalds committed
145 146 147 148 149
/* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
static int maxolduid = 65535;
static int minolduid;

static int ngroups_max = NGROUPS_MAX;
150
static const int cap_last_cap = CAP_LAST_CAP;
Linus Torvalds's avatar
Linus Torvalds committed
151

152 153 154 155
/*
 * This is needed for proc_doulongvec_minmax of sysctl_hung_task_timeout_secs
 * and hung_task_check_interval_secs
 */
156 157 158 159
#ifdef CONFIG_DETECT_HUNG_TASK
static unsigned long hung_task_timeout_max = (LONG_MAX/HZ);
#endif

Dave Young's avatar
Dave Young committed
160 161 162
#ifdef CONFIG_INOTIFY_USER
#include <linux/inotify.h>
#endif
163
#ifdef CONFIG_SPARC
Linus Torvalds's avatar
Linus Torvalds committed
164 165
#endif

166
#ifdef CONFIG_PARISC
Linus Torvalds's avatar
Linus Torvalds committed
167
extern int pwrsw_enabled;
168 169 170
#endif

#ifdef CONFIG_SYSCTL_ARCH_UNALIGN_ALLOW
Linus Torvalds's avatar
Linus Torvalds committed
171 172 173
extern int unaligned_enabled;
#endif

174
#ifdef CONFIG_IA64
175
extern int unaligned_dump_stack;
176 177
#endif

178 179 180 181
#ifdef CONFIG_SYSCTL_ARCH_UNALIGN_NO_WARN
extern int no_unaligned_warning;
#endif

182
#ifdef CONFIG_PROC_SYSCTL
183

184 185 186 187
/**
 * enum sysctl_writes_mode - supported sysctl write modes
 *
 * @SYSCTL_WRITES_LEGACY: each write syscall must fully contain the sysctl value
188 189 190
 *	to be written, and multiple writes on the same sysctl file descriptor
 *	will rewrite the sysctl value, regardless of file position. No warning
 *	is issued when the initial position is not 0.
191
 * @SYSCTL_WRITES_WARN: same as above but warn when the initial file position is
192
 *	not 0.
193
 * @SYSCTL_WRITES_STRICT: writes to numeric sysctl entries must always be at
194 195 196 197 198
 *	file position 0 and the value must be fully contained in the buffer
 *	sent to the write syscall. If dealing with strings respect the file
 *	position, but restrict this to the max length of the buffer, anything
 *	passed the max length will be ignored. Multiple writes will append
 *	to the buffer.
199 200 201 202 203 204 205 206 207
 *
 * These write modes control how current file position affects the behavior of
 * updating sysctl values through the proc interface on each write.
 */
enum sysctl_writes_mode {
	SYSCTL_WRITES_LEGACY		= -1,
	SYSCTL_WRITES_WARN		= 0,
	SYSCTL_WRITES_STRICT		= 1,
};
208

209
static enum sysctl_writes_mode sysctl_writes_strict = SYSCTL_WRITES_STRICT;
210

211
static int proc_do_cad_pid(struct ctl_table *table, int write,
212
		  void __user *buffer, size_t *lenp, loff_t *ppos);
213
static int proc_taint(struct ctl_table *table, int write,
214
			       void __user *buffer, size_t *lenp, loff_t *ppos);
215 216 217 218 219
#ifdef CONFIG_COMPACTION
static int proc_dointvec_minmax_warn_RT_change(struct ctl_table *table,
					       int write, void __user *buffer,
					       size_t *lenp, loff_t *ppos);
#endif
220
#endif
221

222
#ifdef CONFIG_PRINTK
223
static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
224 225 226
				void __user *buffer, size_t *lenp, loff_t *ppos);
#endif

227 228
static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write,
		void __user *buffer, size_t *lenp, loff_t *ppos);
229
#ifdef CONFIG_COREDUMP
230 231
static int proc_dostring_coredump(struct ctl_table *table, int write,
		void __user *buffer, size_t *lenp, loff_t *ppos);
232
#endif
233 234
static int proc_dopipe_max_size(struct ctl_table *table, int write,
		void __user *buffer, size_t *lenp, loff_t *ppos);
235

236
#ifdef CONFIG_MAGIC_SYSRQ
237
static int sysrq_sysctl_handler(struct ctl_table *table, int write,
238
			void __user *buffer, size_t *lenp, loff_t *ppos);
239 240
#endif

241 242 243 244 245 246
static struct ctl_table kern_table[];
static struct ctl_table vm_table[];
static struct ctl_table fs_table[];
static struct ctl_table debug_table[];
static struct ctl_table dev_table[];
extern struct ctl_table random_table[];
247 248 249
#ifdef CONFIG_EPOLL
extern struct ctl_table epoll_table[];
#endif
Linus Torvalds's avatar
Linus Torvalds committed
250

251 252 253 254
#ifdef CONFIG_FW_LOADER_USER_HELPER
extern struct ctl_table firmware_config_table[];
#endif

255 256
#if defined(HAVE_ARCH_PICK_MMAP_LAYOUT) || \
    defined(CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT)
Linus Torvalds's avatar
Linus Torvalds committed
257 258 259 260 261
int sysctl_legacy_va_layout;
#endif

/* The default sysctl tables: */

262
static struct ctl_table sysctl_base_table[] = {
Linus Torvalds's avatar
Linus Torvalds committed
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
	{
		.procname	= "kernel",
		.mode		= 0555,
		.child		= kern_table,
	},
	{
		.procname	= "vm",
		.mode		= 0555,
		.child		= vm_table,
	},
	{
		.procname	= "fs",
		.mode		= 0555,
		.child		= fs_table,
	},
	{
		.procname	= "debug",
		.mode		= 0555,
		.child		= debug_table,
	},
	{
		.procname	= "dev",
		.mode		= 0555,
		.child		= dev_table,
	},
288
	{ }
Linus Torvalds's avatar
Linus Torvalds committed
289 290
};

Ingo Molnar's avatar
Ingo Molnar committed
291
#ifdef CONFIG_SCHED_DEBUG
292 293 294 295
static int min_sched_granularity_ns = 100000;		/* 100 usecs */
static int max_sched_granularity_ns = NSEC_PER_SEC;	/* 1 second */
static int min_wakeup_granularity_ns;			/* 0 usecs */
static int max_wakeup_granularity_ns = NSEC_PER_SEC;	/* 1 second */
296
#ifdef CONFIG_SMP
297 298
static int min_sched_tunable_scaling = SCHED_TUNABLESCALING_NONE;
static int max_sched_tunable_scaling = SCHED_TUNABLESCALING_END-1;
299 300
#endif /* CONFIG_SMP */
#endif /* CONFIG_SCHED_DEBUG */
Ingo Molnar's avatar
Ingo Molnar committed
301

302 303 304 305 306
#ifdef CONFIG_COMPACTION
static int min_extfrag_threshold;
static int max_extfrag_threshold = 1000;
#endif

307
static struct ctl_table kern_table[] = {
308 309 310 311 312
	{
		.procname	= "sched_child_runs_first",
		.data		= &sysctl_sched_child_runs_first,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
313
		.proc_handler	= proc_dointvec,
314
	},
Ingo Molnar's avatar
Ingo Molnar committed
315 316
#ifdef CONFIG_SCHED_DEBUG
	{
317 318
		.procname	= "sched_min_granularity_ns",
		.data		= &sysctl_sched_min_granularity,
Ingo Molnar's avatar
Ingo Molnar committed
319 320
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
321
		.proc_handler	= sched_proc_update_handler,
322 323
		.extra1		= &min_sched_granularity_ns,
		.extra2		= &max_sched_granularity_ns,
Ingo Molnar's avatar
Ingo Molnar committed
324
	},
325 326 327 328 329
	{
		.procname	= "sched_latency_ns",
		.data		= &sysctl_sched_latency,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
330
		.proc_handler	= sched_proc_update_handler,
331 332 333
		.extra1		= &min_sched_granularity_ns,
		.extra2		= &max_sched_granularity_ns,
	},
Ingo Molnar's avatar
Ingo Molnar committed
334 335 336 337 338
	{
		.procname	= "sched_wakeup_granularity_ns",
		.data		= &sysctl_sched_wakeup_granularity,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
339
		.proc_handler	= sched_proc_update_handler,
Ingo Molnar's avatar
Ingo Molnar committed
340 341 342
		.extra1		= &min_wakeup_granularity_ns,
		.extra2		= &max_wakeup_granularity_ns,
	},
343
#ifdef CONFIG_SMP
344 345 346 347 348
	{
		.procname	= "sched_tunable_scaling",
		.data		= &sysctl_sched_tunable_scaling,
		.maxlen		= sizeof(enum sched_tunable_scaling),
		.mode		= 0644,
349
		.proc_handler	= sched_proc_update_handler,
350 351
		.extra1		= &min_sched_tunable_scaling,
		.extra2		= &max_sched_tunable_scaling,
352
	},
353
	{
354
		.procname	= "sched_migration_cost_ns",
355 356 357
		.data		= &sysctl_sched_migration_cost,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
358
		.proc_handler	= proc_dointvec,
359
	},
360 361 362 363
	{
		.procname	= "sched_nr_migrate",
		.data		= &sysctl_sched_nr_migrate,
		.maxlen		= sizeof(unsigned int),
Peter Zijlstra's avatar
Peter Zijlstra committed
364
		.mode		= 0644,
365
		.proc_handler	= proc_dointvec,
Peter Zijlstra's avatar
Peter Zijlstra committed
366
	},
367 368 369 370 371 372 373
#ifdef CONFIG_SCHEDSTATS
	{
		.procname	= "sched_schedstats",
		.data		= NULL,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= sysctl_schedstats,
374 375
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
376 377
	},
#endif /* CONFIG_SCHEDSTATS */
378 379
#endif /* CONFIG_SMP */
#ifdef CONFIG_NUMA_BALANCING
380 381 382 383 384 385 386
	{
		.procname	= "numa_balancing_scan_delay_ms",
		.data		= &sysctl_numa_balancing_scan_delay,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
	},
387 388 389 390 391 392 393 394 395 396 397 398 399 400
	{
		.procname	= "numa_balancing_scan_period_min_ms",
		.data		= &sysctl_numa_balancing_scan_period_min,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
	},
	{
		.procname	= "numa_balancing_scan_period_max_ms",
		.data		= &sysctl_numa_balancing_scan_period_max,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
	},
401 402 403 404 405
	{
		.procname	= "numa_balancing_scan_size_mb",
		.data		= &sysctl_numa_balancing_scan_size,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
406
		.proc_handler	= proc_dointvec_minmax,
407
		.extra1		= SYSCTL_ONE,
408
	},
409 410 411 412 413 414
	{
		.procname	= "numa_balancing",
		.data		= NULL, /* filled in by handler */
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= sysctl_numa_balancing,
415 416
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
417
	},
418 419
#endif /* CONFIG_NUMA_BALANCING */
#endif /* CONFIG_SCHED_DEBUG */
Peter Zijlstra's avatar
Peter Zijlstra committed
420 421 422 423 424
	{
		.procname	= "sched_rt_period_us",
		.data		= &sysctl_sched_rt_period,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
425
		.proc_handler	= sched_rt_handler,
Peter Zijlstra's avatar
Peter Zijlstra committed
426 427 428 429 430 431
	},
	{
		.procname	= "sched_rt_runtime_us",
		.data		= &sysctl_sched_rt_runtime,
		.maxlen		= sizeof(int),
		.mode		= 0644,
432
		.proc_handler	= sched_rt_handler,
Peter Zijlstra's avatar
Peter Zijlstra committed
433
	},
434 435
	{
		.procname	= "sched_rr_timeslice_ms",
436
		.data		= &sysctl_sched_rr_timeslice,
437 438 439 440
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= sched_rr_handler,
	},
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
#ifdef CONFIG_UCLAMP_TASK
	{
		.procname	= "sched_util_clamp_min",
		.data		= &sysctl_sched_uclamp_util_min,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= sysctl_sched_uclamp_handler,
	},
	{
		.procname	= "sched_util_clamp_max",
		.data		= &sysctl_sched_uclamp_util_max,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= sysctl_sched_uclamp_handler,
	},
#endif
457 458 459 460 461 462
#ifdef CONFIG_SCHED_AUTOGROUP
	{
		.procname	= "sched_autogroup_enabled",
		.data		= &sysctl_sched_autogroup_enabled,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
463
		.proc_handler	= proc_dointvec_minmax,
464 465
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
466 467
	},
#endif
468 469 470 471 472 473 474
#ifdef CONFIG_CFS_BANDWIDTH
	{
		.procname	= "sched_cfs_bandwidth_slice_us",
		.data		= &sysctl_sched_cfs_bandwidth_slice,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
475
		.extra1		= SYSCTL_ONE,
476 477
	},
#endif
478 479 480 481 482 483 484
#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL)
	{
		.procname	= "sched_energy_aware",
		.data		= &sysctl_sched_energy_aware,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= sched_energy_aware_handler,
485 486
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
487 488
	},
#endif
489 490 491 492 493 494
#ifdef CONFIG_PROVE_LOCKING
	{
		.procname	= "prove_locking",
		.data		= &prove_locking,
		.maxlen		= sizeof(int),
		.mode		= 0644,
495
		.proc_handler	= proc_dointvec,
496 497 498 499 500 501 502 503
	},
#endif
#ifdef CONFIG_LOCK_STAT
	{
		.procname	= "lock_stat",
		.data		= &lock_stat,
		.maxlen		= sizeof(int),
		.mode		= 0644,
504
		.proc_handler	= proc_dointvec,
505
	},
Ingo Molnar's avatar
Ingo Molnar committed
506
#endif
Linus Torvalds's avatar
Linus Torvalds committed
507 508 509 510 511
	{
		.procname	= "panic",
		.data		= &panic_timeout,
		.maxlen		= sizeof(int),
		.mode		= 0644,
512
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
513
	},
514
#ifdef CONFIG_COREDUMP
Linus Torvalds's avatar
Linus Torvalds committed
515 516 517 518 519
	{
		.procname	= "core_uses_pid",
		.data		= &core_uses_pid,
		.maxlen		= sizeof(int),
		.mode		= 0644,
520
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
521 522 523 524
	},
	{
		.procname	= "core_pattern",
		.data		= core_pattern,
525
		.maxlen		= CORENAME_MAX_SIZE,
Linus Torvalds's avatar
Linus Torvalds committed
526
		.mode		= 0644,
527
		.proc_handler	= proc_dostring_coredump,
Linus Torvalds's avatar
Linus Torvalds committed
528
	},
529 530 531 532 533
	{
		.procname	= "core_pipe_limit",
		.data		= &core_pipe_limit,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
534
		.proc_handler	= proc_dointvec,
535
	},
536
#endif
537
#ifdef CONFIG_PROC_SYSCTL
Linus Torvalds's avatar
Linus Torvalds committed
538 539
	{
		.procname	= "tainted",
Andi Kleen's avatar
Andi Kleen committed
540
		.maxlen 	= sizeof(long),
541
		.mode		= 0644,
542
		.proc_handler	= proc_taint,
Linus Torvalds's avatar
Linus Torvalds committed
543
	},
544 545 546 547 548 549 550
	{
		.procname	= "sysctl_writes_strict",
		.data		= &sysctl_writes_strict,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
		.extra1		= &neg_one,
551
		.extra2		= SYSCTL_ONE,
552
	},
553
#endif
Arjan van de Ven's avatar
Arjan van de Ven committed
554 555 556 557 558 559
#ifdef CONFIG_LATENCYTOP
	{
		.procname	= "latencytop",
		.data		= &latencytop_enabled,
		.maxlen		= sizeof(int),
		.mode		= 0644,
560
		.proc_handler	= sysctl_latencytop,
Arjan van de Ven's avatar
Arjan van de Ven committed
561 562
	},
#endif
Linus Torvalds's avatar
Linus Torvalds committed
563 564 565 566 567 568
#ifdef CONFIG_BLK_DEV_INITRD
	{
		.procname	= "real-root-dev",
		.data		= &real_root_dev,
		.maxlen		= sizeof(int),
		.mode		= 0644,
569
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
570 571
	},
#endif
Ingo Molnar's avatar
Ingo Molnar committed
572 573 574 575 576
	{
		.procname	= "print-fatal-signals",
		.data		= &print_fatal_signals,
		.maxlen		= sizeof(int),
		.mode		= 0644,
577
		.proc_handler	= proc_dointvec,
Ingo Molnar's avatar
Ingo Molnar committed
578
	},
579
#ifdef CONFIG_SPARC
Linus Torvalds's avatar
Linus Torvalds committed
580 581 582 583 584
	{
		.procname	= "reboot-cmd",
		.data		= reboot_command,
		.maxlen		= 256,
		.mode		= 0644,
585
		.proc_handler	= proc_dostring,
Linus Torvalds's avatar
Linus Torvalds committed
586 587 588 589 590 591
	},
	{
		.procname	= "stop-a",
		.data		= &stop_a_enabled,
		.maxlen		= sizeof (int),
		.mode		= 0644,
592
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
593 594 595 596 597 598
	},
	{
		.procname	= "scons-poweroff",
		.data		= &scons_pwroff,
		.maxlen		= sizeof (int),
		.mode		= 0644,
599
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
600 601
	},
#endif
602 603 604 605 606 607
#ifdef CONFIG_SPARC64
	{
		.procname	= "tsb-ratio",
		.data		= &sysctl_tsb_ratio,
		.maxlen		= sizeof (int),
		.mode		= 0644,
608
		.proc_handler	= proc_dointvec,
609 610
	},
#endif
611
#ifdef CONFIG_PARISC
Linus Torvalds's avatar
Linus Torvalds committed
612 613 614 615 616
	{
		.procname	= "soft-power",
		.data		= &pwrsw_enabled,
		.maxlen		= sizeof (int),
	 	.mode		= 0644,
617
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
618
	},
619 620
#endif
#ifdef CONFIG_SYSCTL_ARCH_UNALIGN_ALLOW
Linus Torvalds's avatar
Linus Torvalds committed
621 622 623 624 625
	{
		.procname	= "unaligned-trap",
		.data		= &unaligned_enabled,
		.maxlen		= sizeof (int),
		.mode		= 0644,
626
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
627 628 629 630 631 632 633
	},
#endif
	{
		.procname	= "ctrl-alt-del",
		.data		= &C_A_D,
		.maxlen		= sizeof(int),
		.mode		= 0644,
634
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
635
	},
636
#ifdef CONFIG_FUNCTION_TRACER
637 638 639 640 641
	{
		.procname	= "ftrace_enabled",
		.data		= &ftrace_enabled,
		.maxlen		= sizeof(int),
		.mode		= 0644,
642
		.proc_handler	= ftrace_enable_sysctl,
643 644
	},
#endif
645 646 647 648 649 650
#ifdef CONFIG_STACK_TRACER
	{
		.procname	= "stack_tracer_enabled",
		.data		= &stack_tracer_enabled,
		.maxlen		= sizeof(int),
		.mode		= 0644,
651
		.proc_handler	= stack_trace_sysctl,
652 653
	},
#endif
654 655
#ifdef CONFIG_TRACING
	{
Peter Zijlstra's avatar
Peter Zijlstra committed
656
		.procname	= "ftrace_dump_on_oops",
657 658 659
		.data		= &ftrace_dump_on_oops,
		.maxlen		= sizeof(int),
		.mode		= 0644,
660
		.proc_handler	= proc_dointvec,
661
	},
662 663 664 665 666 667 668
	{
		.procname	= "traceoff_on_warning",
		.data		= &__disable_trace_on_warning,
		.maxlen		= sizeof(__disable_trace_on_warning),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
	},
669 670 671 672 673
	{
		.procname	= "tracepoint_printk",
		.data		= &tracepoint_printk,
		.maxlen		= sizeof(tracepoint_printk),
		.mode		= 0644,
674
		.proc_handler	= tracepoint_printk_sysctl,
675
	},
676
#endif
677
#ifdef CONFIG_KEXEC_CORE
678 679 680 681 682 683 684
	{
		.procname	= "kexec_load_disabled",
		.data		= &kexec_load_disabled,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		/* only handle a transition from default "0" to "1" */
		.proc_handler	= proc_dointvec_minmax,
685 686
		.extra1		= SYSCTL_ONE,
		.extra2		= SYSCTL_ONE,
687 688
	},
#endif
689
#ifdef CONFIG_MODULES
Linus Torvalds's avatar
Linus Torvalds committed
690 691 692 693 694
	{
		.procname	= "modprobe",
		.data		= &modprobe_path,
		.maxlen		= KMOD_PATH_LEN,
		.mode		= 0644,
695
		.proc_handler	= proc_dostring,
Linus Torvalds's avatar
Linus Torvalds committed
696
	},
697 698 699 700 701 702
	{
		.procname	= "modules_disabled",
		.data		= &modules_disabled,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		/* only handle a transition from default "0" to "1" */
703
		.proc_handler	= proc_dointvec_minmax,
704 705
		.extra1		= SYSCTL_ONE,
		.extra2		= SYSCTL_ONE,
706
	},
Linus Torvalds's avatar
Linus Torvalds committed
707
#endif
708
#ifdef CONFIG_UEVENT_HELPER
Linus Torvalds's avatar
Linus Torvalds committed
709 710
	{
		.procname	= "hotplug",
711 712
		.data		= &uevent_helper,
		.maxlen		= UEVENT_HELPER_PATH_LEN,
Linus Torvalds's avatar
Linus Torvalds committed
713
		.mode		= 0644,
714
		.proc_handler	= proc_dostring,
Linus Torvalds's avatar
Linus Torvalds committed
715
	},
716
#endif
Linus Torvalds's avatar
Linus Torvalds committed
717 718 719 720 721 722
#ifdef CONFIG_CHR_DEV_SG
	{
		.procname	= "sg-big-buff",
		.data		= &sg_big_buff,
		.maxlen		= sizeof (int),
		.mode		= 0444,
723
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
724 725 726 727 728 729 730 731
	},
#endif
#ifdef CONFIG_BSD_PROCESS_ACCT
	{
		.procname	= "acct",
		.data		= &acct_parm,
		.maxlen		= 3*sizeof(int),
		.mode		= 0644,
732
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
733 734 735 736 737
	},
#endif
#ifdef CONFIG_MAGIC_SYSRQ
	{
		.procname	= "sysrq",
738
		.data		= NULL,
Linus Torvalds's avatar
Linus Torvalds committed
739 740
		.maxlen		= sizeof (int),
		.mode		= 0644,
741
		.proc_handler	= sysrq_sysctl_handler,
Linus Torvalds's avatar
Linus Torvalds committed
742 743
	},
#endif
744
#ifdef CONFIG_PROC_SYSCTL
Linus Torvalds's avatar
Linus Torvalds committed
745 746
	{
		.procname	= "cad_pid",
747
		.data		= NULL,
Linus Torvalds's avatar
Linus Torvalds committed
748 749
		.maxlen		= sizeof (int),
		.mode		= 0600,
750
		.proc_handler	= proc_do_cad_pid,
Linus Torvalds's avatar
Linus Torvalds committed
751
	},
752
#endif
Linus Torvalds's avatar
Linus Torvalds committed
753 754
	{
		.procname	= "threads-max",
755
		.data		= NULL,
Linus Torvalds's avatar
Linus Torvalds committed
756 757
		.maxlen		= sizeof(int),
		.mode		= 0644,
758
		.proc_handler	= sysctl_max_threads,
Linus Torvalds's avatar
Linus Torvalds committed
759 760 761 762 763 764
	},
	{
		.procname	= "random",
		.mode		= 0555,
		.child		= random_table,
	},
765 766 767 768 769
	{
		.procname	= "usermodehelper",
		.mode		= 0555,
		.child		= usermodehelper_table,
	},
770 771 772 773 774 775 776
#ifdef CONFIG_FW_LOADER_USER_HELPER
	{
		.procname	= "firmware_config",
		.mode		= 0555,
		.child		= firmware_config_table,
	},
#endif
Linus Torvalds's avatar
Linus Torvalds committed
777 778 779 780 781
	{
		.procname	= "overflowuid",
		.data		= &overflowuid,
		.maxlen		= sizeof(int),
		.mode		= 0644,
782
		.proc_handler	= proc_dointvec_minmax,
Linus Torvalds's avatar
Linus Torvalds committed
783 784 785 786 787 788 789 790
		.extra1		= &minolduid,
		.extra2		= &maxolduid,
	},
	{
		.procname	= "overflowgid",
		.data		= &overflowgid,
		.maxlen		= sizeof(int),
		.mode		= 0644,
791
		.proc_handler	= proc_dointvec_minmax,
Linus Torvalds's avatar
Linus Torvalds committed
792 793 794
		.extra1		= &minolduid,
		.extra2		= &maxolduid,
	},
795
#ifdef CONFIG_S390
Linus Torvalds's avatar
Linus Torvalds committed
796 797
	{
		.procname	= "userprocess_debug",
798
		.data		= &show_unhandled_signals,
Linus Torvalds's avatar
Linus Torvalds committed
799 800
		.maxlen		= sizeof(int),
		.mode		= 0644,
801
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
802 803 804 805 806 807 808
	},
#endif
	{
		.procname	= "pid_max",
		.data		= &pid_max,
		.maxlen		= sizeof (int),
		.mode		= 0644,
809
		.proc_handler	= proc_dointvec_minmax,
Linus Torvalds's avatar
Linus Torvalds committed
810 811 812 813 814 815 816 817
		.extra1		= &pid_max_min,
		.extra2		= &pid_max_max,
	},
	{
		.procname	= "panic_on_oops",
		.data		= &panic_on_oops,
		.maxlen		= sizeof(int),
		.mode		= 0644,
818
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
819
	},
820 821 822 823 824 825 826
	{
		.procname	= "panic_print",
		.data		= &panic_print,
		.maxlen		= sizeof(unsigned long),
		.mode		= 0644,
		.proc_handler	= proc_doulongvec_minmax,
	},
827 828 829 830 831 832
#if defined CONFIG_PRINTK
	{
		.procname	= "printk",
		.data		= &console_loglevel,
		.maxlen		= 4*sizeof(int),
		.mode		= 0644,
833
		.proc_handler	= proc_dointvec,
834
	},
Linus Torvalds's avatar
Linus Torvalds committed
835 836
	{
		.procname	= "printk_ratelimit",
Dave Young's avatar
Dave Young committed
837
		.data		= &printk_ratelimit_state.interval,
Linus Torvalds's avatar
Linus Torvalds committed
838 839
		.maxlen		= sizeof(int),
		.mode		= 0644,
840
		.proc_handler	= proc_dointvec_jiffies,
Linus Torvalds's avatar
Linus Torvalds committed
841 842 843
	},
	{
		.procname	= "printk_ratelimit_burst",
Dave Young's avatar
Dave Young committed
844
		.data		= &printk_ratelimit_state.burst,
Linus Torvalds's avatar
Linus Torvalds committed
845 846
		.maxlen		= sizeof(int),
		.mode		= 0644,
847
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
848
	},
849 850 851 852 853
	{
		.procname	= "printk_delay",
		.data		= &printk_delay_msec,
		.maxlen		= sizeof(int),
		.mode		= 0644,
854
		.proc_handler	= proc_dointvec_minmax,
855
		.extra1		= SYSCTL_ZERO,
856 857
		.extra2		= &ten_thousand,
	},
858 859 860 861 862 863 864
	{
		.procname	= "printk_devkmsg",
		.data		= devkmsg_log_str,
		.maxlen		= DEVKMSG_STR_MAX_SIZE,
		.mode		= 0644,
		.proc_handler	= devkmsg_sysctl_set_loglvl,
	},
865 866 867 868 869
	{
		.procname	= "dmesg_restrict",
		.data		= &dmesg_restrict,
		.maxlen		= sizeof(int),
		.mode		= 0644,
870
		.proc_handler	= proc_dointvec_minmax_sysadmin,
871 872
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
873
	},
874 875 876 877 878
	{
		.procname	= "kptr_restrict",
		.data		= &kptr_restrict,
		.maxlen		= sizeof(int),
		.mode		= 0644,
879
		.proc_handler	= proc_dointvec_minmax_sysadmin,
880
		.extra1		= SYSCTL_ZERO,
881 882
		.extra2		= &two,
	},
883
#endif
Linus Torvalds's avatar
Linus Torvalds committed
884 885 886 887 888
	{
		.procname	= "ngroups_max",
		.data		= &ngroups_max,
		.maxlen		= sizeof (int),
		.mode		= 0444,
889
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
890
	},
891 892 893 894 895 896 897
	{
		.procname	= "cap_last_cap",
		.data		= (void *)&cap_last_cap,
		.maxlen		= sizeof(int),
		.mode		= 0444,
		.proc_handler	= proc_dointvec,
	},
898
#if defined(CONFIG_LOCKUP_DETECTOR)
899
	{
900
		.procname       = "watchdog",
901 902 903
		.data		= &watchdog_user_enabled,
		.maxlen		= sizeof(int),
		.mode		= 0644,
904
		.proc_handler   = proc_watchdog,
905 906
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
907 908 909
	},
	{
		.procname	= "watchdog_thresh",
910
		.data		= &watchdog_thresh,
911 912
		.maxlen		= sizeof(int),
		.mode		= 0644,
913
		.proc_handler	= proc_watchdog_thresh,
914
		.extra1		= SYSCTL_ZERO,
915
		.extra2		= &sixty,
916
	},
917 918
	{
		.procname       = "nmi_watchdog",
919 920
		.data		= &nmi_watchdog_user_enabled,
		.maxlen		= sizeof(int),
921
		.mode		= NMI_WATCHDOG_SYSCTL_PERM,
922
		.proc_handler   = proc_nmi_watchdog,
923 924
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
925
	},
926 927 928 929 930 931 932 933
	{
		.procname	= "watchdog_cpumask",
		.data		= &watchdog_cpumask_bits,
		.maxlen		= NR_CPUS,
		.mode		= 0644,
		.proc_handler	= proc_watchdog_cpumask,
	},
#ifdef CONFIG_SOFTLOCKUP_DETECTOR
934 935
	{
		.procname       = "soft_watchdog",
936 937 938
		.data		= &soft_watchdog_user_enabled,
		.maxlen		= sizeof(int),
		.mode		= 0644,
939
		.proc_handler   = proc_soft_watchdog,
940 941
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
942
	},
943 944 945 946 947 948
	{
		.procname	= "softlockup_panic",
		.data		= &softlockup_panic,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
949 950
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
951
	},
952
#ifdef CONFIG_SMP
953
	{
954 955
		.procname	= "softlockup_all_cpu_backtrace",
		.data		= &sysctl_softlockup_all_cpu_backtrace,
956 957 958
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
959 960
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
961
	},
962
#endif /* CONFIG_SMP */
963
#endif
964
#ifdef CONFIG_HARDLOCKUP_DETECTOR
965
	{
966 967
		.procname	= "hardlockup_panic",
		.data		= &hardlockup_panic,
968 969 970
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
971 972
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
973
	},
974
#ifdef CONFIG_SMP
975 976 977 978 979 980
	{
		.procname	= "hardlockup_all_cpu_backtrace",
		.data		= &sysctl_hardlockup_all_cpu_backtrace,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
981 982
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
983
	},
984
#endif /* CONFIG_SMP */
985
#endif
986 987
#endif

988 989 990 991 992 993 994 995
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
	{
		.procname       = "unknown_nmi_panic",
		.data           = &unknown_nmi_panic,
		.maxlen         = sizeof (int),
		.mode           = 0644,
		.proc_handler   = proc_dointvec,
	},
996
#endif
997 998 999

#if (defined(CONFIG_X86_32) || defined(CONFIG_PARISC)) && \
	defined(CONFIG_DEBUG_STACKOVERFLOW)
1000
	{
1001 1002
		.procname	= "panic_on_stackoverflow",
		.data		= &sysctl_panic_on_stackoverflow,
1003 1004
		.maxlen		= sizeof(int),
		.mode		= 0644,
1005
		.proc_handler	= proc_dointvec,
1006
	},
1007 1008
#endif
#if defined(CONFIG_X86)
1009
	{
1010 1011
		.procname	= "panic_on_unrecovered_nmi",
		.data		= &panic_on_unrecovered_nmi,
1012 1013
		.maxlen		= sizeof(int),
		.mode		= 0644,
1014
		.proc_handler	= proc_dointvec,
1015
	},
1016
	{
1017 1018
		.procname	= "panic_on_io_nmi",
		.data		= &panic_on_io_nmi,
1019 1020 1021 1022
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
	},
Linus Torvalds's avatar
Linus Torvalds committed
1023 1024 1025 1026 1027
	{
		.procname	= "bootloader_type",
		.data		= &bootloader_type,
		.maxlen		= sizeof (int),
		.mode		= 0444,
1028
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
1029
	},
1030 1031 1032 1033 1034
	{
		.procname	= "bootloader_version",
		.data		= &bootloader_version,
		.maxlen		= sizeof (int),
		.mode		= 0444,
1035
		.proc_handler	= proc_dointvec,
1036
	},
1037 1038 1039 1040 1041
	{
		.procname	= "io_delay_type",
		.data		= &io_delay_type,
		.maxlen		= sizeof(int),
		.mode		= 0644,
1042
		.proc_handler	= proc_dointvec,
1043
	},
Linus Torvalds's avatar
Linus Torvalds committed
1044
#endif
1045
#if defined(CONFIG_MMU)
Linus Torvalds's avatar
Linus Torvalds committed
1046 1047 1048 1049 1050
	{
		.procname	= "randomize_va_space",
		.data		= &randomize_va_space,
		.maxlen		= sizeof(int),
		.mode		= 0644,
1051
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
1052
	},
1053
#endif
1054
#if defined(CONFIG_S390) && defined(CONFIG_SMP)
1055 1056 1057 1058 1059
	{
		.procname	= "spin_retry",
		.data		= &spin_retry,
		.maxlen		= sizeof (int),
		.mode		= 0644,
1060
		.proc_handler	= proc_dointvec,
1061
	},
1062
#endif
Len Brown's avatar
Len Brown committed
1063
#if	defined(CONFIG_ACPI_SLEEP) && defined(CONFIG_X86)
1064 1065
	{
		.procname	= "acpi_video_flags",
1066
		.data		= &acpi_realmode_flags,
1067 1068
		.maxlen		= sizeof (unsigned long),
		.mode		= 0644,
1069
		.proc_handler	= proc_doulongvec_minmax,
1070
	},
1071
#endif
1072
#ifdef CONFIG_SYSCTL_ARCH_UNALIGN_NO_WARN
1073 1074 1075 1076 1077
	{
		.procname	= "ignore-unaligned-usertrap",
		.data		= &no_unaligned_warning,
		.maxlen		= sizeof (int),
	 	.mode		= 0644,
1078
		.proc_handler	= proc_dointvec,
1079
	},
1080 1081
#endif
#ifdef CONFIG_IA64
1082 1083 1084 1085 1086
	{
		.procname	= "unaligned-dump-stack",
		.data		= &unaligned_dump_stack,
		.maxlen		= sizeof (int),
		.mode		= 0644,
1087
		.proc_handler	= proc_dointvec,
1088
	},
1089
#endif
1090 1091 1092 1093 1094 1095
#ifdef CONFIG_DETECT_HUNG_TASK
	{
		.procname	= "hung_task_panic",
		.data		= &sysctl_hung_task_panic,
		.maxlen		= sizeof(int),
		.mode		= 0644,
1096
		.proc_handler	= proc_dointvec_minmax,
1097 1098
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
1099
	},
1100 1101 1102
	{
		.procname	= "hung_task_check_count",
		.data		= &sysctl_hung_task_check_count,
1103
		.maxlen		= sizeof(int),
1104
		.mode		= 0644,
1105
		.proc_handler	= proc_dointvec_minmax,
1106
		.extra1		= SYSCTL_ZERO,
1107 1108 1109 1110
	},
	{
		.procname	= "hung_task_timeout_secs",
		.data		= &sysctl_hung_task_timeout_secs,
Ingo Molnar's avatar
Ingo Molnar committed
1111
		.maxlen		= sizeof(unsigned long),
1112
		.mode		= 0644,
1113
		.proc_handler	= proc_dohung_task_timeout_secs,
1114
		.extra2		= &hung_task_timeout_max,
1115
	},
1116 1117 1118 1119 1120 1121 1122 1123
	{
		.procname	= "hung_task_check_interval_secs",
		.data		= &sysctl_hung_task_check_interval_secs,
		.maxlen		= sizeof(unsigned long),
		.mode		= 0644,
		.proc_handler	= proc_dohung_task_timeout_secs,
		.extra2		= &hung_task_timeout_max,
	},
1124 1125 1126
	{
		.procname	= "hung_task_warnings",
		.data		= &sysctl_hung_task_warnings,
1127
		.maxlen		= sizeof(int),
1128
		.mode		= 0644,
1129 1130
		.proc_handler	= proc_dointvec_minmax,
		.extra1		= &neg_one,
1131
	},
1132
#endif
1133 1134 1135 1136 1137 1138
#ifdef CONFIG_RT_MUTEXES
	{
		.procname	= "max_lock_depth",
		.data		= &max_lock_depth,
		.maxlen		= sizeof(int),
		.mode		= 0644,
1139
		.proc_handler	= proc_dointvec,
1140
	},
Kees Cook's avatar
Kees Cook committed
1141
#endif
1142 1143 1144 1145 1146
	{
		.procname	= "poweroff_cmd",
		.data		= &poweroff_cmd,
		.maxlen		= POWEROFF_CMD_PATH_LEN,
		.mode		= 0644,
1147
		.proc_handler	= proc_dostring,
1148
	},
1149 1150 1151 1152 1153 1154 1155
#ifdef CONFIG_KEYS
	{
		.procname	= "keys",
		.mode		= 0555,
		.child		= key_sysctls,
	},
#endif
1156
#ifdef CONFIG_PERF_EVENTS
1157 1158 1159 1160 1161 1162
	/*
	 * User-space scripts rely on the existence of this file
	 * as a feature check for perf_events being enabled.
	 *
	 * So it's an ABI, do not remove!
	 */
1163
	{
1164 1165 1166
		.procname	= "perf_event_paranoid",
		.data		= &sysctl_perf_event_paranoid,
		.maxlen		= sizeof(sysctl_perf_event_paranoid),
1167
		.mode		= 0644,
1168
		.proc_handler	= proc_dointvec,
1169
	},
1170
	{
1171 1172 1173
		.procname	= "perf_event_mlock_kb",
		.data		= &sysctl_perf_event_mlock,
		.maxlen		= sizeof(sysctl_perf_event_mlock),
1174
		.mode		= 0644,
1175
		.proc_handler	= proc_dointvec,
1176
	},
1177
	{
1178 1179 1180
		.procname	= "perf_event_max_sample_rate",
		.data		= &sysctl_perf_event_sample_rate,
		.maxlen		= sizeof(sysctl_perf_event_sample_rate),
1181
		.mode		= 0644,
1182
		.proc_handler	= perf_proc_update_handler,
1183
		.extra1		= SYSCTL_ONE,
1184
	},
1185 1186 1187 1188 1189 1190
	{
		.procname	= "perf_cpu_time_max_percent",
		.data		= &sysctl_perf_cpu_time_max_percent,
		.maxlen		= sizeof(sysctl_perf_cpu_time_max_percent),
		.mode		= 0644,
		.proc_handler	= perf_cpu_time_max_percent_handler,
1191
		.extra1		= SYSCTL_ZERO,
1192 1193
		.extra2		= &one_hundred,
	},
1194 1195
	{
		.procname	= "perf_event_max_stack",
1196
		.data		= &sysctl_perf_event_max_stack,
1197 1198 1199
		.maxlen		= sizeof(sysctl_perf_event_max_stack),
		.mode		= 0644,
		.proc_handler	= perf_event_max_stack_handler,
1200
		.extra1		= SYSCTL_ZERO,
1201 1202
		.extra2		= &six_hundred_forty_kb,
	},
1203 1204 1205 1206 1207 1208
	{
		.procname	= "perf_event_max_contexts_per_stack",
		.data		= &sysctl_perf_event_max_contexts_per_stack,
		.maxlen		= sizeof(sysctl_perf_event_max_contexts_per_stack),
		.mode		= 0644,
		.proc_handler	= perf_event_max_stack_handler,
1209
		.extra1		= SYSCTL_ZERO,
1210 1211
		.extra2		= &one_thousand,
	},
1212
#endif
Prarit Bhargava's avatar
Prarit Bhargava committed
1213 1214 1215 1216 1217 1218
	{
		.procname	= "panic_on_warn",
		.data		= &panic_on_warn,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
1219 1220
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
Prarit Bhargava's avatar
Prarit Bhargava committed
1221
	},
1222 1223 1224 1225 1226 1227 1228
#if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
	{
		.procname	= "timer_migration",
		.data		= &sysctl_timer_migration,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= timer_migration_handler,
1229 1230
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
1231
	},
1232 1233 1234 1235 1236 1237 1238 1239 1240
#endif
#ifdef CONFIG_BPF_SYSCALL
	{
		.procname	= "unprivileged_bpf_disabled",
		.data		= &sysctl_unprivileged_bpf_disabled,
		.maxlen		= sizeof(sysctl_unprivileged_bpf_disabled),
		.mode		= 0644,
		/* only handle a transition from default "0" to "1" */
		.proc_handler	= proc_dointvec_minmax,
1241 1242
		.extra1		= SYSCTL_ONE,
		.extra2		= SYSCTL_ONE,
1243
	},
1244 1245
	{
		.procname	= "bpf_stats_enabled",
1246 1247
		.data		= &bpf_stats_enabled_key.key,
		.maxlen		= sizeof(bpf_stats_enabled_key),
1248
		.mode		= 0644,
1249
		.proc_handler	= proc_do_static_key,
1250
	},
1251
#endif
1252
#if defined(CONFIG_TREE_RCU)
1253 1254 1255 1256 1257 1258
	{
		.procname	= "panic_on_rcu_stall",
		.data		= &sysctl_panic_on_rcu_stall,
		.maxlen		= sizeof(sysctl_panic_on_rcu_stall),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
1259 1260
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
1261
	},
1262 1263 1264 1265 1266 1267 1268 1269
#endif
#ifdef CONFIG_STACKLEAK_RUNTIME_DISABLE
	{
		.procname	= "stack_erasing",
		.data		= NULL,
		.maxlen		= sizeof(int),
		.mode		= 0600,
		.proc_handler	= stack_erasing_sysctl,
1270 1271
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
1272
	},
1273
#endif
1274
	{ }
Linus Torvalds's avatar
Linus Torvalds committed
1275 1276
};

1277
static struct ctl_table vm_table[] = {
Linus Torvalds's avatar
Linus Torvalds committed
1278 1279 1280 1281 1282
	{
		.procname	= "overcommit_memory",
		.data		= &sysctl_overcommit_memory,
		.maxlen		= sizeof(sysctl_overcommit_memory),
		.mode		= 0644,
1283
		.proc_handler	= proc_dointvec_minmax,
1284
		.extra1		= SYSCTL_ZERO,
1285
		.extra2		= &two,
Linus Torvalds's avatar
Linus Torvalds committed
1286
	},
1287 1288 1289 1290 1291
	{
		.procname	= "panic_on_oom",
		.data		= &sysctl_panic_on_oom,
		.maxlen		= sizeof(sysctl_panic_on_oom),
		.mode		= 0644,
1292
		.proc_handler	= proc_dointvec_minmax,
1293
		.extra1		= SYSCTL_ZERO,
1294
		.extra2		= &two,
1295
	},
1296 1297 1298 1299 1300
	{
		.procname	= "oom_kill_allocating_task",
		.data		= &sysctl_oom_kill_allocating_task,
		.maxlen		= sizeof(sysctl_oom_kill_allocating_task),
		.mode		= 0644,
1301
		.proc_handler	= proc_dointvec,
1302
	},
1303 1304 1305 1306 1307
	{
		.procname	= "oom_dump_tasks",
		.data		= &sysctl_oom_dump_tasks,
		.maxlen		= sizeof(sysctl_oom_dump_tasks),
		.mode		= 0644,
1308
		.proc_handler	= proc_dointvec,
1309
	},
Linus Torvalds's avatar
Linus Torvalds committed
1310 1311 1312 1313 1314
	{
		.procname	= "overcommit_ratio",
		.data		= &sysctl_overcommit_ratio,
		.maxlen		= sizeof(sysctl_overcommit_ratio),
		.mode		= 0644,
1315 1316 1317 1318 1319 1320 1321 1322
		.proc_handler	= overcommit_ratio_handler,
	},
	{
		.procname	= "overcommit_kbytes",
		.data		= &sysctl_overcommit_kbytes,
		.maxlen		= sizeof(sysctl_overcommit_kbytes),
		.mode		= 0644,
		.proc_handler	= overcommit_kbytes_handler,
Linus Torvalds's avatar
Linus Torvalds committed
1323 1324 1325 1326 1327 1328
	},
	{
		.procname	= "page-cluster", 
		.data		= &page_cluster,
		.maxlen		= sizeof(int),
		.mode		= 0644,
1329
		.proc_handler	= proc_dointvec_minmax,
1330
		.extra1		= SYSCTL_ZERO,
Linus Torvalds's avatar
Linus Torvalds committed
1331 1332 1333 1334 1335 1336
	},
	{
		.procname	= "dirty_background_ratio",
		.data		= &dirty_background_ratio,
		.maxlen		= sizeof(dirty_background_ratio),
		.mode		= 0644,
1337
		.proc_handler	= dirty_background_ratio_handler,
1338
		.extra1		= SYSCTL_ZERO,
Linus Torvalds's avatar
Linus Torvalds committed
1339 1340
		.extra2		= &one_hundred,
	},
1341 1342 1343 1344 1345
	{
		.procname	= "dirty_background_bytes",
		.data		= &dirty_background_bytes,
		.maxlen		= sizeof(dirty_background_bytes),
		.mode		= 0644,
1346
		.proc_handler	= dirty_background_bytes_handler,
1347
		.extra1		= &one_ul,
1348
	},
Linus Torvalds's avatar
Linus Torvalds committed
1349 1350 1351 1352 1353
	{
		.procname	= "dirty_ratio",
		.data		= &vm_dirty_ratio,
		.maxlen		= sizeof(vm_dirty_ratio),
		.mode		= 0644,
1354
		.proc_handler	= dirty_ratio_handler,
1355
		.extra1		= SYSCTL_ZERO,
Linus Torvalds's avatar
Linus Torvalds committed
1356 1357
		.extra2		= &one_hundred,
	},
1358 1359 1360 1361 1362
	{
		.procname	= "dirty_bytes",
		.data		= &vm_dirty_bytes,
		.maxlen		= sizeof(vm_dirty_bytes),
		.mode		= 0644,
1363
		.proc_handler	= dirty_bytes_handler,
1364
		.extra1		= &dirty_bytes_min,
1365
	},
Linus Torvalds's avatar
Linus Torvalds committed
1366 1367
	{
		.procname	= "dirty_writeback_centisecs",
1368 1369
		.data		= &dirty_writeback_interval,
		.maxlen		= sizeof(dirty_writeback_interval),
Linus Torvalds's avatar
Linus Torvalds committed
1370
		.mode		= 0644,
1371
		.proc_handler	= dirty_writeback_centisecs_handler,
Linus Torvalds's avatar
Linus Torvalds committed
1372 1373 1374
	},
	{
		.procname	= "dirty_expire_centisecs",
1375 1376
		.data		= &dirty_expire_interval,
		.maxlen		= sizeof(dirty_expire_interval),
Linus Torvalds's avatar
Linus Torvalds committed
1377
		.mode		= 0644,
1378
		.proc_handler	= proc_dointvec_minmax,
1379
		.extra1		= SYSCTL_ZERO,
Linus Torvalds's avatar
Linus Torvalds committed
1380
	},
1381 1382 1383
	{
		.procname	= "dirtytime_expire_seconds",
		.data		= &dirtytime_expire_interval,
1384
		.maxlen		= sizeof(dirtytime_expire_interval),
1385 1386
		.mode		= 0644,
		.proc_handler	= dirtytime_interval_handler,
1387
		.extra1		= SYSCTL_ZERO,
1388
	},
Linus Torvalds's avatar
Linus Torvalds committed
1389 1390 1391 1392 1393
	{
		.procname	= "swappiness",
		.data		= &vm_swappiness,
		.maxlen		= sizeof(vm_swappiness),
		.mode		= 0644,
1394
		.proc_handler	= proc_dointvec_minmax,
1395
		.extra1		= SYSCTL_ZERO,
Linus Torvalds's avatar
Linus Torvalds committed
1396 1397 1398
		.extra2		= &one_hundred,
	},
#ifdef CONFIG_HUGETLB_PAGE
1399
	{
Linus Torvalds's avatar
Linus Torvalds committed
1400
		.procname	= "nr_hugepages",
1401
		.data		= NULL,
Linus Torvalds's avatar
Linus Torvalds committed
1402 1403
		.maxlen		= sizeof(unsigned long),
		.mode		= 0644,
1404
		.proc_handler	= hugetlb_sysctl_handler,
1405 1406 1407 1408 1409 1410 1411 1412 1413
	},
#ifdef CONFIG_NUMA
	{
		.procname       = "nr_hugepages_mempolicy",
		.data           = NULL,
		.maxlen         = sizeof(unsigned long),
		.mode           = 0644,
		.proc_handler   = &hugetlb_mempolicy_sysctl_handler,
	},
1414 1415 1416 1417 1418 1419
	{
		.procname		= "numa_stat",
		.data			= &sysctl_vm_numa_stat,
		.maxlen			= sizeof(int),
		.mode			= 0644,
		.proc_handler	= sysctl_vm_numa_stat_handler,
1420 1421
		.extra1			= SYSCTL_ZERO,
		.extra2			= SYSCTL_ONE,
1422
	},
1423
#endif
Linus Torvalds's avatar
Linus Torvalds committed
1424 1425 1426 1427 1428
	 {
		.procname	= "hugetlb_shm_group",
		.data		= &sysctl_hugetlb_shm_group,
		.maxlen		= sizeof(gid_t),
		.mode		= 0644,
1429
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
1430
	 },
1431 1432
	{
		.procname	= "nr_overcommit_hugepages",
1433 1434
		.data		= NULL,
		.maxlen		= sizeof(unsigned long),
1435
		.mode		= 0644,
1436
		.proc_handler	= hugetlb_overcommit_handler,
1437
	},
Linus Torvalds's avatar
Linus Torvalds committed
1438 1439 1440 1441 1442 1443
#endif
	{
		.procname	= "lowmem_reserve_ratio",
		.data		= &sysctl_lowmem_reserve_ratio,
		.maxlen		= sizeof(sysctl_lowmem_reserve_ratio),
		.mode		= 0644,
1444
		.proc_handler	= lowmem_reserve_ratio_sysctl_handler,
Linus Torvalds's avatar
Linus Torvalds committed
1445
	},
Andrew Morton's avatar
Andrew Morton committed
1446 1447 1448 1449
	{
		.procname	= "drop_caches",
		.data		= &sysctl_drop_caches,
		.maxlen		= sizeof(int),
1450
		.mode		= 0200,
Andrew Morton's avatar
Andrew Morton committed
1451
		.proc_handler	= drop_caches_sysctl_handler,
1452
		.extra1		= SYSCTL_ONE,
1453
		.extra2		= &four,
Andrew Morton's avatar
Andrew Morton committed
1454
	},
1455 1456 1457 1458 1459 1460 1461 1462
#ifdef CONFIG_COMPACTION
	{
		.procname	= "compact_memory",
		.data		= &sysctl_compact_memory,
		.maxlen		= sizeof(int),
		.mode		= 0200,
		.proc_handler	= sysctl_compaction_handler,
	},
1463 1464 1465 1466 1467
	{
		.procname	= "extfrag_threshold",
		.data		= &sysctl_extfrag_threshold,
		.maxlen		= sizeof(int),
		.mode		= 0644,
1468
		.proc_handler	= proc_dointvec_minmax,
1469 1470 1471
		.extra1		= &min_extfrag_threshold,
		.extra2		= &max_extfrag_threshold,
	},
1472 1473 1474 1475 1476
	{
		.procname	= "compact_unevictable_allowed",
		.data		= &sysctl_compact_unevictable_allowed,
		.maxlen		= sizeof(int),
		.mode		= 0644,
1477
		.proc_handler	= proc_dointvec_minmax_warn_RT_change,
1478 1479
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
1480
	},
1481

1482
#endif /* CONFIG_COMPACTION */
Linus Torvalds's avatar
Linus Torvalds committed
1483 1484 1485 1486 1487
	{
		.procname	= "min_free_kbytes",
		.data		= &min_free_kbytes,
		.maxlen		= sizeof(min_free_kbytes),
		.mode		= 0644,
1488
		.proc_handler	= min_free_kbytes_sysctl_handler,
1489
		.extra1		= SYSCTL_ZERO,
Linus Torvalds's avatar
Linus Torvalds committed
1490
	},
1491 1492 1493 1494 1495 1496
	{
		.procname	= "watermark_boost_factor",
		.data		= &watermark_boost_factor,
		.maxlen		= sizeof(watermark_boost_factor),
		.mode		= 0644,
		.proc_handler	= watermark_boost_factor_sysctl_handler,
1497
		.extra1		= SYSCTL_ZERO,
1498
	},
1499 1500 1501 1502 1503 1504
	{
		.procname	= "watermark_scale_factor",
		.data		= &watermark_scale_factor,
		.maxlen		= sizeof(watermark_scale_factor),
		.mode		= 0644,
		.proc_handler	= watermark_scale_factor_sysctl_handler,
1505
		.extra1		= SYSCTL_ONE,
1506 1507
		.extra2		= &one_thousand,
	},
1508 1509 1510 1511 1512
	{
		.procname	= "percpu_pagelist_fraction",
		.data		= &percpu_pagelist_fraction,
		.maxlen		= sizeof(percpu_pagelist_fraction),
		.mode		= 0644,
1513
		.proc_handler	= percpu_pagelist_fraction_sysctl_handler,
1514
		.extra1		= SYSCTL_ZERO,
1515
	},
Linus Torvalds's avatar
Linus Torvalds committed
1516 1517 1518 1519 1520 1521
#ifdef CONFIG_MMU
	{
		.procname	= "max_map_count",
		.data		= &sysctl_max_map_count,
		.maxlen		= sizeof(sysctl_max_map_count),
		.mode		= 0644,
1522
		.proc_handler	= proc_dointvec_minmax,
1523
		.extra1		= SYSCTL_ZERO,
Linus Torvalds's avatar
Linus Torvalds committed
1524
	},
1525 1526 1527 1528 1529 1530
#else
	{
		.procname	= "nr_trim_pages",
		.data		= &sysctl_nr_trim_pages,
		.maxlen		= sizeof(sysctl_nr_trim_pages),
		.mode		= 0644,
1531
		.proc_handler	= proc_dointvec_minmax,
1532
		.extra1		= SYSCTL_ZERO,
1533
	},
Linus Torvalds's avatar
Linus Torvalds committed
1534 1535 1536 1537 1538 1539
#endif
	{
		.procname	= "laptop_mode",
		.data		= &laptop_mode,
		.maxlen		= sizeof(laptop_mode),
		.mode		= 0644,
1540
		.proc_handler	= proc_dointvec_jiffies,
Linus Torvalds's avatar
Linus Torvalds committed
1541 1542 1543 1544 1545 1546
	},
	{
		.procname	= "block_dump",
		.data		= &block_dump,
		.maxlen		= sizeof(block_dump),
		.mode		= 0644,
1547
		.proc_handler	= proc_dointvec,
1548
		.extra1		= SYSCTL_ZERO,
Linus Torvalds's avatar
Linus Torvalds committed
1549 1550 1551 1552 1553 1554
	},
	{
		.procname	= "vfs_cache_pressure",
		.data		= &sysctl_vfs_cache_pressure,
		.maxlen		= sizeof(sysctl_vfs_cache_pressure),
		.mode		= 0644,
1555
		.proc_handler	= proc_dointvec,
1556
		.extra1		= SYSCTL_ZERO,
Linus Torvalds's avatar
Linus Torvalds committed
1557
	},
1558 1559
#if defined(HAVE_ARCH_PICK_MMAP_LAYOUT) || \
    defined(CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT)
Linus Torvalds's avatar
Linus Torvalds committed
1560 1561 1562 1563 1564
	{
		.procname	= "legacy_va_layout",
		.data		= &sysctl_legacy_va_layout,
		.maxlen		= sizeof(sysctl_legacy_va_layout),
		.mode		= 0644,
1565
		.proc_handler	= proc_dointvec,
1566
		.extra1		= SYSCTL_ZERO,
Linus Torvalds's avatar
Linus Torvalds committed
1567 1568
	},
#endif
1569 1570 1571
#ifdef CONFIG_NUMA
	{
		.procname	= "zone_reclaim_mode",
1572 1573
		.data		= &node_reclaim_mode,
		.maxlen		= sizeof(node_reclaim_mode),
1574
		.mode		= 0644,
1575
		.proc_handler	= proc_dointvec,
1576
		.extra1		= SYSCTL_ZERO,
1577
	},
1578 1579 1580 1581 1582
	{
		.procname	= "min_unmapped_ratio",
		.data		= &sysctl_min_unmapped_ratio,
		.maxlen		= sizeof(sysctl_min_unmapped_ratio),
		.mode		= 0644,
1583
		.proc_handler	= sysctl_min_unmapped_ratio_sysctl_handler,
1584
		.extra1		= SYSCTL_ZERO,
1585 1586
		.extra2		= &one_hundred,
	},
1587 1588 1589 1590 1591
	{
		.procname	= "min_slab_ratio",
		.data		= &sysctl_min_slab_ratio,
		.maxlen		= sizeof(sysctl_min_slab_ratio),
		.mode		= 0644,
1592
		.proc_handler	= sysctl_min_slab_ratio_sysctl_handler,
1593
		.extra1		= SYSCTL_ZERO,
1594 1595
		.extra2		= &one_hundred,
	},
1596
#endif
1597 1598 1599 1600 1601 1602
#ifdef CONFIG_SMP
	{
		.procname	= "stat_interval",
		.data		= &sysctl_stat_interval,
		.maxlen		= sizeof(sysctl_stat_interval),
		.mode		= 0644,
1603
		.proc_handler	= proc_dointvec_jiffies,
1604
	},
1605 1606 1607 1608 1609 1610 1611
	{
		.procname	= "stat_refresh",
		.data		= NULL,
		.maxlen		= 0,
		.mode		= 0600,
		.proc_handler	= vmstat_refresh,
	},
1612
#endif
1613
#ifdef CONFIG_MMU
1614 1615
	{
		.procname	= "mmap_min_addr",
1616 1617
		.data		= &dac_mmap_min_addr,
		.maxlen		= sizeof(unsigned long),
1618
		.mode		= 0644,
1619
		.proc_handler	= mmap_min_addr_handler,
1620
	},
1621
#endif
1622 1623 1624 1625 1626 1627
#ifdef CONFIG_NUMA
	{
		.procname	= "numa_zonelist_order",
		.data		= &numa_zonelist_order,
		.maxlen		= NUMA_ZONELIST_ORDER_LEN,
		.mode		= 0644,
1628
		.proc_handler	= numa_zonelist_order_handler,
1629 1630
	},
#endif
1631
#if (defined(CONFIG_X86_32) && !defined(CONFIG_UML))|| \
1632
   (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL))
1633 1634
	{
		.procname	= "vdso_enabled",
1635 1636 1637 1638
#ifdef CONFIG_X86_32
		.data		= &vdso32_enabled,
		.maxlen		= sizeof(vdso32_enabled),
#else
1639 1640
		.data		= &vdso_enabled,
		.maxlen		= sizeof(vdso_enabled),
1641
#endif
1642
		.mode		= 0644,
1643
		.proc_handler	= proc_dointvec,
1644
		.extra1		= SYSCTL_ZERO,
1645
	},
Linus Torvalds's avatar
Linus Torvalds committed
1646
#endif
1647 1648 1649 1650 1651 1652
#ifdef CONFIG_HIGHMEM
	{
		.procname	= "highmem_is_dirtyable",
		.data		= &vm_highmem_is_dirtyable,
		.maxlen		= sizeof(vm_highmem_is_dirtyable),
		.mode		= 0644,
1653
		.proc_handler	= proc_dointvec_minmax,
1654 1655
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
1656 1657
	},
#endif
1658 1659 1660 1661 1662 1663
#ifdef CONFIG_MEMORY_FAILURE
	{
		.procname	= "memory_failure_early_kill",
		.data		= &sysctl_memory_failure_early_kill,
		.maxlen		= sizeof(sysctl_memory_failure_early_kill),
		.mode		= 0644,
1664
		.proc_handler	= proc_dointvec_minmax,
1665 1666
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
1667 1668 1669 1670 1671 1672
	},
	{
		.procname	= "memory_failure_recovery",
		.data		= &sysctl_memory_failure_recovery,
		.maxlen		= sizeof(sysctl_memory_failure_recovery),
		.mode		= 0644,
1673
		.proc_handler	= proc_dointvec_minmax,
1674 1675
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
1676 1677
	},
#endif
1678 1679 1680 1681 1682 1683 1684
	{
		.procname	= "user_reserve_kbytes",
		.data		= &sysctl_user_reserve_kbytes,
		.maxlen		= sizeof(sysctl_user_reserve_kbytes),
		.mode		= 0644,
		.proc_handler	= proc_doulongvec_minmax,
	},
1685 1686 1687 1688 1689 1690 1691
	{
		.procname	= "admin_reserve_kbytes",
		.data		= &sysctl_admin_reserve_kbytes,
		.maxlen		= sizeof(sysctl_admin_reserve_kbytes),
		.mode		= 0644,
		.proc_handler	= proc_doulongvec_minmax,
	},
1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712
#ifdef CONFIG_HAVE_ARCH_MMAP_RND_BITS
	{
		.procname	= "mmap_rnd_bits",
		.data		= &mmap_rnd_bits,
		.maxlen		= sizeof(mmap_rnd_bits),
		.mode		= 0600,
		.proc_handler	= proc_dointvec_minmax,
		.extra1		= (void *)&mmap_rnd_bits_min,
		.extra2		= (void *)&mmap_rnd_bits_max,
	},
#endif
#ifdef CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS
	{
		.procname	= "mmap_rnd_compat_bits",
		.data		= &mmap_rnd_compat_bits,
		.maxlen		= sizeof(mmap_rnd_compat_bits),
		.mode		= 0600,
		.proc_handler	= proc_dointvec_minmax,
		.extra1		= (void *)&mmap_rnd_compat_bits_min,
		.extra2		= (void *)&mmap_rnd_compat_bits_max,
	},
1713 1714 1715 1716 1717 1718 1719 1720
#endif
#ifdef CONFIG_USERFAULTFD
	{
		.procname	= "unprivileged_userfaultfd",
		.data		= &sysctl_unprivileged_userfaultfd,
		.maxlen		= sizeof(sysctl_unprivileged_userfaultfd),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
1721 1722
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
1723
	},
1724
#endif
1725
	{ }
Linus Torvalds's avatar
Linus Torvalds committed
1726 1727
};

1728
static struct ctl_table fs_table[] = {
Linus Torvalds's avatar
Linus Torvalds committed
1729 1730 1731
	{
		.procname	= "inode-nr",
		.data		= &inodes_stat,
1732
		.maxlen		= 2*sizeof(long),
Linus Torvalds's avatar
Linus Torvalds committed
1733
		.mode		= 0444,
1734
		.proc_handler	= proc_nr_inodes,
Linus Torvalds's avatar
Linus Torvalds committed
1735 1736 1737 1738
	},
	{
		.procname	= "inode-state",
		.data		= &inodes_stat,
1739
		.maxlen		= 7*sizeof(long),
Linus Torvalds's avatar
Linus Torvalds committed
1740
		.mode		= 0444,
1741
		.proc_handler	= proc_nr_inodes,
Linus Torvalds's avatar
Linus Torvalds committed
1742 1743 1744 1745
	},
	{
		.procname	= "file-nr",
		.data		= &files_stat,
1746
		.maxlen		= sizeof(files_stat),
Linus Torvalds's avatar
Linus Torvalds committed
1747
		.mode		= 0444,
1748
		.proc_handler	= proc_nr_files,
Linus Torvalds's avatar
Linus Torvalds committed
1749 1750 1751 1752
	},
	{
		.procname	= "file-max",
		.data		= &files_stat.max_files,
1753
		.maxlen		= sizeof(files_stat.max_files),
Linus Torvalds's avatar
Linus Torvalds committed
1754
		.mode		= 0644,
1755
		.proc_handler	= proc_doulongvec_minmax,
1756
		.extra1		= &zero_ul,
1757
		.extra2		= &long_max,
Linus Torvalds's avatar
Linus Torvalds committed
1758
	},
1759 1760 1761
	{
		.procname	= "nr_open",
		.data		= &sysctl_nr_open,
1762
		.maxlen		= sizeof(unsigned int),
1763
		.mode		= 0644,
1764
		.proc_handler	= proc_dointvec_minmax,
1765 1766
		.extra1		= &sysctl_nr_open_min,
		.extra2		= &sysctl_nr_open_max,
1767
	},
Linus Torvalds's avatar
Linus Torvalds committed
1768 1769 1770
	{
		.procname	= "dentry-state",
		.data		= &dentry_stat,
1771
		.maxlen		= 6*sizeof(long),
Linus Torvalds's avatar
Linus Torvalds committed
1772
		.mode		= 0444,
1773
		.proc_handler	= proc_nr_dentry,
Linus Torvalds's avatar
Linus Torvalds committed
1774 1775 1776 1777 1778 1779
	},
	{
		.procname	= "overflowuid",
		.data		= &fs_overflowuid,
		.maxlen		= sizeof(int),
		.mode		= 0644,
1780
		.proc_handler	= proc_dointvec_minmax,
Linus Torvalds's avatar
Linus Torvalds committed
1781 1782 1783 1784 1785 1786 1787 1788
		.extra1		= &minolduid,
		.extra2		= &maxolduid,
	},
	{
		.procname	= "overflowgid",
		.data		= &fs_overflowgid,
		.maxlen		= sizeof(int),
		.mode		= 0644,
1789
		.proc_handler	= proc_dointvec_minmax,
Linus Torvalds's avatar
Linus Torvalds committed
1790 1791 1792
		.extra1		= &minolduid,
		.extra2		= &maxolduid,
	},
1793
#ifdef CONFIG_FILE_LOCKING
Linus Torvalds's avatar
Linus Torvalds committed
1794 1795 1796 1797 1798
	{
		.procname	= "leases-enable",
		.data		= &leases_enable,
		.maxlen		= sizeof(int),
		.mode		= 0644,
1799
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
1800
	},
1801
#endif
Linus Torvalds's avatar
Linus Torvalds committed
1802 1803 1804 1805 1806 1807
#ifdef CONFIG_DNOTIFY
	{
		.procname	= "dir-notify-enable",
		.data		= &dir_notify_enable,
		.maxlen		= sizeof(int),
		.mode		= 0644,
1808
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
1809 1810 1811
	},
#endif
#ifdef CONFIG_MMU
1812
#ifdef CONFIG_FILE_LOCKING
Linus Torvalds's avatar
Linus Torvalds committed
1813 1814 1815 1816 1817
	{
		.procname	= "lease-break-time",
		.data		= &lease_break_time,
		.maxlen		= sizeof(int),
		.mode		= 0644,
1818
		.proc_handler	= proc_dointvec,
Linus Torvalds's avatar
Linus Torvalds committed
1819
	},
1820
#endif
Thomas Petazzoni's avatar
Thomas Petazzoni committed
1821
#ifdef CONFIG_AIO
Linus Torvalds's avatar
Linus Torvalds committed
1822 1823 1824 1825 1826
	{
		.procname	= "aio-nr",
		.data		= &aio_nr,
		.maxlen		= sizeof(aio_nr),
		.mode		= 0444,
1827
		.proc_handler	= proc_doulongvec_minmax,
Linus Torvalds's avatar
Linus Torvalds committed
1828 1829 1830 1831 1832 1833
	},
	{
		.procname	= "aio-max-nr",
		.data		= &aio_max_nr,
		.maxlen		= sizeof(aio_max_nr),
		.mode		= 0644,
1834
		.proc_handler	= proc_doulongvec_minmax,
Linus Torvalds's avatar
Linus Torvalds committed
1835
	},
Thomas Petazzoni's avatar
Thomas Petazzoni committed
1836
#endif /* CONFIG_AIO */
1837
#ifdef CONFIG_INOTIFY_USER
Robert Love's avatar
Robert Love committed
1838 1839 1840 1841 1842 1843
	{
		.procname	= "inotify",
		.mode		= 0555,
		.child		= inotify_table,
	},
#endif	
1844 1845 1846 1847 1848 1849 1850
#ifdef CONFIG_EPOLL
	{
		.procname	= "epoll",
		.mode		= 0555,
		.child		= epoll_table,
	},
#endif
Linus Torvalds's avatar
Linus Torvalds committed
1851
#endif
Kees Cook's avatar
Kees Cook committed
1852 1853 1854 1855 1856 1857
	{
		.procname	= "protected_symlinks",
		.data		= &sysctl_protected_symlinks,
		.maxlen		= sizeof(int),
		.mode		= 0600,
		.proc_handler	= proc_dointvec_minmax,
1858 1859
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
Kees Cook's avatar
Kees Cook committed
1860 1861 1862 1863 1864 1865 1866
	},
	{
		.procname	= "protected_hardlinks",
		.data		= &sysctl_protected_hardlinks,
		.maxlen		= sizeof(int),
		.mode		= 0600,
		.proc_handler	= proc_dointvec_minmax,
1867 1868
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
Kees Cook's avatar
Kees Cook committed
1869
	},
1870 1871 1872 1873 1874 1875
	{
		.procname	= "protected_fifos",
		.data		= &sysctl_protected_fifos,
		.maxlen		= sizeof(int),
		.mode		= 0600,
		.proc_handler	= proc_dointvec_minmax,
1876
		.extra1		= SYSCTL_ZERO,
1877 1878 1879 1880 1881 1882 1883 1884
		.extra2		= &two,
	},
	{
		.procname	= "protected_regular",
		.data		= &sysctl_protected_regular,
		.maxlen		= sizeof(int),
		.mode		= 0600,
		.proc_handler	= proc_dointvec_minmax,
1885
		.extra1		= SYSCTL_ZERO,
1886 1887
		.extra2		= &two,
	},
Alan Cox's avatar
Alan Cox committed
1888 1889 1890 1891 1892
	{
		.procname	= "suid_dumpable",
		.data		= &suid_dumpable,
		.maxlen		= sizeof(int),
		.mode		= 0644,
1893
		.proc_handler	= proc_dointvec_minmax_coredump,
1894
		.extra1		= SYSCTL_ZERO,
1895
		.extra2		= &two,
Alan Cox's avatar
Alan Cox committed
1896
	},
1897 1898 1899 1900
#if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
	{
		.procname	= "binfmt_misc",
		.mode		= 0555,
1901
		.child		= sysctl_mount_point,
1902 1903
	},
#endif
1904
	{
1905 1906
		.procname	= "pipe-max-size",
		.data		= &pipe_max_size,
1907
		.maxlen		= sizeof(pipe_max_size),
1908
		.mode		= 0644,
1909
		.proc_handler	= proc_dopipe_max_size,
1910
	},
1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924
	{
		.procname	= "pipe-user-pages-hard",
		.data		= &pipe_user_pages_hard,
		.maxlen		= sizeof(pipe_user_pages_hard),
		.mode		= 0644,
		.proc_handler	= proc_doulongvec_minmax,
	},
	{
		.procname	= "pipe-user-pages-soft",
		.data		= &pipe_user_pages_soft,
		.maxlen		= sizeof(pipe_user_pages_soft),
		.mode		= 0644,
		.proc_handler	= proc_doulongvec_minmax,
	},
1925 1926 1927 1928 1929 1930
	{
		.procname	= "mount-max",
		.data		= &sysctl_mount_max,
		.maxlen		= sizeof(unsigned int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec_minmax,
1931
		.extra1		= SYSCTL_ONE,
1932
	},
1933
	{ }
Linus Torvalds's avatar
Linus Torvalds committed
1934 1935
};

1936
static struct ctl_table debug_table[] = {
1937
#ifdef CONFIG_SYSCTL_EXCEPTION_TRACE
1938 1939 1940 1941 1942 1943 1944
	{
		.procname	= "exception-trace",
		.data		= &show_unhandled_signals,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec
	},
1945 1946 1947 1948 1949 1950 1951 1952
#endif
#if defined(CONFIG_OPTPROBES)
	{
		.procname	= "kprobes-optimization",
		.data		= &sysctl_kprobes_optimization,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_kprobes_optimization_handler,
1953 1954
		.extra1		= SYSCTL_ZERO,
		.extra2		= SYSCTL_ONE,
1955
	},
1956
#endif
1957
	{ }
Linus Torvalds's avatar
Linus Torvalds committed
1958 1959
};

1960
static struct ctl_table dev_table[] = {
1961
	{ }
Robert Love's avatar
Robert Love committed
1962
};
Linus Torvalds's avatar
Linus Torvalds committed
1963

1964
int __init sysctl_init(void)
1965
{
1966 1967 1968 1969
	struct ctl_table_header *hdr;

	hdr = register_sysctl_table(sysctl_base_table);
	kmemleak_not_leak(hdr);
1970 1971 1972
	return 0;
}

1973 1974
#endif /* CONFIG_SYSCTL */

Linus Torvalds's avatar
Linus Torvalds committed
1975 1976 1977 1978
/*
 * /proc/sys support
 */

1979
#ifdef CONFIG_PROC_SYSCTL
Linus Torvalds's avatar
Linus Torvalds committed
1980

1981 1982
static int _proc_do_string(char *data, int maxlen, int write,
			   char __user *buffer,
1983
			   size_t *lenp, loff_t *ppos)
Linus Torvalds's avatar
Linus Torvalds committed
1984 1985 1986 1987
{
	size_t len;
	char __user *p;
	char c;
1988 1989

	if (!data || !maxlen || !*lenp) {
Linus Torvalds's avatar
Linus Torvalds committed
1990 1991 1992
		*lenp = 0;
		return 0;
	}
1993

Linus Torvalds's avatar
Linus Torvalds committed
1994
	if (write) {
1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008
		if (sysctl_writes_strict == SYSCTL_WRITES_STRICT) {
			/* Only continue writes not past the end of buffer. */
			len = strlen(data);
			if (len > maxlen - 1)
				len = maxlen - 1;

			if (*ppos > len)
				return 0;
			len = *ppos;
		} else {
			/* Start writing from beginning of buffer. */
			len = 0;
		}

2009
		*ppos += *lenp;
Linus Torvalds's avatar
Linus Torvalds committed
2010
		p = buffer;
2011
		while ((p - buffer) < *lenp && len < maxlen - 1) {
Linus Torvalds's avatar
Linus Torvalds committed
2012 2013 2014 2015
			if (get_user(c, p++))
				return -EFAULT;
			if (c == 0 || c == '\n')
				break;
2016
			data[len++] = c;
Linus Torvalds's avatar
Linus Torvalds committed
2017
		}
2018
		data[len] = 0;
Linus Torvalds's avatar
Linus Torvalds committed
2019
	} else {
2020 2021 2022
		len = strlen(data);
		if (len > maxlen)
			len = maxlen;
2023 2024 2025 2026 2027 2028 2029 2030 2031

		if (*ppos > len) {
			*lenp = 0;
			return 0;
		}

		data += *ppos;
		len  -= *ppos;

Linus Torvalds's avatar
Linus Torvalds committed
2032 2033 2034
		if (len > *lenp)
			len = *lenp;
		if (len)
2035
			if (copy_to_user(buffer, data, len))
Linus Torvalds's avatar
Linus Torvalds committed
2036 2037
				return -EFAULT;
		if (len < *lenp) {
2038
			if (put_user('\n', buffer + len))
Linus Torvalds's avatar
Linus Torvalds committed
2039 2040 2041 2042 2043 2044 2045 2046 2047
				return -EFAULT;
			len++;
		}
		*lenp = len;
		*ppos += len;
	}
	return 0;
}

2048 2049 2050 2051 2052 2053 2054 2055
static void warn_sysctl_write(struct ctl_table *table)
{
	pr_warn_once("%s wrote to %s when file position was not 0!\n"
		"This will not be supported in the future. To silence this\n"
		"warning, set kernel.sysctl_writes_strict = -1\n",
		current->comm, table->procname);
}

2056
/**
2057
 * proc_first_pos_non_zero_ignore - check if first position is allowed
2058 2059 2060 2061 2062
 * @ppos: file position
 * @table: the sysctl table
 *
 * Returns true if the first position is non-zero and the sysctl_writes_strict
 * mode indicates this is not allowed for numeric input types. String proc
2063
 * handlers can ignore the return value.
2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081
 */
static bool proc_first_pos_non_zero_ignore(loff_t *ppos,
					   struct ctl_table *table)
{
	if (!*ppos)
		return false;

	switch (sysctl_writes_strict) {
	case SYSCTL_WRITES_STRICT:
		return true;
	case SYSCTL_WRITES_WARN:
		warn_sysctl_write(table);
		return false;
	default:
		return false;
	}
}

2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098
/**
 * proc_dostring - read a string sysctl
 * @table: the sysctl table
 * @write: %TRUE if this is a write to the sysctl file
 * @buffer: the user buffer
 * @lenp: the size of the user buffer
 * @ppos: file position
 *
 * Reads/writes a string from/to the user buffer. If the kernel
 * buffer provided is not large enough to hold the string, the
 * string is truncated. The copied string is %NULL-terminated.
 * If the string is being read by the user process, it is copied
 * and a newline '\n' is added. It is truncated if the buffer is
 * not large enough.
 *
 * Returns 0 on success.
 */
2099
int proc_dostring(struct ctl_table *table, int write,
2100 2101
		  void __user *buffer, size_t *lenp, loff_t *ppos)
{
2102 2103
	if (write)
		proc_first_pos_non_zero_ignore(ppos, table);
2104

2105 2106
	return _proc_do_string((char *)(table->data), table->maxlen, write,
			       (char __user *)buffer, lenp, ppos);
2107 2108
}

2109 2110 2111 2112 2113 2114 2115 2116 2117
static size_t proc_skip_spaces(char **buf)
{
	size_t ret;
	char *tmp = skip_spaces(*buf);
	ret = tmp - *buf;
	*buf = tmp;
	return ret;
}

2118 2119 2120 2121 2122 2123 2124 2125 2126 2127
static void proc_skip_char(char **buf, size_t *size, const char v)
{
	while (*size) {
		if (**buf != v)
			break;
		(*size)--;
		(*buf)++;
	}
}

2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162
/**
 * strtoul_lenient - parse an ASCII formatted integer from a buffer and only
 *                   fail on overflow
 *
 * @cp: kernel buffer containing the string to parse
 * @endp: pointer to store the trailing characters
 * @base: the base to use
 * @res: where the parsed integer will be stored
 *
 * In case of success 0 is returned and @res will contain the parsed integer,
 * @endp will hold any trailing characters.
 * This function will fail the parse on overflow. If there wasn't an overflow
 * the function will defer the decision what characters count as invalid to the
 * caller.
 */
static int strtoul_lenient(const char *cp, char **endp, unsigned int base,
			   unsigned long *res)
{
	unsigned long long result;
	unsigned int rv;

	cp = _parse_integer_fixup_radix(cp, &base);
	rv = _parse_integer(cp, base, &result);
	if ((rv & KSTRTOX_OVERFLOW) || (result != (unsigned long)result))
		return -ERANGE;

	cp += rv;

	if (endp)
		*endp = (char *)cp;

	*res = (unsigned long)result;
	return 0;
}

2163 2164
#define TMPBUFLEN 22
/**
2165
 * proc_get_long - reads an ASCII formatted integer from a user buffer
2166
 *
2167 2168 2169 2170 2171 2172 2173
 * @buf: a kernel buffer
 * @size: size of the kernel buffer
 * @val: this is where the number will be stored
 * @neg: set to %TRUE if number is negative
 * @perm_tr: a vector which contains the allowed trailers
 * @perm_tr_len: size of the perm_tr vector
 * @tr: pointer to store the trailer character
2174
 *
2175 2176 2177 2178
 * In case of success %0 is returned and @buf and @size are updated with
 * the amount of bytes read. If @tr is non-NULL and a trailing
 * character exists (size is non-zero after returning from this
 * function), @tr is updated with the trailing character.
2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205
 */
static int proc_get_long(char **buf, size_t *size,
			  unsigned long *val, bool *neg,
			  const char *perm_tr, unsigned perm_tr_len, char *tr)
{
	int len;
	char *p, tmp[TMPBUFLEN];

	if (!*size)
		return -EINVAL;

	len = *size;
	if (len > TMPBUFLEN - 1)
		len = TMPBUFLEN - 1;

	memcpy(tmp, *buf, len);

	tmp[len] = 0;
	p = tmp;
	if (*p == '-' && *size > 1) {
		*neg = true;
		p++;
	} else
		*neg = false;
	if (!isdigit(*p))
		return -EINVAL;

2206 2207
	if (strtoul_lenient(p, &p, 0, val))
		return -EINVAL;
2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218

	len = p - tmp;

	/* We don't know if the next char is whitespace thus we may accept
	 * invalid integers (e.g. 1234...a) or two integers instead of one
	 * (e.g. 123...1). So lets not allow such large numbers. */
	if (len == TMPBUFLEN - 1)
		return -EINVAL;

	if (len < *size && perm_tr_len && !memchr(perm_tr, *p, perm_tr_len))
		return -EINVAL;
Linus Torvalds's avatar
Linus Torvalds committed
2219

2220 2221 2222 2223 2224 2225 2226 2227 2228 2229
	if (tr && (len < *size))
		*tr = *p;

	*buf += len;
	*size -= len;

	return 0;
}

/**
2230
 * proc_put_long - converts an integer to a decimal ASCII formatted string
2231
 *
2232 2233 2234 2235
 * @buf: the user buffer
 * @size: the size of the user buffer
 * @val: the integer to be converted
 * @neg: sign of the number, %TRUE for negative
2236
 *
2237 2238
 * In case of success %0 is returned and @buf and @size are updated with
 * the amount of bytes written.
2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268
 */
static int proc_put_long(void __user **buf, size_t *size, unsigned long val,
			  bool neg)
{
	int len;
	char tmp[TMPBUFLEN], *p = tmp;

	sprintf(p, "%s%lu", neg ? "-" : "", val);
	len = strlen(tmp);
	if (len > *size)
		len = *size;
	if (copy_to_user(*buf, tmp, len))
		return -EFAULT;
	*size -= len;
	*buf += len;
	return 0;
}
#undef TMPBUFLEN

static int proc_put_char(void __user **buf, size_t *size, char c)
{
	if (*size) {
		char __user **buffer = (char __user **)buf;
		if (put_user(c, *buffer))
			return -EFAULT;
		(*size)--, (*buffer)++;
		*buf = *buffer;
	}
	return 0;
}
Linus Torvalds's avatar
Linus Torvalds committed
2269

2270
static int do_proc_dointvec_conv(bool *negp, unsigned long *lvalp,
Linus Torvalds's avatar
Linus Torvalds committed
2271 2272 2273 2274
				 int *valp,
				 int write, void *data)
{
	if (write) {
2275 2276 2277 2278 2279 2280 2281 2282 2283
		if (*negp) {
			if (*lvalp > (unsigned long) INT_MAX + 1)
				return -EINVAL;
			*valp = -*lvalp;
		} else {
			if (*lvalp > (unsigned long) INT_MAX)
				return -EINVAL;
			*valp = *lvalp;
		}
Linus Torvalds's avatar
Linus Torvalds committed
2284 2285 2286
	} else {
		int val = *valp;
		if (val < 0) {
2287
			*negp = true;
2288
			*lvalp = -(unsigned long)val;
Linus Torvalds's avatar
Linus Torvalds committed
2289
		} else {
2290
			*negp = false;
Linus Torvalds's avatar
Linus Torvalds committed
2291 2292 2293 2294 2295 2296
			*lvalp = (unsigned long)val;
		}
	}
	return 0;
}

2297 2298 2299
static int do_proc_douintvec_conv(unsigned long *lvalp,
				  unsigned int *valp,
				  int write, void *data)
2300 2301
{
	if (write) {
2302 2303
		if (*lvalp > UINT_MAX)
			return -EINVAL;
2304 2305 2306 2307 2308 2309 2310 2311
		*valp = *lvalp;
	} else {
		unsigned int val = *valp;
		*lvalp = (unsigned long)val;
	}
	return 0;
}

2312 2313
static const char proc_wspace_sep[] = { ' ', '\t', '\n' };

2314
static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
2315
		  int write, void __user *buffer,
2316
		  size_t *lenp, loff_t *ppos,
2317
		  int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
Linus Torvalds's avatar
Linus Torvalds committed
2318 2319 2320
			      int write, void *data),
		  void *data)
{
2321 2322
	int *i, vleft, first = 1, err = 0;
	size_t left;
2323
	char *kbuf = NULL, *p;
Linus Torvalds's avatar
Linus Torvalds committed
2324
	
2325
	if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
Linus Torvalds's avatar
Linus Torvalds committed
2326 2327 2328 2329
		*lenp = 0;
		return 0;
	}
	
2330
	i = (int *) tbl_data;
Linus Torvalds's avatar
Linus Torvalds committed
2331 2332 2333 2334 2335 2336
	vleft = table->maxlen / sizeof(*i);
	left = *lenp;

	if (!conv)
		conv = do_proc_dointvec_conv;

2337
	if (write) {
2338 2339
		if (proc_first_pos_non_zero_ignore(ppos, table))
			goto out;
2340

2341 2342
		if (left > PAGE_SIZE - 1)
			left = PAGE_SIZE - 1;
2343 2344 2345
		p = kbuf = memdup_user_nul(buffer, left);
		if (IS_ERR(kbuf))
			return PTR_ERR(kbuf);
2346 2347
	}

Linus Torvalds's avatar
Linus Torvalds committed
2348
	for (; left && vleft--; i++, first=0) {
2349 2350
		unsigned long lval;
		bool neg;
Linus Torvalds's avatar
Linus Torvalds committed
2351

2352
		if (write) {
2353
			left -= proc_skip_spaces(&p);
Linus Torvalds's avatar
Linus Torvalds committed
2354

2355 2356
			if (!left)
				break;
2357
			err = proc_get_long(&p, &left, &lval, &neg,
2358 2359 2360
					     proc_wspace_sep,
					     sizeof(proc_wspace_sep), NULL);
			if (err)
Linus Torvalds's avatar
Linus Torvalds committed
2361
				break;
2362 2363
			if (conv(&neg, &lval, i, 1, data)) {
				err = -EINVAL;
Linus Torvalds's avatar
Linus Torvalds committed
2364
				break;
2365
			}
Linus Torvalds's avatar
Linus Torvalds committed
2366
		} else {
2367 2368 2369 2370
			if (conv(&neg, &lval, i, 0, data)) {
				err = -EINVAL;
				break;
			}
Linus Torvalds's avatar
Linus Torvalds committed
2371
			if (!first)
2372 2373 2374 2375 2376
				err = proc_put_char(&buffer, &left, '\t');
			if (err)
				break;
			err = proc_put_long(&buffer, &left, lval, neg);
			if (err)
Linus Torvalds's avatar
Linus Torvalds committed
2377 2378 2379 2380
				break;
		}
	}

2381 2382
	if (!write && !first && left && !err)
		err = proc_put_char(&buffer, &left, '\n');
2383
	if (write && !err && left)
2384
		left -= proc_skip_spaces(&p);
Linus Torvalds's avatar
Linus Torvalds committed
2385
	if (write) {
2386
		kfree(kbuf);
2387 2388
		if (first)
			return err ? : -EINVAL;
Linus Torvalds's avatar
Linus Torvalds committed
2389 2390
	}
	*lenp -= left;
2391
out:
Linus Torvalds's avatar
Linus Torvalds committed
2392
	*ppos += *lenp;
2393
	return err;
Linus Torvalds's avatar
Linus Torvalds committed
2394 2395
}

2396
static int do_proc_dointvec(struct ctl_table *table, int write,
2397
		  void __user *buffer, size_t *lenp, loff_t *ppos,
2398
		  int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
2399 2400 2401
			      int write, void *data),
		  void *data)
{
2402
	return __do_proc_dointvec(table->data, table, write,
2403 2404 2405
			buffer, lenp, ppos, conv, data);
}

2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545
static int do_proc_douintvec_w(unsigned int *tbl_data,
			       struct ctl_table *table,
			       void __user *buffer,
			       size_t *lenp, loff_t *ppos,
			       int (*conv)(unsigned long *lvalp,
					   unsigned int *valp,
					   int write, void *data),
			       void *data)
{
	unsigned long lval;
	int err = 0;
	size_t left;
	bool neg;
	char *kbuf = NULL, *p;

	left = *lenp;

	if (proc_first_pos_non_zero_ignore(ppos, table))
		goto bail_early;

	if (left > PAGE_SIZE - 1)
		left = PAGE_SIZE - 1;

	p = kbuf = memdup_user_nul(buffer, left);
	if (IS_ERR(kbuf))
		return -EINVAL;

	left -= proc_skip_spaces(&p);
	if (!left) {
		err = -EINVAL;
		goto out_free;
	}

	err = proc_get_long(&p, &left, &lval, &neg,
			     proc_wspace_sep,
			     sizeof(proc_wspace_sep), NULL);
	if (err || neg) {
		err = -EINVAL;
		goto out_free;
	}

	if (conv(&lval, tbl_data, 1, data)) {
		err = -EINVAL;
		goto out_free;
	}

	if (!err && left)
		left -= proc_skip_spaces(&p);

out_free:
	kfree(kbuf);
	if (err)
		return -EINVAL;

	return 0;

	/* This is in keeping with old __do_proc_dointvec() */
bail_early:
	*ppos += *lenp;
	return err;
}

static int do_proc_douintvec_r(unsigned int *tbl_data, void __user *buffer,
			       size_t *lenp, loff_t *ppos,
			       int (*conv)(unsigned long *lvalp,
					   unsigned int *valp,
					   int write, void *data),
			       void *data)
{
	unsigned long lval;
	int err = 0;
	size_t left;

	left = *lenp;

	if (conv(&lval, tbl_data, 0, data)) {
		err = -EINVAL;
		goto out;
	}

	err = proc_put_long(&buffer, &left, lval, false);
	if (err || !left)
		goto out;

	err = proc_put_char(&buffer, &left, '\n');

out:
	*lenp -= left;
	*ppos += *lenp;

	return err;
}

static int __do_proc_douintvec(void *tbl_data, struct ctl_table *table,
			       int write, void __user *buffer,
			       size_t *lenp, loff_t *ppos,
			       int (*conv)(unsigned long *lvalp,
					   unsigned int *valp,
					   int write, void *data),
			       void *data)
{
	unsigned int *i, vleft;

	if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
		*lenp = 0;
		return 0;
	}

	i = (unsigned int *) tbl_data;
	vleft = table->maxlen / sizeof(*i);

	/*
	 * Arrays are not supported, keep this simple. *Do not* add
	 * support for them.
	 */
	if (vleft != 1) {
		*lenp = 0;
		return -EINVAL;
	}

	if (!conv)
		conv = do_proc_douintvec_conv;

	if (write)
		return do_proc_douintvec_w(i, table, buffer, lenp, ppos,
					   conv, data);
	return do_proc_douintvec_r(i, buffer, lenp, ppos, conv, data);
}

static int do_proc_douintvec(struct ctl_table *table, int write,
			     void __user *buffer, size_t *lenp, loff_t *ppos,
			     int (*conv)(unsigned long *lvalp,
					 unsigned int *valp,
					 int write, void *data),
			     void *data)
{
	return __do_proc_douintvec(table->data, table, write,
				   buffer, lenp, ppos, conv, data);
}

Linus Torvalds's avatar
Linus Torvalds committed
2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558
/**
 * proc_dointvec - read a vector of integers
 * @table: the sysctl table
 * @write: %TRUE if this is a write to the sysctl file
 * @buffer: the user buffer
 * @lenp: the size of the user buffer
 * @ppos: file position
 *
 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
 * values from/to the user buffer, treated as an ASCII string. 
 *
 * Returns 0 on success.
 */
2559
int proc_dointvec(struct ctl_table *table, int write,
Linus Torvalds's avatar
Linus Torvalds committed
2560 2561
		     void __user *buffer, size_t *lenp, loff_t *ppos)
{
2562 2563 2564
	return do_proc_dointvec(table, write, buffer, lenp, ppos, NULL, NULL);
}

2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586
#ifdef CONFIG_COMPACTION
static int proc_dointvec_minmax_warn_RT_change(struct ctl_table *table,
					       int write, void __user *buffer,
					       size_t *lenp, loff_t *ppos)
{
	int ret, old;

	if (!IS_ENABLED(CONFIG_PREEMPT_RT) || !write)
		return proc_dointvec_minmax(table, write, buffer, lenp, ppos);

	old = *(int *)table->data;
	ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
	if (ret)
		return ret;
	if (old != *(int *)table->data)
		pr_warn_once("sysctl attribute %s changed by %s[%d]\n",
			     table->procname, current->comm,
			     task_pid_nr(current));
	return ret;
}
#endif

2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602
/**
 * proc_douintvec - read a vector of unsigned integers
 * @table: the sysctl table
 * @write: %TRUE if this is a write to the sysctl file
 * @buffer: the user buffer
 * @lenp: the size of the user buffer
 * @ppos: file position
 *
 * Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
 * values from/to the user buffer, treated as an ASCII string.
 *
 * Returns 0 on success.
 */
int proc_douintvec(struct ctl_table *table, int write,
		     void __user *buffer, size_t *lenp, loff_t *ppos)
{
2603 2604
	return do_proc_douintvec(table, write, buffer, lenp, ppos,
				 do_proc_douintvec_conv, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
2605 2606
}

2607
/*
Andi Kleen's avatar
Andi Kleen committed
2608 2609
 * Taint values can only be increased
 * This means we can safely use a temporary.
2610
 */
2611
static int proc_taint(struct ctl_table *table, int write,
2612 2613
			       void __user *buffer, size_t *lenp, loff_t *ppos)
{
Andi Kleen's avatar
Andi Kleen committed
2614 2615 2616
	struct ctl_table t;
	unsigned long tmptaint = get_taint();
	int err;
2617

2618
	if (write && !capable(CAP_SYS_ADMIN))
2619 2620
		return -EPERM;

Andi Kleen's avatar
Andi Kleen committed
2621 2622
	t = *table;
	t.data = &tmptaint;
2623
	err = proc_doulongvec_minmax(&t, write, buffer, lenp, ppos);
Andi Kleen's avatar
Andi Kleen committed
2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634
	if (err < 0)
		return err;

	if (write) {
		/*
		 * Poor man's atomic or. Not worth adding a primitive
		 * to everyone's atomic.h for this
		 */
		int i;
		for (i = 0; i < BITS_PER_LONG && tmptaint >> i; i++) {
			if ((tmptaint >> i) & 1)
2635
				add_taint(i, LOCKDEP_STILL_OK);
Andi Kleen's avatar
Andi Kleen committed
2636 2637 2638 2639
		}
	}

	return err;
2640 2641
}

2642
#ifdef CONFIG_PRINTK
2643
static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
2644 2645 2646 2647 2648 2649 2650 2651 2652
				void __user *buffer, size_t *lenp, loff_t *ppos)
{
	if (write && !capable(CAP_SYS_ADMIN))
		return -EPERM;

	return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
}
#endif

2653 2654 2655 2656 2657 2658 2659 2660 2661
/**
 * struct do_proc_dointvec_minmax_conv_param - proc_dointvec_minmax() range checking structure
 * @min: pointer to minimum allowable value
 * @max: pointer to maximum allowable value
 *
 * The do_proc_dointvec_minmax_conv_param structure provides the
 * minimum and maximum values for doing range checking for those sysctl
 * parameters that use the proc_dointvec_minmax() handler.
 */
Linus Torvalds's avatar
Linus Torvalds committed
2662 2663 2664 2665 2666
struct do_proc_dointvec_minmax_conv_param {
	int *min;
	int *max;
};

2667 2668
static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp,
					int *valp,
Linus Torvalds's avatar
Linus Torvalds committed
2669 2670
					int write, void *data)
{
2671
	int tmp, ret;
Linus Torvalds's avatar
Linus Torvalds committed
2672
	struct do_proc_dointvec_minmax_conv_param *param = data;
2673 2674 2675 2676 2677 2678 2679 2680 2681 2682
	/*
	 * If writing, first do so via a temporary local int so we can
	 * bounds-check it before touching *valp.
	 */
	int *ip = write ? &tmp : valp;

	ret = do_proc_dointvec_conv(negp, lvalp, ip, write, data);
	if (ret)
		return ret;

Linus Torvalds's avatar
Linus Torvalds committed
2683
	if (write) {
2684 2685
		if ((param->min && *param->min > tmp) ||
		    (param->max && *param->max < tmp))
Linus Torvalds's avatar
Linus Torvalds committed
2686
			return -EINVAL;
2687
		*valp = tmp;
Linus Torvalds's avatar
Linus Torvalds committed
2688
	}
2689

Linus Torvalds's avatar
Linus Torvalds committed
2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706
	return 0;
}

/**
 * proc_dointvec_minmax - read a vector of integers with min/max values
 * @table: the sysctl table
 * @write: %TRUE if this is a write to the sysctl file
 * @buffer: the user buffer
 * @lenp: the size of the user buffer
 * @ppos: file position
 *
 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
 * values from/to the user buffer, treated as an ASCII string.
 *
 * This routine will ensure the values are within the range specified by
 * table->extra1 (min) and table->extra2 (max).
 *
2707
 * Returns 0 on success or -EINVAL on write when the range check fails.
Linus Torvalds's avatar
Linus Torvalds committed
2708
 */
2709
int proc_dointvec_minmax(struct ctl_table *table, int write,
Linus Torvalds's avatar
Linus Torvalds committed
2710 2711 2712 2713 2714 2715
		  void __user *buffer, size_t *lenp, loff_t *ppos)
{
	struct do_proc_dointvec_minmax_conv_param param = {
		.min = (int *) table->extra1,
		.max = (int *) table->extra2,
	};
2716
	return do_proc_dointvec(table, write, buffer, lenp, ppos,
Linus Torvalds's avatar
Linus Torvalds committed
2717 2718 2719
				do_proc_dointvec_minmax_conv, &param);
}

2720 2721 2722 2723 2724 2725 2726 2727 2728
/**
 * struct do_proc_douintvec_minmax_conv_param - proc_douintvec_minmax() range checking structure
 * @min: pointer to minimum allowable value
 * @max: pointer to maximum allowable value
 *
 * The do_proc_douintvec_minmax_conv_param structure provides the
 * minimum and maximum values for doing range checking for those sysctl
 * parameters that use the proc_douintvec_minmax() handler.
 */
2729 2730 2731 2732 2733 2734 2735 2736 2737
struct do_proc_douintvec_minmax_conv_param {
	unsigned int *min;
	unsigned int *max;
};

static int do_proc_douintvec_minmax_conv(unsigned long *lvalp,
					 unsigned int *valp,
					 int write, void *data)
{
2738 2739
	int ret;
	unsigned int tmp;
2740
	struct do_proc_douintvec_minmax_conv_param *param = data;
2741 2742
	/* write via temporary local uint for bounds-checking */
	unsigned int *up = write ? &tmp : valp;
2743

2744 2745 2746
	ret = do_proc_douintvec_conv(lvalp, up, write, data);
	if (ret)
		return ret;
2747

2748 2749 2750
	if (write) {
		if ((param->min && *param->min > tmp) ||
		    (param->max && *param->max < tmp))
2751 2752
			return -ERANGE;

2753
		*valp = tmp;
2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775
	}

	return 0;
}

/**
 * proc_douintvec_minmax - read a vector of unsigned ints with min/max values
 * @table: the sysctl table
 * @write: %TRUE if this is a write to the sysctl file
 * @buffer: the user buffer
 * @lenp: the size of the user buffer
 * @ppos: file position
 *
 * Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
 * values from/to the user buffer, treated as an ASCII string. Negative
 * strings are not allowed.
 *
 * This routine will ensure the values are within the range specified by
 * table->extra1 (min) and table->extra2 (max). There is a final sanity
 * check for UINT_MAX to avoid having to support wrap around uses from
 * userspace.
 *
2776
 * Returns 0 on success or -ERANGE on write when the range check fails.
2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788
 */
int proc_douintvec_minmax(struct ctl_table *table, int write,
			  void __user *buffer, size_t *lenp, loff_t *ppos)
{
	struct do_proc_douintvec_minmax_conv_param param = {
		.min = (unsigned int *) table->extra1,
		.max = (unsigned int *) table->extra2,
	};
	return do_proc_douintvec(table, write, buffer, lenp, ppos,
				 do_proc_douintvec_minmax_conv, &param);
}

2789 2790 2791 2792 2793
static int do_proc_dopipe_max_size_conv(unsigned long *lvalp,
					unsigned int *valp,
					int write, void *data)
{
	if (write) {
2794
		unsigned int val;
2795

2796
		val = round_pipe_size(*lvalp);
2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808
		if (val == 0)
			return -EINVAL;

		*valp = val;
	} else {
		unsigned int val = *valp;
		*lvalp = (unsigned long) val;
	}

	return 0;
}

2809 2810
static int proc_dopipe_max_size(struct ctl_table *table, int write,
				void __user *buffer, size_t *lenp, loff_t *ppos)
2811 2812
{
	return do_proc_douintvec(table, write, buffer, lenp, ppos,
2813
				 do_proc_dopipe_max_size_conv, NULL);
2814 2815
}

2816 2817
static void validate_coredump_safety(void)
{
2818
#ifdef CONFIG_COREDUMP
2819
	if (suid_dumpable == SUID_DUMP_ROOT &&
2820
	    core_pattern[0] != '/' && core_pattern[0] != '|') {
2821 2822 2823 2824 2825
		printk(KERN_WARNING
"Unsafe core_pattern used with fs.suid_dumpable=2.\n"
"Pipe handler or fully qualified core dump path required.\n"
"Set kernel.core_pattern before fs.suid_dumpable.\n"
		);
2826
	}
2827
#endif
2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838
}

static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write,
		void __user *buffer, size_t *lenp, loff_t *ppos)
{
	int error = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
	if (!error)
		validate_coredump_safety();
	return error;
}

2839
#ifdef CONFIG_COREDUMP
2840 2841 2842 2843 2844 2845 2846 2847
static int proc_dostring_coredump(struct ctl_table *table, int write,
		  void __user *buffer, size_t *lenp, loff_t *ppos)
{
	int error = proc_dostring(table, write, buffer, lenp, ppos);
	if (!error)
		validate_coredump_safety();
	return error;
}
2848
#endif
2849

2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869
#ifdef CONFIG_MAGIC_SYSRQ
static int sysrq_sysctl_handler(struct ctl_table *table, int write,
				void __user *buffer, size_t *lenp, loff_t *ppos)
{
	int tmp, ret;

	tmp = sysrq_mask();

	ret = __do_proc_dointvec(&tmp, table, write, buffer,
			       lenp, ppos, NULL, NULL);
	if (ret || !write)
		return ret;

	if (write)
		sysrq_toggle_support(tmp);

	return 0;
}
#endif

2870
static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int write,
Linus Torvalds's avatar
Linus Torvalds committed
2871 2872 2873 2874 2875
				     void __user *buffer,
				     size_t *lenp, loff_t *ppos,
				     unsigned long convmul,
				     unsigned long convdiv)
{
2876 2877 2878
	unsigned long *i, *min, *max;
	int vleft, first = 1, err = 0;
	size_t left;
2879
	char *kbuf = NULL, *p;
2880 2881

	if (!data || !table->maxlen || !*lenp || (*ppos && !write)) {
Linus Torvalds's avatar
Linus Torvalds committed
2882 2883 2884
		*lenp = 0;
		return 0;
	}
2885

2886
	i = (unsigned long *) data;
Linus Torvalds's avatar
Linus Torvalds committed
2887 2888 2889 2890
	min = (unsigned long *) table->extra1;
	max = (unsigned long *) table->extra2;
	vleft = table->maxlen / sizeof(unsigned long);
	left = *lenp;
2891 2892

	if (write) {
2893 2894
		if (proc_first_pos_non_zero_ignore(ppos, table))
			goto out;
2895

2896 2897
		if (left > PAGE_SIZE - 1)
			left = PAGE_SIZE - 1;
2898 2899 2900
		p = kbuf = memdup_user_nul(buffer, left);
		if (IS_ERR(kbuf))
			return PTR_ERR(kbuf);
2901 2902
	}

2903
	for (; left && vleft--; i++, first = 0) {
2904 2905
		unsigned long val;

Linus Torvalds's avatar
Linus Torvalds committed
2906
		if (write) {
2907 2908
			bool neg;

2909
			left -= proc_skip_spaces(&p);
2910 2911
			if (!left)
				break;
2912

2913
			err = proc_get_long(&p, &left, &val, &neg,
2914 2915 2916
					     proc_wspace_sep,
					     sizeof(proc_wspace_sep), NULL);
			if (err)
Linus Torvalds's avatar
Linus Torvalds committed
2917 2918 2919
				break;
			if (neg)
				continue;
2920
			val = convmul * val / convdiv;
2921 2922 2923 2924
			if ((min && val < *min) || (max && val > *max)) {
				err = -EINVAL;
				break;
			}
Linus Torvalds's avatar
Linus Torvalds committed
2925 2926
			*i = val;
		} else {
2927
			val = convdiv * (*i) / convmul;
2928
			if (!first) {
2929
				err = proc_put_char(&buffer, &left, '\t');
2930 2931 2932
				if (err)
					break;
			}
2933 2934 2935
			err = proc_put_long(&buffer, &left, val, false);
			if (err)
				break;
Linus Torvalds's avatar
Linus Torvalds committed
2936 2937 2938
		}
	}

2939 2940 2941
	if (!write && !first && left && !err)
		err = proc_put_char(&buffer, &left, '\n');
	if (write && !err)
2942
		left -= proc_skip_spaces(&p);
Linus Torvalds's avatar
Linus Torvalds committed
2943
	if (write) {
2944
		kfree(kbuf);
2945 2946
		if (first)
			return err ? : -EINVAL;
Linus Torvalds's avatar
Linus Torvalds committed
2947 2948
	}
	*lenp -= left;
2949
out:
Linus Torvalds's avatar
Linus Torvalds committed
2950
	*ppos += *lenp;
2951
	return err;
Linus Torvalds's avatar
Linus Torvalds committed
2952 2953
}

2954
static int do_proc_doulongvec_minmax(struct ctl_table *table, int write,
2955 2956 2957 2958 2959 2960
				     void __user *buffer,
				     size_t *lenp, loff_t *ppos,
				     unsigned long convmul,
				     unsigned long convdiv)
{
	return __do_proc_doulongvec_minmax(table->data, table, write,
2961
			buffer, lenp, ppos, convmul, convdiv);
2962 2963
}

Linus Torvalds's avatar
Linus Torvalds committed
2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979
/**
 * proc_doulongvec_minmax - read a vector of long integers with min/max values
 * @table: the sysctl table
 * @write: %TRUE if this is a write to the sysctl file
 * @buffer: the user buffer
 * @lenp: the size of the user buffer
 * @ppos: file position
 *
 * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
 * values from/to the user buffer, treated as an ASCII string.
 *
 * This routine will ensure the values are within the range specified by
 * table->extra1 (min) and table->extra2 (max).
 *
 * Returns 0 on success.
 */
2980
int proc_doulongvec_minmax(struct ctl_table *table, int write,
Linus Torvalds's avatar
Linus Torvalds committed
2981 2982
			   void __user *buffer, size_t *lenp, loff_t *ppos)
{
2983
    return do_proc_doulongvec_minmax(table, write, buffer, lenp, ppos, 1l, 1l);
Linus Torvalds's avatar
Linus Torvalds committed
2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002
}

/**
 * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values
 * @table: the sysctl table
 * @write: %TRUE if this is a write to the sysctl file
 * @buffer: the user buffer
 * @lenp: the size of the user buffer
 * @ppos: file position
 *
 * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
 * values from/to the user buffer, treated as an ASCII string. The values
 * are treated as milliseconds, and converted to jiffies when they are stored.
 *
 * This routine will ensure the values are within the range specified by
 * table->extra1 (min) and table->extra2 (max).
 *
 * Returns 0 on success.
 */
3003
int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
Linus Torvalds's avatar
Linus Torvalds committed
3004 3005 3006
				      void __user *buffer,
				      size_t *lenp, loff_t *ppos)
{
3007
    return do_proc_doulongvec_minmax(table, write, buffer,
Linus Torvalds's avatar
Linus Torvalds committed
3008 3009 3010 3011
				     lenp, ppos, HZ, 1000l);
}


3012
static int do_proc_dointvec_jiffies_conv(bool *negp, unsigned long *lvalp,
Linus Torvalds's avatar
Linus Torvalds committed
3013 3014 3015 3016
					 int *valp,
					 int write, void *data)
{
	if (write) {
3017
		if (*lvalp > INT_MAX / HZ)
3018
			return 1;
Linus Torvalds's avatar
Linus Torvalds committed
3019 3020 3021 3022 3023
		*valp = *negp ? -(*lvalp*HZ) : (*lvalp*HZ);
	} else {
		int val = *valp;
		unsigned long lval;
		if (val < 0) {
3024
			*negp = true;
3025
			lval = -(unsigned long)val;
Linus Torvalds's avatar
Linus Torvalds committed
3026
		} else {
3027
			*negp = false;
Linus Torvalds's avatar
Linus Torvalds committed
3028 3029 3030 3031 3032 3033 3034
			lval = (unsigned long)val;
		}
		*lvalp = lval / HZ;
	}
	return 0;
}

3035
static int do_proc_dointvec_userhz_jiffies_conv(bool *negp, unsigned long *lvalp,
Linus Torvalds's avatar
Linus Torvalds committed
3036 3037 3038 3039
						int *valp,
						int write, void *data)
{
	if (write) {
3040 3041
		if (USER_HZ < HZ && *lvalp > (LONG_MAX / HZ) * USER_HZ)
			return 1;
Linus Torvalds's avatar
Linus Torvalds committed
3042 3043 3044 3045 3046
		*valp = clock_t_to_jiffies(*negp ? -*lvalp : *lvalp);
	} else {
		int val = *valp;
		unsigned long lval;
		if (val < 0) {
3047
			*negp = true;
3048
			lval = -(unsigned long)val;
Linus Torvalds's avatar
Linus Torvalds committed
3049
		} else {
3050
			*negp = false;
Linus Torvalds's avatar
Linus Torvalds committed
3051 3052 3053 3054 3055 3056 3057
			lval = (unsigned long)val;
		}
		*lvalp = jiffies_to_clock_t(lval);
	}
	return 0;
}

3058
static int do_proc_dointvec_ms_jiffies_conv(bool *negp, unsigned long *lvalp,
Linus Torvalds's avatar
Linus Torvalds committed
3059 3060 3061 3062
					    int *valp,
					    int write, void *data)
{
	if (write) {
3063 3064 3065 3066 3067
		unsigned long jif = msecs_to_jiffies(*negp ? -*lvalp : *lvalp);

		if (jif > INT_MAX)
			return 1;
		*valp = (int)jif;
Linus Torvalds's avatar
Linus Torvalds committed
3068 3069 3070 3071
	} else {
		int val = *valp;
		unsigned long lval;
		if (val < 0) {
3072
			*negp = true;
3073
			lval = -(unsigned long)val;
Linus Torvalds's avatar
Linus Torvalds committed
3074
		} else {
3075
			*negp = false;
Linus Torvalds's avatar
Linus Torvalds committed
3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097
			lval = (unsigned long)val;
		}
		*lvalp = jiffies_to_msecs(lval);
	}
	return 0;
}

/**
 * proc_dointvec_jiffies - read a vector of integers as seconds
 * @table: the sysctl table
 * @write: %TRUE if this is a write to the sysctl file
 * @buffer: the user buffer
 * @lenp: the size of the user buffer
 * @ppos: file position
 *
 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
 * values from/to the user buffer, treated as an ASCII string. 
 * The values read are assumed to be in seconds, and are converted into
 * jiffies.
 *
 * Returns 0 on success.
 */
3098
int proc_dointvec_jiffies(struct ctl_table *table, int write,
Linus Torvalds's avatar
Linus Torvalds committed
3099 3100
			  void __user *buffer, size_t *lenp, loff_t *ppos)
{
3101
    return do_proc_dointvec(table,write,buffer,lenp,ppos,
Linus Torvalds's avatar
Linus Torvalds committed
3102 3103 3104 3105 3106 3107 3108 3109 3110
		    	    do_proc_dointvec_jiffies_conv,NULL);
}

/**
 * proc_dointvec_userhz_jiffies - read a vector of integers as 1/USER_HZ seconds
 * @table: the sysctl table
 * @write: %TRUE if this is a write to the sysctl file
 * @buffer: the user buffer
 * @lenp: the size of the user buffer
3111
 * @ppos: pointer to the file position
Linus Torvalds's avatar
Linus Torvalds committed
3112 3113 3114 3115 3116 3117 3118 3119
 *
 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
 * values from/to the user buffer, treated as an ASCII string. 
 * The values read are assumed to be in 1/USER_HZ seconds, and 
 * are converted into jiffies.
 *
 * Returns 0 on success.
 */
3120
int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
Linus Torvalds's avatar
Linus Torvalds committed
3121 3122
				 void __user *buffer, size_t *lenp, loff_t *ppos)
{
3123
    return do_proc_dointvec(table,write,buffer,lenp,ppos,
Linus Torvalds's avatar
Linus Torvalds committed
3124 3125 3126 3127 3128 3129 3130 3131 3132
		    	    do_proc_dointvec_userhz_jiffies_conv,NULL);
}

/**
 * proc_dointvec_ms_jiffies - read a vector of integers as 1 milliseconds
 * @table: the sysctl table
 * @write: %TRUE if this is a write to the sysctl file
 * @buffer: the user buffer
 * @lenp: the size of the user buffer
3133 3134
 * @ppos: file position
 * @ppos: the current position in the file
Linus Torvalds's avatar
Linus Torvalds committed
3135 3136 3137 3138 3139 3140 3141 3142
 *
 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
 * values from/to the user buffer, treated as an ASCII string. 
 * The values read are assumed to be in 1/1000 seconds, and 
 * are converted into jiffies.
 *
 * Returns 0 on success.
 */
3143
int proc_dointvec_ms_jiffies(struct ctl_table *table, int write,
Linus Torvalds's avatar
Linus Torvalds committed
3144 3145
			     void __user *buffer, size_t *lenp, loff_t *ppos)
{
3146
	return do_proc_dointvec(table, write, buffer, lenp, ppos,
Linus Torvalds's avatar
Linus Torvalds committed
3147 3148 3149
				do_proc_dointvec_ms_jiffies_conv, NULL);
}

3150
static int proc_do_cad_pid(struct ctl_table *table, int write,
3151 3152 3153 3154 3155 3156
			   void __user *buffer, size_t *lenp, loff_t *ppos)
{
	struct pid *new_pid;
	pid_t tmp;
	int r;

3157
	tmp = pid_vnr(cad_pid);
3158

3159
	r = __do_proc_dointvec(&tmp, table, write, buffer,
3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171
			       lenp, ppos, NULL, NULL);
	if (r || !write)
		return r;

	new_pid = find_get_pid(tmp);
	if (!new_pid)
		return -ESRCH;

	put_pid(xchg(&cad_pid, new_pid));
	return 0;
}

3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195
/**
 * proc_do_large_bitmap - read/write from/to a large bitmap
 * @table: the sysctl table
 * @write: %TRUE if this is a write to the sysctl file
 * @buffer: the user buffer
 * @lenp: the size of the user buffer
 * @ppos: file position
 *
 * The bitmap is stored at table->data and the bitmap length (in bits)
 * in table->maxlen.
 *
 * We use a range comma separated format (e.g. 1,3-4,10-10) so that
 * large bitmaps may be represented in a compact manner. Writing into
 * the file will clear the bitmap then update it with the given input.
 *
 * Returns 0 on success.
 */
int proc_do_large_bitmap(struct ctl_table *table, int write,
			 void __user *buffer, size_t *lenp, loff_t *ppos)
{
	int err = 0;
	bool first = 1;
	size_t left = *lenp;
	unsigned long bitmap_len = table->maxlen;
3196
	unsigned long *bitmap = *(unsigned long **) table->data;
3197 3198 3199
	unsigned long *tmp_bitmap = NULL;
	char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;

3200
	if (!bitmap || !bitmap_len || !left || (*ppos && !write)) {
3201 3202 3203 3204 3205
		*lenp = 0;
		return 0;
	}

	if (write) {
3206
		char *kbuf, *p;
3207
		size_t skipped = 0;
3208

3209
		if (left > PAGE_SIZE - 1) {
3210
			left = PAGE_SIZE - 1;
3211 3212 3213
			/* How much of the buffer we'll skip this pass */
			skipped = *lenp - left;
		}
3214

3215 3216 3217
		p = kbuf = memdup_user_nul(buffer, left);
		if (IS_ERR(kbuf))
			return PTR_ERR(kbuf);
3218

3219
		tmp_bitmap = bitmap_zalloc(bitmap_len, GFP_KERNEL);
3220
		if (!tmp_bitmap) {
3221
			kfree(kbuf);
3222 3223
			return -ENOMEM;
		}
3224
		proc_skip_char(&p, &left, '\n');
3225 3226 3227
		while (!err && left) {
			unsigned long val_a, val_b;
			bool neg;
3228
			size_t saved_left;
3229

3230 3231
			/* In case we stop parsing mid-number, we can reset */
			saved_left = left;
3232
			err = proc_get_long(&p, &left, &val_a, &neg, tr_a,
3233
					     sizeof(tr_a), &c);
3234 3235 3236 3237 3238 3239 3240 3241 3242 3243
			/*
			 * If we consumed the entirety of a truncated buffer or
			 * only one char is left (may be a "-"), then stop here,
			 * reset, & come back for more.
			 */
			if ((left <= 1) && skipped) {
				left = saved_left;
				break;
			}

3244 3245 3246 3247 3248 3249 3250 3251 3252
			if (err)
				break;
			if (val_a >= bitmap_len || neg) {
				err = -EINVAL;
				break;
			}

			val_b = val_a;
			if (left) {
3253
				p++;
3254 3255 3256 3257
				left--;
			}

			if (c == '-') {
3258
				err = proc_get_long(&p, &left, &val_b,
3259 3260
						     &neg, tr_b, sizeof(tr_b),
						     &c);
3261 3262 3263 3264 3265 3266 3267 3268 3269
				/*
				 * If we consumed all of a truncated buffer or
				 * then stop here, reset, & come back for more.
				 */
				if (!left && skipped) {
					left = saved_left;
					break;
				}

3270 3271 3272 3273 3274 3275 3276 3277
				if (err)
					break;
				if (val_b >= bitmap_len || neg ||
				    val_a > val_b) {
					err = -EINVAL;
					break;
				}
				if (left) {
3278
					p++;
3279 3280 3281 3282
					left--;
				}
			}

3283
			bitmap_set(tmp_bitmap, val_a, val_b - val_a + 1);
3284
			first = 0;
3285
			proc_skip_char(&p, &left, '\n');
3286
		}
3287
		kfree(kbuf);
3288
		left += skipped;
3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326
	} else {
		unsigned long bit_a, bit_b = 0;

		while (left) {
			bit_a = find_next_bit(bitmap, bitmap_len, bit_b);
			if (bit_a >= bitmap_len)
				break;
			bit_b = find_next_zero_bit(bitmap, bitmap_len,
						   bit_a + 1) - 1;

			if (!first) {
				err = proc_put_char(&buffer, &left, ',');
				if (err)
					break;
			}
			err = proc_put_long(&buffer, &left, bit_a, false);
			if (err)
				break;
			if (bit_a != bit_b) {
				err = proc_put_char(&buffer, &left, '-');
				if (err)
					break;
				err = proc_put_long(&buffer, &left, bit_b, false);
				if (err)
					break;
			}

			first = 0; bit_b++;
		}
		if (!err)
			err = proc_put_char(&buffer, &left, '\n');
	}

	if (!err) {
		if (write) {
			if (*ppos)
				bitmap_or(bitmap, bitmap, tmp_bitmap, bitmap_len);
			else
3327
				bitmap_copy(bitmap, tmp_bitmap, bitmap_len);
3328 3329 3330 3331
		}
		*lenp -= left;
		*ppos += *lenp;
	}
3332

3333
	bitmap_free(tmp_bitmap);
3334
	return err;
3335 3336
}

3337
#else /* CONFIG_PROC_SYSCTL */
Linus Torvalds's avatar
Linus Torvalds committed
3338

3339
int proc_dostring(struct ctl_table *table, int write,
Linus Torvalds's avatar
Linus Torvalds committed
3340 3341 3342 3343 3344
		  void __user *buffer, size_t *lenp, loff_t *ppos)
{
	return -ENOSYS;
}

3345
int proc_dointvec(struct ctl_table *table, int write,
Linus Torvalds's avatar
Linus Torvalds committed
3346 3347 3348 3349 3350
		  void __user *buffer, size_t *lenp, loff_t *ppos)
{
	return -ENOSYS;
}

3351 3352 3353 3354 3355 3356
int proc_douintvec(struct ctl_table *table, int write,
		  void __user *buffer, size_t *lenp, loff_t *ppos)
{
	return -ENOSYS;
}

3357
int proc_dointvec_minmax(struct ctl_table *table, int write,
Linus Torvalds's avatar
Linus Torvalds committed
3358 3359 3360 3361 3362
		    void __user *buffer, size_t *lenp, loff_t *ppos)
{
	return -ENOSYS;
}

3363 3364 3365 3366 3367 3368
int proc_douintvec_minmax(struct ctl_table *table, int write,
			  void __user *buffer, size_t *lenp, loff_t *ppos)
{
	return -ENOSYS;
}

3369
int proc_dointvec_jiffies(struct ctl_table *table, int write,
Linus Torvalds's avatar
Linus Torvalds committed
3370 3371 3372 3373 3374
		    void __user *buffer, size_t *lenp, loff_t *ppos)
{
	return -ENOSYS;
}

3375
int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
Linus Torvalds's avatar
Linus Torvalds committed
3376 3377 3378 3379 3380
		    void __user *buffer, size_t *lenp, loff_t *ppos)
{
	return -ENOSYS;
}

3381
int proc_dointvec_ms_jiffies(struct ctl_table *table, int write,
Linus Torvalds's avatar
Linus Torvalds committed
3382 3383 3384 3385 3386
			     void __user *buffer, size_t *lenp, loff_t *ppos)
{
	return -ENOSYS;
}

3387
int proc_doulongvec_minmax(struct ctl_table *table, int write,
Linus Torvalds's avatar
Linus Torvalds committed
3388 3389 3390 3391 3392
		    void __user *buffer, size_t *lenp, loff_t *ppos)
{
	return -ENOSYS;
}

3393
int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
Linus Torvalds's avatar
Linus Torvalds committed
3394 3395 3396 3397 3398 3399
				      void __user *buffer,
				      size_t *lenp, loff_t *ppos)
{
    return -ENOSYS;
}

3400 3401 3402 3403 3404
int proc_do_large_bitmap(struct ctl_table *table, int write,
			 void __user *buffer, size_t *lenp, loff_t *ppos)
{
	return -ENOSYS;
}
Linus Torvalds's avatar
Linus Torvalds committed
3405

3406
#endif /* CONFIG_PROC_SYSCTL */
Linus Torvalds's avatar
Linus Torvalds committed
3407

3408 3409 3410 3411
#if defined(CONFIG_SYSCTL)
int proc_do_static_key(struct ctl_table *table, int write,
		       void __user *buffer, size_t *lenp,
		       loff_t *ppos)
3412
{
3413 3414 3415 3416 3417 3418 3419
	struct static_key *key = (struct static_key *)table->data;
	static DEFINE_MUTEX(static_key_mutex);
	int val, ret;
	struct ctl_table tmp = {
		.data   = &val,
		.maxlen = sizeof(val),
		.mode   = table->mode,
3420 3421
		.extra1 = SYSCTL_ZERO,
		.extra2 = SYSCTL_ONE,
3422
	};
3423 3424 3425 3426

	if (write && !capable(CAP_SYS_ADMIN))
		return -EPERM;

3427 3428
	mutex_lock(&static_key_mutex);
	val = static_key_enabled(key);
3429 3430
	ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
	if (write && !ret) {
3431 3432
		if (val)
			static_key_enable(key);
3433
		else
3434
			static_key_disable(key);
3435
	}
3436
	mutex_unlock(&static_key_mutex);
3437 3438
	return ret;
}
3439
#endif
Linus Torvalds's avatar
Linus Torvalds committed
3440 3441 3442 3443 3444
/*
 * No sense putting this after each symbol definition, twice,
 * exception granted :-)
 */
EXPORT_SYMBOL(proc_dointvec);
3445
EXPORT_SYMBOL(proc_douintvec);
Linus Torvalds's avatar
Linus Torvalds committed
3446 3447
EXPORT_SYMBOL(proc_dointvec_jiffies);
EXPORT_SYMBOL(proc_dointvec_minmax);
3448
EXPORT_SYMBOL_GPL(proc_douintvec_minmax);
Linus Torvalds's avatar
Linus Torvalds committed
3449 3450 3451 3452 3453
EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
EXPORT_SYMBOL(proc_dointvec_ms_jiffies);
EXPORT_SYMBOL(proc_dostring);
EXPORT_SYMBOL(proc_doulongvec_minmax);
EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
3454
EXPORT_SYMBOL(proc_do_large_bitmap);