Magellan Linux

Contents of /alx-src/tags/kernel26-2.6.12-alx-r9/kernel/sysctl.c

Parent Directory Parent Directory | Revision Log Revision Log


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