[PATCH] drop-pagecache
[linux-2.6-block.git] / kernel / sysctl.c
CommitLineData
1da177e4
LT
1/*
2 * sysctl.c: General linux system control interface
3 *
4 * Begun 24 March 1995, Stephen Tweedie
5 * Added /proc support, Dec 1995
6 * Added bdflush entry and intvec min/max checking, 2/23/96, Tom Dyas.
7 * Added hooks for /proc/sys/net (minor, minor patch), 96/4/1, Mike Shaver.
8 * Added kernel/java-{interpreter,appletviewer}, 96/5/10, Mike Shaver.
9 * Dynamic registration fixes, Stephen Tweedie.
10 * Added kswapd-interval, ctrl-alt-del, printk stuff, 1/8/97, Chris Horn.
11 * Made sysctl support optional via CONFIG_SYSCTL, 1/10/97, Chris
12 * Horn.
13 * Added proc_doulongvec_ms_jiffies_minmax, 09/08/99, Carlos H. Bauer.
14 * Added proc_doulongvec_minmax, 09/08/99, Carlos H. Bauer.
15 * Changed linked lists to use list.h instead of lists.h, 02/24/00, Bill
16 * Wendling.
17 * The list_for_each() macro wasn't appropriate for the sysctl loop.
18 * Removed it and replaced it with older style, 03/23/00, Bill Wendling
19 */
20
21#include <linux/config.h>
22#include <linux/module.h>
23#include <linux/mm.h>
24#include <linux/swap.h>
25#include <linux/slab.h>
26#include <linux/sysctl.h>
27#include <linux/proc_fs.h>
28#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>
0296b228 34#include <linux/kobject.h>
20380731 35#include <linux/net.h>
1da177e4
LT
36#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>
46
47#include <asm/uaccess.h>
48#include <asm/processor.h>
49
50#ifdef CONFIG_ROOT_NFS
51#include <linux/nfs_fs.h>
52#endif
53
54#if defined(CONFIG_SYSCTL)
55
56/* External variables not in a header file. */
57extern int C_A_D;
58extern int sysctl_overcommit_memory;
59extern int sysctl_overcommit_ratio;
60extern int max_threads;
61extern int sysrq_enabled;
62extern int core_uses_pid;
d6e71144 63extern int suid_dumpable;
1da177e4
LT
64extern char core_pattern[];
65extern int cad_pid;
66extern int pid_max;
67extern int min_free_kbytes;
68extern int printk_ratelimit_jiffies;
69extern int printk_ratelimit_burst;
70extern int pid_max_min, pid_max_max;
9d0243bc 71extern int sysctl_drop_caches;
1da177e4
LT
72
73#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
74int unknown_nmi_panic;
75extern int proc_unknown_nmi_panic(ctl_table *, int, struct file *,
76 void __user *, size_t *, loff_t *);
77#endif
78
79/* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
80static int maxolduid = 65535;
81static int minolduid;
82
83static int ngroups_max = NGROUPS_MAX;
84
85#ifdef CONFIG_KMOD
86extern char modprobe_path[];
87#endif
1da177e4
LT
88#ifdef CONFIG_CHR_DEV_SG
89extern int sg_big_buff;
90#endif
91#ifdef CONFIG_SYSVIPC
92extern size_t shm_ctlmax;
93extern size_t shm_ctlall;
94extern int shm_ctlmni;
95extern int msg_ctlmax;
96extern int msg_ctlmnb;
97extern int msg_ctlmni;
98extern int sem_ctls[];
99#endif
100
101#ifdef __sparc__
102extern char reboot_command [];
103extern int stop_a_enabled;
104extern int scons_pwroff;
105#endif
106
107#ifdef __hppa__
108extern int pwrsw_enabled;
109extern int unaligned_enabled;
110#endif
111
347a8dc3 112#ifdef CONFIG_S390
1da177e4
LT
113#ifdef CONFIG_MATHEMU
114extern int sysctl_ieee_emulation_warnings;
115#endif
116extern int sysctl_userprocess_debug;
951f22d5 117extern int spin_retry;
1da177e4
LT
118#endif
119
120extern int sysctl_hz_timer;
121
122#ifdef CONFIG_BSD_PROCESS_ACCT
123extern int acct_parm[];
124#endif
125
126int randomize_va_space = 1;
127
128static int parse_table(int __user *, int, void __user *, size_t __user *, void __user *, size_t,
129 ctl_table *, void **);
130static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
131 void __user *buffer, size_t *lenp, loff_t *ppos);
132
133static ctl_table root_table[];
134static struct ctl_table_header root_table_header =
135 { root_table, LIST_HEAD_INIT(root_table_header.ctl_entry) };
136
137static ctl_table kern_table[];
138static ctl_table vm_table[];
1da177e4
LT
139static ctl_table proc_table[];
140static ctl_table fs_table[];
141static ctl_table debug_table[];
142static ctl_table dev_table[];
143extern ctl_table random_table[];
144#ifdef CONFIG_UNIX98_PTYS
145extern ctl_table pty_table[];
146#endif
0399cb08
RL
147#ifdef CONFIG_INOTIFY
148extern ctl_table inotify_table[];
149#endif
1da177e4
LT
150
151#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
152int sysctl_legacy_va_layout;
153#endif
154
155/* /proc declarations: */
156
157#ifdef CONFIG_PROC_FS
158
159static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *);
160static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *);
161static int proc_opensys(struct inode *, struct file *);
162
163struct file_operations proc_sys_file_operations = {
164 .open = proc_opensys,
165 .read = proc_readsys,
166 .write = proc_writesys,
167};
168
169extern struct proc_dir_entry *proc_sys_root;
170
330d57fb 171static void register_proc_table(ctl_table *, struct proc_dir_entry *, void *);
1da177e4
LT
172static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
173#endif
174
175/* The default sysctl tables: */
176
177static ctl_table root_table[] = {
178 {
179 .ctl_name = CTL_KERN,
180 .procname = "kernel",
181 .mode = 0555,
182 .child = kern_table,
183 },
184 {
185 .ctl_name = CTL_VM,
186 .procname = "vm",
187 .mode = 0555,
188 .child = vm_table,
189 },
190#ifdef CONFIG_NET
191 {
192 .ctl_name = CTL_NET,
193 .procname = "net",
194 .mode = 0555,
195 .child = net_table,
196 },
197#endif
198 {
199 .ctl_name = CTL_PROC,
200 .procname = "proc",
201 .mode = 0555,
202 .child = proc_table,
203 },
204 {
205 .ctl_name = CTL_FS,
206 .procname = "fs",
207 .mode = 0555,
208 .child = fs_table,
209 },
210 {
211 .ctl_name = CTL_DEBUG,
212 .procname = "debug",
213 .mode = 0555,
214 .child = debug_table,
215 },
216 {
217 .ctl_name = CTL_DEV,
218 .procname = "dev",
219 .mode = 0555,
220 .child = dev_table,
221 },
0eeca283 222
1da177e4
LT
223 { .ctl_name = 0 }
224};
225
226static ctl_table kern_table[] = {
227 {
228 .ctl_name = KERN_OSTYPE,
229 .procname = "ostype",
230 .data = system_utsname.sysname,
231 .maxlen = sizeof(system_utsname.sysname),
232 .mode = 0444,
233 .proc_handler = &proc_doutsstring,
234 .strategy = &sysctl_string,
235 },
236 {
237 .ctl_name = KERN_OSRELEASE,
238 .procname = "osrelease",
239 .data = system_utsname.release,
240 .maxlen = sizeof(system_utsname.release),
241 .mode = 0444,
242 .proc_handler = &proc_doutsstring,
243 .strategy = &sysctl_string,
244 },
245 {
246 .ctl_name = KERN_VERSION,
247 .procname = "version",
248 .data = system_utsname.version,
249 .maxlen = sizeof(system_utsname.version),
250 .mode = 0444,
251 .proc_handler = &proc_doutsstring,
252 .strategy = &sysctl_string,
253 },
254 {
255 .ctl_name = KERN_NODENAME,
256 .procname = "hostname",
257 .data = system_utsname.nodename,
258 .maxlen = sizeof(system_utsname.nodename),
259 .mode = 0644,
260 .proc_handler = &proc_doutsstring,
261 .strategy = &sysctl_string,
262 },
263 {
264 .ctl_name = KERN_DOMAINNAME,
265 .procname = "domainname",
266 .data = system_utsname.domainname,
267 .maxlen = sizeof(system_utsname.domainname),
268 .mode = 0644,
269 .proc_handler = &proc_doutsstring,
270 .strategy = &sysctl_string,
271 },
272 {
273 .ctl_name = KERN_PANIC,
274 .procname = "panic",
275 .data = &panic_timeout,
276 .maxlen = sizeof(int),
277 .mode = 0644,
278 .proc_handler = &proc_dointvec,
279 },
280 {
281 .ctl_name = KERN_CORE_USES_PID,
282 .procname = "core_uses_pid",
283 .data = &core_uses_pid,
284 .maxlen = sizeof(int),
285 .mode = 0644,
286 .proc_handler = &proc_dointvec,
287 },
288 {
289 .ctl_name = KERN_CORE_PATTERN,
290 .procname = "core_pattern",
291 .data = core_pattern,
292 .maxlen = 64,
293 .mode = 0644,
294 .proc_handler = &proc_dostring,
295 .strategy = &sysctl_string,
296 },
297 {
298 .ctl_name = KERN_TAINTED,
299 .procname = "tainted",
300 .data = &tainted,
301 .maxlen = sizeof(int),
302 .mode = 0444,
303 .proc_handler = &proc_dointvec,
304 },
305 {
306 .ctl_name = KERN_CAP_BSET,
307 .procname = "cap-bound",
308 .data = &cap_bset,
309 .maxlen = sizeof(kernel_cap_t),
310 .mode = 0600,
311 .proc_handler = &proc_dointvec_bset,
312 },
313#ifdef CONFIG_BLK_DEV_INITRD
314 {
315 .ctl_name = KERN_REALROOTDEV,
316 .procname = "real-root-dev",
317 .data = &real_root_dev,
318 .maxlen = sizeof(int),
319 .mode = 0644,
320 .proc_handler = &proc_dointvec,
321 },
322#endif
323#ifdef __sparc__
324 {
325 .ctl_name = KERN_SPARC_REBOOT,
326 .procname = "reboot-cmd",
327 .data = reboot_command,
328 .maxlen = 256,
329 .mode = 0644,
330 .proc_handler = &proc_dostring,
331 .strategy = &sysctl_string,
332 },
333 {
334 .ctl_name = KERN_SPARC_STOP_A,
335 .procname = "stop-a",
336 .data = &stop_a_enabled,
337 .maxlen = sizeof (int),
338 .mode = 0644,
339 .proc_handler = &proc_dointvec,
340 },
341 {
342 .ctl_name = KERN_SPARC_SCONS_PWROFF,
343 .procname = "scons-poweroff",
344 .data = &scons_pwroff,
345 .maxlen = sizeof (int),
346 .mode = 0644,
347 .proc_handler = &proc_dointvec,
348 },
349#endif
350#ifdef __hppa__
351 {
352 .ctl_name = KERN_HPPA_PWRSW,
353 .procname = "soft-power",
354 .data = &pwrsw_enabled,
355 .maxlen = sizeof (int),
356 .mode = 0644,
357 .proc_handler = &proc_dointvec,
358 },
359 {
360 .ctl_name = KERN_HPPA_UNALIGNED,
361 .procname = "unaligned-trap",
362 .data = &unaligned_enabled,
363 .maxlen = sizeof (int),
364 .mode = 0644,
365 .proc_handler = &proc_dointvec,
366 },
367#endif
368 {
369 .ctl_name = KERN_CTLALTDEL,
370 .procname = "ctrl-alt-del",
371 .data = &C_A_D,
372 .maxlen = sizeof(int),
373 .mode = 0644,
374 .proc_handler = &proc_dointvec,
375 },
376 {
377 .ctl_name = KERN_PRINTK,
378 .procname = "printk",
379 .data = &console_loglevel,
380 .maxlen = 4*sizeof(int),
381 .mode = 0644,
382 .proc_handler = &proc_dointvec,
383 },
384#ifdef CONFIG_KMOD
385 {
386 .ctl_name = KERN_MODPROBE,
387 .procname = "modprobe",
388 .data = &modprobe_path,
389 .maxlen = KMOD_PATH_LEN,
390 .mode = 0644,
391 .proc_handler = &proc_dostring,
392 .strategy = &sysctl_string,
393 },
394#endif
395#ifdef CONFIG_HOTPLUG
396 {
397 .ctl_name = KERN_HOTPLUG,
398 .procname = "hotplug",
312c004d
KS
399 .data = &uevent_helper,
400 .maxlen = UEVENT_HELPER_PATH_LEN,
1da177e4
LT
401 .mode = 0644,
402 .proc_handler = &proc_dostring,
403 .strategy = &sysctl_string,
404 },
405#endif
406#ifdef CONFIG_CHR_DEV_SG
407 {
408 .ctl_name = KERN_SG_BIG_BUFF,
409 .procname = "sg-big-buff",
410 .data = &sg_big_buff,
411 .maxlen = sizeof (int),
412 .mode = 0444,
413 .proc_handler = &proc_dointvec,
414 },
415#endif
416#ifdef CONFIG_BSD_PROCESS_ACCT
417 {
418 .ctl_name = KERN_ACCT,
419 .procname = "acct",
420 .data = &acct_parm,
421 .maxlen = 3*sizeof(int),
422 .mode = 0644,
423 .proc_handler = &proc_dointvec,
424 },
425#endif
426#ifdef CONFIG_SYSVIPC
427 {
428 .ctl_name = KERN_SHMMAX,
429 .procname = "shmmax",
430 .data = &shm_ctlmax,
431 .maxlen = sizeof (size_t),
432 .mode = 0644,
433 .proc_handler = &proc_doulongvec_minmax,
434 },
435 {
436 .ctl_name = KERN_SHMALL,
437 .procname = "shmall",
438 .data = &shm_ctlall,
439 .maxlen = sizeof (size_t),
440 .mode = 0644,
441 .proc_handler = &proc_doulongvec_minmax,
442 },
443 {
444 .ctl_name = KERN_SHMMNI,
445 .procname = "shmmni",
446 .data = &shm_ctlmni,
447 .maxlen = sizeof (int),
448 .mode = 0644,
449 .proc_handler = &proc_dointvec,
450 },
451 {
452 .ctl_name = KERN_MSGMAX,
453 .procname = "msgmax",
454 .data = &msg_ctlmax,
455 .maxlen = sizeof (int),
456 .mode = 0644,
457 .proc_handler = &proc_dointvec,
458 },
459 {
460 .ctl_name = KERN_MSGMNI,
461 .procname = "msgmni",
462 .data = &msg_ctlmni,
463 .maxlen = sizeof (int),
464 .mode = 0644,
465 .proc_handler = &proc_dointvec,
466 },
467 {
468 .ctl_name = KERN_MSGMNB,
469 .procname = "msgmnb",
470 .data = &msg_ctlmnb,
471 .maxlen = sizeof (int),
472 .mode = 0644,
473 .proc_handler = &proc_dointvec,
474 },
475 {
476 .ctl_name = KERN_SEM,
477 .procname = "sem",
478 .data = &sem_ctls,
479 .maxlen = 4*sizeof (int),
480 .mode = 0644,
481 .proc_handler = &proc_dointvec,
482 },
483#endif
484#ifdef CONFIG_MAGIC_SYSRQ
485 {
486 .ctl_name = KERN_SYSRQ,
487 .procname = "sysrq",
488 .data = &sysrq_enabled,
489 .maxlen = sizeof (int),
490 .mode = 0644,
491 .proc_handler = &proc_dointvec,
492 },
493#endif
494 {
495 .ctl_name = KERN_CADPID,
496 .procname = "cad_pid",
497 .data = &cad_pid,
498 .maxlen = sizeof (int),
499 .mode = 0600,
500 .proc_handler = &proc_dointvec,
501 },
502 {
503 .ctl_name = KERN_MAX_THREADS,
504 .procname = "threads-max",
505 .data = &max_threads,
506 .maxlen = sizeof(int),
507 .mode = 0644,
508 .proc_handler = &proc_dointvec,
509 },
510 {
511 .ctl_name = KERN_RANDOM,
512 .procname = "random",
513 .mode = 0555,
514 .child = random_table,
515 },
516#ifdef CONFIG_UNIX98_PTYS
517 {
518 .ctl_name = KERN_PTY,
519 .procname = "pty",
520 .mode = 0555,
521 .child = pty_table,
522 },
523#endif
524 {
525 .ctl_name = KERN_OVERFLOWUID,
526 .procname = "overflowuid",
527 .data = &overflowuid,
528 .maxlen = sizeof(int),
529 .mode = 0644,
530 .proc_handler = &proc_dointvec_minmax,
531 .strategy = &sysctl_intvec,
532 .extra1 = &minolduid,
533 .extra2 = &maxolduid,
534 },
535 {
536 .ctl_name = KERN_OVERFLOWGID,
537 .procname = "overflowgid",
538 .data = &overflowgid,
539 .maxlen = sizeof(int),
540 .mode = 0644,
541 .proc_handler = &proc_dointvec_minmax,
542 .strategy = &sysctl_intvec,
543 .extra1 = &minolduid,
544 .extra2 = &maxolduid,
545 },
347a8dc3 546#ifdef CONFIG_S390
1da177e4
LT
547#ifdef CONFIG_MATHEMU
548 {
549 .ctl_name = KERN_IEEE_EMULATION_WARNINGS,
550 .procname = "ieee_emulation_warnings",
551 .data = &sysctl_ieee_emulation_warnings,
552 .maxlen = sizeof(int),
553 .mode = 0644,
554 .proc_handler = &proc_dointvec,
555 },
556#endif
557#ifdef CONFIG_NO_IDLE_HZ
558 {
559 .ctl_name = KERN_HZ_TIMER,
560 .procname = "hz_timer",
561 .data = &sysctl_hz_timer,
562 .maxlen = sizeof(int),
563 .mode = 0644,
564 .proc_handler = &proc_dointvec,
565 },
566#endif
567 {
568 .ctl_name = KERN_S390_USER_DEBUG_LOGGING,
569 .procname = "userprocess_debug",
570 .data = &sysctl_userprocess_debug,
571 .maxlen = sizeof(int),
572 .mode = 0644,
573 .proc_handler = &proc_dointvec,
574 },
575#endif
576 {
577 .ctl_name = KERN_PIDMAX,
578 .procname = "pid_max",
579 .data = &pid_max,
580 .maxlen = sizeof (int),
581 .mode = 0644,
582 .proc_handler = &proc_dointvec_minmax,
583 .strategy = sysctl_intvec,
584 .extra1 = &pid_max_min,
585 .extra2 = &pid_max_max,
586 },
587 {
588 .ctl_name = KERN_PANIC_ON_OOPS,
589 .procname = "panic_on_oops",
590 .data = &panic_on_oops,
591 .maxlen = sizeof(int),
592 .mode = 0644,
593 .proc_handler = &proc_dointvec,
594 },
595 {
596 .ctl_name = KERN_PRINTK_RATELIMIT,
597 .procname = "printk_ratelimit",
598 .data = &printk_ratelimit_jiffies,
599 .maxlen = sizeof(int),
600 .mode = 0644,
601 .proc_handler = &proc_dointvec_jiffies,
602 .strategy = &sysctl_jiffies,
603 },
604 {
605 .ctl_name = KERN_PRINTK_RATELIMIT_BURST,
606 .procname = "printk_ratelimit_burst",
607 .data = &printk_ratelimit_burst,
608 .maxlen = sizeof(int),
609 .mode = 0644,
610 .proc_handler = &proc_dointvec,
611 },
612 {
613 .ctl_name = KERN_NGROUPS_MAX,
614 .procname = "ngroups_max",
615 .data = &ngroups_max,
616 .maxlen = sizeof (int),
617 .mode = 0444,
618 .proc_handler = &proc_dointvec,
619 },
620#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
621 {
622 .ctl_name = KERN_UNKNOWN_NMI_PANIC,
623 .procname = "unknown_nmi_panic",
624 .data = &unknown_nmi_panic,
625 .maxlen = sizeof (int),
626 .mode = 0644,
627 .proc_handler = &proc_unknown_nmi_panic,
628 },
629#endif
630#if defined(CONFIG_X86)
631 {
632 .ctl_name = KERN_BOOTLOADER_TYPE,
633 .procname = "bootloader_type",
634 .data = &bootloader_type,
635 .maxlen = sizeof (int),
636 .mode = 0444,
637 .proc_handler = &proc_dointvec,
638 },
639#endif
640 {
641 .ctl_name = KERN_RANDOMIZE,
642 .procname = "randomize_va_space",
643 .data = &randomize_va_space,
644 .maxlen = sizeof(int),
645 .mode = 0644,
646 .proc_handler = &proc_dointvec,
647 },
347a8dc3 648#if defined(CONFIG_S390)
951f22d5
MS
649 {
650 .ctl_name = KERN_SPIN_RETRY,
651 .procname = "spin_retry",
652 .data = &spin_retry,
653 .maxlen = sizeof (int),
654 .mode = 0644,
655 .proc_handler = &proc_dointvec,
656 },
657#endif
1da177e4
LT
658 { .ctl_name = 0 }
659};
660
661/* Constants for minimum and maximum testing in vm_table.
662 We use these as one-element integer vectors. */
663static int zero;
664static int one_hundred = 100;
665
666
667static ctl_table vm_table[] = {
668 {
669 .ctl_name = VM_OVERCOMMIT_MEMORY,
670 .procname = "overcommit_memory",
671 .data = &sysctl_overcommit_memory,
672 .maxlen = sizeof(sysctl_overcommit_memory),
673 .mode = 0644,
674 .proc_handler = &proc_dointvec,
675 },
676 {
677 .ctl_name = VM_OVERCOMMIT_RATIO,
678 .procname = "overcommit_ratio",
679 .data = &sysctl_overcommit_ratio,
680 .maxlen = sizeof(sysctl_overcommit_ratio),
681 .mode = 0644,
682 .proc_handler = &proc_dointvec,
683 },
684 {
685 .ctl_name = VM_PAGE_CLUSTER,
686 .procname = "page-cluster",
687 .data = &page_cluster,
688 .maxlen = sizeof(int),
689 .mode = 0644,
690 .proc_handler = &proc_dointvec,
691 },
692 {
693 .ctl_name = VM_DIRTY_BACKGROUND,
694 .procname = "dirty_background_ratio",
695 .data = &dirty_background_ratio,
696 .maxlen = sizeof(dirty_background_ratio),
697 .mode = 0644,
698 .proc_handler = &proc_dointvec_minmax,
699 .strategy = &sysctl_intvec,
700 .extra1 = &zero,
701 .extra2 = &one_hundred,
702 },
703 {
704 .ctl_name = VM_DIRTY_RATIO,
705 .procname = "dirty_ratio",
706 .data = &vm_dirty_ratio,
707 .maxlen = sizeof(vm_dirty_ratio),
708 .mode = 0644,
709 .proc_handler = &proc_dointvec_minmax,
710 .strategy = &sysctl_intvec,
711 .extra1 = &zero,
712 .extra2 = &one_hundred,
713 },
714 {
715 .ctl_name = VM_DIRTY_WB_CS,
716 .procname = "dirty_writeback_centisecs",
717 .data = &dirty_writeback_centisecs,
718 .maxlen = sizeof(dirty_writeback_centisecs),
719 .mode = 0644,
720 .proc_handler = &dirty_writeback_centisecs_handler,
721 },
722 {
723 .ctl_name = VM_DIRTY_EXPIRE_CS,
724 .procname = "dirty_expire_centisecs",
725 .data = &dirty_expire_centisecs,
726 .maxlen = sizeof(dirty_expire_centisecs),
727 .mode = 0644,
728 .proc_handler = &proc_dointvec,
729 },
730 {
731 .ctl_name = VM_NR_PDFLUSH_THREADS,
732 .procname = "nr_pdflush_threads",
733 .data = &nr_pdflush_threads,
734 .maxlen = sizeof nr_pdflush_threads,
735 .mode = 0444 /* read-only*/,
736 .proc_handler = &proc_dointvec,
737 },
738 {
739 .ctl_name = VM_SWAPPINESS,
740 .procname = "swappiness",
741 .data = &vm_swappiness,
742 .maxlen = sizeof(vm_swappiness),
743 .mode = 0644,
744 .proc_handler = &proc_dointvec_minmax,
745 .strategy = &sysctl_intvec,
746 .extra1 = &zero,
747 .extra2 = &one_hundred,
748 },
749#ifdef CONFIG_HUGETLB_PAGE
750 {
751 .ctl_name = VM_HUGETLB_PAGES,
752 .procname = "nr_hugepages",
753 .data = &max_huge_pages,
754 .maxlen = sizeof(unsigned long),
755 .mode = 0644,
756 .proc_handler = &hugetlb_sysctl_handler,
757 .extra1 = (void *)&hugetlb_zero,
758 .extra2 = (void *)&hugetlb_infinity,
759 },
760 {
761 .ctl_name = VM_HUGETLB_GROUP,
762 .procname = "hugetlb_shm_group",
763 .data = &sysctl_hugetlb_shm_group,
764 .maxlen = sizeof(gid_t),
765 .mode = 0644,
766 .proc_handler = &proc_dointvec,
767 },
768#endif
769 {
770 .ctl_name = VM_LOWMEM_RESERVE_RATIO,
771 .procname = "lowmem_reserve_ratio",
772 .data = &sysctl_lowmem_reserve_ratio,
773 .maxlen = sizeof(sysctl_lowmem_reserve_ratio),
774 .mode = 0644,
775 .proc_handler = &lowmem_reserve_ratio_sysctl_handler,
776 .strategy = &sysctl_intvec,
777 },
9d0243bc
AM
778 {
779 .ctl_name = VM_DROP_PAGECACHE,
780 .procname = "drop_caches",
781 .data = &sysctl_drop_caches,
782 .maxlen = sizeof(int),
783 .mode = 0644,
784 .proc_handler = drop_caches_sysctl_handler,
785 .strategy = &sysctl_intvec,
786 },
1da177e4
LT
787 {
788 .ctl_name = VM_MIN_FREE_KBYTES,
789 .procname = "min_free_kbytes",
790 .data = &min_free_kbytes,
791 .maxlen = sizeof(min_free_kbytes),
792 .mode = 0644,
793 .proc_handler = &min_free_kbytes_sysctl_handler,
794 .strategy = &sysctl_intvec,
795 .extra1 = &zero,
796 },
797#ifdef CONFIG_MMU
798 {
799 .ctl_name = VM_MAX_MAP_COUNT,
800 .procname = "max_map_count",
801 .data = &sysctl_max_map_count,
802 .maxlen = sizeof(sysctl_max_map_count),
803 .mode = 0644,
804 .proc_handler = &proc_dointvec
805 },
806#endif
807 {
808 .ctl_name = VM_LAPTOP_MODE,
809 .procname = "laptop_mode",
810 .data = &laptop_mode,
811 .maxlen = sizeof(laptop_mode),
812 .mode = 0644,
813 .proc_handler = &proc_dointvec,
814 .strategy = &sysctl_intvec,
815 .extra1 = &zero,
816 },
817 {
818 .ctl_name = VM_BLOCK_DUMP,
819 .procname = "block_dump",
820 .data = &block_dump,
821 .maxlen = sizeof(block_dump),
822 .mode = 0644,
823 .proc_handler = &proc_dointvec,
824 .strategy = &sysctl_intvec,
825 .extra1 = &zero,
826 },
827 {
828 .ctl_name = VM_VFS_CACHE_PRESSURE,
829 .procname = "vfs_cache_pressure",
830 .data = &sysctl_vfs_cache_pressure,
831 .maxlen = sizeof(sysctl_vfs_cache_pressure),
832 .mode = 0644,
833 .proc_handler = &proc_dointvec,
834 .strategy = &sysctl_intvec,
835 .extra1 = &zero,
836 },
837#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
838 {
839 .ctl_name = VM_LEGACY_VA_LAYOUT,
840 .procname = "legacy_va_layout",
841 .data = &sysctl_legacy_va_layout,
842 .maxlen = sizeof(sysctl_legacy_va_layout),
843 .mode = 0644,
844 .proc_handler = &proc_dointvec,
845 .strategy = &sysctl_intvec,
846 .extra1 = &zero,
847 },
848#endif
849#ifdef CONFIG_SWAP
850 {
851 .ctl_name = VM_SWAP_TOKEN_TIMEOUT,
852 .procname = "swap_token_timeout",
853 .data = &swap_token_default_timeout,
854 .maxlen = sizeof(swap_token_default_timeout),
855 .mode = 0644,
856 .proc_handler = &proc_dointvec_jiffies,
857 .strategy = &sysctl_jiffies,
858 },
859#endif
860 { .ctl_name = 0 }
861};
862
863static ctl_table proc_table[] = {
864 { .ctl_name = 0 }
865};
866
867static ctl_table fs_table[] = {
868 {
869 .ctl_name = FS_NRINODE,
870 .procname = "inode-nr",
871 .data = &inodes_stat,
872 .maxlen = 2*sizeof(int),
873 .mode = 0444,
874 .proc_handler = &proc_dointvec,
875 },
876 {
877 .ctl_name = FS_STATINODE,
878 .procname = "inode-state",
879 .data = &inodes_stat,
880 .maxlen = 7*sizeof(int),
881 .mode = 0444,
882 .proc_handler = &proc_dointvec,
883 },
884 {
885 .ctl_name = FS_NRFILE,
886 .procname = "file-nr",
887 .data = &files_stat,
888 .maxlen = 3*sizeof(int),
889 .mode = 0444,
890 .proc_handler = &proc_dointvec,
891 },
892 {
893 .ctl_name = FS_MAXFILE,
894 .procname = "file-max",
895 .data = &files_stat.max_files,
896 .maxlen = sizeof(int),
897 .mode = 0644,
898 .proc_handler = &proc_dointvec,
899 },
900 {
901 .ctl_name = FS_DENTRY,
902 .procname = "dentry-state",
903 .data = &dentry_stat,
904 .maxlen = 6*sizeof(int),
905 .mode = 0444,
906 .proc_handler = &proc_dointvec,
907 },
908 {
909 .ctl_name = FS_OVERFLOWUID,
910 .procname = "overflowuid",
911 .data = &fs_overflowuid,
912 .maxlen = sizeof(int),
913 .mode = 0644,
914 .proc_handler = &proc_dointvec_minmax,
915 .strategy = &sysctl_intvec,
916 .extra1 = &minolduid,
917 .extra2 = &maxolduid,
918 },
919 {
920 .ctl_name = FS_OVERFLOWGID,
921 .procname = "overflowgid",
922 .data = &fs_overflowgid,
923 .maxlen = sizeof(int),
924 .mode = 0644,
925 .proc_handler = &proc_dointvec_minmax,
926 .strategy = &sysctl_intvec,
927 .extra1 = &minolduid,
928 .extra2 = &maxolduid,
929 },
930 {
931 .ctl_name = FS_LEASES,
932 .procname = "leases-enable",
933 .data = &leases_enable,
934 .maxlen = sizeof(int),
935 .mode = 0644,
936 .proc_handler = &proc_dointvec,
937 },
938#ifdef CONFIG_DNOTIFY
939 {
940 .ctl_name = FS_DIR_NOTIFY,
941 .procname = "dir-notify-enable",
942 .data = &dir_notify_enable,
943 .maxlen = sizeof(int),
944 .mode = 0644,
945 .proc_handler = &proc_dointvec,
946 },
947#endif
948#ifdef CONFIG_MMU
949 {
950 .ctl_name = FS_LEASE_TIME,
951 .procname = "lease-break-time",
952 .data = &lease_break_time,
953 .maxlen = sizeof(int),
954 .mode = 0644,
955 .proc_handler = &proc_dointvec,
956 },
957 {
958 .ctl_name = FS_AIO_NR,
959 .procname = "aio-nr",
960 .data = &aio_nr,
961 .maxlen = sizeof(aio_nr),
962 .mode = 0444,
d55b5fda 963 .proc_handler = &proc_doulongvec_minmax,
1da177e4
LT
964 },
965 {
966 .ctl_name = FS_AIO_MAX_NR,
967 .procname = "aio-max-nr",
968 .data = &aio_max_nr,
969 .maxlen = sizeof(aio_max_nr),
970 .mode = 0644,
d55b5fda 971 .proc_handler = &proc_doulongvec_minmax,
1da177e4 972 },
0399cb08
RL
973#ifdef CONFIG_INOTIFY
974 {
975 .ctl_name = FS_INOTIFY,
976 .procname = "inotify",
977 .mode = 0555,
978 .child = inotify_table,
979 },
980#endif
1da177e4 981#endif
d6e71144
AC
982 {
983 .ctl_name = KERN_SETUID_DUMPABLE,
984 .procname = "suid_dumpable",
985 .data = &suid_dumpable,
986 .maxlen = sizeof(int),
987 .mode = 0644,
988 .proc_handler = &proc_dointvec,
989 },
1da177e4
LT
990 { .ctl_name = 0 }
991};
992
993static ctl_table debug_table[] = {
994 { .ctl_name = 0 }
995};
996
997static ctl_table dev_table[] = {
998 { .ctl_name = 0 }
0eeca283 999};
1da177e4
LT
1000
1001extern void init_irq_proc (void);
1002
330d57fb
AV
1003static DEFINE_SPINLOCK(sysctl_lock);
1004
1005/* called under sysctl_lock */
1006static int use_table(struct ctl_table_header *p)
1007{
1008 if (unlikely(p->unregistering))
1009 return 0;
1010 p->used++;
1011 return 1;
1012}
1013
1014/* called under sysctl_lock */
1015static void unuse_table(struct ctl_table_header *p)
1016{
1017 if (!--p->used)
1018 if (unlikely(p->unregistering))
1019 complete(p->unregistering);
1020}
1021
1022/* called under sysctl_lock, will reacquire if has to wait */
1023static void start_unregistering(struct ctl_table_header *p)
1024{
1025 /*
1026 * if p->used is 0, nobody will ever touch that entry again;
1027 * we'll eliminate all paths to it before dropping sysctl_lock
1028 */
1029 if (unlikely(p->used)) {
1030 struct completion wait;
1031 init_completion(&wait);
1032 p->unregistering = &wait;
1033 spin_unlock(&sysctl_lock);
1034 wait_for_completion(&wait);
1035 spin_lock(&sysctl_lock);
1036 }
1037 /*
1038 * do not remove from the list until nobody holds it; walking the
1039 * list in do_sysctl() relies on that.
1040 */
1041 list_del_init(&p->ctl_entry);
1042}
1043
1da177e4
LT
1044void __init sysctl_init(void)
1045{
1046#ifdef CONFIG_PROC_FS
330d57fb 1047 register_proc_table(root_table, proc_sys_root, &root_table_header);
1da177e4
LT
1048 init_irq_proc();
1049#endif
1050}
1051
1052int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
1053 void __user *newval, size_t newlen)
1054{
1055 struct list_head *tmp;
330d57fb 1056 int error = -ENOTDIR;
1da177e4
LT
1057
1058 if (nlen <= 0 || nlen >= CTL_MAXNAME)
1059 return -ENOTDIR;
1060 if (oldval) {
1061 int old_len;
1062 if (!oldlenp || get_user(old_len, oldlenp))
1063 return -EFAULT;
1064 }
330d57fb 1065 spin_lock(&sysctl_lock);
1da177e4
LT
1066 tmp = &root_table_header.ctl_entry;
1067 do {
1068 struct ctl_table_header *head =
1069 list_entry(tmp, struct ctl_table_header, ctl_entry);
1070 void *context = NULL;
330d57fb
AV
1071
1072 if (!use_table(head))
1073 continue;
1074
1075 spin_unlock(&sysctl_lock);
1076
1077 error = parse_table(name, nlen, oldval, oldlenp,
1da177e4
LT
1078 newval, newlen, head->ctl_table,
1079 &context);
5a6b454f 1080 kfree(context);
330d57fb
AV
1081
1082 spin_lock(&sysctl_lock);
1083 unuse_table(head);
1da177e4 1084 if (error != -ENOTDIR)
330d57fb
AV
1085 break;
1086 } while ((tmp = tmp->next) != &root_table_header.ctl_entry);
1087 spin_unlock(&sysctl_lock);
1088 return error;
1da177e4
LT
1089}
1090
1091asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
1092{
1093 struct __sysctl_args tmp;
1094 int error;
1095
1096 if (copy_from_user(&tmp, args, sizeof(tmp)))
1097 return -EFAULT;
1098
1099 lock_kernel();
1100 error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp,
1101 tmp.newval, tmp.newlen);
1102 unlock_kernel();
1103 return error;
1104}
1105
1106/*
1107 * ctl_perm does NOT grant the superuser all rights automatically, because
1108 * some sysctl variables are readonly even to root.
1109 */
1110
1111static int test_perm(int mode, int op)
1112{
1113 if (!current->euid)
1114 mode >>= 6;
1115 else if (in_egroup_p(0))
1116 mode >>= 3;
1117 if ((mode & op & 0007) == op)
1118 return 0;
1119 return -EACCES;
1120}
1121
1122static inline int ctl_perm(ctl_table *table, int op)
1123{
1124 int error;
1125 error = security_sysctl(table, op);
1126 if (error)
1127 return error;
1128 return test_perm(table->mode, op);
1129}
1130
1131static int parse_table(int __user *name, int nlen,
1132 void __user *oldval, size_t __user *oldlenp,
1133 void __user *newval, size_t newlen,
1134 ctl_table *table, void **context)
1135{
1136 int n;
1137repeat:
1138 if (!nlen)
1139 return -ENOTDIR;
1140 if (get_user(n, name))
1141 return -EFAULT;
1142 for ( ; table->ctl_name; table++) {
1143 if (n == table->ctl_name || table->ctl_name == CTL_ANY) {
1144 int error;
1145 if (table->child) {
1146 if (ctl_perm(table, 001))
1147 return -EPERM;
1148 if (table->strategy) {
1149 error = table->strategy(
1150 table, name, nlen,
1151 oldval, oldlenp,
1152 newval, newlen, context);
1153 if (error)
1154 return error;
1155 }
1156 name++;
1157 nlen--;
1158 table = table->child;
1159 goto repeat;
1160 }
1161 error = do_sysctl_strategy(table, name, nlen,
1162 oldval, oldlenp,
1163 newval, newlen, context);
1164 return error;
1165 }
1166 }
1167 return -ENOTDIR;
1168}
1169
1170/* Perform the actual read/write of a sysctl table entry. */
1171int do_sysctl_strategy (ctl_table *table,
1172 int __user *name, int nlen,
1173 void __user *oldval, size_t __user *oldlenp,
1174 void __user *newval, size_t newlen, void **context)
1175{
1176 int op = 0, rc;
1177 size_t len;
1178
1179 if (oldval)
1180 op |= 004;
1181 if (newval)
1182 op |= 002;
1183 if (ctl_perm(table, op))
1184 return -EPERM;
1185
1186 if (table->strategy) {
1187 rc = table->strategy(table, name, nlen, oldval, oldlenp,
1188 newval, newlen, context);
1189 if (rc < 0)
1190 return rc;
1191 if (rc > 0)
1192 return 0;
1193 }
1194
1195 /* If there is no strategy routine, or if the strategy returns
1196 * zero, proceed with automatic r/w */
1197 if (table->data && table->maxlen) {
1198 if (oldval && oldlenp) {
1199 if (get_user(len, oldlenp))
1200 return -EFAULT;
1201 if (len) {
1202 if (len > table->maxlen)
1203 len = table->maxlen;
1204 if(copy_to_user(oldval, table->data, len))
1205 return -EFAULT;
1206 if(put_user(len, oldlenp))
1207 return -EFAULT;
1208 }
1209 }
1210 if (newval && newlen) {
1211 len = newlen;
1212 if (len > table->maxlen)
1213 len = table->maxlen;
1214 if(copy_from_user(table->data, newval, len))
1215 return -EFAULT;
1216 }
1217 }
1218 return 0;
1219}
1220
1221/**
1222 * register_sysctl_table - register a sysctl hierarchy
1223 * @table: the top-level table structure
1224 * @insert_at_head: whether the entry should be inserted in front or at the end
1225 *
1226 * Register a sysctl table hierarchy. @table should be a filled in ctl_table
1227 * array. An entry with a ctl_name of 0 terminates the table.
1228 *
1229 * The members of the &ctl_table structure are used as follows:
1230 *
1231 * ctl_name - This is the numeric sysctl value used by sysctl(2). The number
1232 * must be unique within that level of sysctl
1233 *
1234 * procname - the name of the sysctl file under /proc/sys. Set to %NULL to not
1235 * enter a sysctl file
1236 *
1237 * data - a pointer to data for use by proc_handler
1238 *
1239 * maxlen - the maximum size in bytes of the data
1240 *
1241 * mode - the file permissions for the /proc/sys file, and for sysctl(2)
1242 *
1243 * child - a pointer to the child sysctl table if this entry is a directory, or
1244 * %NULL.
1245 *
1246 * proc_handler - the text handler routine (described below)
1247 *
1248 * strategy - the strategy routine (described below)
1249 *
1250 * de - for internal use by the sysctl routines
1251 *
1252 * extra1, extra2 - extra pointers usable by the proc handler routines
1253 *
1254 * Leaf nodes in the sysctl tree will be represented by a single file
1255 * under /proc; non-leaf nodes will be represented by directories.
1256 *
1257 * sysctl(2) can automatically manage read and write requests through
1258 * the sysctl table. The data and maxlen fields of the ctl_table
1259 * struct enable minimal validation of the values being written to be
1260 * performed, and the mode field allows minimal authentication.
1261 *
1262 * More sophisticated management can be enabled by the provision of a
1263 * strategy routine with the table entry. This will be called before
1264 * any automatic read or write of the data is performed.
1265 *
1266 * The strategy routine may return
1267 *
1268 * < 0 - Error occurred (error is passed to user process)
1269 *
1270 * 0 - OK - proceed with automatic read or write.
1271 *
1272 * > 0 - OK - read or write has been done by the strategy routine, so
1273 * return immediately.
1274 *
1275 * There must be a proc_handler routine for any terminal nodes
1276 * mirrored under /proc/sys (non-terminals are handled by a built-in
1277 * directory handler). Several default handlers are available to
1278 * cover common cases -
1279 *
1280 * proc_dostring(), proc_dointvec(), proc_dointvec_jiffies(),
1281 * proc_dointvec_userhz_jiffies(), proc_dointvec_minmax(),
1282 * proc_doulongvec_ms_jiffies_minmax(), proc_doulongvec_minmax()
1283 *
1284 * It is the handler's job to read the input buffer from user memory
1285 * and process it. The handler should return 0 on success.
1286 *
1287 * This routine returns %NULL on a failure to register, and a pointer
1288 * to the table header on success.
1289 */
1290struct ctl_table_header *register_sysctl_table(ctl_table * table,
1291 int insert_at_head)
1292{
1293 struct ctl_table_header *tmp;
1294 tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL);
1295 if (!tmp)
1296 return NULL;
1297 tmp->ctl_table = table;
1298 INIT_LIST_HEAD(&tmp->ctl_entry);
330d57fb
AV
1299 tmp->used = 0;
1300 tmp->unregistering = NULL;
1301 spin_lock(&sysctl_lock);
1da177e4
LT
1302 if (insert_at_head)
1303 list_add(&tmp->ctl_entry, &root_table_header.ctl_entry);
1304 else
1305 list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
330d57fb 1306 spin_unlock(&sysctl_lock);
1da177e4 1307#ifdef CONFIG_PROC_FS
330d57fb 1308 register_proc_table(table, proc_sys_root, tmp);
1da177e4
LT
1309#endif
1310 return tmp;
1311}
1312
1313/**
1314 * unregister_sysctl_table - unregister a sysctl table hierarchy
1315 * @header: the header returned from register_sysctl_table
1316 *
1317 * Unregisters the sysctl table and all children. proc entries may not
1318 * actually be removed until they are no longer used by anyone.
1319 */
1320void unregister_sysctl_table(struct ctl_table_header * header)
1321{
330d57fb
AV
1322 might_sleep();
1323 spin_lock(&sysctl_lock);
1324 start_unregistering(header);
1da177e4
LT
1325#ifdef CONFIG_PROC_FS
1326 unregister_proc_table(header->ctl_table, proc_sys_root);
1327#endif
330d57fb 1328 spin_unlock(&sysctl_lock);
1da177e4
LT
1329 kfree(header);
1330}
1331
1332/*
1333 * /proc/sys support
1334 */
1335
1336#ifdef CONFIG_PROC_FS
1337
1338/* Scan the sysctl entries in table and add them all into /proc */
330d57fb 1339static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, void *set)
1da177e4
LT
1340{
1341 struct proc_dir_entry *de;
1342 int len;
1343 mode_t mode;
1344
1345 for (; table->ctl_name; table++) {
1346 /* Can't do anything without a proc name. */
1347 if (!table->procname)
1348 continue;
1349 /* Maybe we can't do anything with it... */
1350 if (!table->proc_handler && !table->child) {
1351 printk(KERN_WARNING "SYSCTL: Can't register %s\n",
1352 table->procname);
1353 continue;
1354 }
1355
1356 len = strlen(table->procname);
1357 mode = table->mode;
1358
1359 de = NULL;
1360 if (table->proc_handler)
1361 mode |= S_IFREG;
1362 else {
1363 mode |= S_IFDIR;
1364 for (de = root->subdir; de; de = de->next) {
1365 if (proc_match(len, table->procname, de))
1366 break;
1367 }
1368 /* If the subdir exists already, de is non-NULL */
1369 }
1370
1371 if (!de) {
1372 de = create_proc_entry(table->procname, mode, root);
1373 if (!de)
1374 continue;
330d57fb 1375 de->set = set;
1da177e4
LT
1376 de->data = (void *) table;
1377 if (table->proc_handler)
1378 de->proc_fops = &proc_sys_file_operations;
1379 }
1380 table->de = de;
1381 if (de->mode & S_IFDIR)
330d57fb 1382 register_proc_table(table->child, de, set);
1da177e4
LT
1383 }
1384}
1385
1386/*
1387 * Unregister a /proc sysctl table and any subdirectories.
1388 */
1389static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root)
1390{
1391 struct proc_dir_entry *de;
1392 for (; table->ctl_name; table++) {
1393 if (!(de = table->de))
1394 continue;
1395 if (de->mode & S_IFDIR) {
1396 if (!table->child) {
1397 printk (KERN_ALERT "Help - malformed sysctl tree on free\n");
1398 continue;
1399 }
1400 unregister_proc_table(table->child, de);
1401
1402 /* Don't unregister directories which still have entries.. */
1403 if (de->subdir)
1404 continue;
1405 }
1406
330d57fb
AV
1407 /*
1408 * In any case, mark the entry as goner; we'll keep it
1409 * around if it's busy, but we'll know to do nothing with
1410 * its fields. We are under sysctl_lock here.
1411 */
1412 de->data = NULL;
1413
1da177e4
LT
1414 /* Don't unregister proc entries that are still being used.. */
1415 if (atomic_read(&de->count))
1416 continue;
1417
1418 table->de = NULL;
1419 remove_proc_entry(table->procname, root);
1420 }
1421}
1422
1423static ssize_t do_rw_proc(int write, struct file * file, char __user * buf,
1424 size_t count, loff_t *ppos)
1425{
1426 int op;
330d57fb 1427 struct proc_dir_entry *de = PDE(file->f_dentry->d_inode);
1da177e4
LT
1428 struct ctl_table *table;
1429 size_t res;
330d57fb 1430 ssize_t error = -ENOTDIR;
1da177e4 1431
330d57fb
AV
1432 spin_lock(&sysctl_lock);
1433 if (de && de->data && use_table(de->set)) {
1434 /*
1435 * at that point we know that sysctl was not unregistered
1436 * and won't be until we finish
1437 */
1438 spin_unlock(&sysctl_lock);
1439 table = (struct ctl_table *) de->data;
1440 if (!table || !table->proc_handler)
1441 goto out;
1442 error = -EPERM;
1443 op = (write ? 002 : 004);
1444 if (ctl_perm(table, op))
1445 goto out;
1446
1447 /* careful: calling conventions are nasty here */
1448 res = count;
1449 error = (*table->proc_handler)(table, write, file,
1450 buf, &res, ppos);
1451 if (!error)
1452 error = res;
1453 out:
1454 spin_lock(&sysctl_lock);
1455 unuse_table(de->set);
1456 }
1457 spin_unlock(&sysctl_lock);
1458 return error;
1da177e4
LT
1459}
1460
1461static int proc_opensys(struct inode *inode, struct file *file)
1462{
1463 if (file->f_mode & FMODE_WRITE) {
1464 /*
1465 * sysctl entries that are not writable,
1466 * are _NOT_ writable, capabilities or not.
1467 */
1468 if (!(inode->i_mode & S_IWUSR))
1469 return -EPERM;
1470 }
1471
1472 return 0;
1473}
1474
1475static ssize_t proc_readsys(struct file * file, char __user * buf,
1476 size_t count, loff_t *ppos)
1477{
1478 return do_rw_proc(0, file, buf, count, ppos);
1479}
1480
1481static ssize_t proc_writesys(struct file * file, const char __user * buf,
1482 size_t count, loff_t *ppos)
1483{
1484 return do_rw_proc(1, file, (char __user *) buf, count, ppos);
1485}
1486
1487/**
1488 * proc_dostring - read a string sysctl
1489 * @table: the sysctl table
1490 * @write: %TRUE if this is a write to the sysctl file
1491 * @filp: the file structure
1492 * @buffer: the user buffer
1493 * @lenp: the size of the user buffer
1494 * @ppos: file position
1495 *
1496 * Reads/writes a string from/to the user buffer. If the kernel
1497 * buffer provided is not large enough to hold the string, the
1498 * string is truncated. The copied string is %NULL-terminated.
1499 * If the string is being read by the user process, it is copied
1500 * and a newline '\n' is added. It is truncated if the buffer is
1501 * not large enough.
1502 *
1503 * Returns 0 on success.
1504 */
1505int proc_dostring(ctl_table *table, int write, struct file *filp,
1506 void __user *buffer, size_t *lenp, loff_t *ppos)
1507{
1508 size_t len;
1509 char __user *p;
1510 char c;
1511
1512 if (!table->data || !table->maxlen || !*lenp ||
1513 (*ppos && !write)) {
1514 *lenp = 0;
1515 return 0;
1516 }
1517
1518 if (write) {
1519 len = 0;
1520 p = buffer;
1521 while (len < *lenp) {
1522 if (get_user(c, p++))
1523 return -EFAULT;
1524 if (c == 0 || c == '\n')
1525 break;
1526 len++;
1527 }
1528 if (len >= table->maxlen)
1529 len = table->maxlen-1;
1530 if(copy_from_user(table->data, buffer, len))
1531 return -EFAULT;
1532 ((char *) table->data)[len] = 0;
1533 *ppos += *lenp;
1534 } else {
1535 len = strlen(table->data);
1536 if (len > table->maxlen)
1537 len = table->maxlen;
1538 if (len > *lenp)
1539 len = *lenp;
1540 if (len)
1541 if(copy_to_user(buffer, table->data, len))
1542 return -EFAULT;
1543 if (len < *lenp) {
1544 if(put_user('\n', ((char __user *) buffer) + len))
1545 return -EFAULT;
1546 len++;
1547 }
1548 *lenp = len;
1549 *ppos += len;
1550 }
1551 return 0;
1552}
1553
1554/*
1555 * Special case of dostring for the UTS structure. This has locks
1556 * to observe. Should this be in kernel/sys.c ????
1557 */
1558
1559static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
1560 void __user *buffer, size_t *lenp, loff_t *ppos)
1561{
1562 int r;
1563
1564 if (!write) {
1565 down_read(&uts_sem);
1566 r=proc_dostring(table,0,filp,buffer,lenp, ppos);
1567 up_read(&uts_sem);
1568 } else {
1569 down_write(&uts_sem);
1570 r=proc_dostring(table,1,filp,buffer,lenp, ppos);
1571 up_write(&uts_sem);
1572 }
1573 return r;
1574}
1575
1576static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp,
1577 int *valp,
1578 int write, void *data)
1579{
1580 if (write) {
1581 *valp = *negp ? -*lvalp : *lvalp;
1582 } else {
1583 int val = *valp;
1584 if (val < 0) {
1585 *negp = -1;
1586 *lvalp = (unsigned long)-val;
1587 } else {
1588 *negp = 0;
1589 *lvalp = (unsigned long)val;
1590 }
1591 }
1592 return 0;
1593}
1594
1595static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
1596 void __user *buffer, size_t *lenp, loff_t *ppos,
1597 int (*conv)(int *negp, unsigned long *lvalp, int *valp,
1598 int write, void *data),
1599 void *data)
1600{
1601#define TMPBUFLEN 21
1602 int *i, vleft, first=1, neg, val;
1603 unsigned long lval;
1604 size_t left, len;
1605
1606 char buf[TMPBUFLEN], *p;
1607 char __user *s = buffer;
1608
1609 if (!table->data || !table->maxlen || !*lenp ||
1610 (*ppos && !write)) {
1611 *lenp = 0;
1612 return 0;
1613 }
1614
1615 i = (int *) table->data;
1616 vleft = table->maxlen / sizeof(*i);
1617 left = *lenp;
1618
1619 if (!conv)
1620 conv = do_proc_dointvec_conv;
1621
1622 for (; left && vleft--; i++, first=0) {
1623 if (write) {
1624 while (left) {
1625 char c;
1626 if (get_user(c, s))
1627 return -EFAULT;
1628 if (!isspace(c))
1629 break;
1630 left--;
1631 s++;
1632 }
1633 if (!left)
1634 break;
1635 neg = 0;
1636 len = left;
1637 if (len > sizeof(buf) - 1)
1638 len = sizeof(buf) - 1;
1639 if (copy_from_user(buf, s, len))
1640 return -EFAULT;
1641 buf[len] = 0;
1642 p = buf;
1643 if (*p == '-' && left > 1) {
1644 neg = 1;
1645 left--, p++;
1646 }
1647 if (*p < '0' || *p > '9')
1648 break;
1649
1650 lval = simple_strtoul(p, &p, 0);
1651
1652 len = p-buf;
1653 if ((len < left) && *p && !isspace(*p))
1654 break;
1655 if (neg)
1656 val = -val;
1657 s += len;
1658 left -= len;
1659
1660 if (conv(&neg, &lval, i, 1, data))
1661 break;
1662 } else {
1663 p = buf;
1664 if (!first)
1665 *p++ = '\t';
1666
1667 if (conv(&neg, &lval, i, 0, data))
1668 break;
1669
1670 sprintf(p, "%s%lu", neg ? "-" : "", lval);
1671 len = strlen(buf);
1672 if (len > left)
1673 len = left;
1674 if(copy_to_user(s, buf, len))
1675 return -EFAULT;
1676 left -= len;
1677 s += len;
1678 }
1679 }
1680
1681 if (!write && !first && left) {
1682 if(put_user('\n', s))
1683 return -EFAULT;
1684 left--, s++;
1685 }
1686 if (write) {
1687 while (left) {
1688 char c;
1689 if (get_user(c, s++))
1690 return -EFAULT;
1691 if (!isspace(c))
1692 break;
1693 left--;
1694 }
1695 }
1696 if (write && first)
1697 return -EINVAL;
1698 *lenp -= left;
1699 *ppos += *lenp;
1700 return 0;
1701#undef TMPBUFLEN
1702}
1703
1704/**
1705 * proc_dointvec - read a vector of integers
1706 * @table: the sysctl table
1707 * @write: %TRUE if this is a write to the sysctl file
1708 * @filp: the file structure
1709 * @buffer: the user buffer
1710 * @lenp: the size of the user buffer
1711 * @ppos: file position
1712 *
1713 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1714 * values from/to the user buffer, treated as an ASCII string.
1715 *
1716 * Returns 0 on success.
1717 */
1718int proc_dointvec(ctl_table *table, int write, struct file *filp,
1719 void __user *buffer, size_t *lenp, loff_t *ppos)
1720{
1721 return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
1722 NULL,NULL);
1723}
1724
1725#define OP_SET 0
1726#define OP_AND 1
1727#define OP_OR 2
1728#define OP_MAX 3
1729#define OP_MIN 4
1730
1731static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
1732 int *valp,
1733 int write, void *data)
1734{
1735 int op = *(int *)data;
1736 if (write) {
1737 int val = *negp ? -*lvalp : *lvalp;
1738 switch(op) {
1739 case OP_SET: *valp = val; break;
1740 case OP_AND: *valp &= val; break;
1741 case OP_OR: *valp |= val; break;
1742 case OP_MAX: if(*valp < val)
1743 *valp = val;
1744 break;
1745 case OP_MIN: if(*valp > val)
1746 *valp = val;
1747 break;
1748 }
1749 } else {
1750 int val = *valp;
1751 if (val < 0) {
1752 *negp = -1;
1753 *lvalp = (unsigned long)-val;
1754 } else {
1755 *negp = 0;
1756 *lvalp = (unsigned long)val;
1757 }
1758 }
1759 return 0;
1760}
1761
1762/*
1763 * init may raise the set.
1764 */
1765
1766int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
1767 void __user *buffer, size_t *lenp, loff_t *ppos)
1768{
1769 int op;
1770
1771 if (!capable(CAP_SYS_MODULE)) {
1772 return -EPERM;
1773 }
1774
1775 op = (current->pid == 1) ? OP_SET : OP_AND;
1776 return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
1777 do_proc_dointvec_bset_conv,&op);
1778}
1779
1780struct do_proc_dointvec_minmax_conv_param {
1781 int *min;
1782 int *max;
1783};
1784
1785static int do_proc_dointvec_minmax_conv(int *negp, unsigned long *lvalp,
1786 int *valp,
1787 int write, void *data)
1788{
1789 struct do_proc_dointvec_minmax_conv_param *param = data;
1790 if (write) {
1791 int val = *negp ? -*lvalp : *lvalp;
1792 if ((param->min && *param->min > val) ||
1793 (param->max && *param->max < val))
1794 return -EINVAL;
1795 *valp = val;
1796 } else {
1797 int val = *valp;
1798 if (val < 0) {
1799 *negp = -1;
1800 *lvalp = (unsigned long)-val;
1801 } else {
1802 *negp = 0;
1803 *lvalp = (unsigned long)val;
1804 }
1805 }
1806 return 0;
1807}
1808
1809/**
1810 * proc_dointvec_minmax - read a vector of integers with min/max values
1811 * @table: the sysctl table
1812 * @write: %TRUE if this is a write to the sysctl file
1813 * @filp: the file structure
1814 * @buffer: the user buffer
1815 * @lenp: the size of the user buffer
1816 * @ppos: file position
1817 *
1818 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1819 * values from/to the user buffer, treated as an ASCII string.
1820 *
1821 * This routine will ensure the values are within the range specified by
1822 * table->extra1 (min) and table->extra2 (max).
1823 *
1824 * Returns 0 on success.
1825 */
1826int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
1827 void __user *buffer, size_t *lenp, loff_t *ppos)
1828{
1829 struct do_proc_dointvec_minmax_conv_param param = {
1830 .min = (int *) table->extra1,
1831 .max = (int *) table->extra2,
1832 };
1833 return do_proc_dointvec(table, write, filp, buffer, lenp, ppos,
1834 do_proc_dointvec_minmax_conv, &param);
1835}
1836
1837static int do_proc_doulongvec_minmax(ctl_table *table, int write,
1838 struct file *filp,
1839 void __user *buffer,
1840 size_t *lenp, loff_t *ppos,
1841 unsigned long convmul,
1842 unsigned long convdiv)
1843{
1844#define TMPBUFLEN 21
1845 unsigned long *i, *min, *max, val;
1846 int vleft, first=1, neg;
1847 size_t len, left;
1848 char buf[TMPBUFLEN], *p;
1849 char __user *s = buffer;
1850
1851 if (!table->data || !table->maxlen || !*lenp ||
1852 (*ppos && !write)) {
1853 *lenp = 0;
1854 return 0;
1855 }
1856
1857 i = (unsigned long *) table->data;
1858 min = (unsigned long *) table->extra1;
1859 max = (unsigned long *) table->extra2;
1860 vleft = table->maxlen / sizeof(unsigned long);
1861 left = *lenp;
1862
1863 for (; left && vleft--; i++, min++, max++, first=0) {
1864 if (write) {
1865 while (left) {
1866 char c;
1867 if (get_user(c, s))
1868 return -EFAULT;
1869 if (!isspace(c))
1870 break;
1871 left--;
1872 s++;
1873 }
1874 if (!left)
1875 break;
1876 neg = 0;
1877 len = left;
1878 if (len > TMPBUFLEN-1)
1879 len = TMPBUFLEN-1;
1880 if (copy_from_user(buf, s, len))
1881 return -EFAULT;
1882 buf[len] = 0;
1883 p = buf;
1884 if (*p == '-' && left > 1) {
1885 neg = 1;
1886 left--, p++;
1887 }
1888 if (*p < '0' || *p > '9')
1889 break;
1890 val = simple_strtoul(p, &p, 0) * convmul / convdiv ;
1891 len = p-buf;
1892 if ((len < left) && *p && !isspace(*p))
1893 break;
1894 if (neg)
1895 val = -val;
1896 s += len;
1897 left -= len;
1898
1899 if(neg)
1900 continue;
1901 if ((min && val < *min) || (max && val > *max))
1902 continue;
1903 *i = val;
1904 } else {
1905 p = buf;
1906 if (!first)
1907 *p++ = '\t';
1908 sprintf(p, "%lu", convdiv * (*i) / convmul);
1909 len = strlen(buf);
1910 if (len > left)
1911 len = left;
1912 if(copy_to_user(s, buf, len))
1913 return -EFAULT;
1914 left -= len;
1915 s += len;
1916 }
1917 }
1918
1919 if (!write && !first && left) {
1920 if(put_user('\n', s))
1921 return -EFAULT;
1922 left--, s++;
1923 }
1924 if (write) {
1925 while (left) {
1926 char c;
1927 if (get_user(c, s++))
1928 return -EFAULT;
1929 if (!isspace(c))
1930 break;
1931 left--;
1932 }
1933 }
1934 if (write && first)
1935 return -EINVAL;
1936 *lenp -= left;
1937 *ppos += *lenp;
1938 return 0;
1939#undef TMPBUFLEN
1940}
1941
1942/**
1943 * proc_doulongvec_minmax - read a vector of long integers with min/max values
1944 * @table: the sysctl table
1945 * @write: %TRUE if this is a write to the sysctl file
1946 * @filp: the file structure
1947 * @buffer: the user buffer
1948 * @lenp: the size of the user buffer
1949 * @ppos: file position
1950 *
1951 * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
1952 * values from/to the user buffer, treated as an ASCII string.
1953 *
1954 * This routine will ensure the values are within the range specified by
1955 * table->extra1 (min) and table->extra2 (max).
1956 *
1957 * Returns 0 on success.
1958 */
1959int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
1960 void __user *buffer, size_t *lenp, loff_t *ppos)
1961{
1962 return do_proc_doulongvec_minmax(table, write, filp, buffer, lenp, ppos, 1l, 1l);
1963}
1964
1965/**
1966 * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values
1967 * @table: the sysctl table
1968 * @write: %TRUE if this is a write to the sysctl file
1969 * @filp: the file structure
1970 * @buffer: the user buffer
1971 * @lenp: the size of the user buffer
1972 * @ppos: file position
1973 *
1974 * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
1975 * values from/to the user buffer, treated as an ASCII string. The values
1976 * are treated as milliseconds, and converted to jiffies when they are stored.
1977 *
1978 * This routine will ensure the values are within the range specified by
1979 * table->extra1 (min) and table->extra2 (max).
1980 *
1981 * Returns 0 on success.
1982 */
1983int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
1984 struct file *filp,
1985 void __user *buffer,
1986 size_t *lenp, loff_t *ppos)
1987{
1988 return do_proc_doulongvec_minmax(table, write, filp, buffer,
1989 lenp, ppos, HZ, 1000l);
1990}
1991
1992
1993static int do_proc_dointvec_jiffies_conv(int *negp, unsigned long *lvalp,
1994 int *valp,
1995 int write, void *data)
1996{
1997 if (write) {
1998 *valp = *negp ? -(*lvalp*HZ) : (*lvalp*HZ);
1999 } else {
2000 int val = *valp;
2001 unsigned long lval;
2002 if (val < 0) {
2003 *negp = -1;
2004 lval = (unsigned long)-val;
2005 } else {
2006 *negp = 0;
2007 lval = (unsigned long)val;
2008 }
2009 *lvalp = lval / HZ;
2010 }
2011 return 0;
2012}
2013
2014static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp,
2015 int *valp,
2016 int write, void *data)
2017{
2018 if (write) {
2019 *valp = clock_t_to_jiffies(*negp ? -*lvalp : *lvalp);
2020 } else {
2021 int val = *valp;
2022 unsigned long lval;
2023 if (val < 0) {
2024 *negp = -1;
2025 lval = (unsigned long)-val;
2026 } else {
2027 *negp = 0;
2028 lval = (unsigned long)val;
2029 }
2030 *lvalp = jiffies_to_clock_t(lval);
2031 }
2032 return 0;
2033}
2034
2035static int do_proc_dointvec_ms_jiffies_conv(int *negp, unsigned long *lvalp,
2036 int *valp,
2037 int write, void *data)
2038{
2039 if (write) {
2040 *valp = msecs_to_jiffies(*negp ? -*lvalp : *lvalp);
2041 } else {
2042 int val = *valp;
2043 unsigned long lval;
2044 if (val < 0) {
2045 *negp = -1;
2046 lval = (unsigned long)-val;
2047 } else {
2048 *negp = 0;
2049 lval = (unsigned long)val;
2050 }
2051 *lvalp = jiffies_to_msecs(lval);
2052 }
2053 return 0;
2054}
2055
2056/**
2057 * proc_dointvec_jiffies - read a vector of integers as seconds
2058 * @table: the sysctl table
2059 * @write: %TRUE if this is a write to the sysctl file
2060 * @filp: the file structure
2061 * @buffer: the user buffer
2062 * @lenp: the size of the user buffer
2063 * @ppos: file position
2064 *
2065 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
2066 * values from/to the user buffer, treated as an ASCII string.
2067 * The values read are assumed to be in seconds, and are converted into
2068 * jiffies.
2069 *
2070 * Returns 0 on success.
2071 */
2072int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
2073 void __user *buffer, size_t *lenp, loff_t *ppos)
2074{
2075 return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
2076 do_proc_dointvec_jiffies_conv,NULL);
2077}
2078
2079/**
2080 * proc_dointvec_userhz_jiffies - read a vector of integers as 1/USER_HZ seconds
2081 * @table: the sysctl table
2082 * @write: %TRUE if this is a write to the sysctl file
2083 * @filp: the file structure
2084 * @buffer: the user buffer
2085 * @lenp: the size of the user buffer
1e5d5331 2086 * @ppos: pointer to the file position
1da177e4
LT
2087 *
2088 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
2089 * values from/to the user buffer, treated as an ASCII string.
2090 * The values read are assumed to be in 1/USER_HZ seconds, and
2091 * are converted into jiffies.
2092 *
2093 * Returns 0 on success.
2094 */
2095int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
2096 void __user *buffer, size_t *lenp, loff_t *ppos)
2097{
2098 return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
2099 do_proc_dointvec_userhz_jiffies_conv,NULL);
2100}
2101
2102/**
2103 * proc_dointvec_ms_jiffies - read a vector of integers as 1 milliseconds
2104 * @table: the sysctl table
2105 * @write: %TRUE if this is a write to the sysctl file
2106 * @filp: the file structure
2107 * @buffer: the user buffer
2108 * @lenp: the size of the user buffer
67be2dd1
MW
2109 * @ppos: file position
2110 * @ppos: the current position in the file
1da177e4
LT
2111 *
2112 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
2113 * values from/to the user buffer, treated as an ASCII string.
2114 * The values read are assumed to be in 1/1000 seconds, and
2115 * are converted into jiffies.
2116 *
2117 * Returns 0 on success.
2118 */
2119int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
2120 void __user *buffer, size_t *lenp, loff_t *ppos)
2121{
2122 return do_proc_dointvec(table, write, filp, buffer, lenp, ppos,
2123 do_proc_dointvec_ms_jiffies_conv, NULL);
2124}
2125
2126#else /* CONFIG_PROC_FS */
2127
2128int proc_dostring(ctl_table *table, int write, struct file *filp,
2129 void __user *buffer, size_t *lenp, loff_t *ppos)
2130{
2131 return -ENOSYS;
2132}
2133
2134static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
2135 void __user *buffer, size_t *lenp, loff_t *ppos)
2136{
2137 return -ENOSYS;
2138}
2139
2140int proc_dointvec(ctl_table *table, int write, struct file *filp,
2141 void __user *buffer, size_t *lenp, loff_t *ppos)
2142{
2143 return -ENOSYS;
2144}
2145
2146int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
2147 void __user *buffer, size_t *lenp, loff_t *ppos)
2148{
2149 return -ENOSYS;
2150}
2151
2152int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
2153 void __user *buffer, size_t *lenp, loff_t *ppos)
2154{
2155 return -ENOSYS;
2156}
2157
2158int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
2159 void __user *buffer, size_t *lenp, loff_t *ppos)
2160{
2161 return -ENOSYS;
2162}
2163
2164int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
2165 void __user *buffer, size_t *lenp, loff_t *ppos)
2166{
2167 return -ENOSYS;
2168}
2169
2170int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
2171 void __user *buffer, size_t *lenp, loff_t *ppos)
2172{
2173 return -ENOSYS;
2174}
2175
2176int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
2177 void __user *buffer, size_t *lenp, loff_t *ppos)
2178{
2179 return -ENOSYS;
2180}
2181
2182int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
2183 struct file *filp,
2184 void __user *buffer,
2185 size_t *lenp, loff_t *ppos)
2186{
2187 return -ENOSYS;
2188}
2189
2190
2191#endif /* CONFIG_PROC_FS */
2192
2193
2194/*
2195 * General sysctl support routines
2196 */
2197
2198/* The generic string strategy routine: */
2199int sysctl_string(ctl_table *table, int __user *name, int nlen,
2200 void __user *oldval, size_t __user *oldlenp,
2201 void __user *newval, size_t newlen, void **context)
2202{
1da177e4
LT
2203 if (!table->data || !table->maxlen)
2204 return -ENOTDIR;
2205
2206 if (oldval && oldlenp) {
de9e007d
LT
2207 size_t bufsize;
2208 if (get_user(bufsize, oldlenp))
1da177e4 2209 return -EFAULT;
de9e007d
LT
2210 if (bufsize) {
2211 size_t len = strlen(table->data), copied;
2212
2213 /* This shouldn't trigger for a well-formed sysctl */
2214 if (len > table->maxlen)
1da177e4 2215 len = table->maxlen;
de9e007d
LT
2216
2217 /* Copy up to a max of bufsize-1 bytes of the string */
2218 copied = (len >= bufsize) ? bufsize - 1 : len;
2219
2220 if (copy_to_user(oldval, table->data, copied) ||
2221 put_user(0, (char __user *)(oldval + copied)))
1da177e4 2222 return -EFAULT;
de9e007d 2223 if (put_user(len, oldlenp))
1da177e4
LT
2224 return -EFAULT;
2225 }
2226 }
2227 if (newval && newlen) {
de9e007d 2228 size_t len = newlen;
1da177e4
LT
2229 if (len > table->maxlen)
2230 len = table->maxlen;
2231 if(copy_from_user(table->data, newval, len))
2232 return -EFAULT;
2233 if (len == table->maxlen)
2234 len--;
2235 ((char *) table->data)[len] = 0;
2236 }
82c9df82 2237 return 1;
1da177e4
LT
2238}
2239
2240/*
2241 * This function makes sure that all of the integers in the vector
2242 * are between the minimum and maximum values given in the arrays
2243 * table->extra1 and table->extra2, respectively.
2244 */
2245int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
2246 void __user *oldval, size_t __user *oldlenp,
2247 void __user *newval, size_t newlen, void **context)
2248{
2249
2250 if (newval && newlen) {
2251 int __user *vec = (int __user *) newval;
2252 int *min = (int *) table->extra1;
2253 int *max = (int *) table->extra2;
2254 size_t length;
2255 int i;
2256
2257 if (newlen % sizeof(int) != 0)
2258 return -EINVAL;
2259
2260 if (!table->extra1 && !table->extra2)
2261 return 0;
2262
2263 if (newlen > table->maxlen)
2264 newlen = table->maxlen;
2265 length = newlen / sizeof(int);
2266
2267 for (i = 0; i < length; i++) {
2268 int value;
2269 if (get_user(value, vec + i))
2270 return -EFAULT;
2271 if (min && value < min[i])
2272 return -EINVAL;
2273 if (max && value > max[i])
2274 return -EINVAL;
2275 }
2276 }
2277 return 0;
2278}
2279
2280/* Strategy function to convert jiffies to seconds */
2281int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
2282 void __user *oldval, size_t __user *oldlenp,
2283 void __user *newval, size_t newlen, void **context)
2284{
2285 if (oldval) {
2286 size_t olen;
2287 if (oldlenp) {
2288 if (get_user(olen, oldlenp))
2289 return -EFAULT;
2290 if (olen!=sizeof(int))
2291 return -EINVAL;
2292 }
2293 if (put_user(*(int *)(table->data)/HZ, (int __user *)oldval) ||
2294 (oldlenp && put_user(sizeof(int),oldlenp)))
2295 return -EFAULT;
2296 }
2297 if (newval && newlen) {
2298 int new;
2299 if (newlen != sizeof(int))
2300 return -EINVAL;
2301 if (get_user(new, (int __user *)newval))
2302 return -EFAULT;
2303 *(int *)(table->data) = new*HZ;
2304 }
2305 return 1;
2306}
2307
2308/* Strategy function to convert jiffies to seconds */
2309int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
2310 void __user *oldval, size_t __user *oldlenp,
2311 void __user *newval, size_t newlen, void **context)
2312{
2313 if (oldval) {
2314 size_t olen;
2315 if (oldlenp) {
2316 if (get_user(olen, oldlenp))
2317 return -EFAULT;
2318 if (olen!=sizeof(int))
2319 return -EINVAL;
2320 }
2321 if (put_user(jiffies_to_msecs(*(int *)(table->data)), (int __user *)oldval) ||
2322 (oldlenp && put_user(sizeof(int),oldlenp)))
2323 return -EFAULT;
2324 }
2325 if (newval && newlen) {
2326 int new;
2327 if (newlen != sizeof(int))
2328 return -EINVAL;
2329 if (get_user(new, (int __user *)newval))
2330 return -EFAULT;
2331 *(int *)(table->data) = msecs_to_jiffies(new);
2332 }
2333 return 1;
2334}
2335
2336#else /* CONFIG_SYSCTL */
2337
2338
2339asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
2340{
2341 return -ENOSYS;
2342}
2343
2344int sysctl_string(ctl_table *table, int __user *name, int nlen,
2345 void __user *oldval, size_t __user *oldlenp,
2346 void __user *newval, size_t newlen, void **context)
2347{
2348 return -ENOSYS;
2349}
2350
2351int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
2352 void __user *oldval, size_t __user *oldlenp,
2353 void __user *newval, size_t newlen, void **context)
2354{
2355 return -ENOSYS;
2356}
2357
2358int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
2359 void __user *oldval, size_t __user *oldlenp,
2360 void __user *newval, size_t newlen, void **context)
2361{
2362 return -ENOSYS;
2363}
2364
2365int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
2366 void __user *oldval, size_t __user *oldlenp,
2367 void __user *newval, size_t newlen, void **context)
2368{
2369 return -ENOSYS;
2370}
2371
2372int proc_dostring(ctl_table *table, int write, struct file *filp,
2373 void __user *buffer, size_t *lenp, loff_t *ppos)
2374{
2375 return -ENOSYS;
2376}
2377
2378int proc_dointvec(ctl_table *table, int write, struct file *filp,
2379 void __user *buffer, size_t *lenp, loff_t *ppos)
2380{
2381 return -ENOSYS;
2382}
2383
2384int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
2385 void __user *buffer, size_t *lenp, loff_t *ppos)
2386{
2387 return -ENOSYS;
2388}
2389
2390int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
2391 void __user *buffer, size_t *lenp, loff_t *ppos)
2392{
2393 return -ENOSYS;
2394}
2395
2396int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
2397 void __user *buffer, size_t *lenp, loff_t *ppos)
2398{
2399 return -ENOSYS;
2400}
2401
2402int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
2403 void __user *buffer, size_t *lenp, loff_t *ppos)
2404{
2405 return -ENOSYS;
2406}
2407
2408int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
2409 void __user *buffer, size_t *lenp, loff_t *ppos)
2410{
2411 return -ENOSYS;
2412}
2413
2414int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
2415 void __user *buffer, size_t *lenp, loff_t *ppos)
2416{
2417 return -ENOSYS;
2418}
2419
2420int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
2421 struct file *filp,
2422 void __user *buffer,
2423 size_t *lenp, loff_t *ppos)
2424{
2425 return -ENOSYS;
2426}
2427
2428struct ctl_table_header * register_sysctl_table(ctl_table * table,
2429 int insert_at_head)
2430{
2431 return NULL;
2432}
2433
2434void unregister_sysctl_table(struct ctl_table_header * table)
2435{
2436}
2437
2438#endif /* CONFIG_SYSCTL */
2439
2440/*
2441 * No sense putting this after each symbol definition, twice,
2442 * exception granted :-)
2443 */
2444EXPORT_SYMBOL(proc_dointvec);
2445EXPORT_SYMBOL(proc_dointvec_jiffies);
2446EXPORT_SYMBOL(proc_dointvec_minmax);
2447EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
2448EXPORT_SYMBOL(proc_dointvec_ms_jiffies);
2449EXPORT_SYMBOL(proc_dostring);
2450EXPORT_SYMBOL(proc_doulongvec_minmax);
2451EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
2452EXPORT_SYMBOL(register_sysctl_table);
2453EXPORT_SYMBOL(sysctl_intvec);
2454EXPORT_SYMBOL(sysctl_jiffies);
2455EXPORT_SYMBOL(sysctl_ms_jiffies);
2456EXPORT_SYMBOL(sysctl_string);
2457EXPORT_SYMBOL(unregister_sysctl_table);