blob: ab59ac008caf8c11a510e2ebe03d7a9e7ea81ec6 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#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/proc_fs.h>
Andrew Morgan72c2d582007-10-18 03:05:59 -070027#include <linux/security.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/ctype.h>
29#include <linux/utsname.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/smp_lock.h>
Adrian Bunk62239ac2007-07-17 04:03:45 -070031#include <linux/fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/init.h>
33#include <linux/kernel.h>
Kay Sievers0296b222005-11-11 05:33:52 +010034#include <linux/kobject.h>
Arnaldo Carvalho de Melo20380732005-08-16 02:18:02 -030035#include <linux/net.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/sysrq.h>
37#include <linux/highuid.h>
38#include <linux/writeback.h>
39#include <linux/hugetlb.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <linux/initrd.h>
David Howells0b77f5b2008-04-29 01:01:32 -070041#include <linux/key.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <linux/times.h>
43#include <linux/limits.h>
44#include <linux/dcache.h>
45#include <linux/syscalls.h>
Pavel Machekc255d842006-02-20 18:27:58 -080046#include <linux/nfs_fs.h>
47#include <linux/acpi.h>
Jeremy Fitzhardinge10a0a8d2007-07-17 18:37:02 -070048#include <linux/reboot.h>
Steven Rostedtb0fc4942008-05-12 21:20:43 +020049#include <linux/ftrace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51#include <asm/uaccess.h>
52#include <asm/processor.h>
53
Andi Kleen29cbc782006-09-30 01:47:55 +020054#ifdef CONFIG_X86
55#include <asm/nmi.h>
Chuck Ebbert0741f4d2006-12-07 02:14:11 +010056#include <asm/stacktrace.h>
Ingo Molnar6e7c4022008-01-30 13:30:05 +010057#include <asm/io.h>
Andi Kleen29cbc782006-09-30 01:47:55 +020058#endif
59
Eric W. Biederman7058cb02007-10-18 03:05:58 -070060static int deprecated_sysctl_warning(struct __sysctl_args *args);
61
Linus Torvalds1da177e2005-04-16 15:20:36 -070062#if defined(CONFIG_SYSCTL)
63
64/* External variables not in a header file. */
65extern int C_A_D;
Ingo Molnar45807a12007-07-15 23:40:10 -070066extern int print_fatal_signals;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067extern int sysctl_overcommit_memory;
68extern int sysctl_overcommit_ratio;
KAMEZAWA Hiroyukifadd8fb2006-06-23 02:03:13 -070069extern int sysctl_panic_on_oom;
David Rientjesfe071d72007-10-16 23:25:56 -070070extern int sysctl_oom_kill_allocating_task;
David Rientjesfef1bdd2008-02-07 00:14:07 -080071extern int sysctl_oom_dump_tasks;
Linus Torvalds1da177e2005-04-16 15:20:36 -070072extern int max_threads;
Linus Torvalds1da177e2005-04-16 15:20:36 -070073extern int core_uses_pid;
Alan Coxd6e71142005-06-23 00:09:43 -070074extern int suid_dumpable;
Linus Torvalds1da177e2005-04-16 15:20:36 -070075extern char core_pattern[];
Linus Torvalds1da177e2005-04-16 15:20:36 -070076extern int pid_max;
77extern int min_free_kbytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -070078extern int pid_max_min, pid_max_max;
Andrew Morton9d0243b2006-01-08 01:00:39 -080079extern int sysctl_drop_caches;
Rohit Seth8ad4b1f2006-01-08 01:00:40 -080080extern int percpu_pagelist_fraction;
Andi Kleenbebfa102006-06-26 13:56:52 +020081extern int compat_log;
Kees Cook5096add2007-05-08 00:26:04 -070082extern int maps_protect;
Christoph Lameter77461ab2007-05-09 02:35:13 -070083extern int sysctl_stat_interval;
Arjan van de Ven97455122008-01-25 21:08:34 +010084extern int latencytop_enabled;
Al Viroeceea0b2008-05-10 10:08:32 -040085extern int sysctl_nr_open_min, sysctl_nr_open_max;
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
Ravikiran G Thirumalaic4f3b632007-10-16 23:26:09 -070087/* Constants used for minimum and maximum */
Ingo Molnar1c4cd6d2008-05-12 21:21:14 +020088#if defined(CONFIG_HIGHMEM) || defined(CONFIG_DETECT_SOFTLOCKUP)
Ravikiran G Thirumalaic4f3b632007-10-16 23:26:09 -070089static int one = 1;
Bron Gondwana195cf4532008-02-04 22:29:20 -080090#endif
91
92#ifdef CONFIG_DETECT_SOFTLOCKUP
Ravikiran G Thirumalaic4f3b632007-10-16 23:26:09 -070093static int sixty = 60;
Dimitri Sivanich9383d962008-05-12 21:21:14 +020094static int neg_one = -1;
Ravikiran G Thirumalaic4f3b632007-10-16 23:26:09 -070095#endif
96
97#ifdef CONFIG_MMU
98static int two = 2;
99#endif
100
101static int zero;
102static int one_hundred = 100;
103
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104/* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
105static int maxolduid = 65535;
106static int minolduid;
Rohit Seth8ad4b1f2006-01-08 01:00:40 -0800107static int min_percpu_pagelist_fract = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
109static int ngroups_max = NGROUPS_MAX;
110
111#ifdef CONFIG_KMOD
112extern char modprobe_path[];
113#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114#ifdef CONFIG_CHR_DEV_SG
115extern int sg_big_buff;
116#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117
118#ifdef __sparc__
119extern char reboot_command [];
120extern int stop_a_enabled;
121extern int scons_pwroff;
122#endif
123
124#ifdef __hppa__
125extern int pwrsw_enabled;
126extern int unaligned_enabled;
127#endif
128
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800129#ifdef CONFIG_S390
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130#ifdef CONFIG_MATHEMU
131extern int sysctl_ieee_emulation_warnings;
132#endif
133extern int sysctl_userprocess_debug;
Martin Schwidefsky951f22d2005-07-27 11:44:57 -0700134extern int spin_retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135#endif
136
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137#ifdef CONFIG_BSD_PROCESS_ACCT
138extern int acct_parm[];
139#endif
140
Jes Sorensend2b176e2006-02-28 09:42:23 -0800141#ifdef CONFIG_IA64
142extern int no_unaligned_warning;
143#endif
144
Ingo Molnar23f78d4a2006-06-27 02:54:53 -0700145#ifdef CONFIG_RT_MUTEXES
146extern int max_lock_depth;
147#endif
148
Randy Dunlapd6f8ff72006-10-19 23:28:34 -0700149#ifdef CONFIG_PROC_SYSCTL
Eric W. Biedermand8217f02007-10-18 03:05:22 -0700150static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp,
Cedric Le Goater9ec52092006-10-02 02:19:00 -0700151 void __user *buffer, size_t *lenp, loff_t *ppos);
Eric W. Biedermand8217f02007-10-18 03:05:22 -0700152static int proc_dointvec_taint(struct ctl_table *table, int write, struct file *filp,
Theodore Ts'o34f5a392007-02-10 01:45:24 -0800153 void __user *buffer, size_t *lenp, loff_t *ppos);
Randy Dunlapd6f8ff72006-10-19 23:28:34 -0700154#endif
Cedric Le Goater9ec52092006-10-02 02:19:00 -0700155
Eric W. Biedermand8217f02007-10-18 03:05:22 -0700156static struct ctl_table root_table[];
Eric W. Biedermane51b6ba2007-11-30 23:54:00 +1100157static struct ctl_table_root sysctl_table_root;
158static struct ctl_table_header root_table_header = {
159 .ctl_table = root_table,
160 .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.header_list),
161 .root = &sysctl_table_root,
162};
163static struct ctl_table_root sysctl_table_root = {
164 .root_list = LIST_HEAD_INIT(sysctl_table_root.root_list),
165 .header_list = LIST_HEAD_INIT(root_table_header.ctl_entry),
166};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167
Eric W. Biedermand8217f02007-10-18 03:05:22 -0700168static struct ctl_table kern_table[];
169static struct ctl_table vm_table[];
170static struct ctl_table fs_table[];
171static struct ctl_table debug_table[];
172static struct ctl_table dev_table[];
173extern struct ctl_table random_table[];
Amy Griffis2d9048e2006-06-01 13:10:59 -0700174#ifdef CONFIG_INOTIFY_USER
Eric W. Biedermand8217f02007-10-18 03:05:22 -0700175extern struct ctl_table inotify_table[];
Robert Love0399cb02005-07-13 12:38:18 -0400176#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177
178#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
179int sysctl_legacy_va_layout;
180#endif
181
Peter Zijlstraf20786f2007-07-19 01:48:56 -0700182extern int prove_locking;
183extern int lock_stat;
Eric W. Biederman9bc9a6b2006-12-08 02:39:56 -0800184
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185/* The default sysctl tables: */
186
Eric W. Biedermand8217f02007-10-18 03:05:22 -0700187static struct ctl_table root_table[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 {
189 .ctl_name = CTL_KERN,
190 .procname = "kernel",
191 .mode = 0555,
192 .child = kern_table,
193 },
194 {
195 .ctl_name = CTL_VM,
196 .procname = "vm",
197 .mode = 0555,
198 .child = vm_table,
199 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201 .ctl_name = CTL_FS,
202 .procname = "fs",
203 .mode = 0555,
204 .child = fs_table,
205 },
206 {
207 .ctl_name = CTL_DEBUG,
208 .procname = "debug",
209 .mode = 0555,
210 .child = debug_table,
211 },
212 {
213 .ctl_name = CTL_DEV,
214 .procname = "dev",
215 .mode = 0555,
216 .child = dev_table,
217 },
Andrew Morton2be7fe02007-07-15 23:41:21 -0700218/*
219 * NOTE: do not add new entries to this table unless you have read
220 * Documentation/sysctl/ctl_unnumbered.txt
221 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 { .ctl_name = 0 }
223};
224
Ingo Molnar77e54a12007-07-09 18:52:00 +0200225#ifdef CONFIG_SCHED_DEBUG
Eric Dumazet73c4efd2007-12-18 15:21:13 +0100226static int min_sched_granularity_ns = 100000; /* 100 usecs */
227static int max_sched_granularity_ns = NSEC_PER_SEC; /* 1 second */
228static int min_wakeup_granularity_ns; /* 0 usecs */
229static int max_wakeup_granularity_ns = NSEC_PER_SEC; /* 1 second */
Ingo Molnar77e54a12007-07-09 18:52:00 +0200230#endif
231
Eric W. Biedermand8217f02007-10-18 03:05:22 -0700232static struct ctl_table kern_table[] = {
Ingo Molnar77e54a12007-07-09 18:52:00 +0200233#ifdef CONFIG_SCHED_DEBUG
234 {
235 .ctl_name = CTL_UNNUMBERED,
Peter Zijlstrab2be5e92007-11-09 22:39:37 +0100236 .procname = "sched_min_granularity_ns",
237 .data = &sysctl_sched_min_granularity,
Ingo Molnar77e54a12007-07-09 18:52:00 +0200238 .maxlen = sizeof(unsigned int),
239 .mode = 0644,
Peter Zijlstrab2be5e92007-11-09 22:39:37 +0100240 .proc_handler = &sched_nr_latency_handler,
241 .strategy = &sysctl_intvec,
242 .extra1 = &min_sched_granularity_ns,
243 .extra2 = &max_sched_granularity_ns,
Ingo Molnar77e54a12007-07-09 18:52:00 +0200244 },
245 {
246 .ctl_name = CTL_UNNUMBERED,
Peter Zijlstra21805082007-08-25 18:41:53 +0200247 .procname = "sched_latency_ns",
248 .data = &sysctl_sched_latency,
249 .maxlen = sizeof(unsigned int),
250 .mode = 0644,
Peter Zijlstrab2be5e92007-11-09 22:39:37 +0100251 .proc_handler = &sched_nr_latency_handler,
Peter Zijlstra21805082007-08-25 18:41:53 +0200252 .strategy = &sysctl_intvec,
253 .extra1 = &min_sched_granularity_ns,
254 .extra2 = &max_sched_granularity_ns,
255 },
256 {
257 .ctl_name = CTL_UNNUMBERED,
Ingo Molnar77e54a12007-07-09 18:52:00 +0200258 .procname = "sched_wakeup_granularity_ns",
259 .data = &sysctl_sched_wakeup_granularity,
260 .maxlen = sizeof(unsigned int),
261 .mode = 0644,
262 .proc_handler = &proc_dointvec_minmax,
263 .strategy = &sysctl_intvec,
264 .extra1 = &min_wakeup_granularity_ns,
265 .extra2 = &max_wakeup_granularity_ns,
266 },
267 {
268 .ctl_name = CTL_UNNUMBERED,
Peter Zijlstra2398f2c2008-06-27 13:41:35 +0200269 .procname = "sched_shares_ratelimit",
270 .data = &sysctl_sched_shares_ratelimit,
271 .maxlen = sizeof(unsigned int),
272 .mode = 0644,
273 .proc_handler = &proc_dointvec,
274 },
275 {
276 .ctl_name = CTL_UNNUMBERED,
Ingo Molnar77e54a12007-07-09 18:52:00 +0200277 .procname = "sched_child_runs_first",
278 .data = &sysctl_sched_child_runs_first,
279 .maxlen = sizeof(unsigned int),
280 .mode = 0644,
281 .proc_handler = &proc_dointvec,
282 },
Peter Zijlstra1fc84aa2007-08-25 18:41:52 +0200283 {
284 .ctl_name = CTL_UNNUMBERED,
285 .procname = "sched_features",
286 .data = &sysctl_sched_features,
287 .maxlen = sizeof(unsigned int),
288 .mode = 0644,
289 .proc_handler = &proc_dointvec,
290 },
Ingo Molnarda84d962007-10-15 17:00:18 +0200291 {
292 .ctl_name = CTL_UNNUMBERED,
293 .procname = "sched_migration_cost",
294 .data = &sysctl_sched_migration_cost,
295 .maxlen = sizeof(unsigned int),
296 .mode = 0644,
297 .proc_handler = &proc_dointvec,
298 },
Peter Zijlstrab82d9fd2007-11-09 22:39:39 +0100299 {
300 .ctl_name = CTL_UNNUMBERED,
301 .procname = "sched_nr_migrate",
302 .data = &sysctl_sched_nr_migrate,
303 .maxlen = sizeof(unsigned int),
Peter Zijlstrafa85ae22008-01-25 21:08:29 +0100304 .mode = 0644,
305 .proc_handler = &proc_dointvec,
306 },
Peter Zijlstra1fc84aa2007-08-25 18:41:52 +0200307#endif
Ingo Molnar1799e352007-09-19 23:34:46 +0200308 {
309 .ctl_name = CTL_UNNUMBERED,
Peter Zijlstra9f0c1e52008-02-13 15:45:39 +0100310 .procname = "sched_rt_period_us",
311 .data = &sysctl_sched_rt_period,
312 .maxlen = sizeof(unsigned int),
313 .mode = 0644,
Peter Zijlstrad0b27fa2008-04-19 19:44:57 +0200314 .proc_handler = &sched_rt_handler,
Peter Zijlstra9f0c1e52008-02-13 15:45:39 +0100315 },
316 {
317 .ctl_name = CTL_UNNUMBERED,
318 .procname = "sched_rt_runtime_us",
319 .data = &sysctl_sched_rt_runtime,
320 .maxlen = sizeof(int),
321 .mode = 0644,
Peter Zijlstrad0b27fa2008-04-19 19:44:57 +0200322 .proc_handler = &sched_rt_handler,
Peter Zijlstra9f0c1e52008-02-13 15:45:39 +0100323 },
324 {
325 .ctl_name = CTL_UNNUMBERED,
Ingo Molnar1799e352007-09-19 23:34:46 +0200326 .procname = "sched_compat_yield",
327 .data = &sysctl_sched_compat_yield,
328 .maxlen = sizeof(unsigned int),
329 .mode = 0644,
330 .proc_handler = &proc_dointvec,
331 },
Peter Zijlstraf20786f2007-07-19 01:48:56 -0700332#ifdef CONFIG_PROVE_LOCKING
333 {
334 .ctl_name = CTL_UNNUMBERED,
335 .procname = "prove_locking",
336 .data = &prove_locking,
337 .maxlen = sizeof(int),
338 .mode = 0644,
339 .proc_handler = &proc_dointvec,
340 },
341#endif
342#ifdef CONFIG_LOCK_STAT
343 {
344 .ctl_name = CTL_UNNUMBERED,
345 .procname = "lock_stat",
346 .data = &lock_stat,
347 .maxlen = sizeof(int),
348 .mode = 0644,
349 .proc_handler = &proc_dointvec,
350 },
351#endif
Ingo Molnar77e54a12007-07-09 18:52:00 +0200352 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 .ctl_name = KERN_PANIC,
354 .procname = "panic",
355 .data = &panic_timeout,
356 .maxlen = sizeof(int),
357 .mode = 0644,
358 .proc_handler = &proc_dointvec,
359 },
360 {
361 .ctl_name = KERN_CORE_USES_PID,
362 .procname = "core_uses_pid",
363 .data = &core_uses_pid,
364 .maxlen = sizeof(int),
365 .mode = 0644,
366 .proc_handler = &proc_dointvec,
367 },
368 {
369 .ctl_name = KERN_CORE_PATTERN,
370 .procname = "core_pattern",
371 .data = core_pattern,
Dan Aloni71ce92f2007-05-16 22:11:16 -0700372 .maxlen = CORENAME_MAX_SIZE,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 .mode = 0644,
374 .proc_handler = &proc_dostring,
375 .strategy = &sysctl_string,
376 },
Theodore Ts'o34f5a392007-02-10 01:45:24 -0800377#ifdef CONFIG_PROC_SYSCTL
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 .procname = "tainted",
380 .data = &tainted,
381 .maxlen = sizeof(int),
Theodore Ts'o34f5a392007-02-10 01:45:24 -0800382 .mode = 0644,
383 .proc_handler = &proc_dointvec_taint,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 },
Theodore Ts'o34f5a392007-02-10 01:45:24 -0800385#endif
Arjan van de Ven97455122008-01-25 21:08:34 +0100386#ifdef CONFIG_LATENCYTOP
387 {
388 .procname = "latencytop",
389 .data = &latencytop_enabled,
390 .maxlen = sizeof(int),
391 .mode = 0644,
392 .proc_handler = &proc_dointvec,
393 },
394#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395#ifdef CONFIG_BLK_DEV_INITRD
396 {
397 .ctl_name = KERN_REALROOTDEV,
398 .procname = "real-root-dev",
399 .data = &real_root_dev,
400 .maxlen = sizeof(int),
401 .mode = 0644,
402 .proc_handler = &proc_dointvec,
403 },
404#endif
Ingo Molnar45807a12007-07-15 23:40:10 -0700405 {
406 .ctl_name = CTL_UNNUMBERED,
407 .procname = "print-fatal-signals",
408 .data = &print_fatal_signals,
409 .maxlen = sizeof(int),
410 .mode = 0644,
411 .proc_handler = &proc_dointvec,
412 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413#ifdef __sparc__
414 {
415 .ctl_name = KERN_SPARC_REBOOT,
416 .procname = "reboot-cmd",
417 .data = reboot_command,
418 .maxlen = 256,
419 .mode = 0644,
420 .proc_handler = &proc_dostring,
421 .strategy = &sysctl_string,
422 },
423 {
424 .ctl_name = KERN_SPARC_STOP_A,
425 .procname = "stop-a",
426 .data = &stop_a_enabled,
427 .maxlen = sizeof (int),
428 .mode = 0644,
429 .proc_handler = &proc_dointvec,
430 },
431 {
432 .ctl_name = KERN_SPARC_SCONS_PWROFF,
433 .procname = "scons-poweroff",
434 .data = &scons_pwroff,
435 .maxlen = sizeof (int),
436 .mode = 0644,
437 .proc_handler = &proc_dointvec,
438 },
439#endif
440#ifdef __hppa__
441 {
442 .ctl_name = KERN_HPPA_PWRSW,
443 .procname = "soft-power",
444 .data = &pwrsw_enabled,
445 .maxlen = sizeof (int),
446 .mode = 0644,
447 .proc_handler = &proc_dointvec,
448 },
449 {
450 .ctl_name = KERN_HPPA_UNALIGNED,
451 .procname = "unaligned-trap",
452 .data = &unaligned_enabled,
453 .maxlen = sizeof (int),
454 .mode = 0644,
455 .proc_handler = &proc_dointvec,
456 },
457#endif
458 {
459 .ctl_name = KERN_CTLALTDEL,
460 .procname = "ctrl-alt-del",
461 .data = &C_A_D,
462 .maxlen = sizeof(int),
463 .mode = 0644,
464 .proc_handler = &proc_dointvec,
465 },
Steven Rostedtb0fc4942008-05-12 21:20:43 +0200466#ifdef CONFIG_FTRACE
467 {
468 .ctl_name = CTL_UNNUMBERED,
469 .procname = "ftrace_enabled",
470 .data = &ftrace_enabled,
471 .maxlen = sizeof(int),
472 .mode = 0644,
473 .proc_handler = &ftrace_enable_sysctl,
474 },
475#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476#ifdef CONFIG_KMOD
477 {
478 .ctl_name = KERN_MODPROBE,
479 .procname = "modprobe",
480 .data = &modprobe_path,
481 .maxlen = KMOD_PATH_LEN,
482 .mode = 0644,
483 .proc_handler = &proc_dostring,
484 .strategy = &sysctl_string,
485 },
486#endif
Andrew Morton57ae2502006-06-23 02:05:47 -0700487#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 {
489 .ctl_name = KERN_HOTPLUG,
490 .procname = "hotplug",
Kay Sievers312c0042005-11-16 09:00:00 +0100491 .data = &uevent_helper,
492 .maxlen = UEVENT_HELPER_PATH_LEN,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 .mode = 0644,
494 .proc_handler = &proc_dostring,
495 .strategy = &sysctl_string,
496 },
497#endif
498#ifdef CONFIG_CHR_DEV_SG
499 {
500 .ctl_name = KERN_SG_BIG_BUFF,
501 .procname = "sg-big-buff",
502 .data = &sg_big_buff,
503 .maxlen = sizeof (int),
504 .mode = 0444,
505 .proc_handler = &proc_dointvec,
506 },
507#endif
508#ifdef CONFIG_BSD_PROCESS_ACCT
509 {
510 .ctl_name = KERN_ACCT,
511 .procname = "acct",
512 .data = &acct_parm,
513 .maxlen = 3*sizeof(int),
514 .mode = 0644,
515 .proc_handler = &proc_dointvec,
516 },
517#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518#ifdef CONFIG_MAGIC_SYSRQ
519 {
520 .ctl_name = KERN_SYSRQ,
521 .procname = "sysrq",
Ingo Molnar5d6f6472006-12-13 00:34:36 -0800522 .data = &__sysrq_enabled,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 .maxlen = sizeof (int),
524 .mode = 0644,
525 .proc_handler = &proc_dointvec,
526 },
527#endif
Randy Dunlapd6f8ff72006-10-19 23:28:34 -0700528#ifdef CONFIG_PROC_SYSCTL
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 .procname = "cad_pid",
Cedric Le Goater9ec52092006-10-02 02:19:00 -0700531 .data = NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 .maxlen = sizeof (int),
533 .mode = 0600,
Cedric Le Goater9ec52092006-10-02 02:19:00 -0700534 .proc_handler = &proc_do_cad_pid,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 },
Randy Dunlapd6f8ff72006-10-19 23:28:34 -0700536#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 {
538 .ctl_name = KERN_MAX_THREADS,
539 .procname = "threads-max",
540 .data = &max_threads,
541 .maxlen = sizeof(int),
542 .mode = 0644,
543 .proc_handler = &proc_dointvec,
544 },
545 {
546 .ctl_name = KERN_RANDOM,
547 .procname = "random",
548 .mode = 0555,
549 .child = random_table,
550 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 {
552 .ctl_name = KERN_OVERFLOWUID,
553 .procname = "overflowuid",
554 .data = &overflowuid,
555 .maxlen = sizeof(int),
556 .mode = 0644,
557 .proc_handler = &proc_dointvec_minmax,
558 .strategy = &sysctl_intvec,
559 .extra1 = &minolduid,
560 .extra2 = &maxolduid,
561 },
562 {
563 .ctl_name = KERN_OVERFLOWGID,
564 .procname = "overflowgid",
565 .data = &overflowgid,
566 .maxlen = sizeof(int),
567 .mode = 0644,
568 .proc_handler = &proc_dointvec_minmax,
569 .strategy = &sysctl_intvec,
570 .extra1 = &minolduid,
571 .extra2 = &maxolduid,
572 },
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800573#ifdef CONFIG_S390
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574#ifdef CONFIG_MATHEMU
575 {
576 .ctl_name = KERN_IEEE_EMULATION_WARNINGS,
577 .procname = "ieee_emulation_warnings",
578 .data = &sysctl_ieee_emulation_warnings,
579 .maxlen = sizeof(int),
580 .mode = 0644,
581 .proc_handler = &proc_dointvec,
582 },
583#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 {
585 .ctl_name = KERN_S390_USER_DEBUG_LOGGING,
586 .procname = "userprocess_debug",
587 .data = &sysctl_userprocess_debug,
588 .maxlen = sizeof(int),
589 .mode = 0644,
590 .proc_handler = &proc_dointvec,
591 },
592#endif
593 {
594 .ctl_name = KERN_PIDMAX,
595 .procname = "pid_max",
596 .data = &pid_max,
597 .maxlen = sizeof (int),
598 .mode = 0644,
599 .proc_handler = &proc_dointvec_minmax,
600 .strategy = sysctl_intvec,
601 .extra1 = &pid_max_min,
602 .extra2 = &pid_max_max,
603 },
604 {
605 .ctl_name = KERN_PANIC_ON_OOPS,
606 .procname = "panic_on_oops",
607 .data = &panic_on_oops,
608 .maxlen = sizeof(int),
609 .mode = 0644,
610 .proc_handler = &proc_dointvec,
611 },
Joe Perches7ef3d2f2008-02-08 04:21:25 -0800612#if defined CONFIG_PRINTK
613 {
614 .ctl_name = KERN_PRINTK,
615 .procname = "printk",
616 .data = &console_loglevel,
617 .maxlen = 4*sizeof(int),
618 .mode = 0644,
619 .proc_handler = &proc_dointvec,
620 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 {
622 .ctl_name = KERN_PRINTK_RATELIMIT,
623 .procname = "printk_ratelimit",
624 .data = &printk_ratelimit_jiffies,
625 .maxlen = sizeof(int),
626 .mode = 0644,
627 .proc_handler = &proc_dointvec_jiffies,
628 .strategy = &sysctl_jiffies,
629 },
630 {
631 .ctl_name = KERN_PRINTK_RATELIMIT_BURST,
632 .procname = "printk_ratelimit_burst",
633 .data = &printk_ratelimit_burst,
634 .maxlen = sizeof(int),
635 .mode = 0644,
636 .proc_handler = &proc_dointvec,
637 },
Joe Perches7ef3d2f2008-02-08 04:21:25 -0800638#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 {
640 .ctl_name = KERN_NGROUPS_MAX,
641 .procname = "ngroups_max",
642 .data = &ngroups_max,
643 .maxlen = sizeof (int),
644 .mode = 0444,
645 .proc_handler = &proc_dointvec,
646 },
647#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
648 {
649 .ctl_name = KERN_UNKNOWN_NMI_PANIC,
650 .procname = "unknown_nmi_panic",
651 .data = &unknown_nmi_panic,
652 .maxlen = sizeof (int),
653 .mode = 0644,
Don Zickus2fbe7b22006-09-26 10:52:27 +0200654 .proc_handler = &proc_dointvec,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 },
Don Zickus407984f2006-09-26 10:52:27 +0200656 {
Don Zickus407984f2006-09-26 10:52:27 +0200657 .procname = "nmi_watchdog",
658 .data = &nmi_watchdog_enabled,
659 .maxlen = sizeof (int),
660 .mode = 0644,
661 .proc_handler = &proc_nmi_enabled,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 },
663#endif
664#if defined(CONFIG_X86)
665 {
Don Zickus8da5add2006-09-26 10:52:27 +0200666 .ctl_name = KERN_PANIC_ON_NMI,
667 .procname = "panic_on_unrecovered_nmi",
668 .data = &panic_on_unrecovered_nmi,
669 .maxlen = sizeof(int),
670 .mode = 0644,
671 .proc_handler = &proc_dointvec,
672 },
673 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 .ctl_name = KERN_BOOTLOADER_TYPE,
675 .procname = "bootloader_type",
676 .data = &bootloader_type,
677 .maxlen = sizeof (int),
678 .mode = 0444,
679 .proc_handler = &proc_dointvec,
680 },
Chuck Ebbert0741f4d2006-12-07 02:14:11 +0100681 {
682 .ctl_name = CTL_UNNUMBERED,
683 .procname = "kstack_depth_to_print",
684 .data = &kstack_depth_to_print,
685 .maxlen = sizeof(int),
686 .mode = 0644,
687 .proc_handler = &proc_dointvec,
688 },
Ingo Molnar6e7c4022008-01-30 13:30:05 +0100689 {
690 .ctl_name = CTL_UNNUMBERED,
691 .procname = "io_delay_type",
692 .data = &io_delay_type,
693 .maxlen = sizeof(int),
694 .mode = 0644,
695 .proc_handler = &proc_dointvec,
696 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697#endif
Luke Yang7a9166e2006-02-20 18:28:07 -0800698#if defined(CONFIG_MMU)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 {
700 .ctl_name = KERN_RANDOMIZE,
701 .procname = "randomize_va_space",
702 .data = &randomize_va_space,
703 .maxlen = sizeof(int),
704 .mode = 0644,
705 .proc_handler = &proc_dointvec,
706 },
Luke Yang7a9166e2006-02-20 18:28:07 -0800707#endif
Martin Schwidefsky0152fb32006-01-14 13:21:00 -0800708#if defined(CONFIG_S390) && defined(CONFIG_SMP)
Martin Schwidefsky951f22d2005-07-27 11:44:57 -0700709 {
710 .ctl_name = KERN_SPIN_RETRY,
711 .procname = "spin_retry",
712 .data = &spin_retry,
713 .maxlen = sizeof (int),
714 .mode = 0644,
715 .proc_handler = &proc_dointvec,
716 },
717#endif
Len Brown673d5b42007-07-28 03:33:16 -0400718#if defined(CONFIG_ACPI_SLEEP) && defined(CONFIG_X86)
Pavel Machekc255d842006-02-20 18:27:58 -0800719 {
Pavel Machekc255d842006-02-20 18:27:58 -0800720 .procname = "acpi_video_flags",
Pavel Machek77afcf72007-07-19 01:47:41 -0700721 .data = &acpi_realmode_flags,
Pavel Machekc255d842006-02-20 18:27:58 -0800722 .maxlen = sizeof (unsigned long),
723 .mode = 0644,
Stefan Seyfried7f99f062006-03-02 02:54:34 -0800724 .proc_handler = &proc_doulongvec_minmax,
Pavel Machekc255d842006-02-20 18:27:58 -0800725 },
726#endif
Jes Sorensend2b176e2006-02-28 09:42:23 -0800727#ifdef CONFIG_IA64
728 {
729 .ctl_name = KERN_IA64_UNALIGNED,
730 .procname = "ignore-unaligned-usertrap",
731 .data = &no_unaligned_warning,
732 .maxlen = sizeof (int),
733 .mode = 0644,
734 .proc_handler = &proc_dointvec,
735 },
736#endif
Ravikiran G Thirumalaic4f3b632007-10-16 23:26:09 -0700737#ifdef CONFIG_DETECT_SOFTLOCKUP
738 {
739 .ctl_name = CTL_UNNUMBERED,
Ingo Molnar9c44bc02008-05-12 21:21:04 +0200740 .procname = "softlockup_panic",
741 .data = &softlockup_panic,
742 .maxlen = sizeof(int),
743 .mode = 0644,
Hiroshi Shimamoto4dca10a2008-07-07 18:37:04 -0700744 .proc_handler = &proc_dointvec_minmax,
Ingo Molnar9c44bc02008-05-12 21:21:04 +0200745 .strategy = &sysctl_intvec,
746 .extra1 = &zero,
747 .extra2 = &one,
748 },
749 {
750 .ctl_name = CTL_UNNUMBERED,
Ravikiran G Thirumalaic4f3b632007-10-16 23:26:09 -0700751 .procname = "softlockup_thresh",
752 .data = &softlockup_thresh,
Dimitri Sivanich9383d962008-05-12 21:21:14 +0200753 .maxlen = sizeof(int),
Ravikiran G Thirumalaic4f3b632007-10-16 23:26:09 -0700754 .mode = 0644,
Dimitri Sivanich9383d962008-05-12 21:21:14 +0200755 .proc_handler = &proc_dointvec_minmax,
Ravikiran G Thirumalaic4f3b632007-10-16 23:26:09 -0700756 .strategy = &sysctl_intvec,
Dimitri Sivanich9383d962008-05-12 21:21:14 +0200757 .extra1 = &neg_one,
Ravikiran G Thirumalaic4f3b632007-10-16 23:26:09 -0700758 .extra2 = &sixty,
759 },
Ingo Molnar82a1fcb2008-01-25 21:08:02 +0100760 {
761 .ctl_name = CTL_UNNUMBERED,
762 .procname = "hung_task_check_count",
763 .data = &sysctl_hung_task_check_count,
Ingo Molnar90739082008-01-25 21:08:34 +0100764 .maxlen = sizeof(unsigned long),
Ingo Molnar82a1fcb2008-01-25 21:08:02 +0100765 .mode = 0644,
Ingo Molnar90739082008-01-25 21:08:34 +0100766 .proc_handler = &proc_doulongvec_minmax,
Ingo Molnar82a1fcb2008-01-25 21:08:02 +0100767 .strategy = &sysctl_intvec,
768 },
769 {
770 .ctl_name = CTL_UNNUMBERED,
771 .procname = "hung_task_timeout_secs",
772 .data = &sysctl_hung_task_timeout_secs,
Ingo Molnar90739082008-01-25 21:08:34 +0100773 .maxlen = sizeof(unsigned long),
Ingo Molnar82a1fcb2008-01-25 21:08:02 +0100774 .mode = 0644,
Ingo Molnar90739082008-01-25 21:08:34 +0100775 .proc_handler = &proc_doulongvec_minmax,
Ingo Molnar82a1fcb2008-01-25 21:08:02 +0100776 .strategy = &sysctl_intvec,
777 },
778 {
779 .ctl_name = CTL_UNNUMBERED,
780 .procname = "hung_task_warnings",
781 .data = &sysctl_hung_task_warnings,
Ingo Molnar90739082008-01-25 21:08:34 +0100782 .maxlen = sizeof(unsigned long),
Ingo Molnar82a1fcb2008-01-25 21:08:02 +0100783 .mode = 0644,
Ingo Molnar90739082008-01-25 21:08:34 +0100784 .proc_handler = &proc_doulongvec_minmax,
Ingo Molnar82a1fcb2008-01-25 21:08:02 +0100785 .strategy = &sysctl_intvec,
786 },
Ravikiran G Thirumalaic4f3b632007-10-16 23:26:09 -0700787#endif
Andi Kleenbebfa102006-06-26 13:56:52 +0200788#ifdef CONFIG_COMPAT
789 {
790 .ctl_name = KERN_COMPAT_LOG,
791 .procname = "compat-log",
792 .data = &compat_log,
793 .maxlen = sizeof (int),
794 .mode = 0644,
795 .proc_handler = &proc_dointvec,
796 },
797#endif
Ingo Molnar23f78d4a2006-06-27 02:54:53 -0700798#ifdef CONFIG_RT_MUTEXES
799 {
800 .ctl_name = KERN_MAX_LOCK_DEPTH,
801 .procname = "max_lock_depth",
802 .data = &max_lock_depth,
803 .maxlen = sizeof(int),
804 .mode = 0644,
805 .proc_handler = &proc_dointvec,
806 },
807#endif
Kees Cook5096add2007-05-08 00:26:04 -0700808#ifdef CONFIG_PROC_FS
809 {
810 .ctl_name = CTL_UNNUMBERED,
811 .procname = "maps_protect",
812 .data = &maps_protect,
813 .maxlen = sizeof(int),
814 .mode = 0644,
815 .proc_handler = &proc_dointvec,
816 },
817#endif
Jeremy Fitzhardinge10a0a8d2007-07-17 18:37:02 -0700818 {
819 .ctl_name = CTL_UNNUMBERED,
820 .procname = "poweroff_cmd",
821 .data = &poweroff_cmd,
822 .maxlen = POWEROFF_CMD_PATH_LEN,
823 .mode = 0644,
824 .proc_handler = &proc_dostring,
825 .strategy = &sysctl_string,
826 },
David Howells0b77f5b2008-04-29 01:01:32 -0700827#ifdef CONFIG_KEYS
828 {
829 .ctl_name = CTL_UNNUMBERED,
830 .procname = "keys",
831 .mode = 0555,
832 .child = key_sysctls,
833 },
834#endif
Andrew Mortoned2c12f2007-07-19 01:50:35 -0700835/*
836 * NOTE: do not add new entries to this table unless you have read
837 * Documentation/sysctl/ctl_unnumbered.txt
838 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 { .ctl_name = 0 }
840};
841
Eric W. Biedermand8217f02007-10-18 03:05:22 -0700842static struct ctl_table vm_table[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 {
844 .ctl_name = VM_OVERCOMMIT_MEMORY,
845 .procname = "overcommit_memory",
846 .data = &sysctl_overcommit_memory,
847 .maxlen = sizeof(sysctl_overcommit_memory),
848 .mode = 0644,
849 .proc_handler = &proc_dointvec,
850 },
851 {
KAMEZAWA Hiroyukifadd8fb2006-06-23 02:03:13 -0700852 .ctl_name = VM_PANIC_ON_OOM,
853 .procname = "panic_on_oom",
854 .data = &sysctl_panic_on_oom,
855 .maxlen = sizeof(sysctl_panic_on_oom),
856 .mode = 0644,
857 .proc_handler = &proc_dointvec,
858 },
859 {
David Rientjesfe071d72007-10-16 23:25:56 -0700860 .ctl_name = CTL_UNNUMBERED,
861 .procname = "oom_kill_allocating_task",
862 .data = &sysctl_oom_kill_allocating_task,
863 .maxlen = sizeof(sysctl_oom_kill_allocating_task),
864 .mode = 0644,
865 .proc_handler = &proc_dointvec,
866 },
867 {
David Rientjesfef1bdd2008-02-07 00:14:07 -0800868 .ctl_name = CTL_UNNUMBERED,
869 .procname = "oom_dump_tasks",
870 .data = &sysctl_oom_dump_tasks,
871 .maxlen = sizeof(sysctl_oom_dump_tasks),
872 .mode = 0644,
873 .proc_handler = &proc_dointvec,
874 },
875 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 .ctl_name = VM_OVERCOMMIT_RATIO,
877 .procname = "overcommit_ratio",
878 .data = &sysctl_overcommit_ratio,
879 .maxlen = sizeof(sysctl_overcommit_ratio),
880 .mode = 0644,
881 .proc_handler = &proc_dointvec,
882 },
883 {
884 .ctl_name = VM_PAGE_CLUSTER,
885 .procname = "page-cluster",
886 .data = &page_cluster,
887 .maxlen = sizeof(int),
888 .mode = 0644,
889 .proc_handler = &proc_dointvec,
890 },
891 {
892 .ctl_name = VM_DIRTY_BACKGROUND,
893 .procname = "dirty_background_ratio",
894 .data = &dirty_background_ratio,
895 .maxlen = sizeof(dirty_background_ratio),
896 .mode = 0644,
897 .proc_handler = &proc_dointvec_minmax,
898 .strategy = &sysctl_intvec,
899 .extra1 = &zero,
900 .extra2 = &one_hundred,
901 },
902 {
903 .ctl_name = VM_DIRTY_RATIO,
904 .procname = "dirty_ratio",
905 .data = &vm_dirty_ratio,
906 .maxlen = sizeof(vm_dirty_ratio),
907 .mode = 0644,
Peter Zijlstra04fbfdc2007-10-16 23:25:50 -0700908 .proc_handler = &dirty_ratio_handler,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 .strategy = &sysctl_intvec,
910 .extra1 = &zero,
911 .extra2 = &one_hundred,
912 },
913 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 .procname = "dirty_writeback_centisecs",
Bart Samwelf6ef9432006-03-24 03:15:48 -0800915 .data = &dirty_writeback_interval,
916 .maxlen = sizeof(dirty_writeback_interval),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 .mode = 0644,
918 .proc_handler = &dirty_writeback_centisecs_handler,
919 },
920 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 .procname = "dirty_expire_centisecs",
Bart Samwelf6ef9432006-03-24 03:15:48 -0800922 .data = &dirty_expire_interval,
923 .maxlen = sizeof(dirty_expire_interval),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 .mode = 0644,
Bart Samwelf6ef9432006-03-24 03:15:48 -0800925 .proc_handler = &proc_dointvec_userhz_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 },
927 {
928 .ctl_name = VM_NR_PDFLUSH_THREADS,
929 .procname = "nr_pdflush_threads",
930 .data = &nr_pdflush_threads,
931 .maxlen = sizeof nr_pdflush_threads,
932 .mode = 0444 /* read-only*/,
933 .proc_handler = &proc_dointvec,
934 },
935 {
936 .ctl_name = VM_SWAPPINESS,
937 .procname = "swappiness",
938 .data = &vm_swappiness,
939 .maxlen = sizeof(vm_swappiness),
940 .mode = 0644,
941 .proc_handler = &proc_dointvec_minmax,
942 .strategy = &sysctl_intvec,
943 .extra1 = &zero,
944 .extra2 = &one_hundred,
945 },
946#ifdef CONFIG_HUGETLB_PAGE
947 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 .procname = "nr_hugepages",
949 .data = &max_huge_pages,
950 .maxlen = sizeof(unsigned long),
951 .mode = 0644,
952 .proc_handler = &hugetlb_sysctl_handler,
953 .extra1 = (void *)&hugetlb_zero,
954 .extra2 = (void *)&hugetlb_infinity,
955 },
956 {
957 .ctl_name = VM_HUGETLB_GROUP,
958 .procname = "hugetlb_shm_group",
959 .data = &sysctl_hugetlb_shm_group,
960 .maxlen = sizeof(gid_t),
961 .mode = 0644,
962 .proc_handler = &proc_dointvec,
963 },
Mel Gorman396faf02007-07-17 04:03:13 -0700964 {
965 .ctl_name = CTL_UNNUMBERED,
966 .procname = "hugepages_treat_as_movable",
967 .data = &hugepages_treat_as_movable,
968 .maxlen = sizeof(int),
969 .mode = 0644,
970 .proc_handler = &hugetlb_treat_movable_handler,
971 },
Adam Litke54f9f802007-10-16 01:26:20 -0700972 {
973 .ctl_name = CTL_UNNUMBERED,
Nishanth Aravamudand1c3fb12007-12-17 16:20:12 -0800974 .procname = "nr_overcommit_hugepages",
Nishanth Aravamudan064d9ef2008-02-13 15:03:19 -0800975 .data = &sysctl_overcommit_huge_pages,
976 .maxlen = sizeof(sysctl_overcommit_huge_pages),
Nishanth Aravamudand1c3fb12007-12-17 16:20:12 -0800977 .mode = 0644,
Nishanth Aravamudana3d0c6a2008-02-08 04:18:18 -0800978 .proc_handler = &hugetlb_overcommit_handler,
Nishanth Aravamudand1c3fb12007-12-17 16:20:12 -0800979 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980#endif
981 {
982 .ctl_name = VM_LOWMEM_RESERVE_RATIO,
983 .procname = "lowmem_reserve_ratio",
984 .data = &sysctl_lowmem_reserve_ratio,
985 .maxlen = sizeof(sysctl_lowmem_reserve_ratio),
986 .mode = 0644,
987 .proc_handler = &lowmem_reserve_ratio_sysctl_handler,
988 .strategy = &sysctl_intvec,
989 },
990 {
Andrew Morton9d0243b2006-01-08 01:00:39 -0800991 .ctl_name = VM_DROP_PAGECACHE,
992 .procname = "drop_caches",
993 .data = &sysctl_drop_caches,
994 .maxlen = sizeof(int),
995 .mode = 0644,
996 .proc_handler = drop_caches_sysctl_handler,
997 .strategy = &sysctl_intvec,
998 },
999 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 .ctl_name = VM_MIN_FREE_KBYTES,
1001 .procname = "min_free_kbytes",
1002 .data = &min_free_kbytes,
1003 .maxlen = sizeof(min_free_kbytes),
1004 .mode = 0644,
1005 .proc_handler = &min_free_kbytes_sysctl_handler,
1006 .strategy = &sysctl_intvec,
1007 .extra1 = &zero,
1008 },
Rohit Seth8ad4b1f2006-01-08 01:00:40 -08001009 {
1010 .ctl_name = VM_PERCPU_PAGELIST_FRACTION,
1011 .procname = "percpu_pagelist_fraction",
1012 .data = &percpu_pagelist_fraction,
1013 .maxlen = sizeof(percpu_pagelist_fraction),
1014 .mode = 0644,
1015 .proc_handler = &percpu_pagelist_fraction_sysctl_handler,
1016 .strategy = &sysctl_intvec,
1017 .extra1 = &min_percpu_pagelist_fract,
1018 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019#ifdef CONFIG_MMU
1020 {
1021 .ctl_name = VM_MAX_MAP_COUNT,
1022 .procname = "max_map_count",
1023 .data = &sysctl_max_map_count,
1024 .maxlen = sizeof(sysctl_max_map_count),
1025 .mode = 0644,
1026 .proc_handler = &proc_dointvec
1027 },
1028#endif
1029 {
1030 .ctl_name = VM_LAPTOP_MODE,
1031 .procname = "laptop_mode",
1032 .data = &laptop_mode,
1033 .maxlen = sizeof(laptop_mode),
1034 .mode = 0644,
Bart Samweled5b43f2006-03-24 03:15:49 -08001035 .proc_handler = &proc_dointvec_jiffies,
1036 .strategy = &sysctl_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 },
1038 {
1039 .ctl_name = VM_BLOCK_DUMP,
1040 .procname = "block_dump",
1041 .data = &block_dump,
1042 .maxlen = sizeof(block_dump),
1043 .mode = 0644,
1044 .proc_handler = &proc_dointvec,
1045 .strategy = &sysctl_intvec,
1046 .extra1 = &zero,
1047 },
1048 {
1049 .ctl_name = VM_VFS_CACHE_PRESSURE,
1050 .procname = "vfs_cache_pressure",
1051 .data = &sysctl_vfs_cache_pressure,
1052 .maxlen = sizeof(sysctl_vfs_cache_pressure),
1053 .mode = 0644,
1054 .proc_handler = &proc_dointvec,
1055 .strategy = &sysctl_intvec,
1056 .extra1 = &zero,
1057 },
1058#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
1059 {
1060 .ctl_name = VM_LEGACY_VA_LAYOUT,
1061 .procname = "legacy_va_layout",
1062 .data = &sysctl_legacy_va_layout,
1063 .maxlen = sizeof(sysctl_legacy_va_layout),
1064 .mode = 0644,
1065 .proc_handler = &proc_dointvec,
1066 .strategy = &sysctl_intvec,
1067 .extra1 = &zero,
1068 },
1069#endif
Christoph Lameter17436602006-01-18 17:42:32 -08001070#ifdef CONFIG_NUMA
1071 {
1072 .ctl_name = VM_ZONE_RECLAIM_MODE,
1073 .procname = "zone_reclaim_mode",
1074 .data = &zone_reclaim_mode,
1075 .maxlen = sizeof(zone_reclaim_mode),
1076 .mode = 0644,
1077 .proc_handler = &proc_dointvec,
Christoph Lameterc84db232006-02-01 03:05:29 -08001078 .strategy = &sysctl_intvec,
1079 .extra1 = &zero,
Christoph Lameter17436602006-01-18 17:42:32 -08001080 },
Christoph Lameter96146342006-07-03 00:24:13 -07001081 {
1082 .ctl_name = VM_MIN_UNMAPPED,
1083 .procname = "min_unmapped_ratio",
1084 .data = &sysctl_min_unmapped_ratio,
1085 .maxlen = sizeof(sysctl_min_unmapped_ratio),
1086 .mode = 0644,
1087 .proc_handler = &sysctl_min_unmapped_ratio_sysctl_handler,
1088 .strategy = &sysctl_intvec,
1089 .extra1 = &zero,
1090 .extra2 = &one_hundred,
1091 },
Christoph Lameter0ff38492006-09-25 23:31:52 -07001092 {
1093 .ctl_name = VM_MIN_SLAB,
1094 .procname = "min_slab_ratio",
1095 .data = &sysctl_min_slab_ratio,
1096 .maxlen = sizeof(sysctl_min_slab_ratio),
1097 .mode = 0644,
1098 .proc_handler = &sysctl_min_slab_ratio_sysctl_handler,
1099 .strategy = &sysctl_intvec,
1100 .extra1 = &zero,
1101 .extra2 = &one_hundred,
1102 },
Christoph Lameter17436602006-01-18 17:42:32 -08001103#endif
Christoph Lameter77461ab2007-05-09 02:35:13 -07001104#ifdef CONFIG_SMP
1105 {
1106 .ctl_name = CTL_UNNUMBERED,
1107 .procname = "stat_interval",
1108 .data = &sysctl_stat_interval,
1109 .maxlen = sizeof(sysctl_stat_interval),
1110 .mode = 0644,
1111 .proc_handler = &proc_dointvec_jiffies,
1112 .strategy = &sysctl_jiffies,
1113 },
1114#endif
Eric Parised032182007-06-28 15:55:21 -04001115#ifdef CONFIG_SECURITY
1116 {
1117 .ctl_name = CTL_UNNUMBERED,
1118 .procname = "mmap_min_addr",
1119 .data = &mmap_min_addr,
1120 .maxlen = sizeof(unsigned long),
1121 .mode = 0644,
1122 .proc_handler = &proc_doulongvec_minmax,
1123 },
Lee Schermerhorn8daec962007-08-10 13:00:51 -07001124#endif
KAMEZAWA Hiroyukif0c0b2b2007-07-15 23:38:01 -07001125#ifdef CONFIG_NUMA
1126 {
1127 .ctl_name = CTL_UNNUMBERED,
1128 .procname = "numa_zonelist_order",
1129 .data = &numa_zonelist_order,
1130 .maxlen = NUMA_ZONELIST_ORDER_LEN,
1131 .mode = 0644,
1132 .proc_handler = &numa_zonelist_order_handler,
1133 .strategy = &sysctl_string,
1134 },
1135#endif
Al Viro2b8232c2007-10-13 08:16:04 +01001136#if (defined(CONFIG_X86_32) && !defined(CONFIG_UML))|| \
Paul Mundt5c36e652007-03-01 10:07:42 +09001137 (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL))
Ingo Molnare6e54942006-06-27 02:53:50 -07001138 {
1139 .ctl_name = VM_VDSO_ENABLED,
1140 .procname = "vdso_enabled",
1141 .data = &vdso_enabled,
1142 .maxlen = sizeof(vdso_enabled),
1143 .mode = 0644,
1144 .proc_handler = &proc_dointvec,
1145 .strategy = &sysctl_intvec,
1146 .extra1 = &zero,
1147 },
1148#endif
Bron Gondwana195cf4532008-02-04 22:29:20 -08001149#ifdef CONFIG_HIGHMEM
1150 {
1151 .ctl_name = CTL_UNNUMBERED,
1152 .procname = "highmem_is_dirtyable",
1153 .data = &vm_highmem_is_dirtyable,
1154 .maxlen = sizeof(vm_highmem_is_dirtyable),
1155 .mode = 0644,
1156 .proc_handler = &proc_dointvec_minmax,
1157 .strategy = &sysctl_intvec,
1158 .extra1 = &zero,
1159 .extra2 = &one,
1160 },
1161#endif
Andrew Morton2be7fe02007-07-15 23:41:21 -07001162/*
1163 * NOTE: do not add new entries to this table unless you have read
1164 * Documentation/sysctl/ctl_unnumbered.txt
1165 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 { .ctl_name = 0 }
1167};
1168
Eric W. Biederman2abc26f2007-02-14 00:34:07 -08001169#if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
Eric W. Biedermand8217f02007-10-18 03:05:22 -07001170static struct ctl_table binfmt_misc_table[] = {
Eric W. Biederman2abc26f2007-02-14 00:34:07 -08001171 { .ctl_name = 0 }
1172};
1173#endif
1174
Eric W. Biedermand8217f02007-10-18 03:05:22 -07001175static struct ctl_table fs_table[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 {
1177 .ctl_name = FS_NRINODE,
1178 .procname = "inode-nr",
1179 .data = &inodes_stat,
1180 .maxlen = 2*sizeof(int),
1181 .mode = 0444,
1182 .proc_handler = &proc_dointvec,
1183 },
1184 {
1185 .ctl_name = FS_STATINODE,
1186 .procname = "inode-state",
1187 .data = &inodes_stat,
1188 .maxlen = 7*sizeof(int),
1189 .mode = 0444,
1190 .proc_handler = &proc_dointvec,
1191 },
1192 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 .procname = "file-nr",
1194 .data = &files_stat,
1195 .maxlen = 3*sizeof(int),
1196 .mode = 0444,
Dipankar Sarma529bf6b2006-03-07 21:55:35 -08001197 .proc_handler = &proc_nr_files,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 },
1199 {
1200 .ctl_name = FS_MAXFILE,
1201 .procname = "file-max",
1202 .data = &files_stat.max_files,
1203 .maxlen = sizeof(int),
1204 .mode = 0644,
1205 .proc_handler = &proc_dointvec,
1206 },
1207 {
Eric Dumazet9cfe0152008-02-06 01:37:16 -08001208 .ctl_name = CTL_UNNUMBERED,
1209 .procname = "nr_open",
1210 .data = &sysctl_nr_open,
1211 .maxlen = sizeof(int),
1212 .mode = 0644,
Al Viroeceea0b2008-05-10 10:08:32 -04001213 .proc_handler = &proc_dointvec_minmax,
1214 .extra1 = &sysctl_nr_open_min,
1215 .extra2 = &sysctl_nr_open_max,
Eric Dumazet9cfe0152008-02-06 01:37:16 -08001216 },
1217 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 .ctl_name = FS_DENTRY,
1219 .procname = "dentry-state",
1220 .data = &dentry_stat,
1221 .maxlen = 6*sizeof(int),
1222 .mode = 0444,
1223 .proc_handler = &proc_dointvec,
1224 },
1225 {
1226 .ctl_name = FS_OVERFLOWUID,
1227 .procname = "overflowuid",
1228 .data = &fs_overflowuid,
1229 .maxlen = sizeof(int),
1230 .mode = 0644,
1231 .proc_handler = &proc_dointvec_minmax,
1232 .strategy = &sysctl_intvec,
1233 .extra1 = &minolduid,
1234 .extra2 = &maxolduid,
1235 },
1236 {
1237 .ctl_name = FS_OVERFLOWGID,
1238 .procname = "overflowgid",
1239 .data = &fs_overflowgid,
1240 .maxlen = sizeof(int),
1241 .mode = 0644,
1242 .proc_handler = &proc_dointvec_minmax,
1243 .strategy = &sysctl_intvec,
1244 .extra1 = &minolduid,
1245 .extra2 = &maxolduid,
1246 },
1247 {
1248 .ctl_name = FS_LEASES,
1249 .procname = "leases-enable",
1250 .data = &leases_enable,
1251 .maxlen = sizeof(int),
1252 .mode = 0644,
1253 .proc_handler = &proc_dointvec,
1254 },
1255#ifdef CONFIG_DNOTIFY
1256 {
1257 .ctl_name = FS_DIR_NOTIFY,
1258 .procname = "dir-notify-enable",
1259 .data = &dir_notify_enable,
1260 .maxlen = sizeof(int),
1261 .mode = 0644,
1262 .proc_handler = &proc_dointvec,
1263 },
1264#endif
1265#ifdef CONFIG_MMU
1266 {
1267 .ctl_name = FS_LEASE_TIME,
1268 .procname = "lease-break-time",
1269 .data = &lease_break_time,
1270 .maxlen = sizeof(int),
1271 .mode = 0644,
Kawai, Hidehiro76fdbb22007-07-19 01:48:26 -07001272 .proc_handler = &proc_dointvec_minmax,
1273 .strategy = &sysctl_intvec,
1274 .extra1 = &zero,
1275 .extra2 = &two,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 },
1277 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 .procname = "aio-nr",
1279 .data = &aio_nr,
1280 .maxlen = sizeof(aio_nr),
1281 .mode = 0444,
Zach Brownd55b5fd2005-11-07 00:59:31 -08001282 .proc_handler = &proc_doulongvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 },
1284 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 .procname = "aio-max-nr",
1286 .data = &aio_max_nr,
1287 .maxlen = sizeof(aio_max_nr),
1288 .mode = 0644,
Zach Brownd55b5fd2005-11-07 00:59:31 -08001289 .proc_handler = &proc_doulongvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 },
Amy Griffis2d9048e2006-06-01 13:10:59 -07001291#ifdef CONFIG_INOTIFY_USER
Robert Love0399cb02005-07-13 12:38:18 -04001292 {
1293 .ctl_name = FS_INOTIFY,
1294 .procname = "inotify",
1295 .mode = 0555,
1296 .child = inotify_table,
1297 },
1298#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299#endif
Alan Coxd6e71142005-06-23 00:09:43 -07001300 {
1301 .ctl_name = KERN_SETUID_DUMPABLE,
1302 .procname = "suid_dumpable",
1303 .data = &suid_dumpable,
1304 .maxlen = sizeof(int),
1305 .mode = 0644,
1306 .proc_handler = &proc_dointvec,
1307 },
Eric W. Biederman2abc26f2007-02-14 00:34:07 -08001308#if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
1309 {
1310 .ctl_name = CTL_UNNUMBERED,
1311 .procname = "binfmt_misc",
1312 .mode = 0555,
1313 .child = binfmt_misc_table,
1314 },
1315#endif
Andrew Morton2be7fe02007-07-15 23:41:21 -07001316/*
1317 * NOTE: do not add new entries to this table unless you have read
1318 * Documentation/sysctl/ctl_unnumbered.txt
1319 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 { .ctl_name = 0 }
1321};
1322
Eric W. Biedermand8217f02007-10-18 03:05:22 -07001323static struct ctl_table debug_table[] = {
Olof Johanssond0c3d532007-10-12 10:20:07 +10001324#if defined(CONFIG_X86) || defined(CONFIG_PPC)
Masoud Asgharifard Sharbianiabd4f752007-07-22 11:12:28 +02001325 {
1326 .ctl_name = CTL_UNNUMBERED,
1327 .procname = "exception-trace",
1328 .data = &show_unhandled_signals,
1329 .maxlen = sizeof(int),
1330 .mode = 0644,
1331 .proc_handler = proc_dointvec
1332 },
1333#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 { .ctl_name = 0 }
1335};
1336
Eric W. Biedermand8217f02007-10-18 03:05:22 -07001337static struct ctl_table dev_table[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 { .ctl_name = 0 }
Robert Love0eeca282005-07-12 17:06:03 -04001339};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340
Al Viro330d57f2005-11-04 10:18:40 +00001341static DEFINE_SPINLOCK(sysctl_lock);
1342
1343/* called under sysctl_lock */
1344static int use_table(struct ctl_table_header *p)
1345{
1346 if (unlikely(p->unregistering))
1347 return 0;
1348 p->used++;
1349 return 1;
1350}
1351
1352/* called under sysctl_lock */
1353static void unuse_table(struct ctl_table_header *p)
1354{
1355 if (!--p->used)
1356 if (unlikely(p->unregistering))
1357 complete(p->unregistering);
1358}
1359
1360/* called under sysctl_lock, will reacquire if has to wait */
1361static void start_unregistering(struct ctl_table_header *p)
1362{
1363 /*
1364 * if p->used is 0, nobody will ever touch that entry again;
1365 * we'll eliminate all paths to it before dropping sysctl_lock
1366 */
1367 if (unlikely(p->used)) {
1368 struct completion wait;
1369 init_completion(&wait);
1370 p->unregistering = &wait;
1371 spin_unlock(&sysctl_lock);
1372 wait_for_completion(&wait);
1373 spin_lock(&sysctl_lock);
1374 }
1375 /*
1376 * do not remove from the list until nobody holds it; walking the
1377 * list in do_sysctl() relies on that.
1378 */
1379 list_del_init(&p->ctl_entry);
1380}
1381
Eric W. Biederman805b5d52007-02-14 00:34:11 -08001382void sysctl_head_finish(struct ctl_table_header *head)
1383{
1384 if (!head)
1385 return;
1386 spin_lock(&sysctl_lock);
1387 unuse_table(head);
1388 spin_unlock(&sysctl_lock);
1389}
1390
Eric W. Biedermane51b6ba2007-11-30 23:54:00 +11001391static struct list_head *
1392lookup_header_list(struct ctl_table_root *root, struct nsproxy *namespaces)
Eric W. Biederman805b5d52007-02-14 00:34:11 -08001393{
Eric W. Biedermane51b6ba2007-11-30 23:54:00 +11001394 struct list_head *header_list;
1395 header_list = &root->header_list;
1396 if (root->lookup)
1397 header_list = root->lookup(root, namespaces);
1398 return header_list;
1399}
1400
1401struct ctl_table_header *__sysctl_head_next(struct nsproxy *namespaces,
1402 struct ctl_table_header *prev)
1403{
1404 struct ctl_table_root *root;
1405 struct list_head *header_list;
Eric W. Biederman805b5d52007-02-14 00:34:11 -08001406 struct ctl_table_header *head;
1407 struct list_head *tmp;
Eric W. Biedermane51b6ba2007-11-30 23:54:00 +11001408
Eric W. Biederman805b5d52007-02-14 00:34:11 -08001409 spin_lock(&sysctl_lock);
1410 if (prev) {
Eric W. Biedermane51b6ba2007-11-30 23:54:00 +11001411 head = prev;
Eric W. Biederman805b5d52007-02-14 00:34:11 -08001412 tmp = &prev->ctl_entry;
1413 unuse_table(prev);
1414 goto next;
1415 }
1416 tmp = &root_table_header.ctl_entry;
1417 for (;;) {
1418 head = list_entry(tmp, struct ctl_table_header, ctl_entry);
1419
1420 if (!use_table(head))
1421 goto next;
1422 spin_unlock(&sysctl_lock);
1423 return head;
1424 next:
Eric W. Biedermane51b6ba2007-11-30 23:54:00 +11001425 root = head->root;
Eric W. Biederman805b5d52007-02-14 00:34:11 -08001426 tmp = tmp->next;
Eric W. Biedermane51b6ba2007-11-30 23:54:00 +11001427 header_list = lookup_header_list(root, namespaces);
1428 if (tmp != header_list)
1429 continue;
1430
1431 do {
1432 root = list_entry(root->root_list.next,
1433 struct ctl_table_root, root_list);
1434 if (root == &sysctl_table_root)
1435 goto out;
1436 header_list = lookup_header_list(root, namespaces);
1437 } while (list_empty(header_list));
1438 tmp = header_list->next;
Eric W. Biederman805b5d52007-02-14 00:34:11 -08001439 }
Eric W. Biedermane51b6ba2007-11-30 23:54:00 +11001440out:
Eric W. Biederman805b5d52007-02-14 00:34:11 -08001441 spin_unlock(&sysctl_lock);
1442 return NULL;
1443}
1444
Eric W. Biedermane51b6ba2007-11-30 23:54:00 +11001445struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev)
1446{
1447 return __sysctl_head_next(current->nsproxy, prev);
1448}
1449
1450void register_sysctl_root(struct ctl_table_root *root)
1451{
1452 spin_lock(&sysctl_lock);
1453 list_add_tail(&root->root_list, &sysctl_table_root.root_list);
1454 spin_unlock(&sysctl_lock);
1455}
1456
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07001457#ifdef CONFIG_SYSCTL_SYSCALL
Pavel Emelyanov2c4c7152008-04-29 01:02:41 -07001458/* Perform the actual read/write of a sysctl table entry. */
Pavel Emelyanovd7321cd2008-04-29 01:02:44 -07001459static int do_sysctl_strategy(struct ctl_table_root *root,
1460 struct ctl_table *table,
Pavel Emelyanov2c4c7152008-04-29 01:02:41 -07001461 int __user *name, int nlen,
1462 void __user *oldval, size_t __user *oldlenp,
1463 void __user *newval, size_t newlen)
1464{
1465 int op = 0, rc;
1466
1467 if (oldval)
1468 op |= 004;
1469 if (newval)
1470 op |= 002;
Pavel Emelyanovd7321cd2008-04-29 01:02:44 -07001471 if (sysctl_perm(root, table, op))
Pavel Emelyanov2c4c7152008-04-29 01:02:41 -07001472 return -EPERM;
1473
1474 if (table->strategy) {
1475 rc = table->strategy(table, name, nlen, oldval, oldlenp,
1476 newval, newlen);
1477 if (rc < 0)
1478 return rc;
1479 if (rc > 0)
1480 return 0;
1481 }
1482
1483 /* If there is no strategy routine, or if the strategy returns
1484 * zero, proceed with automatic r/w */
1485 if (table->data && table->maxlen) {
1486 rc = sysctl_data(table, name, nlen, oldval, oldlenp,
1487 newval, newlen);
1488 if (rc < 0)
1489 return rc;
1490 }
1491 return 0;
1492}
1493
1494static int parse_table(int __user *name, int nlen,
1495 void __user *oldval, size_t __user *oldlenp,
1496 void __user *newval, size_t newlen,
Pavel Emelyanovd7321cd2008-04-29 01:02:44 -07001497 struct ctl_table_root *root,
Pavel Emelyanov2c4c7152008-04-29 01:02:41 -07001498 struct ctl_table *table)
1499{
1500 int n;
1501repeat:
1502 if (!nlen)
1503 return -ENOTDIR;
1504 if (get_user(n, name))
1505 return -EFAULT;
1506 for ( ; table->ctl_name || table->procname; table++) {
1507 if (!table->ctl_name)
1508 continue;
1509 if (n == table->ctl_name) {
1510 int error;
1511 if (table->child) {
Pavel Emelyanovd7321cd2008-04-29 01:02:44 -07001512 if (sysctl_perm(root, table, 001))
Pavel Emelyanov2c4c7152008-04-29 01:02:41 -07001513 return -EPERM;
1514 name++;
1515 nlen--;
1516 table = table->child;
1517 goto repeat;
1518 }
Pavel Emelyanovd7321cd2008-04-29 01:02:44 -07001519 error = do_sysctl_strategy(root, table, name, nlen,
Pavel Emelyanov2c4c7152008-04-29 01:02:41 -07001520 oldval, oldlenp,
1521 newval, newlen);
1522 return error;
1523 }
1524 }
1525 return -ENOTDIR;
1526}
1527
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
1529 void __user *newval, size_t newlen)
1530{
Eric W. Biederman805b5d52007-02-14 00:34:11 -08001531 struct ctl_table_header *head;
Al Viro330d57f2005-11-04 10:18:40 +00001532 int error = -ENOTDIR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533
1534 if (nlen <= 0 || nlen >= CTL_MAXNAME)
1535 return -ENOTDIR;
1536 if (oldval) {
1537 int old_len;
1538 if (!oldlenp || get_user(old_len, oldlenp))
1539 return -EFAULT;
1540 }
Al Viro330d57f2005-11-04 10:18:40 +00001541
Eric W. Biederman805b5d52007-02-14 00:34:11 -08001542 for (head = sysctl_head_next(NULL); head;
1543 head = sysctl_head_next(head)) {
Al Viro330d57f2005-11-04 10:18:40 +00001544 error = parse_table(name, nlen, oldval, oldlenp,
Pavel Emelyanovd7321cd2008-04-29 01:02:44 -07001545 newval, newlen,
1546 head->root, head->ctl_table);
Eric W. Biederman805b5d52007-02-14 00:34:11 -08001547 if (error != -ENOTDIR) {
1548 sysctl_head_finish(head);
Al Viro330d57f2005-11-04 10:18:40 +00001549 break;
Eric W. Biederman805b5d52007-02-14 00:34:11 -08001550 }
1551 }
Al Viro330d57f2005-11-04 10:18:40 +00001552 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553}
1554
1555asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
1556{
1557 struct __sysctl_args tmp;
1558 int error;
1559
1560 if (copy_from_user(&tmp, args, sizeof(tmp)))
1561 return -EFAULT;
1562
Eric W. Biederman7058cb02007-10-18 03:05:58 -07001563 error = deprecated_sysctl_warning(&tmp);
1564 if (error)
1565 goto out;
1566
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 lock_kernel();
1568 error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp,
1569 tmp.newval, tmp.newlen);
1570 unlock_kernel();
Eric W. Biederman7058cb02007-10-18 03:05:58 -07001571out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 return error;
1573}
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07001574#endif /* CONFIG_SYSCTL_SYSCALL */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575
1576/*
Eric W. Biederman1ff007e2007-02-14 00:34:11 -08001577 * sysctl_perm does NOT grant the superuser all rights automatically, because
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 * some sysctl variables are readonly even to root.
1579 */
1580
1581static int test_perm(int mode, int op)
1582{
1583 if (!current->euid)
1584 mode >>= 6;
1585 else if (in_egroup_p(0))
1586 mode >>= 3;
1587 if ((mode & op & 0007) == op)
1588 return 0;
1589 return -EACCES;
1590}
1591
Pavel Emelyanovd7321cd2008-04-29 01:02:44 -07001592int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593{
1594 int error;
Pavel Emelyanovd7321cd2008-04-29 01:02:44 -07001595 int mode;
1596
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 error = security_sysctl(table, op);
1598 if (error)
1599 return error;
Pavel Emelyanovd7321cd2008-04-29 01:02:44 -07001600
1601 if (root->permissions)
1602 mode = root->permissions(root, current->nsproxy, table);
1603 else
1604 mode = table->mode;
1605
1606 return test_perm(mode, op);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607}
1608
Eric W. Biedermand912b0c2007-02-14 00:34:13 -08001609static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table)
1610{
1611 for (; table->ctl_name || table->procname; table++) {
1612 table->parent = parent;
1613 if (table->child)
1614 sysctl_set_parent(table, table->child);
1615 }
1616}
1617
1618static __init int sysctl_init(void)
1619{
1620 sysctl_set_parent(NULL, root_table);
Holger Schurig88f458e2008-04-29 01:02:36 -07001621#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
1622 {
1623 int err;
1624 err = sysctl_check_table(current->nsproxy, root_table);
1625 }
1626#endif
Eric W. Biedermand912b0c2007-02-14 00:34:13 -08001627 return 0;
1628}
1629
1630core_initcall(sysctl_init);
1631
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632/**
Eric W. Biedermane51b6ba2007-11-30 23:54:00 +11001633 * __register_sysctl_paths - register a sysctl hierarchy
1634 * @root: List of sysctl headers to register on
1635 * @namespaces: Data to compute which lists of sysctl entries are visible
Eric W. Biederman29e796f2007-11-30 23:50:18 +11001636 * @path: The path to the directory the sysctl table is in.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 * @table: the top-level table structure
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 *
1639 * Register a sysctl table hierarchy. @table should be a filled in ctl_table
Eric W. Biederman29e796f2007-11-30 23:50:18 +11001640 * array. A completely 0 filled entry terminates the table.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 *
Eric W. Biedermand8217f02007-10-18 03:05:22 -07001642 * The members of the &struct ctl_table structure are used as follows:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 *
1644 * ctl_name - This is the numeric sysctl value used by sysctl(2). The number
1645 * must be unique within that level of sysctl
1646 *
1647 * procname - the name of the sysctl file under /proc/sys. Set to %NULL to not
1648 * enter a sysctl file
1649 *
1650 * data - a pointer to data for use by proc_handler
1651 *
1652 * maxlen - the maximum size in bytes of the data
1653 *
1654 * mode - the file permissions for the /proc/sys file, and for sysctl(2)
1655 *
1656 * child - a pointer to the child sysctl table if this entry is a directory, or
1657 * %NULL.
1658 *
1659 * proc_handler - the text handler routine (described below)
1660 *
1661 * strategy - the strategy routine (described below)
1662 *
1663 * de - for internal use by the sysctl routines
1664 *
1665 * extra1, extra2 - extra pointers usable by the proc handler routines
1666 *
1667 * Leaf nodes in the sysctl tree will be represented by a single file
1668 * under /proc; non-leaf nodes will be represented by directories.
1669 *
1670 * sysctl(2) can automatically manage read and write requests through
1671 * the sysctl table. The data and maxlen fields of the ctl_table
1672 * struct enable minimal validation of the values being written to be
1673 * performed, and the mode field allows minimal authentication.
1674 *
1675 * More sophisticated management can be enabled by the provision of a
1676 * strategy routine with the table entry. This will be called before
1677 * any automatic read or write of the data is performed.
1678 *
1679 * The strategy routine may return
1680 *
1681 * < 0 - Error occurred (error is passed to user process)
1682 *
1683 * 0 - OK - proceed with automatic read or write.
1684 *
1685 * > 0 - OK - read or write has been done by the strategy routine, so
1686 * return immediately.
1687 *
1688 * There must be a proc_handler routine for any terminal nodes
1689 * mirrored under /proc/sys (non-terminals are handled by a built-in
1690 * directory handler). Several default handlers are available to
1691 * cover common cases -
1692 *
1693 * proc_dostring(), proc_dointvec(), proc_dointvec_jiffies(),
1694 * proc_dointvec_userhz_jiffies(), proc_dointvec_minmax(),
1695 * proc_doulongvec_ms_jiffies_minmax(), proc_doulongvec_minmax()
1696 *
1697 * It is the handler's job to read the input buffer from user memory
1698 * and process it. The handler should return 0 on success.
1699 *
1700 * This routine returns %NULL on a failure to register, and a pointer
1701 * to the table header on success.
1702 */
Eric W. Biedermane51b6ba2007-11-30 23:54:00 +11001703struct ctl_table_header *__register_sysctl_paths(
1704 struct ctl_table_root *root,
1705 struct nsproxy *namespaces,
1706 const struct ctl_path *path, struct ctl_table *table)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707{
Eric W. Biedermane51b6ba2007-11-30 23:54:00 +11001708 struct list_head *header_list;
Eric W. Biederman29e796f2007-11-30 23:50:18 +11001709 struct ctl_table_header *header;
1710 struct ctl_table *new, **prevp;
1711 unsigned int n, npath;
1712
1713 /* Count the path components */
1714 for (npath = 0; path[npath].ctl_name || path[npath].procname; ++npath)
1715 ;
1716
1717 /*
1718 * For each path component, allocate a 2-element ctl_table array.
1719 * The first array element will be filled with the sysctl entry
1720 * for this, the second will be the sentinel (ctl_name == 0).
1721 *
1722 * We allocate everything in one go so that we don't have to
1723 * worry about freeing additional memory in unregister_sysctl_table.
1724 */
1725 header = kzalloc(sizeof(struct ctl_table_header) +
1726 (2 * npath * sizeof(struct ctl_table)), GFP_KERNEL);
1727 if (!header)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 return NULL;
Eric W. Biederman29e796f2007-11-30 23:50:18 +11001729
1730 new = (struct ctl_table *) (header + 1);
1731
1732 /* Now connect the dots */
1733 prevp = &header->ctl_table;
1734 for (n = 0; n < npath; ++n, ++path) {
1735 /* Copy the procname */
1736 new->procname = path->procname;
1737 new->ctl_name = path->ctl_name;
1738 new->mode = 0555;
1739
1740 *prevp = new;
1741 prevp = &new->child;
1742
1743 new += 2;
1744 }
1745 *prevp = table;
Eric W. Biederman23eb06d2007-11-30 23:52:10 +11001746 header->ctl_table_arg = table;
Eric W. Biederman29e796f2007-11-30 23:50:18 +11001747
1748 INIT_LIST_HEAD(&header->ctl_entry);
1749 header->used = 0;
1750 header->unregistering = NULL;
Eric W. Biedermane51b6ba2007-11-30 23:54:00 +11001751 header->root = root;
Eric W. Biederman29e796f2007-11-30 23:50:18 +11001752 sysctl_set_parent(NULL, header->ctl_table);
Holger Schurig88f458e2008-04-29 01:02:36 -07001753#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
Eric W. Biedermane51b6ba2007-11-30 23:54:00 +11001754 if (sysctl_check_table(namespaces, header->ctl_table)) {
Eric W. Biederman29e796f2007-11-30 23:50:18 +11001755 kfree(header);
Eric W. Biedermanfc6cd252007-10-18 03:05:54 -07001756 return NULL;
1757 }
Holger Schurig88f458e2008-04-29 01:02:36 -07001758#endif
Al Viro330d57f2005-11-04 10:18:40 +00001759 spin_lock(&sysctl_lock);
Eric W. Biedermane51b6ba2007-11-30 23:54:00 +11001760 header_list = lookup_header_list(root, namespaces);
1761 list_add_tail(&header->ctl_entry, header_list);
Al Viro330d57f2005-11-04 10:18:40 +00001762 spin_unlock(&sysctl_lock);
Eric W. Biederman29e796f2007-11-30 23:50:18 +11001763
1764 return header;
1765}
1766
1767/**
Eric W. Biedermane51b6ba2007-11-30 23:54:00 +11001768 * register_sysctl_table_path - register a sysctl table hierarchy
1769 * @path: The path to the directory the sysctl table is in.
1770 * @table: the top-level table structure
1771 *
1772 * Register a sysctl table hierarchy. @table should be a filled in ctl_table
1773 * array. A completely 0 filled entry terminates the table.
1774 *
1775 * See __register_sysctl_paths for more details.
1776 */
1777struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path,
1778 struct ctl_table *table)
1779{
1780 return __register_sysctl_paths(&sysctl_table_root, current->nsproxy,
1781 path, table);
1782}
1783
1784/**
Eric W. Biederman29e796f2007-11-30 23:50:18 +11001785 * register_sysctl_table - register a sysctl table hierarchy
1786 * @table: the top-level table structure
1787 *
1788 * Register a sysctl table hierarchy. @table should be a filled in ctl_table
1789 * array. A completely 0 filled entry terminates the table.
1790 *
1791 * See register_sysctl_paths for more details.
1792 */
1793struct ctl_table_header *register_sysctl_table(struct ctl_table *table)
1794{
1795 static const struct ctl_path null_path[] = { {} };
1796
1797 return register_sysctl_paths(null_path, table);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798}
1799
1800/**
1801 * unregister_sysctl_table - unregister a sysctl table hierarchy
1802 * @header: the header returned from register_sysctl_table
1803 *
1804 * Unregisters the sysctl table and all children. proc entries may not
1805 * actually be removed until they are no longer used by anyone.
1806 */
1807void unregister_sysctl_table(struct ctl_table_header * header)
1808{
Al Viro330d57f2005-11-04 10:18:40 +00001809 might_sleep();
Pavel Emelyanovf1dad162007-12-04 23:45:24 -08001810
1811 if (header == NULL)
1812 return;
1813
Al Viro330d57f2005-11-04 10:18:40 +00001814 spin_lock(&sysctl_lock);
1815 start_unregistering(header);
Al Viro330d57f2005-11-04 10:18:40 +00001816 spin_unlock(&sysctl_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 kfree(header);
1818}
1819
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07001820#else /* !CONFIG_SYSCTL */
Eric W. Biedermand8217f02007-10-18 03:05:22 -07001821struct ctl_table_header *register_sysctl_table(struct ctl_table * table)
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07001822{
1823 return NULL;
1824}
1825
Eric W. Biederman29e796f2007-11-30 23:50:18 +11001826struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path,
1827 struct ctl_table *table)
1828{
1829 return NULL;
1830}
1831
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07001832void unregister_sysctl_table(struct ctl_table_header * table)
1833{
1834}
1835
1836#endif /* CONFIG_SYSCTL */
1837
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838/*
1839 * /proc/sys support
1840 */
1841
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07001842#ifdef CONFIG_PROC_SYSCTL
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843
Adrian Bunkb1ba4dd2006-10-02 02:18:05 -07001844static int _proc_do_string(void* data, int maxlen, int write,
1845 struct file *filp, void __user *buffer,
1846 size_t *lenp, loff_t *ppos)
Sam Vilainf5dd3d62006-10-02 02:18:04 -07001847{
1848 size_t len;
1849 char __user *p;
1850 char c;
Oleg Nesterov8d060872007-02-10 01:46:38 -08001851
1852 if (!data || !maxlen || !*lenp) {
Sam Vilainf5dd3d62006-10-02 02:18:04 -07001853 *lenp = 0;
1854 return 0;
1855 }
Oleg Nesterov8d060872007-02-10 01:46:38 -08001856
Sam Vilainf5dd3d62006-10-02 02:18:04 -07001857 if (write) {
1858 len = 0;
1859 p = buffer;
1860 while (len < *lenp) {
1861 if (get_user(c, p++))
1862 return -EFAULT;
1863 if (c == 0 || c == '\n')
1864 break;
1865 len++;
1866 }
1867 if (len >= maxlen)
1868 len = maxlen-1;
1869 if(copy_from_user(data, buffer, len))
1870 return -EFAULT;
1871 ((char *) data)[len] = 0;
1872 *ppos += *lenp;
1873 } else {
1874 len = strlen(data);
1875 if (len > maxlen)
1876 len = maxlen;
Oleg Nesterov8d060872007-02-10 01:46:38 -08001877
1878 if (*ppos > len) {
1879 *lenp = 0;
1880 return 0;
1881 }
1882
1883 data += *ppos;
1884 len -= *ppos;
1885
Sam Vilainf5dd3d62006-10-02 02:18:04 -07001886 if (len > *lenp)
1887 len = *lenp;
1888 if (len)
1889 if(copy_to_user(buffer, data, len))
1890 return -EFAULT;
1891 if (len < *lenp) {
1892 if(put_user('\n', ((char __user *) buffer) + len))
1893 return -EFAULT;
1894 len++;
1895 }
1896 *lenp = len;
1897 *ppos += len;
1898 }
1899 return 0;
1900}
1901
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902/**
1903 * proc_dostring - read a string sysctl
1904 * @table: the sysctl table
1905 * @write: %TRUE if this is a write to the sysctl file
1906 * @filp: the file structure
1907 * @buffer: the user buffer
1908 * @lenp: the size of the user buffer
1909 * @ppos: file position
1910 *
1911 * Reads/writes a string from/to the user buffer. If the kernel
1912 * buffer provided is not large enough to hold the string, the
1913 * string is truncated. The copied string is %NULL-terminated.
1914 * If the string is being read by the user process, it is copied
1915 * and a newline '\n' is added. It is truncated if the buffer is
1916 * not large enough.
1917 *
1918 * Returns 0 on success.
1919 */
Eric W. Biedermand8217f02007-10-18 03:05:22 -07001920int proc_dostring(struct ctl_table *table, int write, struct file *filp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 void __user *buffer, size_t *lenp, loff_t *ppos)
1922{
Sam Vilainf5dd3d62006-10-02 02:18:04 -07001923 return _proc_do_string(table->data, table->maxlen, write, filp,
1924 buffer, lenp, ppos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925}
1926
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927
1928static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp,
1929 int *valp,
1930 int write, void *data)
1931{
1932 if (write) {
1933 *valp = *negp ? -*lvalp : *lvalp;
1934 } else {
1935 int val = *valp;
1936 if (val < 0) {
1937 *negp = -1;
1938 *lvalp = (unsigned long)-val;
1939 } else {
1940 *negp = 0;
1941 *lvalp = (unsigned long)val;
1942 }
1943 }
1944 return 0;
1945}
1946
Eric W. Biedermand8217f02007-10-18 03:05:22 -07001947static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07001948 int write, struct file *filp, void __user *buffer,
1949 size_t *lenp, loff_t *ppos,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 int (*conv)(int *negp, unsigned long *lvalp, int *valp,
1951 int write, void *data),
1952 void *data)
1953{
1954#define TMPBUFLEN 21
1955 int *i, vleft, first=1, neg, val;
1956 unsigned long lval;
1957 size_t left, len;
1958
1959 char buf[TMPBUFLEN], *p;
1960 char __user *s = buffer;
1961
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07001962 if (!tbl_data || !table->maxlen || !*lenp ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 (*ppos && !write)) {
1964 *lenp = 0;
1965 return 0;
1966 }
1967
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07001968 i = (int *) tbl_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 vleft = table->maxlen / sizeof(*i);
1970 left = *lenp;
1971
1972 if (!conv)
1973 conv = do_proc_dointvec_conv;
1974
1975 for (; left && vleft--; i++, first=0) {
1976 if (write) {
1977 while (left) {
1978 char c;
1979 if (get_user(c, s))
1980 return -EFAULT;
1981 if (!isspace(c))
1982 break;
1983 left--;
1984 s++;
1985 }
1986 if (!left)
1987 break;
1988 neg = 0;
1989 len = left;
1990 if (len > sizeof(buf) - 1)
1991 len = sizeof(buf) - 1;
1992 if (copy_from_user(buf, s, len))
1993 return -EFAULT;
1994 buf[len] = 0;
1995 p = buf;
1996 if (*p == '-' && left > 1) {
1997 neg = 1;
BP, Praveenbd9b0ba2006-12-06 20:39:09 -08001998 p++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 }
2000 if (*p < '0' || *p > '9')
2001 break;
2002
2003 lval = simple_strtoul(p, &p, 0);
2004
2005 len = p-buf;
2006 if ((len < left) && *p && !isspace(*p))
2007 break;
2008 if (neg)
2009 val = -val;
2010 s += len;
2011 left -= len;
2012
2013 if (conv(&neg, &lval, i, 1, data))
2014 break;
2015 } else {
2016 p = buf;
2017 if (!first)
2018 *p++ = '\t';
2019
2020 if (conv(&neg, &lval, i, 0, data))
2021 break;
2022
2023 sprintf(p, "%s%lu", neg ? "-" : "", lval);
2024 len = strlen(buf);
2025 if (len > left)
2026 len = left;
2027 if(copy_to_user(s, buf, len))
2028 return -EFAULT;
2029 left -= len;
2030 s += len;
2031 }
2032 }
2033
2034 if (!write && !first && left) {
2035 if(put_user('\n', s))
2036 return -EFAULT;
2037 left--, s++;
2038 }
2039 if (write) {
2040 while (left) {
2041 char c;
2042 if (get_user(c, s++))
2043 return -EFAULT;
2044 if (!isspace(c))
2045 break;
2046 left--;
2047 }
2048 }
2049 if (write && first)
2050 return -EINVAL;
2051 *lenp -= left;
2052 *ppos += *lenp;
2053 return 0;
2054#undef TMPBUFLEN
2055}
2056
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002057static int do_proc_dointvec(struct ctl_table *table, int write, struct file *filp,
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07002058 void __user *buffer, size_t *lenp, loff_t *ppos,
2059 int (*conv)(int *negp, unsigned long *lvalp, int *valp,
2060 int write, void *data),
2061 void *data)
2062{
2063 return __do_proc_dointvec(table->data, table, write, filp,
2064 buffer, lenp, ppos, conv, data);
2065}
2066
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067/**
2068 * proc_dointvec - read a vector of integers
2069 * @table: the sysctl table
2070 * @write: %TRUE if this is a write to the sysctl file
2071 * @filp: the file structure
2072 * @buffer: the user buffer
2073 * @lenp: the size of the user buffer
2074 * @ppos: file position
2075 *
2076 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
2077 * values from/to the user buffer, treated as an ASCII string.
2078 *
2079 * Returns 0 on success.
2080 */
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002081int proc_dointvec(struct ctl_table *table, int write, struct file *filp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 void __user *buffer, size_t *lenp, loff_t *ppos)
2083{
2084 return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
2085 NULL,NULL);
2086}
2087
2088#define OP_SET 0
2089#define OP_AND 1
Theodore Ts'o34f5a392007-02-10 01:45:24 -08002090#define OP_OR 2
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091
2092static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
2093 int *valp,
2094 int write, void *data)
2095{
2096 int op = *(int *)data;
2097 if (write) {
2098 int val = *negp ? -*lvalp : *lvalp;
2099 switch(op) {
2100 case OP_SET: *valp = val; break;
2101 case OP_AND: *valp &= val; break;
Theodore Ts'o34f5a392007-02-10 01:45:24 -08002102 case OP_OR: *valp |= val; break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 }
2104 } else {
2105 int val = *valp;
2106 if (val < 0) {
2107 *negp = -1;
2108 *lvalp = (unsigned long)-val;
2109 } else {
2110 *negp = 0;
2111 *lvalp = (unsigned long)val;
2112 }
2113 }
2114 return 0;
2115}
2116
Theodore Ts'o34f5a392007-02-10 01:45:24 -08002117/*
2118 * Taint values can only be increased
2119 */
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002120static int proc_dointvec_taint(struct ctl_table *table, int write, struct file *filp,
Theodore Ts'o34f5a392007-02-10 01:45:24 -08002121 void __user *buffer, size_t *lenp, loff_t *ppos)
2122{
2123 int op;
2124
Bastian Blank91fcd412007-04-23 14:41:14 -07002125 if (write && !capable(CAP_SYS_ADMIN))
Theodore Ts'o34f5a392007-02-10 01:45:24 -08002126 return -EPERM;
2127
2128 op = OP_OR;
2129 return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
2130 do_proc_dointvec_bset_conv,&op);
2131}
2132
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133struct do_proc_dointvec_minmax_conv_param {
2134 int *min;
2135 int *max;
2136};
2137
2138static int do_proc_dointvec_minmax_conv(int *negp, unsigned long *lvalp,
2139 int *valp,
2140 int write, void *data)
2141{
2142 struct do_proc_dointvec_minmax_conv_param *param = data;
2143 if (write) {
2144 int val = *negp ? -*lvalp : *lvalp;
2145 if ((param->min && *param->min > val) ||
2146 (param->max && *param->max < val))
2147 return -EINVAL;
2148 *valp = val;
2149 } else {
2150 int val = *valp;
2151 if (val < 0) {
2152 *negp = -1;
2153 *lvalp = (unsigned long)-val;
2154 } else {
2155 *negp = 0;
2156 *lvalp = (unsigned long)val;
2157 }
2158 }
2159 return 0;
2160}
2161
2162/**
2163 * proc_dointvec_minmax - read a vector of integers with min/max values
2164 * @table: the sysctl table
2165 * @write: %TRUE if this is a write to the sysctl file
2166 * @filp: the file structure
2167 * @buffer: the user buffer
2168 * @lenp: the size of the user buffer
2169 * @ppos: file position
2170 *
2171 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
2172 * values from/to the user buffer, treated as an ASCII string.
2173 *
2174 * This routine will ensure the values are within the range specified by
2175 * table->extra1 (min) and table->extra2 (max).
2176 *
2177 * Returns 0 on success.
2178 */
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002179int proc_dointvec_minmax(struct ctl_table *table, int write, struct file *filp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180 void __user *buffer, size_t *lenp, loff_t *ppos)
2181{
2182 struct do_proc_dointvec_minmax_conv_param param = {
2183 .min = (int *) table->extra1,
2184 .max = (int *) table->extra2,
2185 };
2186 return do_proc_dointvec(table, write, filp, buffer, lenp, ppos,
2187 do_proc_dointvec_minmax_conv, &param);
2188}
2189
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002190static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int write,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 struct file *filp,
2192 void __user *buffer,
2193 size_t *lenp, loff_t *ppos,
2194 unsigned long convmul,
2195 unsigned long convdiv)
2196{
2197#define TMPBUFLEN 21
2198 unsigned long *i, *min, *max, val;
2199 int vleft, first=1, neg;
2200 size_t len, left;
2201 char buf[TMPBUFLEN], *p;
2202 char __user *s = buffer;
2203
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07002204 if (!data || !table->maxlen || !*lenp ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205 (*ppos && !write)) {
2206 *lenp = 0;
2207 return 0;
2208 }
2209
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07002210 i = (unsigned long *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 min = (unsigned long *) table->extra1;
2212 max = (unsigned long *) table->extra2;
2213 vleft = table->maxlen / sizeof(unsigned long);
2214 left = *lenp;
2215
2216 for (; left && vleft--; i++, min++, max++, first=0) {
2217 if (write) {
2218 while (left) {
2219 char c;
2220 if (get_user(c, s))
2221 return -EFAULT;
2222 if (!isspace(c))
2223 break;
2224 left--;
2225 s++;
2226 }
2227 if (!left)
2228 break;
2229 neg = 0;
2230 len = left;
2231 if (len > TMPBUFLEN-1)
2232 len = TMPBUFLEN-1;
2233 if (copy_from_user(buf, s, len))
2234 return -EFAULT;
2235 buf[len] = 0;
2236 p = buf;
2237 if (*p == '-' && left > 1) {
2238 neg = 1;
BP, Praveenbd9b0ba2006-12-06 20:39:09 -08002239 p++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240 }
2241 if (*p < '0' || *p > '9')
2242 break;
2243 val = simple_strtoul(p, &p, 0) * convmul / convdiv ;
2244 len = p-buf;
2245 if ((len < left) && *p && !isspace(*p))
2246 break;
2247 if (neg)
2248 val = -val;
2249 s += len;
2250 left -= len;
2251
2252 if(neg)
2253 continue;
2254 if ((min && val < *min) || (max && val > *max))
2255 continue;
2256 *i = val;
2257 } else {
2258 p = buf;
2259 if (!first)
2260 *p++ = '\t';
2261 sprintf(p, "%lu", convdiv * (*i) / convmul);
2262 len = strlen(buf);
2263 if (len > left)
2264 len = left;
2265 if(copy_to_user(s, buf, len))
2266 return -EFAULT;
2267 left -= len;
2268 s += len;
2269 }
2270 }
2271
2272 if (!write && !first && left) {
2273 if(put_user('\n', s))
2274 return -EFAULT;
2275 left--, s++;
2276 }
2277 if (write) {
2278 while (left) {
2279 char c;
2280 if (get_user(c, s++))
2281 return -EFAULT;
2282 if (!isspace(c))
2283 break;
2284 left--;
2285 }
2286 }
2287 if (write && first)
2288 return -EINVAL;
2289 *lenp -= left;
2290 *ppos += *lenp;
2291 return 0;
2292#undef TMPBUFLEN
2293}
2294
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002295static int do_proc_doulongvec_minmax(struct ctl_table *table, int write,
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07002296 struct file *filp,
2297 void __user *buffer,
2298 size_t *lenp, loff_t *ppos,
2299 unsigned long convmul,
2300 unsigned long convdiv)
2301{
2302 return __do_proc_doulongvec_minmax(table->data, table, write,
2303 filp, buffer, lenp, ppos, convmul, convdiv);
2304}
2305
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306/**
2307 * proc_doulongvec_minmax - read a vector of long integers with min/max values
2308 * @table: the sysctl table
2309 * @write: %TRUE if this is a write to the sysctl file
2310 * @filp: the file structure
2311 * @buffer: the user buffer
2312 * @lenp: the size of the user buffer
2313 * @ppos: file position
2314 *
2315 * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
2316 * values from/to the user buffer, treated as an ASCII string.
2317 *
2318 * This routine will ensure the values are within the range specified by
2319 * table->extra1 (min) and table->extra2 (max).
2320 *
2321 * Returns 0 on success.
2322 */
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002323int proc_doulongvec_minmax(struct ctl_table *table, int write, struct file *filp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 void __user *buffer, size_t *lenp, loff_t *ppos)
2325{
2326 return do_proc_doulongvec_minmax(table, write, filp, buffer, lenp, ppos, 1l, 1l);
2327}
2328
2329/**
2330 * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values
2331 * @table: the sysctl table
2332 * @write: %TRUE if this is a write to the sysctl file
2333 * @filp: the file structure
2334 * @buffer: the user buffer
2335 * @lenp: the size of the user buffer
2336 * @ppos: file position
2337 *
2338 * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
2339 * values from/to the user buffer, treated as an ASCII string. The values
2340 * are treated as milliseconds, and converted to jiffies when they are stored.
2341 *
2342 * This routine will ensure the values are within the range specified by
2343 * table->extra1 (min) and table->extra2 (max).
2344 *
2345 * Returns 0 on success.
2346 */
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002347int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 struct file *filp,
2349 void __user *buffer,
2350 size_t *lenp, loff_t *ppos)
2351{
2352 return do_proc_doulongvec_minmax(table, write, filp, buffer,
2353 lenp, ppos, HZ, 1000l);
2354}
2355
2356
2357static int do_proc_dointvec_jiffies_conv(int *negp, unsigned long *lvalp,
2358 int *valp,
2359 int write, void *data)
2360{
2361 if (write) {
Bart Samwelcba9f332006-03-24 03:15:50 -08002362 if (*lvalp > LONG_MAX / HZ)
2363 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364 *valp = *negp ? -(*lvalp*HZ) : (*lvalp*HZ);
2365 } else {
2366 int val = *valp;
2367 unsigned long lval;
2368 if (val < 0) {
2369 *negp = -1;
2370 lval = (unsigned long)-val;
2371 } else {
2372 *negp = 0;
2373 lval = (unsigned long)val;
2374 }
2375 *lvalp = lval / HZ;
2376 }
2377 return 0;
2378}
2379
2380static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp,
2381 int *valp,
2382 int write, void *data)
2383{
2384 if (write) {
Bart Samwelcba9f332006-03-24 03:15:50 -08002385 if (USER_HZ < HZ && *lvalp > (LONG_MAX / HZ) * USER_HZ)
2386 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 *valp = clock_t_to_jiffies(*negp ? -*lvalp : *lvalp);
2388 } else {
2389 int val = *valp;
2390 unsigned long lval;
2391 if (val < 0) {
2392 *negp = -1;
2393 lval = (unsigned long)-val;
2394 } else {
2395 *negp = 0;
2396 lval = (unsigned long)val;
2397 }
2398 *lvalp = jiffies_to_clock_t(lval);
2399 }
2400 return 0;
2401}
2402
2403static int do_proc_dointvec_ms_jiffies_conv(int *negp, unsigned long *lvalp,
2404 int *valp,
2405 int write, void *data)
2406{
2407 if (write) {
2408 *valp = msecs_to_jiffies(*negp ? -*lvalp : *lvalp);
2409 } else {
2410 int val = *valp;
2411 unsigned long lval;
2412 if (val < 0) {
2413 *negp = -1;
2414 lval = (unsigned long)-val;
2415 } else {
2416 *negp = 0;
2417 lval = (unsigned long)val;
2418 }
2419 *lvalp = jiffies_to_msecs(lval);
2420 }
2421 return 0;
2422}
2423
2424/**
2425 * proc_dointvec_jiffies - read a vector of integers as seconds
2426 * @table: the sysctl table
2427 * @write: %TRUE if this is a write to the sysctl file
2428 * @filp: the file structure
2429 * @buffer: the user buffer
2430 * @lenp: the size of the user buffer
2431 * @ppos: file position
2432 *
2433 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
2434 * values from/to the user buffer, treated as an ASCII string.
2435 * The values read are assumed to be in seconds, and are converted into
2436 * jiffies.
2437 *
2438 * Returns 0 on success.
2439 */
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002440int proc_dointvec_jiffies(struct ctl_table *table, int write, struct file *filp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441 void __user *buffer, size_t *lenp, loff_t *ppos)
2442{
2443 return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
2444 do_proc_dointvec_jiffies_conv,NULL);
2445}
2446
2447/**
2448 * proc_dointvec_userhz_jiffies - read a vector of integers as 1/USER_HZ seconds
2449 * @table: the sysctl table
2450 * @write: %TRUE if this is a write to the sysctl file
2451 * @filp: the file structure
2452 * @buffer: the user buffer
2453 * @lenp: the size of the user buffer
Randy Dunlap1e5d5332005-11-07 01:01:06 -08002454 * @ppos: pointer to the file position
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 *
2456 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
2457 * values from/to the user buffer, treated as an ASCII string.
2458 * The values read are assumed to be in 1/USER_HZ seconds, and
2459 * are converted into jiffies.
2460 *
2461 * Returns 0 on success.
2462 */
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002463int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write, struct file *filp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 void __user *buffer, size_t *lenp, loff_t *ppos)
2465{
2466 return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
2467 do_proc_dointvec_userhz_jiffies_conv,NULL);
2468}
2469
2470/**
2471 * proc_dointvec_ms_jiffies - read a vector of integers as 1 milliseconds
2472 * @table: the sysctl table
2473 * @write: %TRUE if this is a write to the sysctl file
2474 * @filp: the file structure
2475 * @buffer: the user buffer
2476 * @lenp: the size of the user buffer
Martin Waitz67be2dd2005-05-01 08:59:26 -07002477 * @ppos: file position
2478 * @ppos: the current position in the file
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 *
2480 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
2481 * values from/to the user buffer, treated as an ASCII string.
2482 * The values read are assumed to be in 1/1000 seconds, and
2483 * are converted into jiffies.
2484 *
2485 * Returns 0 on success.
2486 */
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002487int proc_dointvec_ms_jiffies(struct ctl_table *table, int write, struct file *filp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 void __user *buffer, size_t *lenp, loff_t *ppos)
2489{
2490 return do_proc_dointvec(table, write, filp, buffer, lenp, ppos,
2491 do_proc_dointvec_ms_jiffies_conv, NULL);
2492}
2493
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002494static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp,
Cedric Le Goater9ec52092006-10-02 02:19:00 -07002495 void __user *buffer, size_t *lenp, loff_t *ppos)
2496{
2497 struct pid *new_pid;
2498 pid_t tmp;
2499 int r;
2500
Pavel Emelyanov6c5f3e72008-02-08 04:19:20 -08002501 tmp = pid_vnr(cad_pid);
Cedric Le Goater9ec52092006-10-02 02:19:00 -07002502
2503 r = __do_proc_dointvec(&tmp, table, write, filp, buffer,
2504 lenp, ppos, NULL, NULL);
2505 if (r || !write)
2506 return r;
2507
2508 new_pid = find_get_pid(tmp);
2509 if (!new_pid)
2510 return -ESRCH;
2511
2512 put_pid(xchg(&cad_pid, new_pid));
2513 return 0;
2514}
2515
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516#else /* CONFIG_PROC_FS */
2517
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002518int proc_dostring(struct ctl_table *table, int write, struct file *filp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519 void __user *buffer, size_t *lenp, loff_t *ppos)
2520{
2521 return -ENOSYS;
2522}
2523
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002524int proc_dointvec(struct ctl_table *table, int write, struct file *filp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525 void __user *buffer, size_t *lenp, loff_t *ppos)
2526{
2527 return -ENOSYS;
2528}
2529
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002530int proc_dointvec_minmax(struct ctl_table *table, int write, struct file *filp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531 void __user *buffer, size_t *lenp, loff_t *ppos)
2532{
2533 return -ENOSYS;
2534}
2535
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002536int proc_dointvec_jiffies(struct ctl_table *table, int write, struct file *filp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537 void __user *buffer, size_t *lenp, loff_t *ppos)
2538{
2539 return -ENOSYS;
2540}
2541
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002542int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write, struct file *filp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543 void __user *buffer, size_t *lenp, loff_t *ppos)
2544{
2545 return -ENOSYS;
2546}
2547
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002548int proc_dointvec_ms_jiffies(struct ctl_table *table, int write, struct file *filp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549 void __user *buffer, size_t *lenp, loff_t *ppos)
2550{
2551 return -ENOSYS;
2552}
2553
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002554int proc_doulongvec_minmax(struct ctl_table *table, int write, struct file *filp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555 void __user *buffer, size_t *lenp, loff_t *ppos)
2556{
2557 return -ENOSYS;
2558}
2559
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002560int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 struct file *filp,
2562 void __user *buffer,
2563 size_t *lenp, loff_t *ppos)
2564{
2565 return -ENOSYS;
2566}
2567
2568
2569#endif /* CONFIG_PROC_FS */
2570
2571
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07002572#ifdef CONFIG_SYSCTL_SYSCALL
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573/*
2574 * General sysctl support routines
2575 */
2576
Eric W. Biederman49a0c452007-10-18 03:05:23 -07002577/* The generic sysctl data routine (used if no strategy routine supplied) */
2578int sysctl_data(struct ctl_table *table, int __user *name, int nlen,
2579 void __user *oldval, size_t __user *oldlenp,
2580 void __user *newval, size_t newlen)
2581{
2582 size_t len;
2583
2584 /* Get out of I don't have a variable */
2585 if (!table->data || !table->maxlen)
2586 return -ENOTDIR;
2587
2588 if (oldval && oldlenp) {
2589 if (get_user(len, oldlenp))
2590 return -EFAULT;
2591 if (len) {
2592 if (len > table->maxlen)
2593 len = table->maxlen;
2594 if (copy_to_user(oldval, table->data, len))
2595 return -EFAULT;
2596 if (put_user(len, oldlenp))
2597 return -EFAULT;
2598 }
2599 }
2600
2601 if (newval && newlen) {
2602 if (newlen > table->maxlen)
2603 newlen = table->maxlen;
2604
2605 if (copy_from_user(table->data, newval, newlen))
2606 return -EFAULT;
2607 }
2608 return 1;
2609}
2610
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611/* The generic string strategy routine: */
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002612int sysctl_string(struct ctl_table *table, int __user *name, int nlen,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 void __user *oldval, size_t __user *oldlenp,
Alexey Dobriyan1f29bcd2006-12-10 02:19:10 -08002614 void __user *newval, size_t newlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 if (!table->data || !table->maxlen)
2617 return -ENOTDIR;
2618
2619 if (oldval && oldlenp) {
Linus Torvaldsde9e0072005-12-31 17:00:29 -08002620 size_t bufsize;
2621 if (get_user(bufsize, oldlenp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 return -EFAULT;
Linus Torvaldsde9e0072005-12-31 17:00:29 -08002623 if (bufsize) {
2624 size_t len = strlen(table->data), copied;
2625
2626 /* This shouldn't trigger for a well-formed sysctl */
2627 if (len > table->maxlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628 len = table->maxlen;
Linus Torvaldsde9e0072005-12-31 17:00:29 -08002629
2630 /* Copy up to a max of bufsize-1 bytes of the string */
2631 copied = (len >= bufsize) ? bufsize - 1 : len;
2632
2633 if (copy_to_user(oldval, table->data, copied) ||
2634 put_user(0, (char __user *)(oldval + copied)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635 return -EFAULT;
Linus Torvaldsde9e0072005-12-31 17:00:29 -08002636 if (put_user(len, oldlenp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 return -EFAULT;
2638 }
2639 }
2640 if (newval && newlen) {
Linus Torvaldsde9e0072005-12-31 17:00:29 -08002641 size_t len = newlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642 if (len > table->maxlen)
2643 len = table->maxlen;
2644 if(copy_from_user(table->data, newval, len))
2645 return -EFAULT;
2646 if (len == table->maxlen)
2647 len--;
2648 ((char *) table->data)[len] = 0;
2649 }
Yi Yang82c9df82005-12-30 16:37:10 +08002650 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651}
2652
2653/*
2654 * This function makes sure that all of the integers in the vector
2655 * are between the minimum and maximum values given in the arrays
2656 * table->extra1 and table->extra2, respectively.
2657 */
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002658int sysctl_intvec(struct ctl_table *table, int __user *name, int nlen,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659 void __user *oldval, size_t __user *oldlenp,
Alexey Dobriyan1f29bcd2006-12-10 02:19:10 -08002660 void __user *newval, size_t newlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661{
2662
2663 if (newval && newlen) {
2664 int __user *vec = (int __user *) newval;
2665 int *min = (int *) table->extra1;
2666 int *max = (int *) table->extra2;
2667 size_t length;
2668 int i;
2669
2670 if (newlen % sizeof(int) != 0)
2671 return -EINVAL;
2672
2673 if (!table->extra1 && !table->extra2)
2674 return 0;
2675
2676 if (newlen > table->maxlen)
2677 newlen = table->maxlen;
2678 length = newlen / sizeof(int);
2679
2680 for (i = 0; i < length; i++) {
2681 int value;
2682 if (get_user(value, vec + i))
2683 return -EFAULT;
2684 if (min && value < min[i])
2685 return -EINVAL;
2686 if (max && value > max[i])
2687 return -EINVAL;
2688 }
2689 }
2690 return 0;
2691}
2692
2693/* Strategy function to convert jiffies to seconds */
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002694int sysctl_jiffies(struct ctl_table *table, int __user *name, int nlen,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 void __user *oldval, size_t __user *oldlenp,
Alexey Dobriyan1f29bcd2006-12-10 02:19:10 -08002696 void __user *newval, size_t newlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697{
Alexey Dobriyan3ee75ac2007-02-10 01:44:39 -08002698 if (oldval && oldlenp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699 size_t olen;
Alexey Dobriyan3ee75ac2007-02-10 01:44:39 -08002700
2701 if (get_user(olen, oldlenp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 return -EFAULT;
Alexey Dobriyan3ee75ac2007-02-10 01:44:39 -08002703 if (olen) {
2704 int val;
2705
2706 if (olen < sizeof(int))
2707 return -EINVAL;
2708
2709 val = *(int *)(table->data) / HZ;
2710 if (put_user(val, (int __user *)oldval))
2711 return -EFAULT;
2712 if (put_user(sizeof(int), oldlenp))
2713 return -EFAULT;
2714 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 }
2716 if (newval && newlen) {
2717 int new;
2718 if (newlen != sizeof(int))
2719 return -EINVAL;
2720 if (get_user(new, (int __user *)newval))
2721 return -EFAULT;
2722 *(int *)(table->data) = new*HZ;
2723 }
2724 return 1;
2725}
2726
2727/* Strategy function to convert jiffies to seconds */
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002728int sysctl_ms_jiffies(struct ctl_table *table, int __user *name, int nlen,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729 void __user *oldval, size_t __user *oldlenp,
Alexey Dobriyan1f29bcd2006-12-10 02:19:10 -08002730 void __user *newval, size_t newlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731{
Alexey Dobriyan3ee75ac2007-02-10 01:44:39 -08002732 if (oldval && oldlenp) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 size_t olen;
Alexey Dobriyan3ee75ac2007-02-10 01:44:39 -08002734
2735 if (get_user(olen, oldlenp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736 return -EFAULT;
Alexey Dobriyan3ee75ac2007-02-10 01:44:39 -08002737 if (olen) {
2738 int val;
2739
2740 if (olen < sizeof(int))
2741 return -EINVAL;
2742
2743 val = jiffies_to_msecs(*(int *)(table->data));
2744 if (put_user(val, (int __user *)oldval))
2745 return -EFAULT;
2746 if (put_user(sizeof(int), oldlenp))
2747 return -EFAULT;
2748 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749 }
2750 if (newval && newlen) {
2751 int new;
2752 if (newlen != sizeof(int))
2753 return -EINVAL;
2754 if (get_user(new, (int __user *)newval))
2755 return -EFAULT;
2756 *(int *)(table->data) = msecs_to_jiffies(new);
2757 }
2758 return 1;
2759}
2760
Eric W. Biedermanc4b8b762006-12-08 02:39:55 -08002761
Eric W. Biedermanc4b8b762006-12-08 02:39:55 -08002762
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07002763#else /* CONFIG_SYSCTL_SYSCALL */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764
2765
2766asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
2767{
Eric W. Biederman0e009be2006-11-05 23:52:11 -08002768 struct __sysctl_args tmp;
Eric W. Biederman7058cb02007-10-18 03:05:58 -07002769 int error;
Eric W. Biederman0e009be2006-11-05 23:52:11 -08002770
Eric W. Biederman0e009be2006-11-05 23:52:11 -08002771 if (copy_from_user(&tmp, args, sizeof(tmp)))
2772 return -EFAULT;
Eric W. Biederman0e009be2006-11-05 23:52:11 -08002773
Eric W. Biederman7058cb02007-10-18 03:05:58 -07002774 error = deprecated_sysctl_warning(&tmp);
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07002775
Eric W. Biederman7058cb02007-10-18 03:05:58 -07002776 /* If no error reading the parameters then just -ENOSYS ... */
2777 if (!error)
2778 error = -ENOSYS;
2779
2780 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781}
2782
Eric W. Biederman49a0c452007-10-18 03:05:23 -07002783int sysctl_data(struct ctl_table *table, int __user *name, int nlen,
2784 void __user *oldval, size_t __user *oldlenp,
2785 void __user *newval, size_t newlen)
2786{
2787 return -ENOSYS;
2788}
2789
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002790int sysctl_string(struct ctl_table *table, int __user *name, int nlen,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 void __user *oldval, size_t __user *oldlenp,
Alexey Dobriyan1f29bcd2006-12-10 02:19:10 -08002792 void __user *newval, size_t newlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793{
2794 return -ENOSYS;
2795}
2796
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002797int sysctl_intvec(struct ctl_table *table, int __user *name, int nlen,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798 void __user *oldval, size_t __user *oldlenp,
Alexey Dobriyan1f29bcd2006-12-10 02:19:10 -08002799 void __user *newval, size_t newlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800{
2801 return -ENOSYS;
2802}
2803
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002804int sysctl_jiffies(struct ctl_table *table, int __user *name, int nlen,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805 void __user *oldval, size_t __user *oldlenp,
Alexey Dobriyan1f29bcd2006-12-10 02:19:10 -08002806 void __user *newval, size_t newlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807{
2808 return -ENOSYS;
2809}
2810
Eric W. Biedermand8217f02007-10-18 03:05:22 -07002811int sysctl_ms_jiffies(struct ctl_table *table, int __user *name, int nlen,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812 void __user *oldval, size_t __user *oldlenp,
Alexey Dobriyan1f29bcd2006-12-10 02:19:10 -08002813 void __user *newval, size_t newlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814{
2815 return -ENOSYS;
2816}
2817
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07002818#endif /* CONFIG_SYSCTL_SYSCALL */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819
Eric W. Biederman7058cb02007-10-18 03:05:58 -07002820static int deprecated_sysctl_warning(struct __sysctl_args *args)
2821{
2822 static int msg_count;
2823 int name[CTL_MAXNAME];
2824 int i;
2825
Tetsuo Handa6fc48af2007-11-14 16:58:38 -08002826 /* Check args->nlen. */
2827 if (args->nlen < 0 || args->nlen > CTL_MAXNAME)
2828 return -ENOTDIR;
2829
Eric W. Biederman7058cb02007-10-18 03:05:58 -07002830 /* Read in the sysctl name for better debug message logging */
2831 for (i = 0; i < args->nlen; i++)
2832 if (get_user(name[i], args->name + i))
2833 return -EFAULT;
2834
2835 /* Ignore accesses to kernel.version */
2836 if ((args->nlen == 2) && (name[0] == CTL_KERN) && (name[1] == KERN_VERSION))
2837 return 0;
2838
2839 if (msg_count < 5) {
2840 msg_count++;
2841 printk(KERN_INFO
2842 "warning: process `%s' used the deprecated sysctl "
2843 "system call with ", current->comm);
2844 for (i = 0; i < args->nlen; i++)
2845 printk("%d.", name[i]);
2846 printk("\n");
2847 }
2848 return 0;
2849}
2850
Linus Torvalds1da177e2005-04-16 15:20:36 -07002851/*
2852 * No sense putting this after each symbol definition, twice,
2853 * exception granted :-)
2854 */
2855EXPORT_SYMBOL(proc_dointvec);
2856EXPORT_SYMBOL(proc_dointvec_jiffies);
2857EXPORT_SYMBOL(proc_dointvec_minmax);
2858EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
2859EXPORT_SYMBOL(proc_dointvec_ms_jiffies);
2860EXPORT_SYMBOL(proc_dostring);
2861EXPORT_SYMBOL(proc_doulongvec_minmax);
2862EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
2863EXPORT_SYMBOL(register_sysctl_table);
Eric W. Biederman29e796f2007-11-30 23:50:18 +11002864EXPORT_SYMBOL(register_sysctl_paths);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865EXPORT_SYMBOL(sysctl_intvec);
2866EXPORT_SYMBOL(sysctl_jiffies);
2867EXPORT_SYMBOL(sysctl_ms_jiffies);
2868EXPORT_SYMBOL(sysctl_string);
Eric W. Biederman49a0c452007-10-18 03:05:23 -07002869EXPORT_SYMBOL(sysctl_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870EXPORT_SYMBOL(unregister_sysctl_table);