Branch data Line data Source code
1 : : /*
2 : : * sysctl.c: General linux system control interface
3 : : *
4 : : * Begun 24 March 1995, Stephen Tweedie
5 : : * Added /proc support, Dec 1995
6 : : * Added bdflush entry and intvec min/max checking, 2/23/96, Tom Dyas.
7 : : * Added hooks for /proc/sys/net (minor, minor patch), 96/4/1, Mike Shaver.
8 : : * Added kernel/java-{interpreter,appletviewer}, 96/5/10, Mike Shaver.
9 : : * Dynamic registration fixes, Stephen Tweedie.
10 : : * Added kswapd-interval, ctrl-alt-del, printk stuff, 1/8/97, Chris Horn.
11 : : * Made sysctl support optional via CONFIG_SYSCTL, 1/10/97, Chris
12 : : * Horn.
13 : : * Added proc_doulongvec_ms_jiffies_minmax, 09/08/99, Carlos H. Bauer.
14 : : * Added proc_doulongvec_minmax, 09/08/99, Carlos H. Bauer.
15 : : * Changed linked lists to use list.h instead of lists.h, 02/24/00, Bill
16 : : * Wendling.
17 : : * The list_for_each() macro wasn't appropriate for the sysctl loop.
18 : : * Removed it and replaced it with older style, 03/23/00, Bill Wendling
19 : : */
20 : :
21 : : #include <linux/module.h>
22 : : #include <linux/mm.h>
23 : : #include <linux/swap.h>
24 : : #include <linux/slab.h>
25 : : #include <linux/sysctl.h>
26 : : #include <linux/bitmap.h>
27 : : #include <linux/signal.h>
28 : : #include <linux/printk.h>
29 : : #include <linux/proc_fs.h>
30 : : #include <linux/security.h>
31 : : #include <linux/ctype.h>
32 : : #include <linux/kmemcheck.h>
33 : : #include <linux/kmemleak.h>
34 : : #include <linux/fs.h>
35 : : #include <linux/init.h>
36 : : #include <linux/kernel.h>
37 : : #include <linux/kobject.h>
38 : : #include <linux/net.h>
39 : : #include <linux/sysrq.h>
40 : : #include <linux/highuid.h>
41 : : #include <linux/writeback.h>
42 : : #include <linux/ratelimit.h>
43 : : #include <linux/compaction.h>
44 : : #include <linux/hugetlb.h>
45 : : #include <linux/initrd.h>
46 : : #include <linux/key.h>
47 : : #include <linux/times.h>
48 : : #include <linux/limits.h>
49 : : #include <linux/dcache.h>
50 : : #include <linux/dnotify.h>
51 : : #include <linux/syscalls.h>
52 : : #include <linux/vmstat.h>
53 : : #include <linux/nfs_fs.h>
54 : : #include <linux/acpi.h>
55 : : #include <linux/reboot.h>
56 : : #include <linux/ftrace.h>
57 : : #include <linux/perf_event.h>
58 : : #include <linux/kprobes.h>
59 : : #include <linux/pipe_fs_i.h>
60 : : #include <linux/oom.h>
61 : : #include <linux/kmod.h>
62 : : #include <linux/capability.h>
63 : : #include <linux/binfmts.h>
64 : : #include <linux/sched/sysctl.h>
65 : :
66 : : #include <asm/uaccess.h>
67 : : #include <asm/processor.h>
68 : :
69 : : #ifdef CONFIG_X86
70 : : #include <asm/nmi.h>
71 : : #include <asm/stacktrace.h>
72 : : #include <asm/io.h>
73 : : #endif
74 : : #ifdef CONFIG_SPARC
75 : : #include <asm/setup.h>
76 : : #endif
77 : : #ifdef CONFIG_BSD_PROCESS_ACCT
78 : : #include <linux/acct.h>
79 : : #endif
80 : : #ifdef CONFIG_RT_MUTEXES
81 : : #include <linux/rtmutex.h>
82 : : #endif
83 : : #if defined(CONFIG_PROVE_LOCKING) || defined(CONFIG_LOCK_STAT)
84 : : #include <linux/lockdep.h>
85 : : #endif
86 : : #ifdef CONFIG_CHR_DEV_SG
87 : : #include <scsi/sg.h>
88 : : #endif
89 : :
90 : : #ifdef CONFIG_LOCKUP_DETECTOR
91 : : #include <linux/nmi.h>
92 : : #endif
93 : :
94 : :
95 : : #if defined(CONFIG_SYSCTL)
96 : :
97 : : /* External variables not in a header file. */
98 : : extern int sysctl_overcommit_memory;
99 : : extern int sysctl_overcommit_ratio;
100 : : extern int max_threads;
101 : : extern int suid_dumpable;
102 : : #ifdef CONFIG_COREDUMP
103 : : extern int core_uses_pid;
104 : : extern char core_pattern[];
105 : : extern unsigned int core_pipe_limit;
106 : : #endif
107 : : extern int pid_max;
108 : : extern int extra_free_kbytes;
109 : : extern int min_free_order_shift;
110 : : extern int pid_max_min, pid_max_max;
111 : : extern int percpu_pagelist_fraction;
112 : : extern int compat_log;
113 : : extern int latencytop_enabled;
114 : : extern int sysctl_nr_open_min, sysctl_nr_open_max;
115 : : #ifndef CONFIG_MMU
116 : : extern int sysctl_nr_trim_pages;
117 : : #endif
118 : : #ifdef CONFIG_BLOCK
119 : : extern int blk_iopoll_enabled;
120 : : #endif
121 : :
122 : : /* Constants used for minimum and maximum */
123 : : #ifdef CONFIG_LOCKUP_DETECTOR
124 : : static int sixty = 60;
125 : : #endif
126 : :
127 : : static int zero;
128 : : static int __maybe_unused one = 1;
129 : : static int __maybe_unused two = 2;
130 : : static int __maybe_unused three = 3;
131 : : static unsigned long one_ul = 1;
132 : : static int one_hundred = 100;
133 : : #ifdef CONFIG_PRINTK
134 : : static int ten_thousand = 10000;
135 : : #endif
136 : :
137 : : /* this is needed for the proc_doulongvec_minmax of vm_dirty_bytes */
138 : : static unsigned long dirty_bytes_min = 2 * PAGE_SIZE;
139 : :
140 : : /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
141 : : static int maxolduid = 65535;
142 : : static int minolduid;
143 : : static int min_percpu_pagelist_fract = 8;
144 : :
145 : : static int ngroups_max = NGROUPS_MAX;
146 : : static const int cap_last_cap = CAP_LAST_CAP;
147 : :
148 : : #ifdef CONFIG_INOTIFY_USER
149 : : #include <linux/inotify.h>
150 : : #endif
151 : : #ifdef CONFIG_SPARC
152 : : #endif
153 : :
154 : : #ifdef CONFIG_SPARC64
155 : : extern int sysctl_tsb_ratio;
156 : : #endif
157 : :
158 : : #ifdef __hppa__
159 : : extern int pwrsw_enabled;
160 : : #endif
161 : :
162 : : #ifdef CONFIG_SYSCTL_ARCH_UNALIGN_ALLOW
163 : : extern int unaligned_enabled;
164 : : #endif
165 : :
166 : : #ifdef CONFIG_IA64
167 : : extern int unaligned_dump_stack;
168 : : #endif
169 : :
170 : : #ifdef CONFIG_SYSCTL_ARCH_UNALIGN_NO_WARN
171 : : extern int no_unaligned_warning;
172 : : #endif
173 : :
174 : : #ifdef CONFIG_PROC_SYSCTL
175 : : static int proc_do_cad_pid(struct ctl_table *table, int write,
176 : : void __user *buffer, size_t *lenp, loff_t *ppos);
177 : : static int proc_taint(struct ctl_table *table, int write,
178 : : void __user *buffer, size_t *lenp, loff_t *ppos);
179 : : #endif
180 : :
181 : : #ifdef CONFIG_PRINTK
182 : : static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
183 : : void __user *buffer, size_t *lenp, loff_t *ppos);
184 : : #endif
185 : :
186 : : static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write,
187 : : void __user *buffer, size_t *lenp, loff_t *ppos);
188 : : #ifdef CONFIG_COREDUMP
189 : : static int proc_dostring_coredump(struct ctl_table *table, int write,
190 : : void __user *buffer, size_t *lenp, loff_t *ppos);
191 : : #endif
192 : :
193 : : #ifdef CONFIG_MAGIC_SYSRQ
194 : : /* Note: sysrq code uses it's own private copy */
195 : : static int __sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE;
196 : :
197 : 0 : static int sysrq_sysctl_handler(ctl_table *table, int write,
198 : : void __user *buffer, size_t *lenp,
199 : : loff_t *ppos)
200 : : {
201 : : int error;
202 : :
203 : : error = proc_dointvec(table, write, buffer, lenp, ppos);
204 [ + - ]: 2 : if (error)
205 : : return error;
206 : :
207 [ - + ]: 2 : if (write)
208 : 0 : sysrq_toggle_support(__sysrq_enabled);
209 : :
210 : : return 0;
211 : : }
212 : :
213 : : #endif
214 : :
215 : : static struct ctl_table kern_table[];
216 : : static struct ctl_table vm_table[];
217 : : static struct ctl_table fs_table[];
218 : : static struct ctl_table debug_table[];
219 : : static struct ctl_table dev_table[];
220 : : extern struct ctl_table random_table[];
221 : : #ifdef CONFIG_EPOLL
222 : : extern struct ctl_table epoll_table[];
223 : : #endif
224 : :
225 : : #ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
226 : : int sysctl_legacy_va_layout;
227 : : #endif
228 : :
229 : : /* The default sysctl tables: */
230 : :
231 : : static struct ctl_table sysctl_base_table[] = {
232 : : {
233 : : .procname = "kernel",
234 : : .mode = 0555,
235 : : .child = kern_table,
236 : : },
237 : : {
238 : : .procname = "vm",
239 : : .mode = 0555,
240 : : .child = vm_table,
241 : : },
242 : : {
243 : : .procname = "fs",
244 : : .mode = 0555,
245 : : .child = fs_table,
246 : : },
247 : : {
248 : : .procname = "debug",
249 : : .mode = 0555,
250 : : .child = debug_table,
251 : : },
252 : : {
253 : : .procname = "dev",
254 : : .mode = 0555,
255 : : .child = dev_table,
256 : : },
257 : : { }
258 : : };
259 : :
260 : : #ifdef CONFIG_SCHED_DEBUG
261 : : static int min_sched_granularity_ns = 100000; /* 100 usecs */
262 : : static int max_sched_granularity_ns = NSEC_PER_SEC; /* 1 second */
263 : : static int min_wakeup_granularity_ns; /* 0 usecs */
264 : : static int max_wakeup_granularity_ns = NSEC_PER_SEC; /* 1 second */
265 : : #ifdef CONFIG_SMP
266 : : static int min_sched_tunable_scaling = SCHED_TUNABLESCALING_NONE;
267 : : static int max_sched_tunable_scaling = SCHED_TUNABLESCALING_END-1;
268 : : #endif /* CONFIG_SMP */
269 : : #endif /* CONFIG_SCHED_DEBUG */
270 : :
271 : : #ifdef CONFIG_COMPACTION
272 : : static int min_extfrag_threshold;
273 : : static int max_extfrag_threshold = 1000;
274 : : #endif
275 : :
276 : : static struct ctl_table kern_table[] = {
277 : : {
278 : : .procname = "sched_child_runs_first",
279 : : .data = &sysctl_sched_child_runs_first,
280 : : .maxlen = sizeof(unsigned int),
281 : : .mode = 0644,
282 : : .proc_handler = proc_dointvec,
283 : : },
284 : : #ifdef CONFIG_SCHED_DEBUG
285 : : {
286 : : .procname = "sched_min_granularity_ns",
287 : : .data = &sysctl_sched_min_granularity,
288 : : .maxlen = sizeof(unsigned int),
289 : : .mode = 0644,
290 : : .proc_handler = sched_proc_update_handler,
291 : : .extra1 = &min_sched_granularity_ns,
292 : : .extra2 = &max_sched_granularity_ns,
293 : : },
294 : : {
295 : : .procname = "sched_latency_ns",
296 : : .data = &sysctl_sched_latency,
297 : : .maxlen = sizeof(unsigned int),
298 : : .mode = 0644,
299 : : .proc_handler = sched_proc_update_handler,
300 : : .extra1 = &min_sched_granularity_ns,
301 : : .extra2 = &max_sched_granularity_ns,
302 : : },
303 : : {
304 : : .procname = "sched_wakeup_granularity_ns",
305 : : .data = &sysctl_sched_wakeup_granularity,
306 : : .maxlen = sizeof(unsigned int),
307 : : .mode = 0644,
308 : : .proc_handler = sched_proc_update_handler,
309 : : .extra1 = &min_wakeup_granularity_ns,
310 : : .extra2 = &max_wakeup_granularity_ns,
311 : : },
312 : : #ifdef CONFIG_SMP
313 : : {
314 : : .procname = "sched_tunable_scaling",
315 : : .data = &sysctl_sched_tunable_scaling,
316 : : .maxlen = sizeof(enum sched_tunable_scaling),
317 : : .mode = 0644,
318 : : .proc_handler = sched_proc_update_handler,
319 : : .extra1 = &min_sched_tunable_scaling,
320 : : .extra2 = &max_sched_tunable_scaling,
321 : : },
322 : : {
323 : : .procname = "sched_migration_cost_ns",
324 : : .data = &sysctl_sched_migration_cost,
325 : : .maxlen = sizeof(unsigned int),
326 : : .mode = 0644,
327 : : .proc_handler = proc_dointvec,
328 : : },
329 : : {
330 : : .procname = "sched_nr_migrate",
331 : : .data = &sysctl_sched_nr_migrate,
332 : : .maxlen = sizeof(unsigned int),
333 : : .mode = 0644,
334 : : .proc_handler = proc_dointvec,
335 : : },
336 : : {
337 : : .procname = "sched_time_avg_ms",
338 : : .data = &sysctl_sched_time_avg,
339 : : .maxlen = sizeof(unsigned int),
340 : : .mode = 0644,
341 : : .proc_handler = proc_dointvec,
342 : : },
343 : : {
344 : : .procname = "sched_shares_window_ns",
345 : : .data = &sysctl_sched_shares_window,
346 : : .maxlen = sizeof(unsigned int),
347 : : .mode = 0644,
348 : : .proc_handler = proc_dointvec,
349 : : },
350 : : {
351 : : .procname = "timer_migration",
352 : : .data = &sysctl_timer_migration,
353 : : .maxlen = sizeof(unsigned int),
354 : : .mode = 0644,
355 : : .proc_handler = proc_dointvec_minmax,
356 : : .extra1 = &zero,
357 : : .extra2 = &one,
358 : : },
359 : : #endif /* CONFIG_SMP */
360 : : #ifdef CONFIG_NUMA_BALANCING
361 : : {
362 : : .procname = "numa_balancing_scan_delay_ms",
363 : : .data = &sysctl_numa_balancing_scan_delay,
364 : : .maxlen = sizeof(unsigned int),
365 : : .mode = 0644,
366 : : .proc_handler = proc_dointvec,
367 : : },
368 : : {
369 : : .procname = "numa_balancing_scan_period_min_ms",
370 : : .data = &sysctl_numa_balancing_scan_period_min,
371 : : .maxlen = sizeof(unsigned int),
372 : : .mode = 0644,
373 : : .proc_handler = proc_dointvec,
374 : : },
375 : : {
376 : : .procname = "numa_balancing_scan_period_max_ms",
377 : : .data = &sysctl_numa_balancing_scan_period_max,
378 : : .maxlen = sizeof(unsigned int),
379 : : .mode = 0644,
380 : : .proc_handler = proc_dointvec,
381 : : },
382 : : {
383 : : .procname = "numa_balancing_scan_size_mb",
384 : : .data = &sysctl_numa_balancing_scan_size,
385 : : .maxlen = sizeof(unsigned int),
386 : : .mode = 0644,
387 : : .proc_handler = proc_dointvec,
388 : : },
389 : : {
390 : : .procname = "numa_balancing_settle_count",
391 : : .data = &sysctl_numa_balancing_settle_count,
392 : : .maxlen = sizeof(unsigned int),
393 : : .mode = 0644,
394 : : .proc_handler = proc_dointvec,
395 : : },
396 : : {
397 : : .procname = "numa_balancing_migrate_deferred",
398 : : .data = &sysctl_numa_balancing_migrate_deferred,
399 : : .maxlen = sizeof(unsigned int),
400 : : .mode = 0644,
401 : : .proc_handler = proc_dointvec,
402 : : },
403 : : #endif /* CONFIG_NUMA_BALANCING */
404 : : #endif /* CONFIG_SCHED_DEBUG */
405 : : {
406 : : .procname = "sched_rt_period_us",
407 : : .data = &sysctl_sched_rt_period,
408 : : .maxlen = sizeof(unsigned int),
409 : : .mode = 0644,
410 : : .proc_handler = sched_rt_handler,
411 : : },
412 : : {
413 : : .procname = "sched_rt_runtime_us",
414 : : .data = &sysctl_sched_rt_runtime,
415 : : .maxlen = sizeof(int),
416 : : .mode = 0644,
417 : : .proc_handler = sched_rt_handler,
418 : : },
419 : : {
420 : : .procname = "sched_rr_timeslice_ms",
421 : : .data = &sched_rr_timeslice,
422 : : .maxlen = sizeof(int),
423 : : .mode = 0644,
424 : : .proc_handler = sched_rr_handler,
425 : : },
426 : : #ifdef CONFIG_SCHED_AUTOGROUP
427 : : {
428 : : .procname = "sched_autogroup_enabled",
429 : : .data = &sysctl_sched_autogroup_enabled,
430 : : .maxlen = sizeof(unsigned int),
431 : : .mode = 0644,
432 : : .proc_handler = proc_dointvec_minmax,
433 : : .extra1 = &zero,
434 : : .extra2 = &one,
435 : : },
436 : : #endif
437 : : #ifdef CONFIG_CFS_BANDWIDTH
438 : : {
439 : : .procname = "sched_cfs_bandwidth_slice_us",
440 : : .data = &sysctl_sched_cfs_bandwidth_slice,
441 : : .maxlen = sizeof(unsigned int),
442 : : .mode = 0644,
443 : : .proc_handler = proc_dointvec_minmax,
444 : : .extra1 = &one,
445 : : },
446 : : #endif
447 : : #ifdef CONFIG_PROVE_LOCKING
448 : : {
449 : : .procname = "prove_locking",
450 : : .data = &prove_locking,
451 : : .maxlen = sizeof(int),
452 : : .mode = 0644,
453 : : .proc_handler = proc_dointvec,
454 : : },
455 : : #endif
456 : : #ifdef CONFIG_LOCK_STAT
457 : : {
458 : : .procname = "lock_stat",
459 : : .data = &lock_stat,
460 : : .maxlen = sizeof(int),
461 : : .mode = 0644,
462 : : .proc_handler = proc_dointvec,
463 : : },
464 : : #endif
465 : : {
466 : : .procname = "panic",
467 : : .data = &panic_timeout,
468 : : .maxlen = sizeof(int),
469 : : .mode = 0644,
470 : : .proc_handler = proc_dointvec,
471 : : },
472 : : #ifdef CONFIG_COREDUMP
473 : : {
474 : : .procname = "core_uses_pid",
475 : : .data = &core_uses_pid,
476 : : .maxlen = sizeof(int),
477 : : .mode = 0644,
478 : : .proc_handler = proc_dointvec,
479 : : },
480 : : {
481 : : .procname = "core_pattern",
482 : : .data = core_pattern,
483 : : .maxlen = CORENAME_MAX_SIZE,
484 : : .mode = 0644,
485 : : .proc_handler = proc_dostring_coredump,
486 : : },
487 : : {
488 : : .procname = "core_pipe_limit",
489 : : .data = &core_pipe_limit,
490 : : .maxlen = sizeof(unsigned int),
491 : : .mode = 0644,
492 : : .proc_handler = proc_dointvec,
493 : : },
494 : : #endif
495 : : #ifdef CONFIG_PROC_SYSCTL
496 : : {
497 : : .procname = "tainted",
498 : : .maxlen = sizeof(long),
499 : : .mode = 0644,
500 : : .proc_handler = proc_taint,
501 : : },
502 : : #endif
503 : : #ifdef CONFIG_LATENCYTOP
504 : : {
505 : : .procname = "latencytop",
506 : : .data = &latencytop_enabled,
507 : : .maxlen = sizeof(int),
508 : : .mode = 0644,
509 : : .proc_handler = proc_dointvec,
510 : : },
511 : : #endif
512 : : #ifdef CONFIG_BLK_DEV_INITRD
513 : : {
514 : : .procname = "real-root-dev",
515 : : .data = &real_root_dev,
516 : : .maxlen = sizeof(int),
517 : : .mode = 0644,
518 : : .proc_handler = proc_dointvec,
519 : : },
520 : : #endif
521 : : {
522 : : .procname = "print-fatal-signals",
523 : : .data = &print_fatal_signals,
524 : : .maxlen = sizeof(int),
525 : : .mode = 0644,
526 : : .proc_handler = proc_dointvec,
527 : : },
528 : : #ifdef CONFIG_SPARC
529 : : {
530 : : .procname = "reboot-cmd",
531 : : .data = reboot_command,
532 : : .maxlen = 256,
533 : : .mode = 0644,
534 : : .proc_handler = proc_dostring,
535 : : },
536 : : {
537 : : .procname = "stop-a",
538 : : .data = &stop_a_enabled,
539 : : .maxlen = sizeof (int),
540 : : .mode = 0644,
541 : : .proc_handler = proc_dointvec,
542 : : },
543 : : {
544 : : .procname = "scons-poweroff",
545 : : .data = &scons_pwroff,
546 : : .maxlen = sizeof (int),
547 : : .mode = 0644,
548 : : .proc_handler = proc_dointvec,
549 : : },
550 : : #endif
551 : : #ifdef CONFIG_SPARC64
552 : : {
553 : : .procname = "tsb-ratio",
554 : : .data = &sysctl_tsb_ratio,
555 : : .maxlen = sizeof (int),
556 : : .mode = 0644,
557 : : .proc_handler = proc_dointvec,
558 : : },
559 : : #endif
560 : : #ifdef __hppa__
561 : : {
562 : : .procname = "soft-power",
563 : : .data = &pwrsw_enabled,
564 : : .maxlen = sizeof (int),
565 : : .mode = 0644,
566 : : .proc_handler = proc_dointvec,
567 : : },
568 : : #endif
569 : : #ifdef CONFIG_SYSCTL_ARCH_UNALIGN_ALLOW
570 : : {
571 : : .procname = "unaligned-trap",
572 : : .data = &unaligned_enabled,
573 : : .maxlen = sizeof (int),
574 : : .mode = 0644,
575 : : .proc_handler = proc_dointvec,
576 : : },
577 : : #endif
578 : : {
579 : : .procname = "ctrl-alt-del",
580 : : .data = &C_A_D,
581 : : .maxlen = sizeof(int),
582 : : .mode = 0644,
583 : : .proc_handler = proc_dointvec,
584 : : },
585 : : #ifdef CONFIG_FUNCTION_TRACER
586 : : {
587 : : .procname = "ftrace_enabled",
588 : : .data = &ftrace_enabled,
589 : : .maxlen = sizeof(int),
590 : : .mode = 0644,
591 : : .proc_handler = ftrace_enable_sysctl,
592 : : },
593 : : #endif
594 : : #ifdef CONFIG_STACK_TRACER
595 : : {
596 : : .procname = "stack_tracer_enabled",
597 : : .data = &stack_tracer_enabled,
598 : : .maxlen = sizeof(int),
599 : : .mode = 0644,
600 : : .proc_handler = stack_trace_sysctl,
601 : : },
602 : : #endif
603 : : #ifdef CONFIG_TRACING
604 : : {
605 : : .procname = "ftrace_dump_on_oops",
606 : : .data = &ftrace_dump_on_oops,
607 : : .maxlen = sizeof(int),
608 : : .mode = 0644,
609 : : .proc_handler = proc_dointvec,
610 : : },
611 : : {
612 : : .procname = "traceoff_on_warning",
613 : : .data = &__disable_trace_on_warning,
614 : : .maxlen = sizeof(__disable_trace_on_warning),
615 : : .mode = 0644,
616 : : .proc_handler = proc_dointvec,
617 : : },
618 : : #endif
619 : : #ifdef CONFIG_MODULES
620 : : {
621 : : .procname = "modprobe",
622 : : .data = &modprobe_path,
623 : : .maxlen = KMOD_PATH_LEN,
624 : : .mode = 0644,
625 : : .proc_handler = proc_dostring,
626 : : },
627 : : {
628 : : .procname = "modules_disabled",
629 : : .data = &modules_disabled,
630 : : .maxlen = sizeof(int),
631 : : .mode = 0644,
632 : : /* only handle a transition from default "0" to "1" */
633 : : .proc_handler = proc_dointvec_minmax,
634 : : .extra1 = &one,
635 : : .extra2 = &one,
636 : : },
637 : : #endif
638 : :
639 : : {
640 : : .procname = "hotplug",
641 : : .data = &uevent_helper,
642 : : .maxlen = UEVENT_HELPER_PATH_LEN,
643 : : .mode = 0644,
644 : : .proc_handler = proc_dostring,
645 : : },
646 : :
647 : : #ifdef CONFIG_CHR_DEV_SG
648 : : {
649 : : .procname = "sg-big-buff",
650 : : .data = &sg_big_buff,
651 : : .maxlen = sizeof (int),
652 : : .mode = 0444,
653 : : .proc_handler = proc_dointvec,
654 : : },
655 : : #endif
656 : : #ifdef CONFIG_BSD_PROCESS_ACCT
657 : : {
658 : : .procname = "acct",
659 : : .data = &acct_parm,
660 : : .maxlen = 3*sizeof(int),
661 : : .mode = 0644,
662 : : .proc_handler = proc_dointvec,
663 : : },
664 : : #endif
665 : : #ifdef CONFIG_MAGIC_SYSRQ
666 : : {
667 : : .procname = "sysrq",
668 : : .data = &__sysrq_enabled,
669 : : .maxlen = sizeof (int),
670 : : .mode = 0644,
671 : : .proc_handler = sysrq_sysctl_handler,
672 : : },
673 : : #endif
674 : : #ifdef CONFIG_PROC_SYSCTL
675 : : {
676 : : .procname = "cad_pid",
677 : : .data = NULL,
678 : : .maxlen = sizeof (int),
679 : : .mode = 0600,
680 : : .proc_handler = proc_do_cad_pid,
681 : : },
682 : : #endif
683 : : {
684 : : .procname = "threads-max",
685 : : .data = &max_threads,
686 : : .maxlen = sizeof(int),
687 : : .mode = 0644,
688 : : .proc_handler = proc_dointvec,
689 : : },
690 : : {
691 : : .procname = "random",
692 : : .mode = 0555,
693 : : .child = random_table,
694 : : },
695 : : {
696 : : .procname = "usermodehelper",
697 : : .mode = 0555,
698 : : .child = usermodehelper_table,
699 : : },
700 : : {
701 : : .procname = "overflowuid",
702 : : .data = &overflowuid,
703 : : .maxlen = sizeof(int),
704 : : .mode = 0644,
705 : : .proc_handler = proc_dointvec_minmax,
706 : : .extra1 = &minolduid,
707 : : .extra2 = &maxolduid,
708 : : },
709 : : {
710 : : .procname = "overflowgid",
711 : : .data = &overflowgid,
712 : : .maxlen = sizeof(int),
713 : : .mode = 0644,
714 : : .proc_handler = proc_dointvec_minmax,
715 : : .extra1 = &minolduid,
716 : : .extra2 = &maxolduid,
717 : : },
718 : : #ifdef CONFIG_S390
719 : : #ifdef CONFIG_MATHEMU
720 : : {
721 : : .procname = "ieee_emulation_warnings",
722 : : .data = &sysctl_ieee_emulation_warnings,
723 : : .maxlen = sizeof(int),
724 : : .mode = 0644,
725 : : .proc_handler = proc_dointvec,
726 : : },
727 : : #endif
728 : : {
729 : : .procname = "userprocess_debug",
730 : : .data = &show_unhandled_signals,
731 : : .maxlen = sizeof(int),
732 : : .mode = 0644,
733 : : .proc_handler = proc_dointvec,
734 : : },
735 : : #endif
736 : : {
737 : : .procname = "pid_max",
738 : : .data = &pid_max,
739 : : .maxlen = sizeof (int),
740 : : .mode = 0644,
741 : : .proc_handler = proc_dointvec_minmax,
742 : : .extra1 = &pid_max_min,
743 : : .extra2 = &pid_max_max,
744 : : },
745 : : {
746 : : .procname = "panic_on_oops",
747 : : .data = &panic_on_oops,
748 : : .maxlen = sizeof(int),
749 : : .mode = 0644,
750 : : .proc_handler = proc_dointvec,
751 : : },
752 : : #if defined CONFIG_PRINTK
753 : : {
754 : : .procname = "printk",
755 : : .data = &console_loglevel,
756 : : .maxlen = 4*sizeof(int),
757 : : .mode = 0644,
758 : : .proc_handler = proc_dointvec,
759 : : },
760 : : {
761 : : .procname = "printk_ratelimit",
762 : : .data = &printk_ratelimit_state.interval,
763 : : .maxlen = sizeof(int),
764 : : .mode = 0644,
765 : : .proc_handler = proc_dointvec_jiffies,
766 : : },
767 : : {
768 : : .procname = "printk_ratelimit_burst",
769 : : .data = &printk_ratelimit_state.burst,
770 : : .maxlen = sizeof(int),
771 : : .mode = 0644,
772 : : .proc_handler = proc_dointvec,
773 : : },
774 : : {
775 : : .procname = "printk_delay",
776 : : .data = &printk_delay_msec,
777 : : .maxlen = sizeof(int),
778 : : .mode = 0644,
779 : : .proc_handler = proc_dointvec_minmax,
780 : : .extra1 = &zero,
781 : : .extra2 = &ten_thousand,
782 : : },
783 : : {
784 : : .procname = "dmesg_restrict",
785 : : .data = &dmesg_restrict,
786 : : .maxlen = sizeof(int),
787 : : .mode = 0644,
788 : : .proc_handler = proc_dointvec_minmax_sysadmin,
789 : : .extra1 = &zero,
790 : : .extra2 = &one,
791 : : },
792 : : {
793 : : .procname = "kptr_restrict",
794 : : .data = &kptr_restrict,
795 : : .maxlen = sizeof(int),
796 : : .mode = 0644,
797 : : .proc_handler = proc_dointvec_minmax_sysadmin,
798 : : .extra1 = &zero,
799 : : .extra2 = &two,
800 : : },
801 : : #endif
802 : : {
803 : : .procname = "ngroups_max",
804 : : .data = &ngroups_max,
805 : : .maxlen = sizeof (int),
806 : : .mode = 0444,
807 : : .proc_handler = proc_dointvec,
808 : : },
809 : : {
810 : : .procname = "cap_last_cap",
811 : : .data = (void *)&cap_last_cap,
812 : : .maxlen = sizeof(int),
813 : : .mode = 0444,
814 : : .proc_handler = proc_dointvec,
815 : : },
816 : : #if defined(CONFIG_LOCKUP_DETECTOR)
817 : : {
818 : : .procname = "watchdog",
819 : : .data = &watchdog_user_enabled,
820 : : .maxlen = sizeof (int),
821 : : .mode = 0644,
822 : : .proc_handler = proc_dowatchdog,
823 : : .extra1 = &zero,
824 : : .extra2 = &one,
825 : : },
826 : : {
827 : : .procname = "watchdog_thresh",
828 : : .data = &watchdog_thresh,
829 : : .maxlen = sizeof(int),
830 : : .mode = 0644,
831 : : .proc_handler = proc_dowatchdog,
832 : : .extra1 = &zero,
833 : : .extra2 = &sixty,
834 : : },
835 : : {
836 : : .procname = "softlockup_panic",
837 : : .data = &softlockup_panic,
838 : : .maxlen = sizeof(int),
839 : : .mode = 0644,
840 : : .proc_handler = proc_dointvec_minmax,
841 : : .extra1 = &zero,
842 : : .extra2 = &one,
843 : : },
844 : : {
845 : : .procname = "nmi_watchdog",
846 : : .data = &watchdog_user_enabled,
847 : : .maxlen = sizeof (int),
848 : : .mode = 0644,
849 : : .proc_handler = proc_dowatchdog,
850 : : .extra1 = &zero,
851 : : .extra2 = &one,
852 : : },
853 : : #endif
854 : : #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
855 : : {
856 : : .procname = "unknown_nmi_panic",
857 : : .data = &unknown_nmi_panic,
858 : : .maxlen = sizeof (int),
859 : : .mode = 0644,
860 : : .proc_handler = proc_dointvec,
861 : : },
862 : : #endif
863 : : #if defined(CONFIG_X86)
864 : : {
865 : : .procname = "panic_on_unrecovered_nmi",
866 : : .data = &panic_on_unrecovered_nmi,
867 : : .maxlen = sizeof(int),
868 : : .mode = 0644,
869 : : .proc_handler = proc_dointvec,
870 : : },
871 : : {
872 : : .procname = "panic_on_io_nmi",
873 : : .data = &panic_on_io_nmi,
874 : : .maxlen = sizeof(int),
875 : : .mode = 0644,
876 : : .proc_handler = proc_dointvec,
877 : : },
878 : : #ifdef CONFIG_DEBUG_STACKOVERFLOW
879 : : {
880 : : .procname = "panic_on_stackoverflow",
881 : : .data = &sysctl_panic_on_stackoverflow,
882 : : .maxlen = sizeof(int),
883 : : .mode = 0644,
884 : : .proc_handler = proc_dointvec,
885 : : },
886 : : #endif
887 : : {
888 : : .procname = "bootloader_type",
889 : : .data = &bootloader_type,
890 : : .maxlen = sizeof (int),
891 : : .mode = 0444,
892 : : .proc_handler = proc_dointvec,
893 : : },
894 : : {
895 : : .procname = "bootloader_version",
896 : : .data = &bootloader_version,
897 : : .maxlen = sizeof (int),
898 : : .mode = 0444,
899 : : .proc_handler = proc_dointvec,
900 : : },
901 : : {
902 : : .procname = "kstack_depth_to_print",
903 : : .data = &kstack_depth_to_print,
904 : : .maxlen = sizeof(int),
905 : : .mode = 0644,
906 : : .proc_handler = proc_dointvec,
907 : : },
908 : : {
909 : : .procname = "io_delay_type",
910 : : .data = &io_delay_type,
911 : : .maxlen = sizeof(int),
912 : : .mode = 0644,
913 : : .proc_handler = proc_dointvec,
914 : : },
915 : : #endif
916 : : #if defined(CONFIG_MMU)
917 : : {
918 : : .procname = "randomize_va_space",
919 : : .data = &randomize_va_space,
920 : : .maxlen = sizeof(int),
921 : : .mode = 0644,
922 : : .proc_handler = proc_dointvec,
923 : : },
924 : : #endif
925 : : #if defined(CONFIG_S390) && defined(CONFIG_SMP)
926 : : {
927 : : .procname = "spin_retry",
928 : : .data = &spin_retry,
929 : : .maxlen = sizeof (int),
930 : : .mode = 0644,
931 : : .proc_handler = proc_dointvec,
932 : : },
933 : : #endif
934 : : #if defined(CONFIG_ACPI_SLEEP) && defined(CONFIG_X86)
935 : : {
936 : : .procname = "acpi_video_flags",
937 : : .data = &acpi_realmode_flags,
938 : : .maxlen = sizeof (unsigned long),
939 : : .mode = 0644,
940 : : .proc_handler = proc_doulongvec_minmax,
941 : : },
942 : : #endif
943 : : #ifdef CONFIG_SYSCTL_ARCH_UNALIGN_NO_WARN
944 : : {
945 : : .procname = "ignore-unaligned-usertrap",
946 : : .data = &no_unaligned_warning,
947 : : .maxlen = sizeof (int),
948 : : .mode = 0644,
949 : : .proc_handler = proc_dointvec,
950 : : },
951 : : #endif
952 : : #ifdef CONFIG_IA64
953 : : {
954 : : .procname = "unaligned-dump-stack",
955 : : .data = &unaligned_dump_stack,
956 : : .maxlen = sizeof (int),
957 : : .mode = 0644,
958 : : .proc_handler = proc_dointvec,
959 : : },
960 : : #endif
961 : : #ifdef CONFIG_DETECT_HUNG_TASK
962 : : {
963 : : .procname = "hung_task_panic",
964 : : .data = &sysctl_hung_task_panic,
965 : : .maxlen = sizeof(int),
966 : : .mode = 0644,
967 : : .proc_handler = proc_dointvec_minmax,
968 : : .extra1 = &zero,
969 : : .extra2 = &one,
970 : : },
971 : : {
972 : : .procname = "hung_task_check_count",
973 : : .data = &sysctl_hung_task_check_count,
974 : : .maxlen = sizeof(int),
975 : : .mode = 0644,
976 : : .proc_handler = proc_dointvec_minmax,
977 : : .extra1 = &zero,
978 : : },
979 : : {
980 : : .procname = "hung_task_timeout_secs",
981 : : .data = &sysctl_hung_task_timeout_secs,
982 : : .maxlen = sizeof(unsigned long),
983 : : .mode = 0644,
984 : : .proc_handler = proc_dohung_task_timeout_secs,
985 : : },
986 : : {
987 : : .procname = "hung_task_warnings",
988 : : .data = &sysctl_hung_task_warnings,
989 : : .maxlen = sizeof(unsigned long),
990 : : .mode = 0644,
991 : : .proc_handler = proc_doulongvec_minmax,
992 : : },
993 : : #endif
994 : : #ifdef CONFIG_COMPAT
995 : : {
996 : : .procname = "compat-log",
997 : : .data = &compat_log,
998 : : .maxlen = sizeof (int),
999 : : .mode = 0644,
1000 : : .proc_handler = proc_dointvec,
1001 : : },
1002 : : #endif
1003 : : #ifdef CONFIG_RT_MUTEXES
1004 : : {
1005 : : .procname = "max_lock_depth",
1006 : : .data = &max_lock_depth,
1007 : : .maxlen = sizeof(int),
1008 : : .mode = 0644,
1009 : : .proc_handler = proc_dointvec,
1010 : : },
1011 : : #endif
1012 : : {
1013 : : .procname = "poweroff_cmd",
1014 : : .data = &poweroff_cmd,
1015 : : .maxlen = POWEROFF_CMD_PATH_LEN,
1016 : : .mode = 0644,
1017 : : .proc_handler = proc_dostring,
1018 : : },
1019 : : #ifdef CONFIG_KEYS
1020 : : {
1021 : : .procname = "keys",
1022 : : .mode = 0555,
1023 : : .child = key_sysctls,
1024 : : },
1025 : : #endif
1026 : : #ifdef CONFIG_RCU_TORTURE_TEST
1027 : : {
1028 : : .procname = "rcutorture_runnable",
1029 : : .data = &rcutorture_runnable,
1030 : : .maxlen = sizeof(int),
1031 : : .mode = 0644,
1032 : : .proc_handler = proc_dointvec,
1033 : : },
1034 : : #endif
1035 : : #ifdef CONFIG_PERF_EVENTS
1036 : : /*
1037 : : * User-space scripts rely on the existence of this file
1038 : : * as a feature check for perf_events being enabled.
1039 : : *
1040 : : * So it's an ABI, do not remove!
1041 : : */
1042 : : {
1043 : : .procname = "perf_event_paranoid",
1044 : : .data = &sysctl_perf_event_paranoid,
1045 : : .maxlen = sizeof(sysctl_perf_event_paranoid),
1046 : : .mode = 0644,
1047 : : .proc_handler = proc_dointvec,
1048 : : },
1049 : : {
1050 : : .procname = "perf_event_mlock_kb",
1051 : : .data = &sysctl_perf_event_mlock,
1052 : : .maxlen = sizeof(sysctl_perf_event_mlock),
1053 : : .mode = 0644,
1054 : : .proc_handler = proc_dointvec,
1055 : : },
1056 : : {
1057 : : .procname = "perf_event_max_sample_rate",
1058 : : .data = &sysctl_perf_event_sample_rate,
1059 : : .maxlen = sizeof(sysctl_perf_event_sample_rate),
1060 : : .mode = 0644,
1061 : : .proc_handler = perf_proc_update_handler,
1062 : : .extra1 = &one,
1063 : : },
1064 : : {
1065 : : .procname = "perf_cpu_time_max_percent",
1066 : : .data = &sysctl_perf_cpu_time_max_percent,
1067 : : .maxlen = sizeof(sysctl_perf_cpu_time_max_percent),
1068 : : .mode = 0644,
1069 : : .proc_handler = perf_cpu_time_max_percent_handler,
1070 : : .extra1 = &zero,
1071 : : .extra2 = &one_hundred,
1072 : : },
1073 : : #endif
1074 : : #ifdef CONFIG_KMEMCHECK
1075 : : {
1076 : : .procname = "kmemcheck",
1077 : : .data = &kmemcheck_enabled,
1078 : : .maxlen = sizeof(int),
1079 : : .mode = 0644,
1080 : : .proc_handler = proc_dointvec,
1081 : : },
1082 : : #endif
1083 : : #ifdef CONFIG_BLOCK
1084 : : {
1085 : : .procname = "blk_iopoll",
1086 : : .data = &blk_iopoll_enabled,
1087 : : .maxlen = sizeof(int),
1088 : : .mode = 0644,
1089 : : .proc_handler = proc_dointvec,
1090 : : },
1091 : : #endif
1092 : : { }
1093 : : };
1094 : :
1095 : : static struct ctl_table vm_table[] = {
1096 : : {
1097 : : .procname = "overcommit_memory",
1098 : : .data = &sysctl_overcommit_memory,
1099 : : .maxlen = sizeof(sysctl_overcommit_memory),
1100 : : .mode = 0644,
1101 : : .proc_handler = proc_dointvec_minmax,
1102 : : .extra1 = &zero,
1103 : : .extra2 = &two,
1104 : : },
1105 : : {
1106 : : .procname = "panic_on_oom",
1107 : : .data = &sysctl_panic_on_oom,
1108 : : .maxlen = sizeof(sysctl_panic_on_oom),
1109 : : .mode = 0644,
1110 : : .proc_handler = proc_dointvec_minmax,
1111 : : .extra1 = &zero,
1112 : : .extra2 = &two,
1113 : : },
1114 : : {
1115 : : .procname = "oom_kill_allocating_task",
1116 : : .data = &sysctl_oom_kill_allocating_task,
1117 : : .maxlen = sizeof(sysctl_oom_kill_allocating_task),
1118 : : .mode = 0644,
1119 : : .proc_handler = proc_dointvec,
1120 : : },
1121 : : {
1122 : : .procname = "oom_dump_tasks",
1123 : : .data = &sysctl_oom_dump_tasks,
1124 : : .maxlen = sizeof(sysctl_oom_dump_tasks),
1125 : : .mode = 0644,
1126 : : .proc_handler = proc_dointvec,
1127 : : },
1128 : : {
1129 : : .procname = "overcommit_ratio",
1130 : : .data = &sysctl_overcommit_ratio,
1131 : : .maxlen = sizeof(sysctl_overcommit_ratio),
1132 : : .mode = 0644,
1133 : : .proc_handler = proc_dointvec,
1134 : : },
1135 : : {
1136 : : .procname = "page-cluster",
1137 : : .data = &page_cluster,
1138 : : .maxlen = sizeof(int),
1139 : : .mode = 0644,
1140 : : .proc_handler = proc_dointvec_minmax,
1141 : : .extra1 = &zero,
1142 : : },
1143 : : {
1144 : : .procname = "dirty_background_ratio",
1145 : : .data = &dirty_background_ratio,
1146 : : .maxlen = sizeof(dirty_background_ratio),
1147 : : .mode = 0644,
1148 : : .proc_handler = dirty_background_ratio_handler,
1149 : : .extra1 = &zero,
1150 : : .extra2 = &one_hundred,
1151 : : },
1152 : : {
1153 : : .procname = "dirty_background_bytes",
1154 : : .data = &dirty_background_bytes,
1155 : : .maxlen = sizeof(dirty_background_bytes),
1156 : : .mode = 0644,
1157 : : .proc_handler = dirty_background_bytes_handler,
1158 : : .extra1 = &one_ul,
1159 : : },
1160 : : {
1161 : : .procname = "dirty_ratio",
1162 : : .data = &vm_dirty_ratio,
1163 : : .maxlen = sizeof(vm_dirty_ratio),
1164 : : .mode = 0644,
1165 : : .proc_handler = dirty_ratio_handler,
1166 : : .extra1 = &zero,
1167 : : .extra2 = &one_hundred,
1168 : : },
1169 : : {
1170 : : .procname = "dirty_bytes",
1171 : : .data = &vm_dirty_bytes,
1172 : : .maxlen = sizeof(vm_dirty_bytes),
1173 : : .mode = 0644,
1174 : : .proc_handler = dirty_bytes_handler,
1175 : : .extra1 = &dirty_bytes_min,
1176 : : },
1177 : : {
1178 : : .procname = "dirty_writeback_centisecs",
1179 : : .data = &dirty_writeback_interval,
1180 : : .maxlen = sizeof(dirty_writeback_interval),
1181 : : .mode = 0644,
1182 : : .proc_handler = dirty_writeback_centisecs_handler,
1183 : : },
1184 : : {
1185 : : .procname = "dirty_expire_centisecs",
1186 : : .data = &dirty_expire_interval,
1187 : : .maxlen = sizeof(dirty_expire_interval),
1188 : : .mode = 0644,
1189 : : .proc_handler = proc_dointvec_minmax,
1190 : : .extra1 = &zero,
1191 : : },
1192 : : {
1193 : : .procname = "nr_pdflush_threads",
1194 : : .mode = 0444 /* read-only */,
1195 : : .proc_handler = pdflush_proc_obsolete,
1196 : : },
1197 : : {
1198 : : .procname = "swappiness",
1199 : : .data = &vm_swappiness,
1200 : : .maxlen = sizeof(vm_swappiness),
1201 : : .mode = 0644,
1202 : : .proc_handler = proc_dointvec_minmax,
1203 : : .extra1 = &zero,
1204 : : .extra2 = &one_hundred,
1205 : : },
1206 : : #ifdef CONFIG_HUGETLB_PAGE
1207 : : {
1208 : : .procname = "nr_hugepages",
1209 : : .data = NULL,
1210 : : .maxlen = sizeof(unsigned long),
1211 : : .mode = 0644,
1212 : : .proc_handler = hugetlb_sysctl_handler,
1213 : : .extra1 = (void *)&hugetlb_zero,
1214 : : .extra2 = (void *)&hugetlb_infinity,
1215 : : },
1216 : : #ifdef CONFIG_NUMA
1217 : : {
1218 : : .procname = "nr_hugepages_mempolicy",
1219 : : .data = NULL,
1220 : : .maxlen = sizeof(unsigned long),
1221 : : .mode = 0644,
1222 : : .proc_handler = &hugetlb_mempolicy_sysctl_handler,
1223 : : .extra1 = (void *)&hugetlb_zero,
1224 : : .extra2 = (void *)&hugetlb_infinity,
1225 : : },
1226 : : #endif
1227 : : {
1228 : : .procname = "hugetlb_shm_group",
1229 : : .data = &sysctl_hugetlb_shm_group,
1230 : : .maxlen = sizeof(gid_t),
1231 : : .mode = 0644,
1232 : : .proc_handler = proc_dointvec,
1233 : : },
1234 : : {
1235 : : .procname = "hugepages_treat_as_movable",
1236 : : .data = &hugepages_treat_as_movable,
1237 : : .maxlen = sizeof(int),
1238 : : .mode = 0644,
1239 : : .proc_handler = proc_dointvec,
1240 : : },
1241 : : {
1242 : : .procname = "nr_overcommit_hugepages",
1243 : : .data = NULL,
1244 : : .maxlen = sizeof(unsigned long),
1245 : : .mode = 0644,
1246 : : .proc_handler = hugetlb_overcommit_handler,
1247 : : .extra1 = (void *)&hugetlb_zero,
1248 : : .extra2 = (void *)&hugetlb_infinity,
1249 : : },
1250 : : #endif
1251 : : {
1252 : : .procname = "lowmem_reserve_ratio",
1253 : : .data = &sysctl_lowmem_reserve_ratio,
1254 : : .maxlen = sizeof(sysctl_lowmem_reserve_ratio),
1255 : : .mode = 0644,
1256 : : .proc_handler = lowmem_reserve_ratio_sysctl_handler,
1257 : : },
1258 : : {
1259 : : .procname = "drop_caches",
1260 : : .data = &sysctl_drop_caches,
1261 : : .maxlen = sizeof(int),
1262 : : .mode = 0644,
1263 : : .proc_handler = drop_caches_sysctl_handler,
1264 : : .extra1 = &one,
1265 : : .extra2 = &three,
1266 : : },
1267 : : #ifdef CONFIG_COMPACTION
1268 : : {
1269 : : .procname = "compact_memory",
1270 : : .data = &sysctl_compact_memory,
1271 : : .maxlen = sizeof(int),
1272 : : .mode = 0200,
1273 : : .proc_handler = sysctl_compaction_handler,
1274 : : },
1275 : : {
1276 : : .procname = "extfrag_threshold",
1277 : : .data = &sysctl_extfrag_threshold,
1278 : : .maxlen = sizeof(int),
1279 : : .mode = 0644,
1280 : : .proc_handler = sysctl_extfrag_handler,
1281 : : .extra1 = &min_extfrag_threshold,
1282 : : .extra2 = &max_extfrag_threshold,
1283 : : },
1284 : :
1285 : : #endif /* CONFIG_COMPACTION */
1286 : : {
1287 : : .procname = "min_free_kbytes",
1288 : : .data = &min_free_kbytes,
1289 : : .maxlen = sizeof(min_free_kbytes),
1290 : : .mode = 0644,
1291 : : .proc_handler = min_free_kbytes_sysctl_handler,
1292 : : .extra1 = &zero,
1293 : : },
1294 : : {
1295 : : .procname = "extra_free_kbytes",
1296 : : .data = &extra_free_kbytes,
1297 : : .maxlen = sizeof(extra_free_kbytes),
1298 : : .mode = 0644,
1299 : : .proc_handler = min_free_kbytes_sysctl_handler,
1300 : : .extra1 = &zero,
1301 : : },
1302 : : {
1303 : : .procname = "min_free_order_shift",
1304 : : .data = &min_free_order_shift,
1305 : : .maxlen = sizeof(min_free_order_shift),
1306 : : .mode = 0644,
1307 : : .proc_handler = &proc_dointvec
1308 : : },
1309 : : {
1310 : : .procname = "percpu_pagelist_fraction",
1311 : : .data = &percpu_pagelist_fraction,
1312 : : .maxlen = sizeof(percpu_pagelist_fraction),
1313 : : .mode = 0644,
1314 : : .proc_handler = percpu_pagelist_fraction_sysctl_handler,
1315 : : .extra1 = &min_percpu_pagelist_fract,
1316 : : },
1317 : : #ifdef CONFIG_MMU
1318 : : {
1319 : : .procname = "max_map_count",
1320 : : .data = &sysctl_max_map_count,
1321 : : .maxlen = sizeof(sysctl_max_map_count),
1322 : : .mode = 0644,
1323 : : .proc_handler = proc_dointvec_minmax,
1324 : : .extra1 = &zero,
1325 : : },
1326 : : #else
1327 : : {
1328 : : .procname = "nr_trim_pages",
1329 : : .data = &sysctl_nr_trim_pages,
1330 : : .maxlen = sizeof(sysctl_nr_trim_pages),
1331 : : .mode = 0644,
1332 : : .proc_handler = proc_dointvec_minmax,
1333 : : .extra1 = &zero,
1334 : : },
1335 : : #endif
1336 : : {
1337 : : .procname = "laptop_mode",
1338 : : .data = &laptop_mode,
1339 : : .maxlen = sizeof(laptop_mode),
1340 : : .mode = 0644,
1341 : : .proc_handler = proc_dointvec_jiffies,
1342 : : },
1343 : : {
1344 : : .procname = "block_dump",
1345 : : .data = &block_dump,
1346 : : .maxlen = sizeof(block_dump),
1347 : : .mode = 0644,
1348 : : .proc_handler = proc_dointvec,
1349 : : .extra1 = &zero,
1350 : : },
1351 : : {
1352 : : .procname = "vfs_cache_pressure",
1353 : : .data = &sysctl_vfs_cache_pressure,
1354 : : .maxlen = sizeof(sysctl_vfs_cache_pressure),
1355 : : .mode = 0644,
1356 : : .proc_handler = proc_dointvec,
1357 : : .extra1 = &zero,
1358 : : },
1359 : : #ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
1360 : : {
1361 : : .procname = "legacy_va_layout",
1362 : : .data = &sysctl_legacy_va_layout,
1363 : : .maxlen = sizeof(sysctl_legacy_va_layout),
1364 : : .mode = 0644,
1365 : : .proc_handler = proc_dointvec,
1366 : : .extra1 = &zero,
1367 : : },
1368 : : #endif
1369 : : #ifdef CONFIG_NUMA
1370 : : {
1371 : : .procname = "zone_reclaim_mode",
1372 : : .data = &zone_reclaim_mode,
1373 : : .maxlen = sizeof(zone_reclaim_mode),
1374 : : .mode = 0644,
1375 : : .proc_handler = proc_dointvec,
1376 : : .extra1 = &zero,
1377 : : },
1378 : : {
1379 : : .procname = "min_unmapped_ratio",
1380 : : .data = &sysctl_min_unmapped_ratio,
1381 : : .maxlen = sizeof(sysctl_min_unmapped_ratio),
1382 : : .mode = 0644,
1383 : : .proc_handler = sysctl_min_unmapped_ratio_sysctl_handler,
1384 : : .extra1 = &zero,
1385 : : .extra2 = &one_hundred,
1386 : : },
1387 : : {
1388 : : .procname = "min_slab_ratio",
1389 : : .data = &sysctl_min_slab_ratio,
1390 : : .maxlen = sizeof(sysctl_min_slab_ratio),
1391 : : .mode = 0644,
1392 : : .proc_handler = sysctl_min_slab_ratio_sysctl_handler,
1393 : : .extra1 = &zero,
1394 : : .extra2 = &one_hundred,
1395 : : },
1396 : : #endif
1397 : : #ifdef CONFIG_SMP
1398 : : {
1399 : : .procname = "stat_interval",
1400 : : .data = &sysctl_stat_interval,
1401 : : .maxlen = sizeof(sysctl_stat_interval),
1402 : : .mode = 0644,
1403 : : .proc_handler = proc_dointvec_jiffies,
1404 : : },
1405 : : #endif
1406 : : #ifdef CONFIG_MMU
1407 : : {
1408 : : .procname = "mmap_min_addr",
1409 : : .data = &dac_mmap_min_addr,
1410 : : .maxlen = sizeof(unsigned long),
1411 : : .mode = 0644,
1412 : : .proc_handler = mmap_min_addr_handler,
1413 : : },
1414 : : #endif
1415 : : #ifdef CONFIG_NUMA
1416 : : {
1417 : : .procname = "numa_zonelist_order",
1418 : : .data = &numa_zonelist_order,
1419 : : .maxlen = NUMA_ZONELIST_ORDER_LEN,
1420 : : .mode = 0644,
1421 : : .proc_handler = numa_zonelist_order_handler,
1422 : : },
1423 : : #endif
1424 : : #if (defined(CONFIG_X86_32) && !defined(CONFIG_UML))|| \
1425 : : (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL))
1426 : : {
1427 : : .procname = "vdso_enabled",
1428 : : .data = &vdso_enabled,
1429 : : .maxlen = sizeof(vdso_enabled),
1430 : : .mode = 0644,
1431 : : .proc_handler = proc_dointvec,
1432 : : .extra1 = &zero,
1433 : : },
1434 : : #endif
1435 : : #ifdef CONFIG_HIGHMEM
1436 : : {
1437 : : .procname = "highmem_is_dirtyable",
1438 : : .data = &vm_highmem_is_dirtyable,
1439 : : .maxlen = sizeof(vm_highmem_is_dirtyable),
1440 : : .mode = 0644,
1441 : : .proc_handler = proc_dointvec_minmax,
1442 : : .extra1 = &zero,
1443 : : .extra2 = &one,
1444 : : },
1445 : : #endif
1446 : : {
1447 : : .procname = "scan_unevictable_pages",
1448 : : .data = &scan_unevictable_pages,
1449 : : .maxlen = sizeof(scan_unevictable_pages),
1450 : : .mode = 0644,
1451 : : .proc_handler = scan_unevictable_handler,
1452 : : },
1453 : : #ifdef CONFIG_MEMORY_FAILURE
1454 : : {
1455 : : .procname = "memory_failure_early_kill",
1456 : : .data = &sysctl_memory_failure_early_kill,
1457 : : .maxlen = sizeof(sysctl_memory_failure_early_kill),
1458 : : .mode = 0644,
1459 : : .proc_handler = proc_dointvec_minmax,
1460 : : .extra1 = &zero,
1461 : : .extra2 = &one,
1462 : : },
1463 : : {
1464 : : .procname = "memory_failure_recovery",
1465 : : .data = &sysctl_memory_failure_recovery,
1466 : : .maxlen = sizeof(sysctl_memory_failure_recovery),
1467 : : .mode = 0644,
1468 : : .proc_handler = proc_dointvec_minmax,
1469 : : .extra1 = &zero,
1470 : : .extra2 = &one,
1471 : : },
1472 : : #endif
1473 : : {
1474 : : .procname = "user_reserve_kbytes",
1475 : : .data = &sysctl_user_reserve_kbytes,
1476 : : .maxlen = sizeof(sysctl_user_reserve_kbytes),
1477 : : .mode = 0644,
1478 : : .proc_handler = proc_doulongvec_minmax,
1479 : : },
1480 : : {
1481 : : .procname = "admin_reserve_kbytes",
1482 : : .data = &sysctl_admin_reserve_kbytes,
1483 : : .maxlen = sizeof(sysctl_admin_reserve_kbytes),
1484 : : .mode = 0644,
1485 : : .proc_handler = proc_doulongvec_minmax,
1486 : : },
1487 : : { }
1488 : : };
1489 : :
1490 : : #if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
1491 : : static struct ctl_table binfmt_misc_table[] = {
1492 : : { }
1493 : : };
1494 : : #endif
1495 : :
1496 : : static struct ctl_table fs_table[] = {
1497 : : {
1498 : : .procname = "inode-nr",
1499 : : .data = &inodes_stat,
1500 : : .maxlen = 2*sizeof(long),
1501 : : .mode = 0444,
1502 : : .proc_handler = proc_nr_inodes,
1503 : : },
1504 : : {
1505 : : .procname = "inode-state",
1506 : : .data = &inodes_stat,
1507 : : .maxlen = 7*sizeof(long),
1508 : : .mode = 0444,
1509 : : .proc_handler = proc_nr_inodes,
1510 : : },
1511 : : {
1512 : : .procname = "file-nr",
1513 : : .data = &files_stat,
1514 : : .maxlen = sizeof(files_stat),
1515 : : .mode = 0444,
1516 : : .proc_handler = proc_nr_files,
1517 : : },
1518 : : {
1519 : : .procname = "file-max",
1520 : : .data = &files_stat.max_files,
1521 : : .maxlen = sizeof(files_stat.max_files),
1522 : : .mode = 0644,
1523 : : .proc_handler = proc_doulongvec_minmax,
1524 : : },
1525 : : {
1526 : : .procname = "nr_open",
1527 : : .data = &sysctl_nr_open,
1528 : : .maxlen = sizeof(int),
1529 : : .mode = 0644,
1530 : : .proc_handler = proc_dointvec_minmax,
1531 : : .extra1 = &sysctl_nr_open_min,
1532 : : .extra2 = &sysctl_nr_open_max,
1533 : : },
1534 : : {
1535 : : .procname = "dentry-state",
1536 : : .data = &dentry_stat,
1537 : : .maxlen = 6*sizeof(long),
1538 : : .mode = 0444,
1539 : : .proc_handler = proc_nr_dentry,
1540 : : },
1541 : : {
1542 : : .procname = "overflowuid",
1543 : : .data = &fs_overflowuid,
1544 : : .maxlen = sizeof(int),
1545 : : .mode = 0644,
1546 : : .proc_handler = proc_dointvec_minmax,
1547 : : .extra1 = &minolduid,
1548 : : .extra2 = &maxolduid,
1549 : : },
1550 : : {
1551 : : .procname = "overflowgid",
1552 : : .data = &fs_overflowgid,
1553 : : .maxlen = sizeof(int),
1554 : : .mode = 0644,
1555 : : .proc_handler = proc_dointvec_minmax,
1556 : : .extra1 = &minolduid,
1557 : : .extra2 = &maxolduid,
1558 : : },
1559 : : #ifdef CONFIG_FILE_LOCKING
1560 : : {
1561 : : .procname = "leases-enable",
1562 : : .data = &leases_enable,
1563 : : .maxlen = sizeof(int),
1564 : : .mode = 0644,
1565 : : .proc_handler = proc_dointvec,
1566 : : },
1567 : : #endif
1568 : : #ifdef CONFIG_DNOTIFY
1569 : : {
1570 : : .procname = "dir-notify-enable",
1571 : : .data = &dir_notify_enable,
1572 : : .maxlen = sizeof(int),
1573 : : .mode = 0644,
1574 : : .proc_handler = proc_dointvec,
1575 : : },
1576 : : #endif
1577 : : #ifdef CONFIG_MMU
1578 : : #ifdef CONFIG_FILE_LOCKING
1579 : : {
1580 : : .procname = "lease-break-time",
1581 : : .data = &lease_break_time,
1582 : : .maxlen = sizeof(int),
1583 : : .mode = 0644,
1584 : : .proc_handler = proc_dointvec,
1585 : : },
1586 : : #endif
1587 : : #ifdef CONFIG_AIO
1588 : : {
1589 : : .procname = "aio-nr",
1590 : : .data = &aio_nr,
1591 : : .maxlen = sizeof(aio_nr),
1592 : : .mode = 0444,
1593 : : .proc_handler = proc_doulongvec_minmax,
1594 : : },
1595 : : {
1596 : : .procname = "aio-max-nr",
1597 : : .data = &aio_max_nr,
1598 : : .maxlen = sizeof(aio_max_nr),
1599 : : .mode = 0644,
1600 : : .proc_handler = proc_doulongvec_minmax,
1601 : : },
1602 : : #endif /* CONFIG_AIO */
1603 : : #ifdef CONFIG_INOTIFY_USER
1604 : : {
1605 : : .procname = "inotify",
1606 : : .mode = 0555,
1607 : : .child = inotify_table,
1608 : : },
1609 : : #endif
1610 : : #ifdef CONFIG_EPOLL
1611 : : {
1612 : : .procname = "epoll",
1613 : : .mode = 0555,
1614 : : .child = epoll_table,
1615 : : },
1616 : : #endif
1617 : : #endif
1618 : : {
1619 : : .procname = "protected_symlinks",
1620 : : .data = &sysctl_protected_symlinks,
1621 : : .maxlen = sizeof(int),
1622 : : .mode = 0600,
1623 : : .proc_handler = proc_dointvec_minmax,
1624 : : .extra1 = &zero,
1625 : : .extra2 = &one,
1626 : : },
1627 : : {
1628 : : .procname = "protected_hardlinks",
1629 : : .data = &sysctl_protected_hardlinks,
1630 : : .maxlen = sizeof(int),
1631 : : .mode = 0600,
1632 : : .proc_handler = proc_dointvec_minmax,
1633 : : .extra1 = &zero,
1634 : : .extra2 = &one,
1635 : : },
1636 : : {
1637 : : .procname = "suid_dumpable",
1638 : : .data = &suid_dumpable,
1639 : : .maxlen = sizeof(int),
1640 : : .mode = 0644,
1641 : : .proc_handler = proc_dointvec_minmax_coredump,
1642 : : .extra1 = &zero,
1643 : : .extra2 = &two,
1644 : : },
1645 : : #if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
1646 : : {
1647 : : .procname = "binfmt_misc",
1648 : : .mode = 0555,
1649 : : .child = binfmt_misc_table,
1650 : : },
1651 : : #endif
1652 : : {
1653 : : .procname = "pipe-max-size",
1654 : : .data = &pipe_max_size,
1655 : : .maxlen = sizeof(int),
1656 : : .mode = 0644,
1657 : : .proc_handler = &pipe_proc_fn,
1658 : : .extra1 = &pipe_min_size,
1659 : : },
1660 : : { }
1661 : : };
1662 : :
1663 : : static struct ctl_table debug_table[] = {
1664 : : #ifdef CONFIG_SYSCTL_EXCEPTION_TRACE
1665 : : {
1666 : : .procname = "exception-trace",
1667 : : .data = &show_unhandled_signals,
1668 : : .maxlen = sizeof(int),
1669 : : .mode = 0644,
1670 : : .proc_handler = proc_dointvec
1671 : : },
1672 : : #endif
1673 : : #if defined(CONFIG_OPTPROBES)
1674 : : {
1675 : : .procname = "kprobes-optimization",
1676 : : .data = &sysctl_kprobes_optimization,
1677 : : .maxlen = sizeof(int),
1678 : : .mode = 0644,
1679 : : .proc_handler = proc_kprobes_optimization_handler,
1680 : : .extra1 = &zero,
1681 : : .extra2 = &one,
1682 : : },
1683 : : #endif
1684 : : { }
1685 : : };
1686 : :
1687 : : static struct ctl_table dev_table[] = {
1688 : : { }
1689 : : };
1690 : :
1691 : 0 : int __init sysctl_init(void)
1692 : : {
1693 : : struct ctl_table_header *hdr;
1694 : :
1695 : 0 : hdr = register_sysctl_table(sysctl_base_table);
1696 : : kmemleak_not_leak(hdr);
1697 : 0 : return 0;
1698 : : }
1699 : :
1700 : : #endif /* CONFIG_SYSCTL */
1701 : :
1702 : : /*
1703 : : * /proc/sys support
1704 : : */
1705 : :
1706 : : #ifdef CONFIG_PROC_SYSCTL
1707 : :
1708 : 0 : static int _proc_do_string(void* data, int maxlen, int write,
1709 : : void __user *buffer,
1710 : : size_t *lenp, loff_t *ppos)
1711 : : {
1712 : : size_t len;
1713 : : char __user *p;
1714 : : char c;
1715 : :
1716 [ + - ][ - + ]: 76 : if (!data || !maxlen || !*lenp) {
1717 : 0 : *lenp = 0;
1718 : 0 : return 0;
1719 : : }
1720 : :
1721 [ - + ]: 76 : if (write) {
1722 : : len = 0;
1723 : : p = buffer;
1724 [ # # ]: 0 : while (len < *lenp) {
1725 [ # # ]: 0 : if (get_user(c, p++))
1726 : : return -EFAULT;
1727 [ # # ]: 0 : if (c == 0 || c == '\n')
1728 : : break;
1729 : 0 : len++;
1730 : : }
1731 [ # # ]: 0 : if (len >= maxlen)
1732 : 0 : len = maxlen-1;
1733 [ # # ]: 0 : if(copy_from_user(data, buffer, len))
1734 : : return -EFAULT;
1735 : 0 : ((char *) data)[len] = 0;
1736 : 0 : *ppos += *lenp;
1737 : : } else {
1738 : 76 : len = strlen(data);
1739 [ - + ]: 76 : if (len > maxlen)
1740 : : len = maxlen;
1741 : :
1742 [ + + ]: 76 : if (*ppos > len) {
1743 : 38 : *lenp = 0;
1744 : 38 : return 0;
1745 : : }
1746 : :
1747 : 38 : data += *ppos;
1748 : 38 : len -= *ppos;
1749 : :
1750 [ - + ]: 38 : if (len > *lenp)
1751 : : len = *lenp;
1752 [ + - ]: 38 : if (len)
1753 [ + - ]: 114 : if(copy_to_user(buffer, data, len))
1754 : : return -EFAULT;
1755 [ + - ]: 38 : if (len < *lenp) {
1756 [ + - ]: 38 : if(put_user('\n', ((char __user *) buffer) + len))
1757 : : return -EFAULT;
1758 : 38 : len++;
1759 : : }
1760 : 38 : *lenp = len;
1761 : 38 : *ppos += len;
1762 : : }
1763 : : return 0;
1764 : : }
1765 : :
1766 : : /**
1767 : : * proc_dostring - read a string sysctl
1768 : : * @table: the sysctl table
1769 : : * @write: %TRUE if this is a write to the sysctl file
1770 : : * @buffer: the user buffer
1771 : : * @lenp: the size of the user buffer
1772 : : * @ppos: file position
1773 : : *
1774 : : * Reads/writes a string from/to the user buffer. If the kernel
1775 : : * buffer provided is not large enough to hold the string, the
1776 : : * string is truncated. The copied string is %NULL-terminated.
1777 : : * If the string is being read by the user process, it is copied
1778 : : * and a newline '\n' is added. It is truncated if the buffer is
1779 : : * not large enough.
1780 : : *
1781 : : * Returns 0 on success.
1782 : : */
1783 : 0 : int proc_dostring(struct ctl_table *table, int write,
1784 : : void __user *buffer, size_t *lenp, loff_t *ppos)
1785 : : {
1786 : 76 : return _proc_do_string(table->data, table->maxlen, write,
1787 : : buffer, lenp, ppos);
1788 : : }
1789 : :
1790 : : static size_t proc_skip_spaces(char **buf)
1791 : : {
1792 : : size_t ret;
1793 : 81 : char *tmp = skip_spaces(*buf);
1794 : 81 : ret = tmp - *buf;
1795 : 81 : *buf = tmp;
1796 : : return ret;
1797 : : }
1798 : :
1799 : : static void proc_skip_char(char **buf, size_t *size, const char v)
1800 : : {
1801 [ # # ][ # # ]: 0 : while (*size) {
1802 [ # # ][ # # ]: 0 : if (**buf != v)
1803 : : break;
1804 : 0 : (*size)--;
1805 : 0 : (*buf)++;
1806 : : }
1807 : : }
1808 : :
1809 : : #define TMPBUFLEN 22
1810 : : /**
1811 : : * proc_get_long - reads an ASCII formatted integer from a user buffer
1812 : : *
1813 : : * @buf: a kernel buffer
1814 : : * @size: size of the kernel buffer
1815 : : * @val: this is where the number will be stored
1816 : : * @neg: set to %TRUE if number is negative
1817 : : * @perm_tr: a vector which contains the allowed trailers
1818 : : * @perm_tr_len: size of the perm_tr vector
1819 : : * @tr: pointer to store the trailer character
1820 : : *
1821 : : * In case of success %0 is returned and @buf and @size are updated with
1822 : : * the amount of bytes read. If @tr is non-NULL and a trailing
1823 : : * character exists (size is non-zero after returning from this
1824 : : * function), @tr is updated with the trailing character.
1825 : : */
1826 : 0 : static int proc_get_long(char **buf, size_t *size,
1827 : : unsigned long *val, bool *neg,
1828 : : const char *perm_tr, unsigned perm_tr_len, char *tr)
1829 : : {
1830 : : int len;
1831 : : char *p, tmp[TMPBUFLEN];
1832 : :
1833 [ + ]: 81 : if (!*size)
1834 : : return -EINVAL;
1835 : :
1836 : 81 : len = *size;
1837 [ - + ]: 162 : if (len > TMPBUFLEN - 1)
1838 : : len = TMPBUFLEN - 1;
1839 : :
1840 : 81 : memcpy(tmp, *buf, len);
1841 : :
1842 : 81 : tmp[len] = 0;
1843 : 81 : p = tmp;
1844 [ - + ][ # # ]: 81 : if (*p == '-' && *size > 1) {
1845 : 0 : *neg = true;
1846 : 0 : p++;
1847 : : } else
1848 : 81 : *neg = false;
1849 [ + - ]: 81 : if (!isdigit(*p))
1850 : : return -EINVAL;
1851 : :
1852 : 81 : *val = simple_strtoul(p, &p, 0);
1853 : :
1854 : 81 : len = p - tmp;
1855 : :
1856 : : /* We don't know if the next char is whitespace thus we may accept
1857 : : * invalid integers (e.g. 1234...a) or two integers instead of one
1858 : : * (e.g. 123...1). So lets not allow such large numbers. */
1859 [ + - ]: 81 : if (len == TMPBUFLEN - 1)
1860 : : return -EINVAL;
1861 : :
1862 [ - + ][ # # ]: 81 : if (len < *size && perm_tr_len && !memchr(perm_tr, *p, perm_tr_len))
[ # # ]
1863 : : return -EINVAL;
1864 : :
1865 [ - + ][ # # ]: 81 : if (tr && (len < *size))
1866 : 0 : *tr = *p;
1867 : :
1868 : 81 : *buf += len;
1869 : 81 : *size -= len;
1870 : :
1871 : 81 : return 0;
1872 : : }
1873 : :
1874 : : /**
1875 : : * proc_put_long - converts an integer to a decimal ASCII formatted string
1876 : : *
1877 : : * @buf: the user buffer
1878 : : * @size: the size of the user buffer
1879 : : * @val: the integer to be converted
1880 : : * @neg: sign of the number, %TRUE for negative
1881 : : *
1882 : : * In case of success %0 is returned and @buf and @size are updated with
1883 : : * the amount of bytes written.
1884 : : */
1885 : 0 : static int proc_put_long(void __user **buf, size_t *size, unsigned long val,
1886 : : bool neg)
1887 : : {
1888 : : int len;
1889 : : char tmp[TMPBUFLEN], *p = tmp;
1890 : :
1891 [ + + ]: 1542 : sprintf(p, "%s%lu", neg ? "-" : "", val);
1892 : 1542 : len = strlen(tmp);
1893 [ - + ]: 1542 : if (len > *size)
1894 : 0 : len = *size;
1895 [ + - ]: 1542 : if (copy_to_user(*buf, tmp, len))
1896 : : return -EFAULT;
1897 : 1542 : *size -= len;
1898 : 1542 : *buf += len;
1899 : 1542 : return 0;
1900 : : }
1901 : : #undef TMPBUFLEN
1902 : :
1903 : 0 : static int proc_put_char(void __user **buf, size_t *size, char c)
1904 : : {
1905 [ + - ]: 1537 : if (*size) {
1906 : : char __user **buffer = (char __user **)buf;
1907 [ + - ]: 1537 : if (put_user(c, *buffer))
1908 : : return -EFAULT;
1909 : 1537 : (*size)--, (*buffer)++;
1910 : : *buf = *buffer;
1911 : : }
1912 : : return 0;
1913 : : }
1914 : :
1915 : 0 : static int do_proc_dointvec_conv(bool *negp, unsigned long *lvalp,
1916 : : int *valp,
1917 : : int write, void *data)
1918 : : {
1919 [ + + ]: 769 : if (write) {
1920 [ - + ]: 10 : *valp = *negp ? -*lvalp : *lvalp;
1921 : : } else {
1922 : 759 : int val = *valp;
1923 [ + + ]: 759 : if (val < 0) {
1924 : 6 : *negp = true;
1925 : 6 : *lvalp = (unsigned long)-val;
1926 : : } else {
1927 : 753 : *negp = false;
1928 : 753 : *lvalp = (unsigned long)val;
1929 : : }
1930 : : }
1931 : 769 : return 0;
1932 : : }
1933 : :
1934 : : static const char proc_wspace_sep[] = { ' ', '\t', '\n' };
1935 : :
1936 : 2298 : static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
1937 : : int write, void __user *buffer,
1938 : : size_t *lenp, loff_t *ppos,
1939 : : int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
1940 : : int write, void *data),
1941 : : void *data)
1942 : : {
1943 : : int *i, vleft, first = 1, err = 0;
1944 : : unsigned long page = 0;
1945 : : size_t left;
1946 : : char *kbuf;
1947 : :
1948 [ + - ][ + - ]: 2298 : if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
[ + - ][ + + ]
[ + - ]
1949 : 757 : *lenp = 0;
1950 : : return 0;
1951 : : }
1952 : :
1953 : : i = (int *) tbl_data;
1954 : 1541 : vleft = table->maxlen / sizeof(*i);
1955 : 1541 : left = *lenp;
1956 : :
1957 [ + + ]: 1541 : if (!conv)
1958 : : conv = do_proc_dointvec_conv;
1959 : :
1960 [ + + ]: 1541 : if (write) {
1961 [ - + ]: 81 : if (left > PAGE_SIZE - 1)
1962 : 0 : left = PAGE_SIZE - 1;
1963 : 81 : page = __get_free_page(GFP_TEMPORARY);
1964 : 81 : kbuf = (char *) page;
1965 [ + - ]: 81 : if (!kbuf)
1966 : : return -ENOMEM;
1967 [ + + ]: 2379 : if (copy_from_user(kbuf, buffer, left)) {
1968 : : err = -EFAULT;
1969 : : goto free;
1970 : : }
1971 : 1541 : kbuf[left] = 0;
1972 : : }
1973 : :
1974 [ + + ][ + + ]: 3100 : for (; left && vleft--; i++, first=0) {
1975 : : unsigned long lval;
1976 : : bool neg;
1977 : :
1978 [ + + ]: 1559 : if (write) {
1979 : 81 : left -= proc_skip_spaces(&kbuf);
1980 : :
1981 [ + - ]: 81 : if (!left)
1982 : : break;
1983 : 81 : err = proc_get_long(&kbuf, &left, &lval, &neg,
1984 : : proc_wspace_sep,
1985 : : sizeof(proc_wspace_sep), NULL);
1986 [ + - ]: 81 : if (err)
1987 : : break;
1988 [ + - ]: 81 : if (conv(&neg, &lval, i, 1, data)) {
1989 : : err = -EINVAL;
1990 : : break;
1991 : : }
1992 : : } else {
1993 [ + - ]: 1478 : if (conv(&neg, &lval, i, 0, data)) {
1994 : : err = -EINVAL;
1995 : : break;
1996 : : }
1997 [ + + ]: 1478 : if (!first)
1998 : 18 : err = proc_put_char(&buffer, &left, '\t');
1999 [ + - ]: 1478 : if (err)
2000 : : break;
2001 : 1478 : err = proc_put_long(&buffer, &left, lval, neg);
2002 [ + - ]: 1478 : if (err)
2003 : : break;
2004 : : }
2005 : : }
2006 : :
2007 [ + + ][ + + ]: 1541 : if (!write && !first && left && !err)
[ + - ]
2008 : 1454 : err = proc_put_char(&buffer, &left, '\n');
2009 [ + + ][ - + ]: 1541 : if (write && !err && left)
2010 : 0 : left -= proc_skip_spaces(&kbuf);
2011 : : free:
2012 [ + + ]: 3839 : if (write) {
2013 : 81 : free_page(page);
2014 [ - + ]: 81 : if (first)
2015 [ # # ]: 0 : return err ? : -EINVAL;
2016 : : }
2017 : 1541 : *lenp -= left;
2018 : 1541 : *ppos += *lenp;
2019 : : return err;
2020 : : }
2021 : :
2022 : : static int do_proc_dointvec(struct ctl_table *table, int write,
2023 : : void __user *buffer, size_t *lenp, loff_t *ppos,
2024 : : int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
2025 : : int write, void *data),
2026 : : void *data)
2027 : : {
2028 : 2296 : return __do_proc_dointvec(table->data, table, write,
2029 : : buffer, lenp, ppos, conv, data);
2030 : : }
2031 : :
2032 : : /**
2033 : : * proc_dointvec - read a vector of integers
2034 : : * @table: the sysctl table
2035 : : * @write: %TRUE if this is a write to the sysctl file
2036 : : * @buffer: the user buffer
2037 : : * @lenp: the size of the user buffer
2038 : : * @ppos: file position
2039 : : *
2040 : : * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
2041 : : * values from/to the user buffer, treated as an ASCII string.
2042 : : *
2043 : : * Returns 0 on success.
2044 : : */
2045 : 0 : int proc_dointvec(struct ctl_table *table, int write,
2046 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2047 : : {
2048 : 1174 : return do_proc_dointvec(table,write,buffer,lenp,ppos,
2049 : : NULL,NULL);
2050 : : }
2051 : :
2052 : : /*
2053 : : * Taint values can only be increased
2054 : : * This means we can safely use a temporary.
2055 : : */
2056 : 0 : static int proc_taint(struct ctl_table *table, int write,
2057 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2058 : : {
2059 : : struct ctl_table t;
2060 : 2 : unsigned long tmptaint = get_taint();
2061 : : int err;
2062 : :
2063 [ - + ][ # # ]: 2 : if (write && !capable(CAP_SYS_ADMIN))
2064 : : return -EPERM;
2065 : :
2066 : 2 : t = *table;
2067 : 2 : t.data = &tmptaint;
2068 : : err = proc_doulongvec_minmax(&t, write, buffer, lenp, ppos);
2069 [ + - ]: 2 : if (err < 0)
2070 : : return err;
2071 : :
2072 [ - + ]: 2 : if (write) {
2073 : : /*
2074 : : * Poor man's atomic or. Not worth adding a primitive
2075 : : * to everyone's atomic.h for this
2076 : : */
2077 : : int i;
2078 [ # # ][ # # ]: 0 : for (i = 0; i < BITS_PER_LONG && tmptaint >> i; i++) {
2079 [ # # ]: 0 : if ((tmptaint >> i) & 1)
2080 : 0 : add_taint(i, LOCKDEP_STILL_OK);
2081 : : }
2082 : : }
2083 : :
2084 : 2 : return err;
2085 : : }
2086 : :
2087 : : #ifdef CONFIG_PRINTK
2088 : 0 : static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
2089 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2090 : : {
2091 [ - + ][ # # ]: 4 : if (write && !capable(CAP_SYS_ADMIN))
2092 : : return -EPERM;
2093 : :
2094 : 4 : return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
2095 : : }
2096 : : #endif
2097 : :
2098 : : struct do_proc_dointvec_minmax_conv_param {
2099 : : int *min;
2100 : : int *max;
2101 : : };
2102 : :
2103 : 0 : static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp,
2104 : : int *valp,
2105 : : int write, void *data)
2106 : : {
2107 : : struct do_proc_dointvec_minmax_conv_param *param = data;
2108 [ + + ]: 673 : if (write) {
2109 [ - + ]: 71 : int val = *negp ? -*lvalp : *lvalp;
2110 [ + - ][ + ]: 71 : if ((param->min && *param->min > val) ||
[ + + ]
2111 [ + - ]: 10 : (param->max && *param->max < val))
2112 : : return -EINVAL;
2113 : 71 : *valp = val;
2114 : : } else {
2115 : 602 : int val = *valp;
2116 [ - + ]: 602 : if (val < 0) {
2117 : 0 : *negp = true;
2118 : 0 : *lvalp = (unsigned long)-val;
2119 : : } else {
2120 : 602 : *negp = false;
2121 : 602 : *lvalp = (unsigned long)val;
2122 : : }
2123 : : }
2124 : : return 0;
2125 : : }
2126 : :
2127 : : /**
2128 : : * proc_dointvec_minmax - read a vector of integers with min/max values
2129 : : * @table: the sysctl table
2130 : : * @write: %TRUE if this is a write to the sysctl file
2131 : : * @buffer: the user buffer
2132 : : * @lenp: the size of the user buffer
2133 : : * @ppos: file position
2134 : : *
2135 : : * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
2136 : : * values from/to the user buffer, treated as an ASCII string.
2137 : : *
2138 : : * This routine will ensure the values are within the range specified by
2139 : : * table->extra1 (min) and table->extra2 (max).
2140 : : *
2141 : : * Returns 0 on success.
2142 : : */
2143 : 0 : int proc_dointvec_minmax(struct ctl_table *table, int write,
2144 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2145 : : {
2146 : 1772 : struct do_proc_dointvec_minmax_conv_param param = {
2147 : 886 : .min = (int *) table->extra1,
2148 : 886 : .max = (int *) table->extra2,
2149 : : };
2150 : 886 : return do_proc_dointvec(table, write, buffer, lenp, ppos,
2151 : : do_proc_dointvec_minmax_conv, ¶m);
2152 : : }
2153 : :
2154 : 0 : static void validate_coredump_safety(void)
2155 : : {
2156 : : #ifdef CONFIG_COREDUMP
2157 [ - + ][ # # ]: 4 : if (suid_dumpable == SUID_DUMP_ROOT &&
2158 [ # # ]: 0 : core_pattern[0] != '/' && core_pattern[0] != '|') {
2159 : 0 : printk(KERN_WARNING "Unsafe core_pattern used with "\
2160 : : "suid_dumpable=2. Pipe handler or fully qualified "\
2161 : : "core dump path required.\n");
2162 : : }
2163 : : #endif
2164 : 0 : }
2165 : :
2166 : 0 : static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write,
2167 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2168 : : {
2169 : 2 : int error = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
2170 [ + - ]: 2 : if (!error)
2171 : 2 : validate_coredump_safety();
2172 : 0 : return error;
2173 : : }
2174 : :
2175 : : #ifdef CONFIG_COREDUMP
2176 : 0 : static int proc_dostring_coredump(struct ctl_table *table, int write,
2177 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2178 : : {
2179 : : int error = proc_dostring(table, write, buffer, lenp, ppos);
2180 [ + - ]: 2 : if (!error)
2181 : 2 : validate_coredump_safety();
2182 : 0 : return error;
2183 : : }
2184 : : #endif
2185 : :
2186 : 0 : static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int write,
2187 : : void __user *buffer,
2188 : : size_t *lenp, loff_t *ppos,
2189 : : unsigned long convmul,
2190 : : unsigned long convdiv)
2191 : : {
2192 : : unsigned long *i, *min, *max;
2193 : : int vleft, first = 1, err = 0;
2194 : : unsigned long page = 0;
2195 : : size_t left;
2196 : : char *kbuf;
2197 : :
2198 [ + - ][ + - ]: 87 : if (!data || !table->maxlen || !*lenp || (*ppos && !write)) {
[ + - ][ + + ]
[ + - ]
2199 : 43 : *lenp = 0;
2200 : 43 : return 0;
2201 : : }
2202 : :
2203 : : i = (unsigned long *) data;
2204 : 44 : min = (unsigned long *) table->extra1;
2205 : 44 : max = (unsigned long *) table->extra2;
2206 : 44 : vleft = table->maxlen / sizeof(unsigned long);
2207 : 44 : left = *lenp;
2208 : :
2209 [ - + ]: 44 : if (write) {
2210 [ # # ]: 0 : if (left > PAGE_SIZE - 1)
2211 : 0 : left = PAGE_SIZE - 1;
2212 : 0 : page = __get_free_page(GFP_TEMPORARY);
2213 : 0 : kbuf = (char *) page;
2214 [ # # ]: 0 : if (!kbuf)
2215 : : return -ENOMEM;
2216 [ # # ]: 0 : if (copy_from_user(kbuf, buffer, left)) {
2217 : : err = -EFAULT;
2218 : : goto free;
2219 : : }
2220 : 44 : kbuf[left] = 0;
2221 : : }
2222 : :
2223 [ + - ][ + + ]: 108 : for (; left && vleft--; i++, first = 0) {
2224 : : unsigned long val;
2225 : :
2226 [ - + ]: 64 : if (write) {
2227 : : bool neg;
2228 : :
2229 : 0 : left -= proc_skip_spaces(&kbuf);
2230 : :
2231 : 0 : err = proc_get_long(&kbuf, &left, &val, &neg,
2232 : : proc_wspace_sep,
2233 : : sizeof(proc_wspace_sep), NULL);
2234 [ # # ]: 87 : if (err)
2235 : : break;
2236 [ # # ]: 0 : if (neg)
2237 : 0 : continue;
2238 [ # # ][ # # ]: 0 : if ((min && val < *min) || (max && val > *max))
[ # # ][ # # ]
2239 : 0 : continue;
2240 : 0 : *i = val;
2241 : : } else {
2242 : 64 : val = convdiv * (*i) / convmul;
2243 [ + + ]: 64 : if (!first) {
2244 : 20 : err = proc_put_char(&buffer, &left, '\t');
2245 [ + - ]: 20 : if (err)
2246 : : break;
2247 : : }
2248 : 64 : err = proc_put_long(&buffer, &left, val, false);
2249 [ + - ]: 64 : if (err)
2250 : : break;
2251 : : }
2252 : : }
2253 : :
2254 [ + - ][ + - ]: 44 : if (!write && !first && left && !err)
[ + - ]
2255 : 44 : err = proc_put_char(&buffer, &left, '\n');
2256 [ - + ]: 44 : if (write && !err)
2257 : 0 : left -= proc_skip_spaces(&kbuf);
2258 : : free:
2259 [ - + ]: 44 : if (write) {
2260 : 0 : free_page(page);
2261 [ # # ]: 0 : if (first)
2262 [ # # ]: 0 : return err ? : -EINVAL;
2263 : : }
2264 : 44 : *lenp -= left;
2265 : 44 : *ppos += *lenp;
2266 : 44 : return err;
2267 : : }
2268 : :
2269 : : static int do_proc_doulongvec_minmax(struct ctl_table *table, int write,
2270 : : void __user *buffer,
2271 : : size_t *lenp, loff_t *ppos,
2272 : : unsigned long convmul,
2273 : : unsigned long convdiv)
2274 : : {
2275 : 87 : return __do_proc_doulongvec_minmax(table->data, table, write,
2276 : : buffer, lenp, ppos, convmul, convdiv);
2277 : : }
2278 : :
2279 : : /**
2280 : : * proc_doulongvec_minmax - read a vector of long integers with min/max values
2281 : : * @table: the sysctl table
2282 : : * @write: %TRUE if this is a write to the sysctl file
2283 : : * @buffer: the user buffer
2284 : : * @lenp: the size of the user buffer
2285 : : * @ppos: file position
2286 : : *
2287 : : * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
2288 : : * values from/to the user buffer, treated as an ASCII string.
2289 : : *
2290 : : * This routine will ensure the values are within the range specified by
2291 : : * table->extra1 (min) and table->extra2 (max).
2292 : : *
2293 : : * Returns 0 on success.
2294 : : */
2295 : 0 : int proc_doulongvec_minmax(struct ctl_table *table, int write,
2296 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2297 : : {
2298 : 85 : return do_proc_doulongvec_minmax(table, write, buffer, lenp, ppos, 1l, 1l);
2299 : : }
2300 : :
2301 : : /**
2302 : : * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values
2303 : : * @table: the sysctl table
2304 : : * @write: %TRUE if this is a write to the sysctl file
2305 : : * @buffer: the user buffer
2306 : : * @lenp: the size of the user buffer
2307 : : * @ppos: file position
2308 : : *
2309 : : * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
2310 : : * values from/to the user buffer, treated as an ASCII string. The values
2311 : : * are treated as milliseconds, and converted to jiffies when they are stored.
2312 : : *
2313 : : * This routine will ensure the values are within the range specified by
2314 : : * table->extra1 (min) and table->extra2 (max).
2315 : : *
2316 : : * Returns 0 on success.
2317 : : */
2318 : 0 : int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
2319 : : void __user *buffer,
2320 : : size_t *lenp, loff_t *ppos)
2321 : : {
2322 : 0 : return do_proc_doulongvec_minmax(table, write, buffer,
2323 : : lenp, ppos, HZ, 1000l);
2324 : : }
2325 : :
2326 : :
2327 : 0 : static int do_proc_dointvec_jiffies_conv(bool *negp, unsigned long *lvalp,
2328 : : int *valp,
2329 : : int write, void *data)
2330 : : {
2331 [ - + ]: 59 : if (write) {
2332 [ # # ]: 0 : if (*lvalp > LONG_MAX / HZ)
2333 : : return 1;
2334 [ # # ]: 59 : *valp = *negp ? -(*lvalp*HZ) : (*lvalp*HZ);
2335 : : } else {
2336 : 59 : int val = *valp;
2337 : : unsigned long lval;
2338 [ - + ]: 59 : if (val < 0) {
2339 : 0 : *negp = true;
2340 : 0 : lval = (unsigned long)-val;
2341 : : } else {
2342 : 59 : *negp = false;
2343 : 59 : lval = (unsigned long)val;
2344 : : }
2345 : 59 : *lvalp = lval / HZ;
2346 : : }
2347 : : return 0;
2348 : : }
2349 : :
2350 : 0 : static int do_proc_dointvec_userhz_jiffies_conv(bool *negp, unsigned long *lvalp,
2351 : : int *valp,
2352 : : int write, void *data)
2353 : : {
2354 [ - + ]: 28 : if (write) {
2355 : : if (USER_HZ < HZ && *lvalp > (LONG_MAX / HZ) * USER_HZ)
2356 : : return 1;
2357 [ # # ]: 0 : *valp = clock_t_to_jiffies(*negp ? -*lvalp : *lvalp);
2358 : : } else {
2359 : 28 : int val = *valp;
2360 : : unsigned long lval;
2361 [ - + ]: 28 : if (val < 0) {
2362 : 0 : *negp = true;
2363 : 0 : lval = (unsigned long)-val;
2364 : : } else {
2365 : 28 : *negp = false;
2366 : 28 : lval = (unsigned long)val;
2367 : : }
2368 : 28 : *lvalp = jiffies_to_clock_t(lval);
2369 : : }
2370 : : return 0;
2371 : : }
2372 : :
2373 : 0 : static int do_proc_dointvec_ms_jiffies_conv(bool *negp, unsigned long *lvalp,
2374 : : int *valp,
2375 : : int write, void *data)
2376 : : {
2377 [ - + ]: 30 : if (write) {
2378 [ # # ]: 0 : unsigned long jif = msecs_to_jiffies(*negp ? -*lvalp : *lvalp);
2379 : :
2380 [ # # ]: 0 : if (jif > INT_MAX)
2381 : : return 1;
2382 : 0 : *valp = (int)jif;
2383 : : } else {
2384 : 30 : int val = *valp;
2385 : : unsigned long lval;
2386 [ - + ]: 30 : if (val < 0) {
2387 : 0 : *negp = true;
2388 : 0 : lval = (unsigned long)-val;
2389 : : } else {
2390 : 30 : *negp = false;
2391 : 30 : lval = (unsigned long)val;
2392 : : }
2393 : 30 : *lvalp = jiffies_to_msecs(lval);
2394 : : }
2395 : : return 0;
2396 : : }
2397 : :
2398 : : /**
2399 : : * proc_dointvec_jiffies - read a vector of integers as seconds
2400 : : * @table: the sysctl table
2401 : : * @write: %TRUE if this is a write to the sysctl file
2402 : : * @buffer: the user buffer
2403 : : * @lenp: the size of the user buffer
2404 : : * @ppos: file position
2405 : : *
2406 : : * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
2407 : : * values from/to the user buffer, treated as an ASCII string.
2408 : : * The values read are assumed to be in seconds, and are converted into
2409 : : * jiffies.
2410 : : *
2411 : : * Returns 0 on success.
2412 : : */
2413 : 0 : int proc_dointvec_jiffies(struct ctl_table *table, int write,
2414 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2415 : : {
2416 : 118 : return do_proc_dointvec(table,write,buffer,lenp,ppos,
2417 : : do_proc_dointvec_jiffies_conv,NULL);
2418 : : }
2419 : :
2420 : : /**
2421 : : * proc_dointvec_userhz_jiffies - read a vector of integers as 1/USER_HZ seconds
2422 : : * @table: the sysctl table
2423 : : * @write: %TRUE if this is a write to the sysctl file
2424 : : * @buffer: the user buffer
2425 : : * @lenp: the size of the user buffer
2426 : : * @ppos: pointer to the file position
2427 : : *
2428 : : * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
2429 : : * values from/to the user buffer, treated as an ASCII string.
2430 : : * The values read are assumed to be in 1/USER_HZ seconds, and
2431 : : * are converted into jiffies.
2432 : : *
2433 : : * Returns 0 on success.
2434 : : */
2435 : 0 : int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
2436 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2437 : : {
2438 : 56 : return do_proc_dointvec(table,write,buffer,lenp,ppos,
2439 : : do_proc_dointvec_userhz_jiffies_conv,NULL);
2440 : : }
2441 : :
2442 : : /**
2443 : : * proc_dointvec_ms_jiffies - read a vector of integers as 1 milliseconds
2444 : : * @table: the sysctl table
2445 : : * @write: %TRUE if this is a write to the sysctl file
2446 : : * @buffer: the user buffer
2447 : : * @lenp: the size of the user buffer
2448 : : * @ppos: file position
2449 : : * @ppos: the current position in the file
2450 : : *
2451 : : * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
2452 : : * values from/to the user buffer, treated as an ASCII string.
2453 : : * The values read are assumed to be in 1/1000 seconds, and
2454 : : * are converted into jiffies.
2455 : : *
2456 : : * Returns 0 on success.
2457 : : */
2458 : 0 : int proc_dointvec_ms_jiffies(struct ctl_table *table, int write,
2459 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2460 : : {
2461 : 60 : return do_proc_dointvec(table, write, buffer, lenp, ppos,
2462 : : do_proc_dointvec_ms_jiffies_conv, NULL);
2463 : : }
2464 : :
2465 : 0 : static int proc_do_cad_pid(struct ctl_table *table, int write,
2466 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2467 : : {
2468 : : struct pid *new_pid;
2469 : : pid_t tmp;
2470 : : int r;
2471 : :
2472 : 2 : tmp = pid_vnr(cad_pid);
2473 : :
2474 : 2 : r = __do_proc_dointvec(&tmp, table, write, buffer,
2475 : : lenp, ppos, NULL, NULL);
2476 [ - + ]: 2 : if (r || !write)
2477 : : return r;
2478 : :
2479 : 0 : new_pid = find_get_pid(tmp);
2480 [ # # ]: 0 : if (!new_pid)
2481 : : return -ESRCH;
2482 : :
2483 : 0 : put_pid(xchg(&cad_pid, new_pid));
2484 : 0 : return 0;
2485 : : }
2486 : :
2487 : : /**
2488 : : * proc_do_large_bitmap - read/write from/to a large bitmap
2489 : : * @table: the sysctl table
2490 : : * @write: %TRUE if this is a write to the sysctl file
2491 : : * @buffer: the user buffer
2492 : : * @lenp: the size of the user buffer
2493 : : * @ppos: file position
2494 : : *
2495 : : * The bitmap is stored at table->data and the bitmap length (in bits)
2496 : : * in table->maxlen.
2497 : : *
2498 : : * We use a range comma separated format (e.g. 1,3-4,10-10) so that
2499 : : * large bitmaps may be represented in a compact manner. Writing into
2500 : : * the file will clear the bitmap then update it with the given input.
2501 : : *
2502 : : * Returns 0 on success.
2503 : : */
2504 : 0 : int proc_do_large_bitmap(struct ctl_table *table, int write,
2505 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2506 : : {
2507 : : int err = 0;
2508 : : bool first = 1;
2509 : 2 : size_t left = *lenp;
2510 : 2 : unsigned long bitmap_len = table->maxlen;
2511 : 2 : unsigned long *bitmap = (unsigned long *) table->data;
2512 : : unsigned long *tmp_bitmap = NULL;
2513 : 2 : char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
2514 : :
2515 [ + - ][ + + ]: 2 : if (!bitmap_len || !left || (*ppos && !write)) {
[ + - ]
2516 : 1 : *lenp = 0;
2517 : 1 : return 0;
2518 : : }
2519 : :
2520 [ + - ]: 1 : if (write) {
2521 : : unsigned long page = 0;
2522 : : char *kbuf;
2523 : :
2524 [ # # ]: 0 : if (left > PAGE_SIZE - 1)
2525 : 0 : left = PAGE_SIZE - 1;
2526 : :
2527 : 0 : page = __get_free_page(GFP_TEMPORARY);
2528 : 0 : kbuf = (char *) page;
2529 [ # # ]: 0 : if (!kbuf)
2530 : 0 : return -ENOMEM;
2531 [ - + ]: 2 : if (copy_from_user(kbuf, buffer, left)) {
2532 : 0 : free_page(page);
2533 : 0 : return -EFAULT;
2534 : : }
2535 : 0 : kbuf[left] = 0;
2536 : :
2537 : 0 : tmp_bitmap = kzalloc(BITS_TO_LONGS(bitmap_len) * sizeof(unsigned long),
2538 : : GFP_KERNEL);
2539 [ # # ]: 0 : if (!tmp_bitmap) {
2540 : 0 : free_page(page);
2541 : 0 : return -ENOMEM;
2542 : : }
2543 : : proc_skip_char(&kbuf, &left, '\n');
2544 [ # # ][ # # ]: 0 : while (!err && left) {
2545 : : unsigned long val_a, val_b;
2546 : : bool neg;
2547 : :
2548 : 0 : err = proc_get_long(&kbuf, &left, &val_a, &neg, tr_a,
2549 : : sizeof(tr_a), &c);
2550 [ # # ]: 0 : if (err)
2551 : : break;
2552 [ # # ][ # # ]: 0 : if (val_a >= bitmap_len || neg) {
2553 : : err = -EINVAL;
2554 : : break;
2555 : : }
2556 : :
2557 : 0 : val_b = val_a;
2558 [ # # ]: 0 : if (left) {
2559 : 0 : kbuf++;
2560 : 0 : left--;
2561 : : }
2562 : :
2563 [ # # ]: 0 : if (c == '-') {
2564 : 0 : err = proc_get_long(&kbuf, &left, &val_b,
2565 : : &neg, tr_b, sizeof(tr_b),
2566 : : &c);
2567 [ # # ]: 0 : if (err)
2568 : : break;
2569 [ # # ][ # # ]: 0 : if (val_b >= bitmap_len || neg ||
[ # # ]
2570 : 0 : val_a > val_b) {
2571 : : err = -EINVAL;
2572 : : break;
2573 : : }
2574 [ # # ]: 0 : if (left) {
2575 : 0 : kbuf++;
2576 : 0 : left--;
2577 : : }
2578 : : }
2579 : :
2580 : 0 : bitmap_set(tmp_bitmap, val_a, val_b - val_a + 1);
2581 : : first = 0;
2582 : : proc_skip_char(&kbuf, &left, '\n');
2583 : : }
2584 : 0 : free_page(page);
2585 : : } else {
2586 : : unsigned long bit_a, bit_b = 0;
2587 : :
2588 [ + - ]: 1 : while (left) {
2589 : 1 : bit_a = find_next_bit(bitmap, bitmap_len, bit_b);
2590 [ - + ]: 1 : if (bit_a >= bitmap_len)
2591 : : break;
2592 : 0 : bit_b = find_next_zero_bit(bitmap, bitmap_len,
2593 : 0 : bit_a + 1) - 1;
2594 : :
2595 [ # # ]: 0 : if (!first) {
2596 : 0 : err = proc_put_char(&buffer, &left, ',');
2597 [ # # ]: 0 : if (err)
2598 : : break;
2599 : : }
2600 : 0 : err = proc_put_long(&buffer, &left, bit_a, false);
2601 [ # # ]: 0 : if (err)
2602 : : break;
2603 [ # # ]: 0 : if (bit_a != bit_b) {
2604 : 0 : err = proc_put_char(&buffer, &left, '-');
2605 [ # # ]: 0 : if (err)
2606 : : break;
2607 : 0 : err = proc_put_long(&buffer, &left, bit_b, false);
2608 [ # # ]: 0 : if (err)
2609 : : break;
2610 : : }
2611 : :
2612 : 0 : first = 0; bit_b++;
2613 : : }
2614 [ + - ]: 1 : if (!err)
2615 : 1 : err = proc_put_char(&buffer, &left, '\n');
2616 : : }
2617 : :
2618 [ + - ]: 1 : if (!err) {
2619 [ - + ]: 1 : if (write) {
2620 [ # # ]: 0 : if (*ppos)
2621 : : bitmap_or(bitmap, bitmap, tmp_bitmap, bitmap_len);
2622 : : else
2623 : : bitmap_copy(bitmap, tmp_bitmap, bitmap_len);
2624 : : }
2625 : 1 : kfree(tmp_bitmap);
2626 : 1 : *lenp -= left;
2627 : 1 : *ppos += *lenp;
2628 : 1 : return 0;
2629 : : } else {
2630 : 0 : kfree(tmp_bitmap);
2631 : 0 : return err;
2632 : : }
2633 : : }
2634 : :
2635 : : #else /* CONFIG_PROC_SYSCTL */
2636 : :
2637 : : int proc_dostring(struct ctl_table *table, int write,
2638 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2639 : : {
2640 : : return -ENOSYS;
2641 : : }
2642 : :
2643 : : int proc_dointvec(struct ctl_table *table, int write,
2644 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2645 : : {
2646 : : return -ENOSYS;
2647 : : }
2648 : :
2649 : : int proc_dointvec_minmax(struct ctl_table *table, int write,
2650 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2651 : : {
2652 : : return -ENOSYS;
2653 : : }
2654 : :
2655 : : int proc_dointvec_jiffies(struct ctl_table *table, int write,
2656 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2657 : : {
2658 : : return -ENOSYS;
2659 : : }
2660 : :
2661 : : int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write,
2662 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2663 : : {
2664 : : return -ENOSYS;
2665 : : }
2666 : :
2667 : : int proc_dointvec_ms_jiffies(struct ctl_table *table, int write,
2668 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2669 : : {
2670 : : return -ENOSYS;
2671 : : }
2672 : :
2673 : : int proc_doulongvec_minmax(struct ctl_table *table, int write,
2674 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2675 : : {
2676 : : return -ENOSYS;
2677 : : }
2678 : :
2679 : : int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
2680 : : void __user *buffer,
2681 : : size_t *lenp, loff_t *ppos)
2682 : : {
2683 : : return -ENOSYS;
2684 : : }
2685 : :
2686 : :
2687 : : #endif /* CONFIG_PROC_SYSCTL */
2688 : :
2689 : : /*
2690 : : * No sense putting this after each symbol definition, twice,
2691 : : * exception granted :-)
2692 : : */
2693 : : EXPORT_SYMBOL(proc_dointvec);
2694 : : EXPORT_SYMBOL(proc_dointvec_jiffies);
2695 : : EXPORT_SYMBOL(proc_dointvec_minmax);
2696 : : EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
2697 : : EXPORT_SYMBOL(proc_dointvec_ms_jiffies);
2698 : : EXPORT_SYMBOL(proc_dostring);
2699 : : EXPORT_SYMBOL(proc_doulongvec_minmax);
2700 : : EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
|