blob: c8bcbfb2e069e7d4ba16350c41c95889bdd8fe19 [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>
Randy.Dunlapc59ede72006-01-11 12:17:46 -080027#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/ctype.h>
29#include <linux/utsname.h>
30#include <linux/capability.h>
31#include <linux/smp_lock.h>
32#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>
40#include <linux/security.h>
41#include <linux/initrd.h>
42#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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
49#include <asm/uaccess.h>
50#include <asm/processor.h>
51
Dipankar Sarma529bf6b2006-03-07 21:55:35 -080052extern int proc_nr_files(ctl_table *table, int write, struct file *filp,
53 void __user *buffer, size_t *lenp, loff_t *ppos);
54
Andi Kleen29cbc782006-09-30 01:47:55 +020055#ifdef CONFIG_X86
56#include <asm/nmi.h>
Chuck Ebbert0741f4d2006-12-07 02:14:11 +010057#include <asm/stacktrace.h>
Andi Kleen29cbc782006-09-30 01:47:55 +020058#endif
59
Linus Torvalds1da177e2005-04-16 15:20:36 -070060#if defined(CONFIG_SYSCTL)
61
62/* External variables not in a header file. */
63extern int C_A_D;
64extern int sysctl_overcommit_memory;
65extern int sysctl_overcommit_ratio;
KAMEZAWA Hiroyukifadd8fb2006-06-23 02:03:13 -070066extern int sysctl_panic_on_oom;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067extern int max_threads;
68extern int sysrq_enabled;
69extern int core_uses_pid;
Alan Coxd6e71142005-06-23 00:09:43 -070070extern int suid_dumpable;
Linus Torvalds1da177e2005-04-16 15:20:36 -070071extern char core_pattern[];
Linus Torvalds1da177e2005-04-16 15:20:36 -070072extern int pid_max;
73extern int min_free_kbytes;
74extern int printk_ratelimit_jiffies;
75extern int printk_ratelimit_burst;
76extern int pid_max_min, pid_max_max;
Andrew Morton9d0243b2006-01-08 01:00:39 -080077extern int sysctl_drop_caches;
Rohit Seth8ad4b1f2006-01-08 01:00:40 -080078extern int percpu_pagelist_fraction;
Andi Kleenbebfa102006-06-26 13:56:52 +020079extern int compat_log;
Linus Torvalds1da177e2005-04-16 15:20:36 -070080
Linus Torvalds1da177e2005-04-16 15:20:36 -070081/* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
82static int maxolduid = 65535;
83static int minolduid;
Rohit Seth8ad4b1f2006-01-08 01:00:40 -080084static int min_percpu_pagelist_fract = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -070085
86static int ngroups_max = NGROUPS_MAX;
87
88#ifdef CONFIG_KMOD
89extern char modprobe_path[];
90#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070091#ifdef CONFIG_CHR_DEV_SG
92extern int sg_big_buff;
93#endif
94#ifdef CONFIG_SYSVIPC
Kirill Korotaevfcfbd542006-10-02 02:18:23 -070095static int proc_do_ipc_string(ctl_table *table, int write, struct file *filp,
96 void __user *buffer, size_t *lenp, loff_t *ppos);
Linus Torvalds1da177e2005-04-16 15:20:36 -070097#endif
98
99#ifdef __sparc__
100extern char reboot_command [];
101extern int stop_a_enabled;
102extern int scons_pwroff;
103#endif
104
105#ifdef __hppa__
106extern int pwrsw_enabled;
107extern int unaligned_enabled;
108#endif
109
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800110#ifdef CONFIG_S390
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111#ifdef CONFIG_MATHEMU
112extern int sysctl_ieee_emulation_warnings;
113#endif
114extern int sysctl_userprocess_debug;
Martin Schwidefsky951f22d2005-07-27 11:44:57 -0700115extern int spin_retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116#endif
117
118extern int sysctl_hz_timer;
119
120#ifdef CONFIG_BSD_PROCESS_ACCT
121extern int acct_parm[];
122#endif
123
Jes Sorensend2b176e2006-02-28 09:42:23 -0800124#ifdef CONFIG_IA64
125extern int no_unaligned_warning;
126#endif
127
Ingo Molnar23f78d42006-06-27 02:54:53 -0700128#ifdef CONFIG_RT_MUTEXES
129extern int max_lock_depth;
130#endif
131
Eric W. Biedermanb89a8172006-09-27 01:51:04 -0700132#ifdef CONFIG_SYSCTL_SYSCALL
133static int parse_table(int __user *, int, void __user *, size_t __user *,
134 void __user *, size_t, ctl_table *, void **);
135#endif
136
Serge E. Hallyn8218c742006-10-02 02:18:15 -0700137static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 void __user *buffer, size_t *lenp, loff_t *ppos);
139
Randy Dunlapd6f8ff72006-10-19 23:28:34 -0700140#ifdef CONFIG_PROC_SYSCTL
Cedric Le Goater9ec52092006-10-02 02:19:00 -0700141static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
142 void __user *buffer, size_t *lenp, loff_t *ppos);
Randy Dunlapd6f8ff72006-10-19 23:28:34 -0700143#endif
Cedric Le Goater9ec52092006-10-02 02:19:00 -0700144
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145static ctl_table root_table[];
146static struct ctl_table_header root_table_header =
147 { root_table, LIST_HEAD_INIT(root_table_header.ctl_entry) };
148
149static ctl_table kern_table[];
150static ctl_table vm_table[];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151static ctl_table fs_table[];
152static ctl_table debug_table[];
153static ctl_table dev_table[];
154extern ctl_table random_table[];
155#ifdef CONFIG_UNIX98_PTYS
156extern ctl_table pty_table[];
157#endif
Amy Griffis2d9048e2006-06-01 13:10:59 -0700158#ifdef CONFIG_INOTIFY_USER
Robert Love0399cb02005-07-13 12:38:18 -0400159extern ctl_table inotify_table[];
160#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161
162#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
163int sysctl_legacy_va_layout;
164#endif
165
Eric W. Biedermancf9f1512006-12-08 02:39:55 -0800166static void *get_uts(ctl_table *table, int write)
167{
168 char *which = table->data;
169#ifdef CONFIG_UTS_NS
170 struct uts_namespace *uts_ns = current->nsproxy->uts_ns;
171 which = (which - (char *)&init_uts_ns) + (char *)uts_ns;
172#endif
173 if (!write)
174 down_read(&uts_sem);
175 else
176 down_write(&uts_sem);
177 return which;
178}
179
180static void put_uts(ctl_table *table, int write, void *which)
181{
182 if (!write)
183 up_read(&uts_sem);
184 else
185 up_write(&uts_sem);
186}
187
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188/* /proc declarations: */
189
Eric W. Biedermanb89a8172006-09-27 01:51:04 -0700190#ifdef CONFIG_PROC_SYSCTL
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191
192static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *);
193static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *);
194static int proc_opensys(struct inode *, struct file *);
195
Helge Deller15ad7cd2006-12-06 20:40:36 -0800196const struct file_operations proc_sys_file_operations = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 .open = proc_opensys,
198 .read = proc_readsys,
199 .write = proc_writesys,
200};
201
202extern struct proc_dir_entry *proc_sys_root;
203
Al Viro330d57f2005-11-04 10:18:40 +0000204static void register_proc_table(ctl_table *, struct proc_dir_entry *, void *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
206#endif
207
208/* The default sysctl tables: */
209
210static ctl_table root_table[] = {
211 {
212 .ctl_name = CTL_KERN,
213 .procname = "kernel",
214 .mode = 0555,
215 .child = kern_table,
216 },
217 {
218 .ctl_name = CTL_VM,
219 .procname = "vm",
220 .mode = 0555,
221 .child = vm_table,
222 },
223#ifdef CONFIG_NET
224 {
225 .ctl_name = CTL_NET,
226 .procname = "net",
227 .mode = 0555,
228 .child = net_table,
229 },
230#endif
231 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 .ctl_name = CTL_FS,
233 .procname = "fs",
234 .mode = 0555,
235 .child = fs_table,
236 },
237 {
238 .ctl_name = CTL_DEBUG,
239 .procname = "debug",
240 .mode = 0555,
241 .child = debug_table,
242 },
243 {
244 .ctl_name = CTL_DEV,
245 .procname = "dev",
246 .mode = 0555,
247 .child = dev_table,
248 },
Robert Love0eeca282005-07-12 17:06:03 -0400249
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 { .ctl_name = 0 }
251};
252
253static ctl_table kern_table[] = {
254 {
255 .ctl_name = KERN_OSTYPE,
256 .procname = "ostype",
Serge E. Hallyn8218c742006-10-02 02:18:15 -0700257 .data = init_uts_ns.name.sysname,
258 .maxlen = sizeof(init_uts_ns.name.sysname),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 .mode = 0444,
Serge E. Hallyn8218c742006-10-02 02:18:15 -0700260 .proc_handler = &proc_do_uts_string,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 .strategy = &sysctl_string,
262 },
263 {
264 .ctl_name = KERN_OSRELEASE,
265 .procname = "osrelease",
Serge E. Hallyn8218c742006-10-02 02:18:15 -0700266 .data = init_uts_ns.name.release,
267 .maxlen = sizeof(init_uts_ns.name.release),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 .mode = 0444,
Serge E. Hallyn8218c742006-10-02 02:18:15 -0700269 .proc_handler = &proc_do_uts_string,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 .strategy = &sysctl_string,
271 },
272 {
273 .ctl_name = KERN_VERSION,
274 .procname = "version",
Serge E. Hallyn8218c742006-10-02 02:18:15 -0700275 .data = init_uts_ns.name.version,
276 .maxlen = sizeof(init_uts_ns.name.version),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 .mode = 0444,
Serge E. Hallyn8218c742006-10-02 02:18:15 -0700278 .proc_handler = &proc_do_uts_string,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 .strategy = &sysctl_string,
280 },
281 {
282 .ctl_name = KERN_NODENAME,
283 .procname = "hostname",
Serge E. Hallyn8218c742006-10-02 02:18:15 -0700284 .data = init_uts_ns.name.nodename,
285 .maxlen = sizeof(init_uts_ns.name.nodename),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 .mode = 0644,
Serge E. Hallyn8218c742006-10-02 02:18:15 -0700287 .proc_handler = &proc_do_uts_string,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 .strategy = &sysctl_string,
289 },
290 {
291 .ctl_name = KERN_DOMAINNAME,
292 .procname = "domainname",
Serge E. Hallyn8218c742006-10-02 02:18:15 -0700293 .data = init_uts_ns.name.domainname,
294 .maxlen = sizeof(init_uts_ns.name.domainname),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 .mode = 0644,
Serge E. Hallyn8218c742006-10-02 02:18:15 -0700296 .proc_handler = &proc_do_uts_string,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 .strategy = &sysctl_string,
298 },
299 {
300 .ctl_name = KERN_PANIC,
301 .procname = "panic",
302 .data = &panic_timeout,
303 .maxlen = sizeof(int),
304 .mode = 0644,
305 .proc_handler = &proc_dointvec,
306 },
307 {
308 .ctl_name = KERN_CORE_USES_PID,
309 .procname = "core_uses_pid",
310 .data = &core_uses_pid,
311 .maxlen = sizeof(int),
312 .mode = 0644,
313 .proc_handler = &proc_dointvec,
314 },
315 {
316 .ctl_name = KERN_CORE_PATTERN,
317 .procname = "core_pattern",
318 .data = core_pattern,
Andi Kleend025c9d2006-09-30 23:29:28 -0700319 .maxlen = 128,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 .mode = 0644,
321 .proc_handler = &proc_dostring,
322 .strategy = &sysctl_string,
323 },
324 {
325 .ctl_name = KERN_TAINTED,
326 .procname = "tainted",
327 .data = &tainted,
328 .maxlen = sizeof(int),
329 .mode = 0444,
330 .proc_handler = &proc_dointvec,
331 },
332 {
333 .ctl_name = KERN_CAP_BSET,
334 .procname = "cap-bound",
335 .data = &cap_bset,
336 .maxlen = sizeof(kernel_cap_t),
337 .mode = 0600,
338 .proc_handler = &proc_dointvec_bset,
339 },
340#ifdef CONFIG_BLK_DEV_INITRD
341 {
342 .ctl_name = KERN_REALROOTDEV,
343 .procname = "real-root-dev",
344 .data = &real_root_dev,
345 .maxlen = sizeof(int),
346 .mode = 0644,
347 .proc_handler = &proc_dointvec,
348 },
349#endif
350#ifdef __sparc__
351 {
352 .ctl_name = KERN_SPARC_REBOOT,
353 .procname = "reboot-cmd",
354 .data = reboot_command,
355 .maxlen = 256,
356 .mode = 0644,
357 .proc_handler = &proc_dostring,
358 .strategy = &sysctl_string,
359 },
360 {
361 .ctl_name = KERN_SPARC_STOP_A,
362 .procname = "stop-a",
363 .data = &stop_a_enabled,
364 .maxlen = sizeof (int),
365 .mode = 0644,
366 .proc_handler = &proc_dointvec,
367 },
368 {
369 .ctl_name = KERN_SPARC_SCONS_PWROFF,
370 .procname = "scons-poweroff",
371 .data = &scons_pwroff,
372 .maxlen = sizeof (int),
373 .mode = 0644,
374 .proc_handler = &proc_dointvec,
375 },
376#endif
377#ifdef __hppa__
378 {
379 .ctl_name = KERN_HPPA_PWRSW,
380 .procname = "soft-power",
381 .data = &pwrsw_enabled,
382 .maxlen = sizeof (int),
383 .mode = 0644,
384 .proc_handler = &proc_dointvec,
385 },
386 {
387 .ctl_name = KERN_HPPA_UNALIGNED,
388 .procname = "unaligned-trap",
389 .data = &unaligned_enabled,
390 .maxlen = sizeof (int),
391 .mode = 0644,
392 .proc_handler = &proc_dointvec,
393 },
394#endif
395 {
396 .ctl_name = KERN_CTLALTDEL,
397 .procname = "ctrl-alt-del",
398 .data = &C_A_D,
399 .maxlen = sizeof(int),
400 .mode = 0644,
401 .proc_handler = &proc_dointvec,
402 },
403 {
404 .ctl_name = KERN_PRINTK,
405 .procname = "printk",
406 .data = &console_loglevel,
407 .maxlen = 4*sizeof(int),
408 .mode = 0644,
409 .proc_handler = &proc_dointvec,
410 },
411#ifdef CONFIG_KMOD
412 {
413 .ctl_name = KERN_MODPROBE,
414 .procname = "modprobe",
415 .data = &modprobe_path,
416 .maxlen = KMOD_PATH_LEN,
417 .mode = 0644,
418 .proc_handler = &proc_dostring,
419 .strategy = &sysctl_string,
420 },
421#endif
Andrew Morton57ae2502006-06-23 02:05:47 -0700422#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 {
424 .ctl_name = KERN_HOTPLUG,
425 .procname = "hotplug",
Kay Sievers312c0042005-11-16 09:00:00 +0100426 .data = &uevent_helper,
427 .maxlen = UEVENT_HELPER_PATH_LEN,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 .mode = 0644,
429 .proc_handler = &proc_dostring,
430 .strategy = &sysctl_string,
431 },
432#endif
433#ifdef CONFIG_CHR_DEV_SG
434 {
435 .ctl_name = KERN_SG_BIG_BUFF,
436 .procname = "sg-big-buff",
437 .data = &sg_big_buff,
438 .maxlen = sizeof (int),
439 .mode = 0444,
440 .proc_handler = &proc_dointvec,
441 },
442#endif
443#ifdef CONFIG_BSD_PROCESS_ACCT
444 {
445 .ctl_name = KERN_ACCT,
446 .procname = "acct",
447 .data = &acct_parm,
448 .maxlen = 3*sizeof(int),
449 .mode = 0644,
450 .proc_handler = &proc_dointvec,
451 },
452#endif
453#ifdef CONFIG_SYSVIPC
454 {
455 .ctl_name = KERN_SHMMAX,
456 .procname = "shmmax",
Kirill Korotaevfcfbd542006-10-02 02:18:23 -0700457 .data = NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 .maxlen = sizeof (size_t),
459 .mode = 0644,
Kirill Korotaevfcfbd542006-10-02 02:18:23 -0700460 .proc_handler = &proc_do_ipc_string,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 },
462 {
463 .ctl_name = KERN_SHMALL,
464 .procname = "shmall",
Kirill Korotaevfcfbd542006-10-02 02:18:23 -0700465 .data = NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 .maxlen = sizeof (size_t),
467 .mode = 0644,
Kirill Korotaevfcfbd542006-10-02 02:18:23 -0700468 .proc_handler = &proc_do_ipc_string,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 },
470 {
471 .ctl_name = KERN_SHMMNI,
472 .procname = "shmmni",
Kirill Korotaevfcfbd542006-10-02 02:18:23 -0700473 .data = NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 .maxlen = sizeof (int),
475 .mode = 0644,
Kirill Korotaevfcfbd542006-10-02 02:18:23 -0700476 .proc_handler = &proc_do_ipc_string,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 },
478 {
479 .ctl_name = KERN_MSGMAX,
480 .procname = "msgmax",
Kirill Korotaevfcfbd542006-10-02 02:18:23 -0700481 .data = NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 .maxlen = sizeof (int),
483 .mode = 0644,
Kirill Korotaevfcfbd542006-10-02 02:18:23 -0700484 .proc_handler = &proc_do_ipc_string,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 },
486 {
487 .ctl_name = KERN_MSGMNI,
488 .procname = "msgmni",
Kirill Korotaevfcfbd542006-10-02 02:18:23 -0700489 .data = NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 .maxlen = sizeof (int),
491 .mode = 0644,
Kirill Korotaevfcfbd542006-10-02 02:18:23 -0700492 .proc_handler = &proc_do_ipc_string,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 },
494 {
495 .ctl_name = KERN_MSGMNB,
496 .procname = "msgmnb",
Kirill Korotaevfcfbd542006-10-02 02:18:23 -0700497 .data = NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 .maxlen = sizeof (int),
499 .mode = 0644,
Kirill Korotaevfcfbd542006-10-02 02:18:23 -0700500 .proc_handler = &proc_do_ipc_string,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 },
502 {
503 .ctl_name = KERN_SEM,
504 .procname = "sem",
Kirill Korotaevfcfbd542006-10-02 02:18:23 -0700505 .data = NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 .maxlen = 4*sizeof (int),
507 .mode = 0644,
Kirill Korotaevfcfbd542006-10-02 02:18:23 -0700508 .proc_handler = &proc_do_ipc_string,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 },
510#endif
511#ifdef CONFIG_MAGIC_SYSRQ
512 {
513 .ctl_name = KERN_SYSRQ,
514 .procname = "sysrq",
515 .data = &sysrq_enabled,
516 .maxlen = sizeof (int),
517 .mode = 0644,
518 .proc_handler = &proc_dointvec,
519 },
520#endif
Randy Dunlapd6f8ff72006-10-19 23:28:34 -0700521#ifdef CONFIG_PROC_SYSCTL
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 {
523 .ctl_name = KERN_CADPID,
524 .procname = "cad_pid",
Cedric Le Goater9ec52092006-10-02 02:19:00 -0700525 .data = NULL,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 .maxlen = sizeof (int),
527 .mode = 0600,
Cedric Le Goater9ec52092006-10-02 02:19:00 -0700528 .proc_handler = &proc_do_cad_pid,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 },
Randy Dunlapd6f8ff72006-10-19 23:28:34 -0700530#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 {
532 .ctl_name = KERN_MAX_THREADS,
533 .procname = "threads-max",
534 .data = &max_threads,
535 .maxlen = sizeof(int),
536 .mode = 0644,
537 .proc_handler = &proc_dointvec,
538 },
539 {
540 .ctl_name = KERN_RANDOM,
541 .procname = "random",
542 .mode = 0555,
543 .child = random_table,
544 },
545#ifdef CONFIG_UNIX98_PTYS
546 {
547 .ctl_name = KERN_PTY,
548 .procname = "pty",
549 .mode = 0555,
550 .child = pty_table,
551 },
552#endif
553 {
554 .ctl_name = KERN_OVERFLOWUID,
555 .procname = "overflowuid",
556 .data = &overflowuid,
557 .maxlen = sizeof(int),
558 .mode = 0644,
559 .proc_handler = &proc_dointvec_minmax,
560 .strategy = &sysctl_intvec,
561 .extra1 = &minolduid,
562 .extra2 = &maxolduid,
563 },
564 {
565 .ctl_name = KERN_OVERFLOWGID,
566 .procname = "overflowgid",
567 .data = &overflowgid,
568 .maxlen = sizeof(int),
569 .mode = 0644,
570 .proc_handler = &proc_dointvec_minmax,
571 .strategy = &sysctl_intvec,
572 .extra1 = &minolduid,
573 .extra2 = &maxolduid,
574 },
Martin Schwidefsky347a8dc2006-01-06 00:19:28 -0800575#ifdef CONFIG_S390
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576#ifdef CONFIG_MATHEMU
577 {
578 .ctl_name = KERN_IEEE_EMULATION_WARNINGS,
579 .procname = "ieee_emulation_warnings",
580 .data = &sysctl_ieee_emulation_warnings,
581 .maxlen = sizeof(int),
582 .mode = 0644,
583 .proc_handler = &proc_dointvec,
584 },
585#endif
586#ifdef CONFIG_NO_IDLE_HZ
587 {
588 .ctl_name = KERN_HZ_TIMER,
589 .procname = "hz_timer",
590 .data = &sysctl_hz_timer,
591 .maxlen = sizeof(int),
592 .mode = 0644,
593 .proc_handler = &proc_dointvec,
594 },
595#endif
596 {
597 .ctl_name = KERN_S390_USER_DEBUG_LOGGING,
598 .procname = "userprocess_debug",
599 .data = &sysctl_userprocess_debug,
600 .maxlen = sizeof(int),
601 .mode = 0644,
602 .proc_handler = &proc_dointvec,
603 },
604#endif
605 {
606 .ctl_name = KERN_PIDMAX,
607 .procname = "pid_max",
608 .data = &pid_max,
609 .maxlen = sizeof (int),
610 .mode = 0644,
611 .proc_handler = &proc_dointvec_minmax,
612 .strategy = sysctl_intvec,
613 .extra1 = &pid_max_min,
614 .extra2 = &pid_max_max,
615 },
616 {
617 .ctl_name = KERN_PANIC_ON_OOPS,
618 .procname = "panic_on_oops",
619 .data = &panic_on_oops,
620 .maxlen = sizeof(int),
621 .mode = 0644,
622 .proc_handler = &proc_dointvec,
623 },
624 {
625 .ctl_name = KERN_PRINTK_RATELIMIT,
626 .procname = "printk_ratelimit",
627 .data = &printk_ratelimit_jiffies,
628 .maxlen = sizeof(int),
629 .mode = 0644,
630 .proc_handler = &proc_dointvec_jiffies,
631 .strategy = &sysctl_jiffies,
632 },
633 {
634 .ctl_name = KERN_PRINTK_RATELIMIT_BURST,
635 .procname = "printk_ratelimit_burst",
636 .data = &printk_ratelimit_burst,
637 .maxlen = sizeof(int),
638 .mode = 0644,
639 .proc_handler = &proc_dointvec,
640 },
641 {
642 .ctl_name = KERN_NGROUPS_MAX,
643 .procname = "ngroups_max",
644 .data = &ngroups_max,
645 .maxlen = sizeof (int),
646 .mode = 0444,
647 .proc_handler = &proc_dointvec,
648 },
649#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
650 {
651 .ctl_name = KERN_UNKNOWN_NMI_PANIC,
652 .procname = "unknown_nmi_panic",
653 .data = &unknown_nmi_panic,
654 .maxlen = sizeof (int),
655 .mode = 0644,
Don Zickus2fbe7b22006-09-26 10:52:27 +0200656 .proc_handler = &proc_dointvec,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 },
Don Zickus407984f2006-09-26 10:52:27 +0200658 {
659 .ctl_name = KERN_NMI_WATCHDOG,
660 .procname = "nmi_watchdog",
661 .data = &nmi_watchdog_enabled,
662 .maxlen = sizeof (int),
663 .mode = 0644,
664 .proc_handler = &proc_nmi_enabled,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 },
666#endif
667#if defined(CONFIG_X86)
668 {
Don Zickus8da5add2006-09-26 10:52:27 +0200669 .ctl_name = KERN_PANIC_ON_NMI,
670 .procname = "panic_on_unrecovered_nmi",
671 .data = &panic_on_unrecovered_nmi,
672 .maxlen = sizeof(int),
673 .mode = 0644,
674 .proc_handler = &proc_dointvec,
675 },
676 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 .ctl_name = KERN_BOOTLOADER_TYPE,
678 .procname = "bootloader_type",
679 .data = &bootloader_type,
680 .maxlen = sizeof (int),
681 .mode = 0444,
682 .proc_handler = &proc_dointvec,
683 },
Chuck Ebbert0741f4d2006-12-07 02:14:11 +0100684 {
685 .ctl_name = CTL_UNNUMBERED,
686 .procname = "kstack_depth_to_print",
687 .data = &kstack_depth_to_print,
688 .maxlen = sizeof(int),
689 .mode = 0644,
690 .proc_handler = &proc_dointvec,
691 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692#endif
Luke Yang7a9166e2006-02-20 18:28:07 -0800693#if defined(CONFIG_MMU)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 {
695 .ctl_name = KERN_RANDOMIZE,
696 .procname = "randomize_va_space",
697 .data = &randomize_va_space,
698 .maxlen = sizeof(int),
699 .mode = 0644,
700 .proc_handler = &proc_dointvec,
701 },
Luke Yang7a9166e2006-02-20 18:28:07 -0800702#endif
Martin Schwidefsky0152fb32006-01-14 13:21:00 -0800703#if defined(CONFIG_S390) && defined(CONFIG_SMP)
Martin Schwidefsky951f22d2005-07-27 11:44:57 -0700704 {
705 .ctl_name = KERN_SPIN_RETRY,
706 .procname = "spin_retry",
707 .data = &spin_retry,
708 .maxlen = sizeof (int),
709 .mode = 0644,
710 .proc_handler = &proc_dointvec,
711 },
712#endif
Pavel Machekc255d842006-02-20 18:27:58 -0800713#ifdef CONFIG_ACPI_SLEEP
714 {
715 .ctl_name = KERN_ACPI_VIDEO_FLAGS,
716 .procname = "acpi_video_flags",
717 .data = &acpi_video_flags,
718 .maxlen = sizeof (unsigned long),
719 .mode = 0644,
Stefan Seyfried7f99f062006-03-02 02:54:34 -0800720 .proc_handler = &proc_doulongvec_minmax,
Pavel Machekc255d842006-02-20 18:27:58 -0800721 },
722#endif
Jes Sorensend2b176e2006-02-28 09:42:23 -0800723#ifdef CONFIG_IA64
724 {
725 .ctl_name = KERN_IA64_UNALIGNED,
726 .procname = "ignore-unaligned-usertrap",
727 .data = &no_unaligned_warning,
728 .maxlen = sizeof (int),
729 .mode = 0644,
730 .proc_handler = &proc_dointvec,
731 },
732#endif
Andi Kleenbebfa102006-06-26 13:56:52 +0200733#ifdef CONFIG_COMPAT
734 {
735 .ctl_name = KERN_COMPAT_LOG,
736 .procname = "compat-log",
737 .data = &compat_log,
738 .maxlen = sizeof (int),
739 .mode = 0644,
740 .proc_handler = &proc_dointvec,
741 },
742#endif
Ingo Molnar23f78d42006-06-27 02:54:53 -0700743#ifdef CONFIG_RT_MUTEXES
744 {
745 .ctl_name = KERN_MAX_LOCK_DEPTH,
746 .procname = "max_lock_depth",
747 .data = &max_lock_depth,
748 .maxlen = sizeof(int),
749 .mode = 0644,
750 .proc_handler = &proc_dointvec,
751 },
752#endif
753
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754 { .ctl_name = 0 }
755};
756
757/* Constants for minimum and maximum testing in vm_table.
758 We use these as one-element integer vectors. */
759static int zero;
760static int one_hundred = 100;
761
762
763static ctl_table vm_table[] = {
764 {
765 .ctl_name = VM_OVERCOMMIT_MEMORY,
766 .procname = "overcommit_memory",
767 .data = &sysctl_overcommit_memory,
768 .maxlen = sizeof(sysctl_overcommit_memory),
769 .mode = 0644,
770 .proc_handler = &proc_dointvec,
771 },
772 {
KAMEZAWA Hiroyukifadd8fb2006-06-23 02:03:13 -0700773 .ctl_name = VM_PANIC_ON_OOM,
774 .procname = "panic_on_oom",
775 .data = &sysctl_panic_on_oom,
776 .maxlen = sizeof(sysctl_panic_on_oom),
777 .mode = 0644,
778 .proc_handler = &proc_dointvec,
779 },
780 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 .ctl_name = VM_OVERCOMMIT_RATIO,
782 .procname = "overcommit_ratio",
783 .data = &sysctl_overcommit_ratio,
784 .maxlen = sizeof(sysctl_overcommit_ratio),
785 .mode = 0644,
786 .proc_handler = &proc_dointvec,
787 },
788 {
789 .ctl_name = VM_PAGE_CLUSTER,
790 .procname = "page-cluster",
791 .data = &page_cluster,
792 .maxlen = sizeof(int),
793 .mode = 0644,
794 .proc_handler = &proc_dointvec,
795 },
796 {
797 .ctl_name = VM_DIRTY_BACKGROUND,
798 .procname = "dirty_background_ratio",
799 .data = &dirty_background_ratio,
800 .maxlen = sizeof(dirty_background_ratio),
801 .mode = 0644,
802 .proc_handler = &proc_dointvec_minmax,
803 .strategy = &sysctl_intvec,
804 .extra1 = &zero,
805 .extra2 = &one_hundred,
806 },
807 {
808 .ctl_name = VM_DIRTY_RATIO,
809 .procname = "dirty_ratio",
810 .data = &vm_dirty_ratio,
811 .maxlen = sizeof(vm_dirty_ratio),
812 .mode = 0644,
813 .proc_handler = &proc_dointvec_minmax,
814 .strategy = &sysctl_intvec,
815 .extra1 = &zero,
816 .extra2 = &one_hundred,
817 },
818 {
819 .ctl_name = VM_DIRTY_WB_CS,
820 .procname = "dirty_writeback_centisecs",
Bart Samwelf6ef9432006-03-24 03:15:48 -0800821 .data = &dirty_writeback_interval,
822 .maxlen = sizeof(dirty_writeback_interval),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 .mode = 0644,
824 .proc_handler = &dirty_writeback_centisecs_handler,
825 },
826 {
827 .ctl_name = VM_DIRTY_EXPIRE_CS,
828 .procname = "dirty_expire_centisecs",
Bart Samwelf6ef9432006-03-24 03:15:48 -0800829 .data = &dirty_expire_interval,
830 .maxlen = sizeof(dirty_expire_interval),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 .mode = 0644,
Bart Samwelf6ef9432006-03-24 03:15:48 -0800832 .proc_handler = &proc_dointvec_userhz_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 },
834 {
835 .ctl_name = VM_NR_PDFLUSH_THREADS,
836 .procname = "nr_pdflush_threads",
837 .data = &nr_pdflush_threads,
838 .maxlen = sizeof nr_pdflush_threads,
839 .mode = 0444 /* read-only*/,
840 .proc_handler = &proc_dointvec,
841 },
842 {
843 .ctl_name = VM_SWAPPINESS,
844 .procname = "swappiness",
845 .data = &vm_swappiness,
846 .maxlen = sizeof(vm_swappiness),
847 .mode = 0644,
848 .proc_handler = &proc_dointvec_minmax,
849 .strategy = &sysctl_intvec,
850 .extra1 = &zero,
851 .extra2 = &one_hundred,
852 },
853#ifdef CONFIG_HUGETLB_PAGE
854 {
855 .ctl_name = VM_HUGETLB_PAGES,
856 .procname = "nr_hugepages",
857 .data = &max_huge_pages,
858 .maxlen = sizeof(unsigned long),
859 .mode = 0644,
860 .proc_handler = &hugetlb_sysctl_handler,
861 .extra1 = (void *)&hugetlb_zero,
862 .extra2 = (void *)&hugetlb_infinity,
863 },
864 {
865 .ctl_name = VM_HUGETLB_GROUP,
866 .procname = "hugetlb_shm_group",
867 .data = &sysctl_hugetlb_shm_group,
868 .maxlen = sizeof(gid_t),
869 .mode = 0644,
870 .proc_handler = &proc_dointvec,
871 },
872#endif
873 {
874 .ctl_name = VM_LOWMEM_RESERVE_RATIO,
875 .procname = "lowmem_reserve_ratio",
876 .data = &sysctl_lowmem_reserve_ratio,
877 .maxlen = sizeof(sysctl_lowmem_reserve_ratio),
878 .mode = 0644,
879 .proc_handler = &lowmem_reserve_ratio_sysctl_handler,
880 .strategy = &sysctl_intvec,
881 },
882 {
Andrew Morton9d0243b2006-01-08 01:00:39 -0800883 .ctl_name = VM_DROP_PAGECACHE,
884 .procname = "drop_caches",
885 .data = &sysctl_drop_caches,
886 .maxlen = sizeof(int),
887 .mode = 0644,
888 .proc_handler = drop_caches_sysctl_handler,
889 .strategy = &sysctl_intvec,
890 },
891 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 .ctl_name = VM_MIN_FREE_KBYTES,
893 .procname = "min_free_kbytes",
894 .data = &min_free_kbytes,
895 .maxlen = sizeof(min_free_kbytes),
896 .mode = 0644,
897 .proc_handler = &min_free_kbytes_sysctl_handler,
898 .strategy = &sysctl_intvec,
899 .extra1 = &zero,
900 },
Rohit Seth8ad4b1f2006-01-08 01:00:40 -0800901 {
902 .ctl_name = VM_PERCPU_PAGELIST_FRACTION,
903 .procname = "percpu_pagelist_fraction",
904 .data = &percpu_pagelist_fraction,
905 .maxlen = sizeof(percpu_pagelist_fraction),
906 .mode = 0644,
907 .proc_handler = &percpu_pagelist_fraction_sysctl_handler,
908 .strategy = &sysctl_intvec,
909 .extra1 = &min_percpu_pagelist_fract,
910 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911#ifdef CONFIG_MMU
912 {
913 .ctl_name = VM_MAX_MAP_COUNT,
914 .procname = "max_map_count",
915 .data = &sysctl_max_map_count,
916 .maxlen = sizeof(sysctl_max_map_count),
917 .mode = 0644,
918 .proc_handler = &proc_dointvec
919 },
920#endif
921 {
922 .ctl_name = VM_LAPTOP_MODE,
923 .procname = "laptop_mode",
924 .data = &laptop_mode,
925 .maxlen = sizeof(laptop_mode),
926 .mode = 0644,
Bart Samweled5b43f2006-03-24 03:15:49 -0800927 .proc_handler = &proc_dointvec_jiffies,
928 .strategy = &sysctl_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 },
930 {
931 .ctl_name = VM_BLOCK_DUMP,
932 .procname = "block_dump",
933 .data = &block_dump,
934 .maxlen = sizeof(block_dump),
935 .mode = 0644,
936 .proc_handler = &proc_dointvec,
937 .strategy = &sysctl_intvec,
938 .extra1 = &zero,
939 },
940 {
941 .ctl_name = VM_VFS_CACHE_PRESSURE,
942 .procname = "vfs_cache_pressure",
943 .data = &sysctl_vfs_cache_pressure,
944 .maxlen = sizeof(sysctl_vfs_cache_pressure),
945 .mode = 0644,
946 .proc_handler = &proc_dointvec,
947 .strategy = &sysctl_intvec,
948 .extra1 = &zero,
949 },
950#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
951 {
952 .ctl_name = VM_LEGACY_VA_LAYOUT,
953 .procname = "legacy_va_layout",
954 .data = &sysctl_legacy_va_layout,
955 .maxlen = sizeof(sysctl_legacy_va_layout),
956 .mode = 0644,
957 .proc_handler = &proc_dointvec,
958 .strategy = &sysctl_intvec,
959 .extra1 = &zero,
960 },
961#endif
Christoph Lameter17436602006-01-18 17:42:32 -0800962#ifdef CONFIG_NUMA
963 {
964 .ctl_name = VM_ZONE_RECLAIM_MODE,
965 .procname = "zone_reclaim_mode",
966 .data = &zone_reclaim_mode,
967 .maxlen = sizeof(zone_reclaim_mode),
968 .mode = 0644,
969 .proc_handler = &proc_dointvec,
Christoph Lameterc84db232006-02-01 03:05:29 -0800970 .strategy = &sysctl_intvec,
971 .extra1 = &zero,
Christoph Lameter17436602006-01-18 17:42:32 -0800972 },
Christoph Lameter96146342006-07-03 00:24:13 -0700973 {
974 .ctl_name = VM_MIN_UNMAPPED,
975 .procname = "min_unmapped_ratio",
976 .data = &sysctl_min_unmapped_ratio,
977 .maxlen = sizeof(sysctl_min_unmapped_ratio),
978 .mode = 0644,
979 .proc_handler = &sysctl_min_unmapped_ratio_sysctl_handler,
980 .strategy = &sysctl_intvec,
981 .extra1 = &zero,
982 .extra2 = &one_hundred,
983 },
Christoph Lameter0ff38492006-09-25 23:31:52 -0700984 {
985 .ctl_name = VM_MIN_SLAB,
986 .procname = "min_slab_ratio",
987 .data = &sysctl_min_slab_ratio,
988 .maxlen = sizeof(sysctl_min_slab_ratio),
989 .mode = 0644,
990 .proc_handler = &sysctl_min_slab_ratio_sysctl_handler,
991 .strategy = &sysctl_intvec,
992 .extra1 = &zero,
993 .extra2 = &one_hundred,
994 },
Christoph Lameter17436602006-01-18 17:42:32 -0800995#endif
Ingo Molnare6e54942006-06-27 02:53:50 -0700996#ifdef CONFIG_X86_32
997 {
998 .ctl_name = VM_VDSO_ENABLED,
999 .procname = "vdso_enabled",
1000 .data = &vdso_enabled,
1001 .maxlen = sizeof(vdso_enabled),
1002 .mode = 0644,
1003 .proc_handler = &proc_dointvec,
1004 .strategy = &sysctl_intvec,
1005 .extra1 = &zero,
1006 },
1007#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 { .ctl_name = 0 }
1009};
1010
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011static ctl_table fs_table[] = {
1012 {
1013 .ctl_name = FS_NRINODE,
1014 .procname = "inode-nr",
1015 .data = &inodes_stat,
1016 .maxlen = 2*sizeof(int),
1017 .mode = 0444,
1018 .proc_handler = &proc_dointvec,
1019 },
1020 {
1021 .ctl_name = FS_STATINODE,
1022 .procname = "inode-state",
1023 .data = &inodes_stat,
1024 .maxlen = 7*sizeof(int),
1025 .mode = 0444,
1026 .proc_handler = &proc_dointvec,
1027 },
1028 {
1029 .ctl_name = FS_NRFILE,
1030 .procname = "file-nr",
1031 .data = &files_stat,
1032 .maxlen = 3*sizeof(int),
1033 .mode = 0444,
Dipankar Sarma529bf6b2006-03-07 21:55:35 -08001034 .proc_handler = &proc_nr_files,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 },
1036 {
1037 .ctl_name = FS_MAXFILE,
1038 .procname = "file-max",
1039 .data = &files_stat.max_files,
1040 .maxlen = sizeof(int),
1041 .mode = 0644,
1042 .proc_handler = &proc_dointvec,
1043 },
1044 {
1045 .ctl_name = FS_DENTRY,
1046 .procname = "dentry-state",
1047 .data = &dentry_stat,
1048 .maxlen = 6*sizeof(int),
1049 .mode = 0444,
1050 .proc_handler = &proc_dointvec,
1051 },
1052 {
1053 .ctl_name = FS_OVERFLOWUID,
1054 .procname = "overflowuid",
1055 .data = &fs_overflowuid,
1056 .maxlen = sizeof(int),
1057 .mode = 0644,
1058 .proc_handler = &proc_dointvec_minmax,
1059 .strategy = &sysctl_intvec,
1060 .extra1 = &minolduid,
1061 .extra2 = &maxolduid,
1062 },
1063 {
1064 .ctl_name = FS_OVERFLOWGID,
1065 .procname = "overflowgid",
1066 .data = &fs_overflowgid,
1067 .maxlen = sizeof(int),
1068 .mode = 0644,
1069 .proc_handler = &proc_dointvec_minmax,
1070 .strategy = &sysctl_intvec,
1071 .extra1 = &minolduid,
1072 .extra2 = &maxolduid,
1073 },
1074 {
1075 .ctl_name = FS_LEASES,
1076 .procname = "leases-enable",
1077 .data = &leases_enable,
1078 .maxlen = sizeof(int),
1079 .mode = 0644,
1080 .proc_handler = &proc_dointvec,
1081 },
1082#ifdef CONFIG_DNOTIFY
1083 {
1084 .ctl_name = FS_DIR_NOTIFY,
1085 .procname = "dir-notify-enable",
1086 .data = &dir_notify_enable,
1087 .maxlen = sizeof(int),
1088 .mode = 0644,
1089 .proc_handler = &proc_dointvec,
1090 },
1091#endif
1092#ifdef CONFIG_MMU
1093 {
1094 .ctl_name = FS_LEASE_TIME,
1095 .procname = "lease-break-time",
1096 .data = &lease_break_time,
1097 .maxlen = sizeof(int),
1098 .mode = 0644,
1099 .proc_handler = &proc_dointvec,
1100 },
1101 {
1102 .ctl_name = FS_AIO_NR,
1103 .procname = "aio-nr",
1104 .data = &aio_nr,
1105 .maxlen = sizeof(aio_nr),
1106 .mode = 0444,
Zach Brownd55b5fd2005-11-07 00:59:31 -08001107 .proc_handler = &proc_doulongvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 },
1109 {
1110 .ctl_name = FS_AIO_MAX_NR,
1111 .procname = "aio-max-nr",
1112 .data = &aio_max_nr,
1113 .maxlen = sizeof(aio_max_nr),
1114 .mode = 0644,
Zach Brownd55b5fd2005-11-07 00:59:31 -08001115 .proc_handler = &proc_doulongvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 },
Amy Griffis2d9048e2006-06-01 13:10:59 -07001117#ifdef CONFIG_INOTIFY_USER
Robert Love0399cb02005-07-13 12:38:18 -04001118 {
1119 .ctl_name = FS_INOTIFY,
1120 .procname = "inotify",
1121 .mode = 0555,
1122 .child = inotify_table,
1123 },
1124#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125#endif
Alan Coxd6e71142005-06-23 00:09:43 -07001126 {
1127 .ctl_name = KERN_SETUID_DUMPABLE,
1128 .procname = "suid_dumpable",
1129 .data = &suid_dumpable,
1130 .maxlen = sizeof(int),
1131 .mode = 0644,
1132 .proc_handler = &proc_dointvec,
1133 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 { .ctl_name = 0 }
1135};
1136
1137static ctl_table debug_table[] = {
1138 { .ctl_name = 0 }
1139};
1140
1141static ctl_table dev_table[] = {
1142 { .ctl_name = 0 }
Robert Love0eeca282005-07-12 17:06:03 -04001143};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144
1145extern void init_irq_proc (void);
1146
Al Viro330d57f2005-11-04 10:18:40 +00001147static DEFINE_SPINLOCK(sysctl_lock);
1148
1149/* called under sysctl_lock */
1150static int use_table(struct ctl_table_header *p)
1151{
1152 if (unlikely(p->unregistering))
1153 return 0;
1154 p->used++;
1155 return 1;
1156}
1157
1158/* called under sysctl_lock */
1159static void unuse_table(struct ctl_table_header *p)
1160{
1161 if (!--p->used)
1162 if (unlikely(p->unregistering))
1163 complete(p->unregistering);
1164}
1165
1166/* called under sysctl_lock, will reacquire if has to wait */
1167static void start_unregistering(struct ctl_table_header *p)
1168{
1169 /*
1170 * if p->used is 0, nobody will ever touch that entry again;
1171 * we'll eliminate all paths to it before dropping sysctl_lock
1172 */
1173 if (unlikely(p->used)) {
1174 struct completion wait;
1175 init_completion(&wait);
1176 p->unregistering = &wait;
1177 spin_unlock(&sysctl_lock);
1178 wait_for_completion(&wait);
1179 spin_lock(&sysctl_lock);
1180 }
1181 /*
1182 * do not remove from the list until nobody holds it; walking the
1183 * list in do_sysctl() relies on that.
1184 */
1185 list_del_init(&p->ctl_entry);
1186}
1187
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188void __init sysctl_init(void)
1189{
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07001190#ifdef CONFIG_PROC_SYSCTL
Al Viro330d57f2005-11-04 10:18:40 +00001191 register_proc_table(root_table, proc_sys_root, &root_table_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 init_irq_proc();
1193#endif
1194}
1195
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07001196#ifdef CONFIG_SYSCTL_SYSCALL
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
1198 void __user *newval, size_t newlen)
1199{
1200 struct list_head *tmp;
Al Viro330d57f2005-11-04 10:18:40 +00001201 int error = -ENOTDIR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202
1203 if (nlen <= 0 || nlen >= CTL_MAXNAME)
1204 return -ENOTDIR;
1205 if (oldval) {
1206 int old_len;
1207 if (!oldlenp || get_user(old_len, oldlenp))
1208 return -EFAULT;
1209 }
Al Viro330d57f2005-11-04 10:18:40 +00001210 spin_lock(&sysctl_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 tmp = &root_table_header.ctl_entry;
1212 do {
1213 struct ctl_table_header *head =
1214 list_entry(tmp, struct ctl_table_header, ctl_entry);
1215 void *context = NULL;
Al Viro330d57f2005-11-04 10:18:40 +00001216
1217 if (!use_table(head))
1218 continue;
1219
1220 spin_unlock(&sysctl_lock);
1221
1222 error = parse_table(name, nlen, oldval, oldlenp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 newval, newlen, head->ctl_table,
1224 &context);
Jesper Juhl5a6b4542005-06-25 14:58:48 -07001225 kfree(context);
Al Viro330d57f2005-11-04 10:18:40 +00001226
1227 spin_lock(&sysctl_lock);
1228 unuse_table(head);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 if (error != -ENOTDIR)
Al Viro330d57f2005-11-04 10:18:40 +00001230 break;
1231 } while ((tmp = tmp->next) != &root_table_header.ctl_entry);
1232 spin_unlock(&sysctl_lock);
1233 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234}
1235
1236asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
1237{
1238 struct __sysctl_args tmp;
1239 int error;
1240
1241 if (copy_from_user(&tmp, args, sizeof(tmp)))
1242 return -EFAULT;
1243
1244 lock_kernel();
1245 error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp,
1246 tmp.newval, tmp.newlen);
1247 unlock_kernel();
1248 return error;
1249}
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07001250#endif /* CONFIG_SYSCTL_SYSCALL */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251
1252/*
1253 * ctl_perm does NOT grant the superuser all rights automatically, because
1254 * some sysctl variables are readonly even to root.
1255 */
1256
1257static int test_perm(int mode, int op)
1258{
1259 if (!current->euid)
1260 mode >>= 6;
1261 else if (in_egroup_p(0))
1262 mode >>= 3;
1263 if ((mode & op & 0007) == op)
1264 return 0;
1265 return -EACCES;
1266}
1267
1268static inline int ctl_perm(ctl_table *table, int op)
1269{
1270 int error;
1271 error = security_sysctl(table, op);
1272 if (error)
1273 return error;
1274 return test_perm(table->mode, op);
1275}
1276
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07001277#ifdef CONFIG_SYSCTL_SYSCALL
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278static int parse_table(int __user *name, int nlen,
1279 void __user *oldval, size_t __user *oldlenp,
1280 void __user *newval, size_t newlen,
1281 ctl_table *table, void **context)
1282{
1283 int n;
1284repeat:
1285 if (!nlen)
1286 return -ENOTDIR;
1287 if (get_user(n, name))
1288 return -EFAULT;
Eric W. Biedermand99f1602006-11-05 23:52:12 -08001289 for ( ; table->ctl_name || table->procname; table++) {
1290 if (!table->ctl_name)
1291 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 if (n == table->ctl_name || table->ctl_name == CTL_ANY) {
1293 int error;
1294 if (table->child) {
1295 if (ctl_perm(table, 001))
1296 return -EPERM;
1297 if (table->strategy) {
1298 error = table->strategy(
1299 table, name, nlen,
1300 oldval, oldlenp,
1301 newval, newlen, context);
1302 if (error)
1303 return error;
1304 }
1305 name++;
1306 nlen--;
1307 table = table->child;
1308 goto repeat;
1309 }
1310 error = do_sysctl_strategy(table, name, nlen,
1311 oldval, oldlenp,
1312 newval, newlen, context);
1313 return error;
1314 }
1315 }
1316 return -ENOTDIR;
1317}
1318
1319/* Perform the actual read/write of a sysctl table entry. */
1320int do_sysctl_strategy (ctl_table *table,
1321 int __user *name, int nlen,
1322 void __user *oldval, size_t __user *oldlenp,
1323 void __user *newval, size_t newlen, void **context)
1324{
1325 int op = 0, rc;
1326 size_t len;
1327
1328 if (oldval)
1329 op |= 004;
1330 if (newval)
1331 op |= 002;
1332 if (ctl_perm(table, op))
1333 return -EPERM;
1334
1335 if (table->strategy) {
1336 rc = table->strategy(table, name, nlen, oldval, oldlenp,
1337 newval, newlen, context);
1338 if (rc < 0)
1339 return rc;
1340 if (rc > 0)
1341 return 0;
1342 }
1343
1344 /* If there is no strategy routine, or if the strategy returns
1345 * zero, proceed with automatic r/w */
1346 if (table->data && table->maxlen) {
1347 if (oldval && oldlenp) {
1348 if (get_user(len, oldlenp))
1349 return -EFAULT;
1350 if (len) {
1351 if (len > table->maxlen)
1352 len = table->maxlen;
1353 if(copy_to_user(oldval, table->data, len))
1354 return -EFAULT;
1355 if(put_user(len, oldlenp))
1356 return -EFAULT;
1357 }
1358 }
1359 if (newval && newlen) {
1360 len = newlen;
1361 if (len > table->maxlen)
1362 len = table->maxlen;
1363 if(copy_from_user(table->data, newval, len))
1364 return -EFAULT;
1365 }
1366 }
1367 return 0;
1368}
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07001369#endif /* CONFIG_SYSCTL_SYSCALL */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370
1371/**
1372 * register_sysctl_table - register a sysctl hierarchy
1373 * @table: the top-level table structure
1374 * @insert_at_head: whether the entry should be inserted in front or at the end
1375 *
1376 * Register a sysctl table hierarchy. @table should be a filled in ctl_table
1377 * array. An entry with a ctl_name of 0 terminates the table.
1378 *
1379 * The members of the &ctl_table structure are used as follows:
1380 *
1381 * ctl_name - This is the numeric sysctl value used by sysctl(2). The number
1382 * must be unique within that level of sysctl
1383 *
1384 * procname - the name of the sysctl file under /proc/sys. Set to %NULL to not
1385 * enter a sysctl file
1386 *
1387 * data - a pointer to data for use by proc_handler
1388 *
1389 * maxlen - the maximum size in bytes of the data
1390 *
1391 * mode - the file permissions for the /proc/sys file, and for sysctl(2)
1392 *
1393 * child - a pointer to the child sysctl table if this entry is a directory, or
1394 * %NULL.
1395 *
1396 * proc_handler - the text handler routine (described below)
1397 *
1398 * strategy - the strategy routine (described below)
1399 *
1400 * de - for internal use by the sysctl routines
1401 *
1402 * extra1, extra2 - extra pointers usable by the proc handler routines
1403 *
1404 * Leaf nodes in the sysctl tree will be represented by a single file
1405 * under /proc; non-leaf nodes will be represented by directories.
1406 *
1407 * sysctl(2) can automatically manage read and write requests through
1408 * the sysctl table. The data and maxlen fields of the ctl_table
1409 * struct enable minimal validation of the values being written to be
1410 * performed, and the mode field allows minimal authentication.
1411 *
1412 * More sophisticated management can be enabled by the provision of a
1413 * strategy routine with the table entry. This will be called before
1414 * any automatic read or write of the data is performed.
1415 *
1416 * The strategy routine may return
1417 *
1418 * < 0 - Error occurred (error is passed to user process)
1419 *
1420 * 0 - OK - proceed with automatic read or write.
1421 *
1422 * > 0 - OK - read or write has been done by the strategy routine, so
1423 * return immediately.
1424 *
1425 * There must be a proc_handler routine for any terminal nodes
1426 * mirrored under /proc/sys (non-terminals are handled by a built-in
1427 * directory handler). Several default handlers are available to
1428 * cover common cases -
1429 *
1430 * proc_dostring(), proc_dointvec(), proc_dointvec_jiffies(),
1431 * proc_dointvec_userhz_jiffies(), proc_dointvec_minmax(),
1432 * proc_doulongvec_ms_jiffies_minmax(), proc_doulongvec_minmax()
1433 *
1434 * It is the handler's job to read the input buffer from user memory
1435 * and process it. The handler should return 0 on success.
1436 *
1437 * This routine returns %NULL on a failure to register, and a pointer
1438 * to the table header on success.
1439 */
1440struct ctl_table_header *register_sysctl_table(ctl_table * table,
1441 int insert_at_head)
1442{
1443 struct ctl_table_header *tmp;
1444 tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL);
1445 if (!tmp)
1446 return NULL;
1447 tmp->ctl_table = table;
1448 INIT_LIST_HEAD(&tmp->ctl_entry);
Al Viro330d57f2005-11-04 10:18:40 +00001449 tmp->used = 0;
1450 tmp->unregistering = NULL;
1451 spin_lock(&sysctl_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 if (insert_at_head)
1453 list_add(&tmp->ctl_entry, &root_table_header.ctl_entry);
1454 else
1455 list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
Al Viro330d57f2005-11-04 10:18:40 +00001456 spin_unlock(&sysctl_lock);
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07001457#ifdef CONFIG_PROC_SYSCTL
Al Viro330d57f2005-11-04 10:18:40 +00001458 register_proc_table(table, proc_sys_root, tmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459#endif
1460 return tmp;
1461}
1462
1463/**
1464 * unregister_sysctl_table - unregister a sysctl table hierarchy
1465 * @header: the header returned from register_sysctl_table
1466 *
1467 * Unregisters the sysctl table and all children. proc entries may not
1468 * actually be removed until they are no longer used by anyone.
1469 */
1470void unregister_sysctl_table(struct ctl_table_header * header)
1471{
Al Viro330d57f2005-11-04 10:18:40 +00001472 might_sleep();
1473 spin_lock(&sysctl_lock);
1474 start_unregistering(header);
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07001475#ifdef CONFIG_PROC_SYSCTL
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 unregister_proc_table(header->ctl_table, proc_sys_root);
1477#endif
Al Viro330d57f2005-11-04 10:18:40 +00001478 spin_unlock(&sysctl_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 kfree(header);
1480}
1481
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07001482#else /* !CONFIG_SYSCTL */
1483struct ctl_table_header * register_sysctl_table(ctl_table * table,
1484 int insert_at_head)
1485{
1486 return NULL;
1487}
1488
1489void unregister_sysctl_table(struct ctl_table_header * table)
1490{
1491}
1492
1493#endif /* CONFIG_SYSCTL */
1494
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495/*
1496 * /proc/sys support
1497 */
1498
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07001499#ifdef CONFIG_PROC_SYSCTL
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500
1501/* Scan the sysctl entries in table and add them all into /proc */
Al Viro330d57f2005-11-04 10:18:40 +00001502static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, void *set)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503{
1504 struct proc_dir_entry *de;
1505 int len;
1506 mode_t mode;
1507
Eric W. Biedermand99f1602006-11-05 23:52:12 -08001508 for (; table->ctl_name || table->procname; table++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 /* Can't do anything without a proc name. */
1510 if (!table->procname)
1511 continue;
1512 /* Maybe we can't do anything with it... */
1513 if (!table->proc_handler && !table->child) {
1514 printk(KERN_WARNING "SYSCTL: Can't register %s\n",
1515 table->procname);
1516 continue;
1517 }
1518
1519 len = strlen(table->procname);
1520 mode = table->mode;
1521
1522 de = NULL;
1523 if (table->proc_handler)
1524 mode |= S_IFREG;
1525 else {
1526 mode |= S_IFDIR;
1527 for (de = root->subdir; de; de = de->next) {
1528 if (proc_match(len, table->procname, de))
1529 break;
1530 }
1531 /* If the subdir exists already, de is non-NULL */
1532 }
1533
1534 if (!de) {
1535 de = create_proc_entry(table->procname, mode, root);
1536 if (!de)
1537 continue;
Al Viro330d57f2005-11-04 10:18:40 +00001538 de->set = set;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 de->data = (void *) table;
1540 if (table->proc_handler)
1541 de->proc_fops = &proc_sys_file_operations;
1542 }
1543 table->de = de;
1544 if (de->mode & S_IFDIR)
Al Viro330d57f2005-11-04 10:18:40 +00001545 register_proc_table(table->child, de, set);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 }
1547}
1548
1549/*
1550 * Unregister a /proc sysctl table and any subdirectories.
1551 */
1552static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root)
1553{
1554 struct proc_dir_entry *de;
Eric W. Biedermand99f1602006-11-05 23:52:12 -08001555 for (; table->ctl_name || table->procname; table++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 if (!(de = table->de))
1557 continue;
1558 if (de->mode & S_IFDIR) {
1559 if (!table->child) {
1560 printk (KERN_ALERT "Help - malformed sysctl tree on free\n");
1561 continue;
1562 }
1563 unregister_proc_table(table->child, de);
1564
1565 /* Don't unregister directories which still have entries.. */
1566 if (de->subdir)
1567 continue;
1568 }
1569
Al Viro330d57f2005-11-04 10:18:40 +00001570 /*
1571 * In any case, mark the entry as goner; we'll keep it
1572 * around if it's busy, but we'll know to do nothing with
1573 * its fields. We are under sysctl_lock here.
1574 */
1575 de->data = NULL;
1576
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 /* Don't unregister proc entries that are still being used.. */
1578 if (atomic_read(&de->count))
1579 continue;
1580
1581 table->de = NULL;
1582 remove_proc_entry(table->procname, root);
1583 }
1584}
1585
1586static ssize_t do_rw_proc(int write, struct file * file, char __user * buf,
1587 size_t count, loff_t *ppos)
1588{
1589 int op;
Josef "Jeff" Sipekf3a43f32006-12-08 02:36:43 -08001590 struct proc_dir_entry *de = PDE(file->f_path.dentry->d_inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 struct ctl_table *table;
1592 size_t res;
Al Viro330d57f2005-11-04 10:18:40 +00001593 ssize_t error = -ENOTDIR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594
Al Viro330d57f2005-11-04 10:18:40 +00001595 spin_lock(&sysctl_lock);
1596 if (de && de->data && use_table(de->set)) {
1597 /*
1598 * at that point we know that sysctl was not unregistered
1599 * and won't be until we finish
1600 */
1601 spin_unlock(&sysctl_lock);
1602 table = (struct ctl_table *) de->data;
1603 if (!table || !table->proc_handler)
1604 goto out;
1605 error = -EPERM;
1606 op = (write ? 002 : 004);
1607 if (ctl_perm(table, op))
1608 goto out;
1609
1610 /* careful: calling conventions are nasty here */
1611 res = count;
1612 error = (*table->proc_handler)(table, write, file,
1613 buf, &res, ppos);
1614 if (!error)
1615 error = res;
1616 out:
1617 spin_lock(&sysctl_lock);
1618 unuse_table(de->set);
1619 }
1620 spin_unlock(&sysctl_lock);
1621 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622}
1623
1624static int proc_opensys(struct inode *inode, struct file *file)
1625{
1626 if (file->f_mode & FMODE_WRITE) {
1627 /*
1628 * sysctl entries that are not writable,
1629 * are _NOT_ writable, capabilities or not.
1630 */
1631 if (!(inode->i_mode & S_IWUSR))
1632 return -EPERM;
1633 }
1634
1635 return 0;
1636}
1637
1638static ssize_t proc_readsys(struct file * file, char __user * buf,
1639 size_t count, loff_t *ppos)
1640{
1641 return do_rw_proc(0, file, buf, count, ppos);
1642}
1643
1644static ssize_t proc_writesys(struct file * file, const char __user * buf,
1645 size_t count, loff_t *ppos)
1646{
1647 return do_rw_proc(1, file, (char __user *) buf, count, ppos);
1648}
1649
Adrian Bunkb1ba4dd2006-10-02 02:18:05 -07001650static int _proc_do_string(void* data, int maxlen, int write,
1651 struct file *filp, void __user *buffer,
1652 size_t *lenp, loff_t *ppos)
Sam Vilainf5dd3d62006-10-02 02:18:04 -07001653{
1654 size_t len;
1655 char __user *p;
1656 char c;
1657
1658 if (!data || !maxlen || !*lenp ||
1659 (*ppos && !write)) {
1660 *lenp = 0;
1661 return 0;
1662 }
1663
1664 if (write) {
1665 len = 0;
1666 p = buffer;
1667 while (len < *lenp) {
1668 if (get_user(c, p++))
1669 return -EFAULT;
1670 if (c == 0 || c == '\n')
1671 break;
1672 len++;
1673 }
1674 if (len >= maxlen)
1675 len = maxlen-1;
1676 if(copy_from_user(data, buffer, len))
1677 return -EFAULT;
1678 ((char *) data)[len] = 0;
1679 *ppos += *lenp;
1680 } else {
1681 len = strlen(data);
1682 if (len > maxlen)
1683 len = maxlen;
1684 if (len > *lenp)
1685 len = *lenp;
1686 if (len)
1687 if(copy_to_user(buffer, data, len))
1688 return -EFAULT;
1689 if (len < *lenp) {
1690 if(put_user('\n', ((char __user *) buffer) + len))
1691 return -EFAULT;
1692 len++;
1693 }
1694 *lenp = len;
1695 *ppos += len;
1696 }
1697 return 0;
1698}
1699
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700/**
1701 * proc_dostring - read a string sysctl
1702 * @table: the sysctl table
1703 * @write: %TRUE if this is a write to the sysctl file
1704 * @filp: the file structure
1705 * @buffer: the user buffer
1706 * @lenp: the size of the user buffer
1707 * @ppos: file position
1708 *
1709 * Reads/writes a string from/to the user buffer. If the kernel
1710 * buffer provided is not large enough to hold the string, the
1711 * string is truncated. The copied string is %NULL-terminated.
1712 * If the string is being read by the user process, it is copied
1713 * and a newline '\n' is added. It is truncated if the buffer is
1714 * not large enough.
1715 *
1716 * Returns 0 on success.
1717 */
1718int proc_dostring(ctl_table *table, int write, struct file *filp,
1719 void __user *buffer, size_t *lenp, loff_t *ppos)
1720{
Sam Vilainf5dd3d62006-10-02 02:18:04 -07001721 return _proc_do_string(table->data, table->maxlen, write, filp,
1722 buffer, lenp, ppos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723}
1724
1725/*
1726 * Special case of dostring for the UTS structure. This has locks
1727 * to observe. Should this be in kernel/sys.c ????
1728 */
Eric W. Biedermancf9f1512006-12-08 02:39:55 -08001729
Serge E. Hallyn8218c742006-10-02 02:18:15 -07001730static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 void __user *buffer, size_t *lenp, loff_t *ppos)
1732{
1733 int r;
Eric W. Biedermancf9f1512006-12-08 02:39:55 -08001734 void *which;
1735 which = get_uts(table, write);
1736 r = _proc_do_string(which, table->maxlen,write,filp,buffer,lenp, ppos);
1737 put_uts(table, write, which);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 return r;
1739}
1740
1741static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp,
1742 int *valp,
1743 int write, void *data)
1744{
1745 if (write) {
1746 *valp = *negp ? -*lvalp : *lvalp;
1747 } else {
1748 int val = *valp;
1749 if (val < 0) {
1750 *negp = -1;
1751 *lvalp = (unsigned long)-val;
1752 } else {
1753 *negp = 0;
1754 *lvalp = (unsigned long)val;
1755 }
1756 }
1757 return 0;
1758}
1759
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07001760static int __do_proc_dointvec(void *tbl_data, ctl_table *table,
1761 int write, struct file *filp, void __user *buffer,
1762 size_t *lenp, loff_t *ppos,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 int (*conv)(int *negp, unsigned long *lvalp, int *valp,
1764 int write, void *data),
1765 void *data)
1766{
1767#define TMPBUFLEN 21
1768 int *i, vleft, first=1, neg, val;
1769 unsigned long lval;
1770 size_t left, len;
1771
1772 char buf[TMPBUFLEN], *p;
1773 char __user *s = buffer;
1774
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07001775 if (!tbl_data || !table->maxlen || !*lenp ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776 (*ppos && !write)) {
1777 *lenp = 0;
1778 return 0;
1779 }
1780
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07001781 i = (int *) tbl_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782 vleft = table->maxlen / sizeof(*i);
1783 left = *lenp;
1784
1785 if (!conv)
1786 conv = do_proc_dointvec_conv;
1787
1788 for (; left && vleft--; i++, first=0) {
1789 if (write) {
1790 while (left) {
1791 char c;
1792 if (get_user(c, s))
1793 return -EFAULT;
1794 if (!isspace(c))
1795 break;
1796 left--;
1797 s++;
1798 }
1799 if (!left)
1800 break;
1801 neg = 0;
1802 len = left;
1803 if (len > sizeof(buf) - 1)
1804 len = sizeof(buf) - 1;
1805 if (copy_from_user(buf, s, len))
1806 return -EFAULT;
1807 buf[len] = 0;
1808 p = buf;
1809 if (*p == '-' && left > 1) {
1810 neg = 1;
BP, Praveenbd9b0ba2006-12-06 20:39:09 -08001811 p++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812 }
1813 if (*p < '0' || *p > '9')
1814 break;
1815
1816 lval = simple_strtoul(p, &p, 0);
1817
1818 len = p-buf;
1819 if ((len < left) && *p && !isspace(*p))
1820 break;
1821 if (neg)
1822 val = -val;
1823 s += len;
1824 left -= len;
1825
1826 if (conv(&neg, &lval, i, 1, data))
1827 break;
1828 } else {
1829 p = buf;
1830 if (!first)
1831 *p++ = '\t';
1832
1833 if (conv(&neg, &lval, i, 0, data))
1834 break;
1835
1836 sprintf(p, "%s%lu", neg ? "-" : "", lval);
1837 len = strlen(buf);
1838 if (len > left)
1839 len = left;
1840 if(copy_to_user(s, buf, len))
1841 return -EFAULT;
1842 left -= len;
1843 s += len;
1844 }
1845 }
1846
1847 if (!write && !first && left) {
1848 if(put_user('\n', s))
1849 return -EFAULT;
1850 left--, s++;
1851 }
1852 if (write) {
1853 while (left) {
1854 char c;
1855 if (get_user(c, s++))
1856 return -EFAULT;
1857 if (!isspace(c))
1858 break;
1859 left--;
1860 }
1861 }
1862 if (write && first)
1863 return -EINVAL;
1864 *lenp -= left;
1865 *ppos += *lenp;
1866 return 0;
1867#undef TMPBUFLEN
1868}
1869
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07001870static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
1871 void __user *buffer, size_t *lenp, loff_t *ppos,
1872 int (*conv)(int *negp, unsigned long *lvalp, int *valp,
1873 int write, void *data),
1874 void *data)
1875{
1876 return __do_proc_dointvec(table->data, table, write, filp,
1877 buffer, lenp, ppos, conv, data);
1878}
1879
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880/**
1881 * proc_dointvec - read a vector of integers
1882 * @table: the sysctl table
1883 * @write: %TRUE if this is a write to the sysctl file
1884 * @filp: the file structure
1885 * @buffer: the user buffer
1886 * @lenp: the size of the user buffer
1887 * @ppos: file position
1888 *
1889 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1890 * values from/to the user buffer, treated as an ASCII string.
1891 *
1892 * Returns 0 on success.
1893 */
1894int proc_dointvec(ctl_table *table, int write, struct file *filp,
1895 void __user *buffer, size_t *lenp, loff_t *ppos)
1896{
1897 return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
1898 NULL,NULL);
1899}
1900
1901#define OP_SET 0
1902#define OP_AND 1
1903#define OP_OR 2
1904#define OP_MAX 3
1905#define OP_MIN 4
1906
1907static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
1908 int *valp,
1909 int write, void *data)
1910{
1911 int op = *(int *)data;
1912 if (write) {
1913 int val = *negp ? -*lvalp : *lvalp;
1914 switch(op) {
1915 case OP_SET: *valp = val; break;
1916 case OP_AND: *valp &= val; break;
1917 case OP_OR: *valp |= val; break;
1918 case OP_MAX: if(*valp < val)
1919 *valp = val;
1920 break;
1921 case OP_MIN: if(*valp > val)
1922 *valp = val;
1923 break;
1924 }
1925 } else {
1926 int val = *valp;
1927 if (val < 0) {
1928 *negp = -1;
1929 *lvalp = (unsigned long)-val;
1930 } else {
1931 *negp = 0;
1932 *lvalp = (unsigned long)val;
1933 }
1934 }
1935 return 0;
1936}
1937
1938/*
1939 * init may raise the set.
1940 */
1941
1942int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
1943 void __user *buffer, size_t *lenp, loff_t *ppos)
1944{
1945 int op;
1946
1947 if (!capable(CAP_SYS_MODULE)) {
1948 return -EPERM;
1949 }
1950
Sukadev Bhattiproluf400e192006-09-29 02:00:07 -07001951 op = is_init(current) ? OP_SET : OP_AND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
1953 do_proc_dointvec_bset_conv,&op);
1954}
1955
1956struct do_proc_dointvec_minmax_conv_param {
1957 int *min;
1958 int *max;
1959};
1960
1961static int do_proc_dointvec_minmax_conv(int *negp, unsigned long *lvalp,
1962 int *valp,
1963 int write, void *data)
1964{
1965 struct do_proc_dointvec_minmax_conv_param *param = data;
1966 if (write) {
1967 int val = *negp ? -*lvalp : *lvalp;
1968 if ((param->min && *param->min > val) ||
1969 (param->max && *param->max < val))
1970 return -EINVAL;
1971 *valp = val;
1972 } else {
1973 int val = *valp;
1974 if (val < 0) {
1975 *negp = -1;
1976 *lvalp = (unsigned long)-val;
1977 } else {
1978 *negp = 0;
1979 *lvalp = (unsigned long)val;
1980 }
1981 }
1982 return 0;
1983}
1984
1985/**
1986 * proc_dointvec_minmax - read a vector of integers with min/max values
1987 * @table: the sysctl table
1988 * @write: %TRUE if this is a write to the sysctl file
1989 * @filp: the file structure
1990 * @buffer: the user buffer
1991 * @lenp: the size of the user buffer
1992 * @ppos: file position
1993 *
1994 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1995 * values from/to the user buffer, treated as an ASCII string.
1996 *
1997 * This routine will ensure the values are within the range specified by
1998 * table->extra1 (min) and table->extra2 (max).
1999 *
2000 * Returns 0 on success.
2001 */
2002int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
2003 void __user *buffer, size_t *lenp, loff_t *ppos)
2004{
2005 struct do_proc_dointvec_minmax_conv_param param = {
2006 .min = (int *) table->extra1,
2007 .max = (int *) table->extra2,
2008 };
2009 return do_proc_dointvec(table, write, filp, buffer, lenp, ppos,
2010 do_proc_dointvec_minmax_conv, &param);
2011}
2012
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07002013static int __do_proc_doulongvec_minmax(void *data, ctl_table *table, int write,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 struct file *filp,
2015 void __user *buffer,
2016 size_t *lenp, loff_t *ppos,
2017 unsigned long convmul,
2018 unsigned long convdiv)
2019{
2020#define TMPBUFLEN 21
2021 unsigned long *i, *min, *max, val;
2022 int vleft, first=1, neg;
2023 size_t len, left;
2024 char buf[TMPBUFLEN], *p;
2025 char __user *s = buffer;
2026
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07002027 if (!data || !table->maxlen || !*lenp ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 (*ppos && !write)) {
2029 *lenp = 0;
2030 return 0;
2031 }
2032
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07002033 i = (unsigned long *) data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034 min = (unsigned long *) table->extra1;
2035 max = (unsigned long *) table->extra2;
2036 vleft = table->maxlen / sizeof(unsigned long);
2037 left = *lenp;
2038
2039 for (; left && vleft--; i++, min++, max++, first=0) {
2040 if (write) {
2041 while (left) {
2042 char c;
2043 if (get_user(c, s))
2044 return -EFAULT;
2045 if (!isspace(c))
2046 break;
2047 left--;
2048 s++;
2049 }
2050 if (!left)
2051 break;
2052 neg = 0;
2053 len = left;
2054 if (len > TMPBUFLEN-1)
2055 len = TMPBUFLEN-1;
2056 if (copy_from_user(buf, s, len))
2057 return -EFAULT;
2058 buf[len] = 0;
2059 p = buf;
2060 if (*p == '-' && left > 1) {
2061 neg = 1;
BP, Praveenbd9b0ba2006-12-06 20:39:09 -08002062 p++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 }
2064 if (*p < '0' || *p > '9')
2065 break;
2066 val = simple_strtoul(p, &p, 0) * convmul / convdiv ;
2067 len = p-buf;
2068 if ((len < left) && *p && !isspace(*p))
2069 break;
2070 if (neg)
2071 val = -val;
2072 s += len;
2073 left -= len;
2074
2075 if(neg)
2076 continue;
2077 if ((min && val < *min) || (max && val > *max))
2078 continue;
2079 *i = val;
2080 } else {
2081 p = buf;
2082 if (!first)
2083 *p++ = '\t';
2084 sprintf(p, "%lu", convdiv * (*i) / convmul);
2085 len = strlen(buf);
2086 if (len > left)
2087 len = left;
2088 if(copy_to_user(s, buf, len))
2089 return -EFAULT;
2090 left -= len;
2091 s += len;
2092 }
2093 }
2094
2095 if (!write && !first && left) {
2096 if(put_user('\n', s))
2097 return -EFAULT;
2098 left--, s++;
2099 }
2100 if (write) {
2101 while (left) {
2102 char c;
2103 if (get_user(c, s++))
2104 return -EFAULT;
2105 if (!isspace(c))
2106 break;
2107 left--;
2108 }
2109 }
2110 if (write && first)
2111 return -EINVAL;
2112 *lenp -= left;
2113 *ppos += *lenp;
2114 return 0;
2115#undef TMPBUFLEN
2116}
2117
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07002118static int do_proc_doulongvec_minmax(ctl_table *table, int write,
2119 struct file *filp,
2120 void __user *buffer,
2121 size_t *lenp, loff_t *ppos,
2122 unsigned long convmul,
2123 unsigned long convdiv)
2124{
2125 return __do_proc_doulongvec_minmax(table->data, table, write,
2126 filp, buffer, lenp, ppos, convmul, convdiv);
2127}
2128
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129/**
2130 * proc_doulongvec_minmax - read a vector of long integers with min/max values
2131 * @table: the sysctl table
2132 * @write: %TRUE if this is a write to the sysctl file
2133 * @filp: the file structure
2134 * @buffer: the user buffer
2135 * @lenp: the size of the user buffer
2136 * @ppos: file position
2137 *
2138 * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
2139 * values from/to the user buffer, treated as an ASCII string.
2140 *
2141 * This routine will ensure the values are within the range specified by
2142 * table->extra1 (min) and table->extra2 (max).
2143 *
2144 * Returns 0 on success.
2145 */
2146int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
2147 void __user *buffer, size_t *lenp, loff_t *ppos)
2148{
2149 return do_proc_doulongvec_minmax(table, write, filp, buffer, lenp, ppos, 1l, 1l);
2150}
2151
2152/**
2153 * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values
2154 * @table: the sysctl table
2155 * @write: %TRUE if this is a write to the sysctl file
2156 * @filp: the file structure
2157 * @buffer: the user buffer
2158 * @lenp: the size of the user buffer
2159 * @ppos: file position
2160 *
2161 * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
2162 * values from/to the user buffer, treated as an ASCII string. The values
2163 * are treated as milliseconds, and converted to jiffies when they are stored.
2164 *
2165 * This routine will ensure the values are within the range specified by
2166 * table->extra1 (min) and table->extra2 (max).
2167 *
2168 * Returns 0 on success.
2169 */
2170int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
2171 struct file *filp,
2172 void __user *buffer,
2173 size_t *lenp, loff_t *ppos)
2174{
2175 return do_proc_doulongvec_minmax(table, write, filp, buffer,
2176 lenp, ppos, HZ, 1000l);
2177}
2178
2179
2180static int do_proc_dointvec_jiffies_conv(int *negp, unsigned long *lvalp,
2181 int *valp,
2182 int write, void *data)
2183{
2184 if (write) {
Bart Samwelcba9f332006-03-24 03:15:50 -08002185 if (*lvalp > LONG_MAX / HZ)
2186 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 *valp = *negp ? -(*lvalp*HZ) : (*lvalp*HZ);
2188 } else {
2189 int val = *valp;
2190 unsigned long lval;
2191 if (val < 0) {
2192 *negp = -1;
2193 lval = (unsigned long)-val;
2194 } else {
2195 *negp = 0;
2196 lval = (unsigned long)val;
2197 }
2198 *lvalp = lval / HZ;
2199 }
2200 return 0;
2201}
2202
2203static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp,
2204 int *valp,
2205 int write, void *data)
2206{
2207 if (write) {
Bart Samwelcba9f332006-03-24 03:15:50 -08002208 if (USER_HZ < HZ && *lvalp > (LONG_MAX / HZ) * USER_HZ)
2209 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 *valp = clock_t_to_jiffies(*negp ? -*lvalp : *lvalp);
2211 } else {
2212 int val = *valp;
2213 unsigned long lval;
2214 if (val < 0) {
2215 *negp = -1;
2216 lval = (unsigned long)-val;
2217 } else {
2218 *negp = 0;
2219 lval = (unsigned long)val;
2220 }
2221 *lvalp = jiffies_to_clock_t(lval);
2222 }
2223 return 0;
2224}
2225
2226static int do_proc_dointvec_ms_jiffies_conv(int *negp, unsigned long *lvalp,
2227 int *valp,
2228 int write, void *data)
2229{
2230 if (write) {
2231 *valp = msecs_to_jiffies(*negp ? -*lvalp : *lvalp);
2232 } else {
2233 int val = *valp;
2234 unsigned long lval;
2235 if (val < 0) {
2236 *negp = -1;
2237 lval = (unsigned long)-val;
2238 } else {
2239 *negp = 0;
2240 lval = (unsigned long)val;
2241 }
2242 *lvalp = jiffies_to_msecs(lval);
2243 }
2244 return 0;
2245}
2246
2247/**
2248 * proc_dointvec_jiffies - read a vector of integers as seconds
2249 * @table: the sysctl table
2250 * @write: %TRUE if this is a write to the sysctl file
2251 * @filp: the file structure
2252 * @buffer: the user buffer
2253 * @lenp: the size of the user buffer
2254 * @ppos: file position
2255 *
2256 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
2257 * values from/to the user buffer, treated as an ASCII string.
2258 * The values read are assumed to be in seconds, and are converted into
2259 * jiffies.
2260 *
2261 * Returns 0 on success.
2262 */
2263int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
2264 void __user *buffer, size_t *lenp, loff_t *ppos)
2265{
2266 return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
2267 do_proc_dointvec_jiffies_conv,NULL);
2268}
2269
2270/**
2271 * proc_dointvec_userhz_jiffies - read a vector of integers as 1/USER_HZ seconds
2272 * @table: the sysctl table
2273 * @write: %TRUE if this is a write to the sysctl file
2274 * @filp: the file structure
2275 * @buffer: the user buffer
2276 * @lenp: the size of the user buffer
Randy Dunlap1e5d5332005-11-07 01:01:06 -08002277 * @ppos: pointer to the file position
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 *
2279 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
2280 * values from/to the user buffer, treated as an ASCII string.
2281 * The values read are assumed to be in 1/USER_HZ seconds, and
2282 * are converted into jiffies.
2283 *
2284 * Returns 0 on success.
2285 */
2286int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
2287 void __user *buffer, size_t *lenp, loff_t *ppos)
2288{
2289 return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
2290 do_proc_dointvec_userhz_jiffies_conv,NULL);
2291}
2292
2293/**
2294 * proc_dointvec_ms_jiffies - read a vector of integers as 1 milliseconds
2295 * @table: the sysctl table
2296 * @write: %TRUE if this is a write to the sysctl file
2297 * @filp: the file structure
2298 * @buffer: the user buffer
2299 * @lenp: the size of the user buffer
Martin Waitz67be2dd2005-05-01 08:59:26 -07002300 * @ppos: file position
2301 * @ppos: the current position in the file
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 *
2303 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
2304 * values from/to the user buffer, treated as an ASCII string.
2305 * The values read are assumed to be in 1/1000 seconds, and
2306 * are converted into jiffies.
2307 *
2308 * Returns 0 on success.
2309 */
2310int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
2311 void __user *buffer, size_t *lenp, loff_t *ppos)
2312{
2313 return do_proc_dointvec(table, write, filp, buffer, lenp, ppos,
2314 do_proc_dointvec_ms_jiffies_conv, NULL);
2315}
2316
Kirill Korotaevfcfbd542006-10-02 02:18:23 -07002317#ifdef CONFIG_SYSVIPC
2318static int proc_do_ipc_string(ctl_table *table, int write, struct file *filp,
2319 void __user *buffer, size_t *lenp, loff_t *ppos)
2320{
2321 void *data;
2322 struct ipc_namespace *ns;
2323
2324 ns = current->nsproxy->ipc_ns;
2325
2326 switch (table->ctl_name) {
2327 case KERN_SHMMAX:
2328 data = &ns->shm_ctlmax;
2329 goto proc_minmax;
2330 case KERN_SHMALL:
2331 data = &ns->shm_ctlall;
2332 goto proc_minmax;
2333 case KERN_SHMMNI:
2334 data = &ns->shm_ctlmni;
2335 break;
2336 case KERN_MSGMAX:
2337 data = &ns->msg_ctlmax;
2338 break;
2339 case KERN_MSGMNI:
2340 data = &ns->msg_ctlmni;
2341 break;
2342 case KERN_MSGMNB:
2343 data = &ns->msg_ctlmnb;
2344 break;
2345 case KERN_SEM:
2346 data = &ns->sem_ctls;
2347 break;
2348 default:
2349 return -EINVAL;
2350 }
2351
2352 return __do_proc_dointvec(data, table, write, filp, buffer,
2353 lenp, ppos, NULL, NULL);
2354proc_minmax:
2355 return __do_proc_doulongvec_minmax(data, table, write, filp, buffer,
2356 lenp, ppos, 1l, 1l);
2357}
2358#endif
2359
Cedric Le Goater9ec52092006-10-02 02:19:00 -07002360static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
2361 void __user *buffer, size_t *lenp, loff_t *ppos)
2362{
2363 struct pid *new_pid;
2364 pid_t tmp;
2365 int r;
2366
2367 tmp = pid_nr(cad_pid);
2368
2369 r = __do_proc_dointvec(&tmp, table, write, filp, buffer,
2370 lenp, ppos, NULL, NULL);
2371 if (r || !write)
2372 return r;
2373
2374 new_pid = find_get_pid(tmp);
2375 if (!new_pid)
2376 return -ESRCH;
2377
2378 put_pid(xchg(&cad_pid, new_pid));
2379 return 0;
2380}
2381
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382#else /* CONFIG_PROC_FS */
2383
2384int proc_dostring(ctl_table *table, int write, struct file *filp,
2385 void __user *buffer, size_t *lenp, loff_t *ppos)
2386{
2387 return -ENOSYS;
2388}
2389
Serge E. Hallyn8218c742006-10-02 02:18:15 -07002390static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
2391 void __user *buffer, size_t *lenp, loff_t *ppos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392{
2393 return -ENOSYS;
2394}
2395
Serge E. Hallyn8218c742006-10-02 02:18:15 -07002396#ifdef CONFIG_SYSVIPC
2397static int proc_do_ipc_string(ctl_table *table, int write, struct file *filp,
2398 void __user *buffer, size_t *lenp, loff_t *ppos)
2399{
2400 return -ENOSYS;
2401}
2402#endif
2403
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404int proc_dointvec(ctl_table *table, int write, struct file *filp,
2405 void __user *buffer, size_t *lenp, loff_t *ppos)
2406{
2407 return -ENOSYS;
2408}
2409
2410int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
2411 void __user *buffer, size_t *lenp, loff_t *ppos)
2412{
2413 return -ENOSYS;
2414}
2415
2416int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
2417 void __user *buffer, size_t *lenp, loff_t *ppos)
2418{
2419 return -ENOSYS;
2420}
2421
2422int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
2423 void __user *buffer, size_t *lenp, loff_t *ppos)
2424{
2425 return -ENOSYS;
2426}
2427
2428int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
2429 void __user *buffer, size_t *lenp, loff_t *ppos)
2430{
2431 return -ENOSYS;
2432}
2433
2434int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
2435 void __user *buffer, size_t *lenp, loff_t *ppos)
2436{
2437 return -ENOSYS;
2438}
2439
2440int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
2441 void __user *buffer, size_t *lenp, loff_t *ppos)
2442{
2443 return -ENOSYS;
2444}
2445
2446int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
2447 struct file *filp,
2448 void __user *buffer,
2449 size_t *lenp, loff_t *ppos)
2450{
2451 return -ENOSYS;
2452}
2453
2454
2455#endif /* CONFIG_PROC_FS */
2456
2457
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07002458#ifdef CONFIG_SYSCTL_SYSCALL
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459/*
2460 * General sysctl support routines
2461 */
2462
2463/* The generic string strategy routine: */
2464int sysctl_string(ctl_table *table, int __user *name, int nlen,
2465 void __user *oldval, size_t __user *oldlenp,
2466 void __user *newval, size_t newlen, void **context)
2467{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468 if (!table->data || !table->maxlen)
2469 return -ENOTDIR;
2470
2471 if (oldval && oldlenp) {
Linus Torvaldsde9e0072005-12-31 17:00:29 -08002472 size_t bufsize;
2473 if (get_user(bufsize, oldlenp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 return -EFAULT;
Linus Torvaldsde9e0072005-12-31 17:00:29 -08002475 if (bufsize) {
2476 size_t len = strlen(table->data), copied;
2477
2478 /* This shouldn't trigger for a well-formed sysctl */
2479 if (len > table->maxlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 len = table->maxlen;
Linus Torvaldsde9e0072005-12-31 17:00:29 -08002481
2482 /* Copy up to a max of bufsize-1 bytes of the string */
2483 copied = (len >= bufsize) ? bufsize - 1 : len;
2484
2485 if (copy_to_user(oldval, table->data, copied) ||
2486 put_user(0, (char __user *)(oldval + copied)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487 return -EFAULT;
Linus Torvaldsde9e0072005-12-31 17:00:29 -08002488 if (put_user(len, oldlenp))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489 return -EFAULT;
2490 }
2491 }
2492 if (newval && newlen) {
Linus Torvaldsde9e0072005-12-31 17:00:29 -08002493 size_t len = newlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 if (len > table->maxlen)
2495 len = table->maxlen;
2496 if(copy_from_user(table->data, newval, len))
2497 return -EFAULT;
2498 if (len == table->maxlen)
2499 len--;
2500 ((char *) table->data)[len] = 0;
2501 }
Yi Yang82c9df82005-12-30 16:37:10 +08002502 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503}
2504
2505/*
2506 * This function makes sure that all of the integers in the vector
2507 * are between the minimum and maximum values given in the arrays
2508 * table->extra1 and table->extra2, respectively.
2509 */
2510int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
2511 void __user *oldval, size_t __user *oldlenp,
2512 void __user *newval, size_t newlen, void **context)
2513{
2514
2515 if (newval && newlen) {
2516 int __user *vec = (int __user *) newval;
2517 int *min = (int *) table->extra1;
2518 int *max = (int *) table->extra2;
2519 size_t length;
2520 int i;
2521
2522 if (newlen % sizeof(int) != 0)
2523 return -EINVAL;
2524
2525 if (!table->extra1 && !table->extra2)
2526 return 0;
2527
2528 if (newlen > table->maxlen)
2529 newlen = table->maxlen;
2530 length = newlen / sizeof(int);
2531
2532 for (i = 0; i < length; i++) {
2533 int value;
2534 if (get_user(value, vec + i))
2535 return -EFAULT;
2536 if (min && value < min[i])
2537 return -EINVAL;
2538 if (max && value > max[i])
2539 return -EINVAL;
2540 }
2541 }
2542 return 0;
2543}
2544
2545/* Strategy function to convert jiffies to seconds */
2546int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
2547 void __user *oldval, size_t __user *oldlenp,
2548 void __user *newval, size_t newlen, void **context)
2549{
2550 if (oldval) {
2551 size_t olen;
2552 if (oldlenp) {
2553 if (get_user(olen, oldlenp))
2554 return -EFAULT;
2555 if (olen!=sizeof(int))
2556 return -EINVAL;
2557 }
2558 if (put_user(*(int *)(table->data)/HZ, (int __user *)oldval) ||
2559 (oldlenp && put_user(sizeof(int),oldlenp)))
2560 return -EFAULT;
2561 }
2562 if (newval && newlen) {
2563 int new;
2564 if (newlen != sizeof(int))
2565 return -EINVAL;
2566 if (get_user(new, (int __user *)newval))
2567 return -EFAULT;
2568 *(int *)(table->data) = new*HZ;
2569 }
2570 return 1;
2571}
2572
2573/* Strategy function to convert jiffies to seconds */
2574int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
2575 void __user *oldval, size_t __user *oldlenp,
2576 void __user *newval, size_t newlen, void **context)
2577{
2578 if (oldval) {
2579 size_t olen;
2580 if (oldlenp) {
2581 if (get_user(olen, oldlenp))
2582 return -EFAULT;
2583 if (olen!=sizeof(int))
2584 return -EINVAL;
2585 }
2586 if (put_user(jiffies_to_msecs(*(int *)(table->data)), (int __user *)oldval) ||
2587 (oldlenp && put_user(sizeof(int),oldlenp)))
2588 return -EFAULT;
2589 }
2590 if (newval && newlen) {
2591 int new;
2592 if (newlen != sizeof(int))
2593 return -EINVAL;
2594 if (get_user(new, (int __user *)newval))
2595 return -EFAULT;
2596 *(int *)(table->data) = msecs_to_jiffies(new);
2597 }
2598 return 1;
2599}
2600
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07002601#else /* CONFIG_SYSCTL_SYSCALL */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602
2603
2604asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
2605{
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07002606 static int msg_count;
Eric W. Biederman0e009be2006-11-05 23:52:11 -08002607 struct __sysctl_args tmp;
2608 int name[CTL_MAXNAME];
2609 int i;
2610
2611 /* Read in the sysctl name for better debug message logging */
2612 if (copy_from_user(&tmp, args, sizeof(tmp)))
2613 return -EFAULT;
2614 if (tmp.nlen <= 0 || tmp.nlen >= CTL_MAXNAME)
2615 return -ENOTDIR;
2616 for (i = 0; i < tmp.nlen; i++)
2617 if (get_user(name[i], tmp.name + i))
2618 return -EFAULT;
2619
2620 /* Ignore accesses to kernel.version */
2621 if ((tmp.nlen == 2) && (name[0] == CTL_KERN) && (name[1] == KERN_VERSION))
2622 goto out;
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07002623
2624 if (msg_count < 5) {
2625 msg_count++;
2626 printk(KERN_INFO
2627 "warning: process `%s' used the removed sysctl "
Eric W. Biederman0e009be2006-11-05 23:52:11 -08002628 "system call with ", current->comm);
2629 for (i = 0; i < tmp.nlen; i++)
2630 printk("%d.", name[i]);
2631 printk("\n");
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07002632 }
Eric W. Biederman0e009be2006-11-05 23:52:11 -08002633out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634 return -ENOSYS;
2635}
2636
2637int sysctl_string(ctl_table *table, int __user *name, int nlen,
2638 void __user *oldval, size_t __user *oldlenp,
2639 void __user *newval, size_t newlen, void **context)
2640{
2641 return -ENOSYS;
2642}
2643
2644int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
2645 void __user *oldval, size_t __user *oldlenp,
2646 void __user *newval, size_t newlen, void **context)
2647{
2648 return -ENOSYS;
2649}
2650
2651int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
2652 void __user *oldval, size_t __user *oldlenp,
2653 void __user *newval, size_t newlen, void **context)
2654{
2655 return -ENOSYS;
2656}
2657
2658int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
2659 void __user *oldval, size_t __user *oldlenp,
2660 void __user *newval, size_t newlen, void **context)
2661{
2662 return -ENOSYS;
2663}
2664
Eric W. Biedermanb89a8172006-09-27 01:51:04 -07002665#endif /* CONFIG_SYSCTL_SYSCALL */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666
2667/*
2668 * No sense putting this after each symbol definition, twice,
2669 * exception granted :-)
2670 */
2671EXPORT_SYMBOL(proc_dointvec);
2672EXPORT_SYMBOL(proc_dointvec_jiffies);
2673EXPORT_SYMBOL(proc_dointvec_minmax);
2674EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
2675EXPORT_SYMBOL(proc_dointvec_ms_jiffies);
2676EXPORT_SYMBOL(proc_dostring);
2677EXPORT_SYMBOL(proc_doulongvec_minmax);
2678EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
2679EXPORT_SYMBOL(register_sysctl_table);
2680EXPORT_SYMBOL(sysctl_intvec);
2681EXPORT_SYMBOL(sysctl_jiffies);
2682EXPORT_SYMBOL(sysctl_ms_jiffies);
2683EXPORT_SYMBOL(sysctl_string);
2684EXPORT_SYMBOL(unregister_sysctl_table);