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