3d543473193d6424441cfd59efe3bc57fcc243e0
[linux-2.4.git] / sysctl.c
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/slab.h>
23 #include <linux/sysctl.h>
24 #include <linux/swapctl.h>
25 #include <linux/proc_fs.h>
26 #include <linux/ctype.h>
27 #include <linux/utsname.h>
28 #include <linux/capability.h>
29 #include <linux/smp_lock.h>
30 #include <linux/init.h>
31 #include <linux/sysrq.h>
32 #include <linux/highuid.h>
33 #include <linux/swap.h>
34
35 #include <asm/uaccess.h>
36
37 #ifdef CONFIG_ROOT_NFS
38 #include <linux/nfs_fs.h>
39 #endif
40
41 #if defined(CONFIG_SYSCTL)
42
43 /* External variables not in a header file. */
44 extern int panic_timeout;
45 extern int C_A_D;
46 extern int bdf_prm[], bdflush_min[], bdflush_max[];
47 extern int sysctl_overcommit_memory;
48 extern int max_threads;
49 extern atomic_t nr_queued_signals;
50 extern int max_queued_signals;
51 extern int sysrq_enabled;
52 extern int core_uses_pid;
53 extern int core_setuid_ok;
54 extern char core_pattern[];
55 extern int cad_pid;
56 extern int laptop_mode;
57 extern int block_dump;
58
59 /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
60 static int maxolduid = 65535;
61 static int minolduid;
62
63 #ifdef CONFIG_KMOD
64 extern char modprobe_path[];
65 #endif
66 #ifdef CONFIG_HOTPLUG
67 extern char hotplug_path[];
68 #endif
69 #ifdef CONFIG_CHR_DEV_SG
70 extern int sg_big_buff;
71 #endif
72 #ifdef CONFIG_SYSVIPC
73 extern size_t shm_ctlmax;
74 extern size_t shm_ctlall;
75 extern int shm_ctlmni;
76 extern int msg_ctlmax;
77 extern int msg_ctlmnb;
78 extern int msg_ctlmni;
79 extern int sem_ctls[];
80 #endif
81
82 extern int exception_trace;
83
84 #ifdef __sparc__
85 extern char reboot_command [];
86 extern int stop_a_enabled;
87 extern int scons_pwroff;
88 #endif
89
90 #ifdef CONFIG_ARCH_S390
91 #ifdef CONFIG_MATHEMU
92 extern int sysctl_ieee_emulation_warnings;
93 #endif
94 extern int sysctl_userprocess_debug;
95 #endif
96
97 #ifdef CONFIG_PPC32
98 extern unsigned long zero_paged_on, powersave_nap;
99 int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
100                 void *buffer, size_t *lenp);
101 int proc_dol3crvec(ctl_table *table, int write, struct file *filp,
102                 void *buffer, size_t *lenp);
103 #endif
104
105 #ifdef CONFIG_BSD_PROCESS_ACCT
106 extern int acct_parm[];
107 #endif
108
109 extern int pgt_cache_water[];
110
111 static int parse_table(int *, int, void *, size_t *, void *, size_t,
112                        ctl_table *, void **);
113 static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
114                   void *buffer, size_t *lenp);
115
116 static ctl_table root_table[];
117 static struct ctl_table_header root_table_header =
118         { root_table, LIST_HEAD_INIT(root_table_header.ctl_entry) };
119
120 static ctl_table kern_table[];
121 static ctl_table vm_table[];
122 #ifdef CONFIG_NET
123 extern ctl_table net_table[];
124 #endif
125 static ctl_table proc_table[];
126 static ctl_table fs_table[];
127 static ctl_table debug_table[];
128 static ctl_table dev_table[];
129 extern ctl_table random_table[];
130
131 /* /proc declarations: */
132
133 #ifdef CONFIG_PROC_FS
134
135 static ssize_t proc_readsys(struct file *, char *, size_t, loff_t *);
136 static ssize_t proc_writesys(struct file *, const char *, size_t, loff_t *);
137 static int proc_sys_permission(struct inode *, int);
138
139 struct file_operations proc_sys_file_operations = {
140         read:           proc_readsys,
141         write:          proc_writesys,
142 };
143
144 static struct inode_operations proc_sys_inode_operations = {
145         permission:     proc_sys_permission,
146 };
147
148 extern struct proc_dir_entry *proc_sys_root;
149
150 static void register_proc_table(ctl_table *, struct proc_dir_entry *, void *);
151 static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
152 #endif
153
154 /* The default sysctl tables: */
155
156 static ctl_table root_table[] = {
157         {CTL_KERN, "kernel", NULL, 0, 0555, kern_table},
158         {CTL_VM, "vm", NULL, 0, 0555, vm_table},
159 #ifdef CONFIG_NET
160         {CTL_NET, "net", NULL, 0, 0555, net_table},
161 #endif
162         {CTL_PROC, "proc", NULL, 0, 0555, proc_table},
163         {CTL_FS, "fs", NULL, 0, 0555, fs_table},
164         {CTL_DEBUG, "debug", NULL, 0, 0555, debug_table},
165         {CTL_DEV, "dev", NULL, 0, 0555, dev_table},
166         {0}
167 };
168
169 static ctl_table kern_table[] = {
170         {KERN_OSTYPE, "ostype", system_utsname.sysname, 64,
171          0444, NULL, &proc_doutsstring, &sysctl_string},
172         {KERN_OSRELEASE, "osrelease", system_utsname.release, 64,
173          0444, NULL, &proc_doutsstring, &sysctl_string},
174         {KERN_VERSION, "version", system_utsname.version, 64,
175          0444, NULL, &proc_doutsstring, &sysctl_string},
176         {KERN_NODENAME, "hostname", system_utsname.nodename, 64,
177          0644, NULL, &proc_doutsstring, &sysctl_string},
178         {KERN_DOMAINNAME, "domainname", system_utsname.domainname, 64,
179          0644, NULL, &proc_doutsstring, &sysctl_string},
180         {KERN_PANIC, "panic", &panic_timeout, sizeof(int),
181          0644, NULL, &proc_dointvec},
182         {KERN_CORE_USES_PID, "core_uses_pid", &core_uses_pid, sizeof(int),
183          0644, NULL, &proc_dointvec},
184         {KERN_CORE_SETUID, "core_setuid_ok", &core_setuid_ok, sizeof(int),
185         0644, NULL, &proc_dointvec},
186         {KERN_CORE_PATTERN, "core_pattern", core_pattern, 64,
187          0644, NULL, &proc_dostring, &sysctl_string},
188         {KERN_TAINTED, "tainted", &tainted, sizeof(int),
189          0644, NULL, &proc_dointvec},
190         {KERN_CAP_BSET, "cap-bound", &cap_bset, sizeof(kernel_cap_t),
191          0600, NULL, &proc_dointvec_bset},
192 #ifdef CONFIG_BLK_DEV_INITRD
193         {KERN_REALROOTDEV, "real-root-dev", &real_root_dev, sizeof(int),
194          0644, NULL, &proc_dointvec},
195 #endif
196 #ifdef __sparc__
197         {KERN_SPARC_REBOOT, "reboot-cmd", reboot_command,
198          256, 0644, NULL, &proc_dostring, &sysctl_string },
199         {KERN_SPARC_STOP_A, "stop-a", &stop_a_enabled, sizeof (int),
200          0644, NULL, &proc_dointvec},
201         {KERN_SPARC_SCONS_PWROFF, "scons-poweroff", &scons_pwroff, sizeof (int),
202          0644, NULL, &proc_dointvec},
203 #endif
204 #ifdef CONFIG_PPC32
205         {KERN_PPC_ZEROPAGED, "zero-paged", &zero_paged_on, sizeof(int),
206          0644, NULL, &proc_dointvec},
207         {KERN_PPC_POWERSAVE_NAP, "powersave-nap", &powersave_nap, sizeof(int),
208          0644, NULL, &proc_dointvec},
209         {KERN_PPC_L2CR, "l2cr", NULL, 0,
210          0644, NULL, &proc_dol2crvec},
211         {KERN_PPC_L3CR, "l3cr", NULL, 0,
212          0644, NULL, &proc_dol3crvec},
213 #endif
214         {KERN_CTLALTDEL, "ctrl-alt-del", &C_A_D, sizeof(int),
215          0644, NULL, &proc_dointvec},
216         {KERN_PRINTK, "printk", &console_loglevel, 4*sizeof(int),
217          0644, NULL, &proc_dointvec},
218 #ifdef CONFIG_KMOD
219         {KERN_MODPROBE, "modprobe", &modprobe_path, 256,
220          0644, NULL, &proc_dostring, &sysctl_string },
221 #endif
222 #ifdef CONFIG_HOTPLUG
223         {KERN_HOTPLUG, "hotplug", &hotplug_path, 256,
224          0644, NULL, &proc_dostring, &sysctl_string },
225 #endif
226 #ifdef CONFIG_CHR_DEV_SG
227         {KERN_SG_BIG_BUFF, "sg-big-buff", &sg_big_buff, sizeof (int),
228          0444, NULL, &proc_dointvec},
229 #endif
230 #ifdef CONFIG_BSD_PROCESS_ACCT
231         {KERN_ACCT, "acct", &acct_parm, 3*sizeof(int),
232         0644, NULL, &proc_dointvec},
233 #endif
234         {KERN_RTSIGNR, "rtsig-nr", &nr_queued_signals, sizeof(int),
235          0444, NULL, &proc_dointvec},
236         {KERN_RTSIGMAX, "rtsig-max", &max_queued_signals, sizeof(int),
237          0644, NULL, &proc_dointvec},
238 #ifdef CONFIG_SYSVIPC
239         {KERN_SHMMAX, "shmmax", &shm_ctlmax, sizeof (size_t),
240          0644, NULL, &proc_doulongvec_minmax},
241         {KERN_SHMALL, "shmall", &shm_ctlall, sizeof (size_t),
242          0644, NULL, &proc_doulongvec_minmax},
243         {KERN_SHMMNI, "shmmni", &shm_ctlmni, sizeof (int),
244          0644, NULL, &proc_dointvec},
245         {KERN_MSGMAX, "msgmax", &msg_ctlmax, sizeof (int),
246          0644, NULL, &proc_dointvec},
247         {KERN_MSGMNI, "msgmni", &msg_ctlmni, sizeof (int),
248          0644, NULL, &proc_dointvec},
249         {KERN_MSGMNB, "msgmnb", &msg_ctlmnb, sizeof (int),
250          0644, NULL, &proc_dointvec},
251         {KERN_SEM, "sem", &sem_ctls, 4*sizeof (int),
252          0644, NULL, &proc_dointvec},
253 #endif
254 #ifdef CONFIG_MAGIC_SYSRQ
255         {KERN_SYSRQ, "sysrq", &sysrq_enabled, sizeof (int),
256          0644, NULL, &proc_dointvec},
257 #endif   
258         {KERN_CADPID, "cad_pid", &cad_pid, sizeof (int),
259          0600, NULL, &proc_dointvec},
260         {KERN_MAX_THREADS, "threads-max", &max_threads, sizeof(int),
261          0644, NULL, &proc_dointvec},
262         {KERN_RANDOM, "random", NULL, 0, 0555, random_table},
263         {KERN_OVERFLOWUID, "overflowuid", &overflowuid, sizeof(int), 0644, NULL,
264          &proc_dointvec_minmax, &sysctl_intvec, NULL,
265          &minolduid, &maxolduid},
266         {KERN_OVERFLOWGID, "overflowgid", &overflowgid, sizeof(int), 0644, NULL,
267          &proc_dointvec_minmax, &sysctl_intvec, NULL,
268          &minolduid, &maxolduid},
269 #ifdef CONFIG_ARCH_S390
270 #ifdef CONFIG_MATHEMU
271         {KERN_IEEE_EMULATION_WARNINGS,"ieee_emulation_warnings",
272          &sysctl_ieee_emulation_warnings,sizeof(int),0644,NULL,&proc_dointvec},
273 #endif
274         {KERN_S390_USER_DEBUG_LOGGING,"userprocess_debug",
275          &sysctl_userprocess_debug,sizeof(int),0644,NULL,&proc_dointvec},
276 #endif
277 #ifdef __x86_64__
278         {KERN_EXCEPTION_TRACE,"exception-trace",
279          &exception_trace,sizeof(int),0644,NULL,&proc_dointvec},
280 #endif  
281         {0}
282 };
283
284 static ctl_table vm_table[] = {
285         {VM_GFP_DEBUG, "vm_gfp_debug", 
286          &vm_gfp_debug, sizeof(int), 0644, NULL, &proc_dointvec},
287         {VM_VFS_SCAN_RATIO, "vm_vfs_scan_ratio", 
288          &vm_vfs_scan_ratio, sizeof(int), 0644, NULL, &proc_dointvec},
289         {VM_CACHE_SCAN_RATIO, "vm_cache_scan_ratio", 
290          &vm_cache_scan_ratio, sizeof(int), 0644, NULL, &proc_dointvec},
291         {VM_MAPPED_RATIO, "vm_mapped_ratio", 
292          &vm_mapped_ratio, sizeof(int), 0644, NULL, &proc_dointvec},
293         {VM_ANON_LRU, "vm_anon_lru", 
294          &vm_anon_lru, sizeof(int), 0644, NULL, &proc_dointvec},
295         {VM_LRU_BALANCE_RATIO, "vm_lru_balance_ratio", 
296          &vm_lru_balance_ratio, sizeof(int), 0644, NULL, &proc_dointvec},
297         {VM_PASSES, "vm_passes", 
298          &vm_passes, sizeof(int), 0644, NULL, &proc_dointvec},
299         {VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0644, NULL,
300          &proc_dointvec_minmax, &sysctl_intvec, NULL,
301          &bdflush_min, &bdflush_max},
302         {VM_OVERCOMMIT_MEMORY, "overcommit_memory", &sysctl_overcommit_memory,
303          sizeof(sysctl_overcommit_memory), 0644, NULL, &proc_dointvec},
304         {VM_PAGERDAEMON, "kswapd",
305          &pager_daemon, sizeof(pager_daemon_t), 0644, NULL, &proc_dointvec},
306         {VM_PGT_CACHE, "pagetable_cache", 
307          &pgt_cache_water, 2*sizeof(int), 0644, NULL, &proc_dointvec},
308         {VM_PAGE_CLUSTER, "page-cluster", 
309          &page_cluster, sizeof(int), 0644, NULL, &proc_dointvec},
310         {VM_MIN_READAHEAD, "min-readahead",
311         &vm_min_readahead,sizeof(int), 0644, NULL, &proc_dointvec},
312         {VM_MAX_READAHEAD, "max-readahead",
313         &vm_max_readahead,sizeof(int), 0644, NULL, &proc_dointvec},
314         {VM_MAX_MAP_COUNT, "max_map_count",
315          &max_map_count, sizeof(int), 0644, NULL, &proc_dointvec},
316         {VM_LAPTOP_MODE, "laptop_mode",
317          &laptop_mode, sizeof(int), 0644, NULL, &proc_dointvec},
318         {VM_BLOCK_DUMP, "block_dump",
319          &block_dump, sizeof(int), 0644, NULL, &proc_dointvec},
320         {0}
321 };
322
323 static ctl_table proc_table[] = {
324         {0}
325 };
326
327 static ctl_table fs_table[] = {
328         {FS_NRINODE, "inode-nr", &inodes_stat, 2*sizeof(int),
329          0444, NULL, &proc_dointvec},
330         {FS_STATINODE, "inode-state", &inodes_stat, 7*sizeof(int),
331          0444, NULL, &proc_dointvec},
332         {FS_NRFILE, "file-nr", &files_stat, 3*sizeof(int),
333          0444, NULL, &proc_dointvec},
334         {FS_MAXFILE, "file-max", &files_stat.max_files, sizeof(int),
335          0644, NULL, &proc_dointvec},
336         {FS_DENTRY, "dentry-state", &dentry_stat, 6*sizeof(int),
337          0444, NULL, &proc_dointvec},
338         {FS_OVERFLOWUID, "overflowuid", &fs_overflowuid, sizeof(int), 0644, NULL,
339          &proc_dointvec_minmax, &sysctl_intvec, NULL,
340          &minolduid, &maxolduid},
341         {FS_OVERFLOWGID, "overflowgid", &fs_overflowgid, sizeof(int), 0644, NULL,
342          &proc_dointvec_minmax, &sysctl_intvec, NULL,
343          &minolduid, &maxolduid},
344         {FS_LEASES, "leases-enable", &leases_enable, sizeof(int),
345          0644, NULL, &proc_dointvec},
346         {FS_DIR_NOTIFY, "dir-notify-enable", &dir_notify_enable,
347          sizeof(int), 0644, NULL, &proc_dointvec},
348         {FS_LEASE_TIME, "lease-break-time", &lease_break_time, sizeof(int),
349          0644, NULL, &proc_dointvec},
350         {0}
351 };
352
353 static ctl_table debug_table[] = {
354         {0}
355 };
356
357 static ctl_table dev_table[] = {
358         {0}
359 };  
360
361 extern void init_irq_proc (void);
362
363 static spinlock_t sysctl_lock = SPIN_LOCK_UNLOCKED;
364
365 /* called under sysctl_lock */
366 static int use_table(struct ctl_table_header *p)
367 {
368         if (unlikely(p->unregistering != NULL))
369                 return 0;
370         p->used++;
371         return 1;
372 }
373
374 /* called under sysctl_lock */
375 static void unuse_table(struct ctl_table_header *p)
376 {
377         if (!--p->used)
378                 if (unlikely(p->unregistering != NULL))
379                         complete(p->unregistering);
380 }
381
382 /* called under sysctl_lock, will reacquire if has to wait */
383 static void start_unregistering(struct ctl_table_header *p)
384 {
385         /*
386          * if p->used is 0, nobody will ever touch that entry again;
387          * we'll eliminate all paths to it before dropping sysctl_lock
388          */
389         if (unlikely(p->used)) {
390                 struct completion wait;
391                 init_completion(&wait);
392                 p->unregistering = &wait;
393                 spin_unlock(&sysctl_lock);
394                 wait_for_completion(&wait);
395                 spin_lock(&sysctl_lock);
396         }
397         /*
398          * do not remove from the list until nobody holds it; walking the
399          * list in do_sysctl() relies on that.
400          */
401         list_del_init(&p->ctl_entry);
402 }
403
404 void __init sysctl_init(void)
405 {
406 #ifdef CONFIG_PROC_FS
407         register_proc_table(root_table, proc_sys_root, &root_table_header);
408         init_irq_proc();
409 #endif
410 }
411
412 int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp,
413                void *newval, size_t newlen)
414 {
415         struct list_head *tmp;
416         int error = -ENOTDIR;
417
418         if (nlen <= 0 || nlen >= CTL_MAXNAME)
419                 return -ENOTDIR;
420         if (oldval) {
421                 int old_len;
422                 if (!oldlenp || get_user(old_len, oldlenp))
423                         return -EFAULT;
424                 /* XXX: insufficient for SMP, but should be redundant anyway */
425                 if ((ssize_t)old_len < 0)
426                         return -EINVAL;
427         }
428         spin_lock(&sysctl_lock);
429         tmp = &root_table_header.ctl_entry;
430         do {
431                 struct ctl_table_header *head =
432                         list_entry(tmp, struct ctl_table_header, ctl_entry);
433                 void *context = NULL;
434
435                 if (!use_table(head))
436                         continue;
437
438                 spin_unlock(&sysctl_lock);
439
440                 error = parse_table(name, nlen, oldval, oldlenp, 
441                                         newval, newlen, head->ctl_table,
442                                         &context);
443                 if (context)
444                         kfree(context);
445
446                 spin_lock(&sysctl_lock);
447                 unuse_table(head);
448                 if (error != -ENOTDIR)
449                         break;
450         } while ((tmp = tmp->next) != &root_table_header.ctl_entry);
451         spin_unlock(&sysctl_lock);
452         return error;
453 }
454
455 extern asmlinkage long sys_sysctl(struct __sysctl_args *args)
456 {
457         struct __sysctl_args tmp;
458         int error;
459
460         if (copy_from_user(&tmp, args, sizeof(tmp)))
461                 return -EFAULT;
462                 
463         lock_kernel();
464         error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp,
465                           tmp.newval, tmp.newlen);
466         unlock_kernel();
467         return error;
468 }
469
470 /*
471  * ctl_perm does NOT grant the superuser all rights automatically, because
472  * some sysctl variables are readonly even to root.
473  */
474
475 static int test_perm(int mode, int op)
476 {
477         if (!current->euid)
478                 mode >>= 6;
479         else if (in_egroup_p(0))
480                 mode >>= 3;
481         if ((mode & op & 0007) == op)
482                 return 0;
483         return -EACCES;
484 }
485
486 static inline int ctl_perm(ctl_table *table, int op)
487 {
488         return test_perm(table->mode, op);
489 }
490
491 static int parse_table(int *name, int nlen,
492                        void *oldval, size_t *oldlenp,
493                        void *newval, size_t newlen,
494                        ctl_table *table, void **context)
495 {
496         int n;
497 repeat:
498         if (!nlen)
499                 return -ENOTDIR;
500         if (get_user(n, name))
501                 return -EFAULT;
502         for ( ; table->ctl_name; table++) {
503                 if (n == table->ctl_name || table->ctl_name == CTL_ANY) {
504                         int error;
505                         if (table->child) {
506                                 if (ctl_perm(table, 001))
507                                         return -EPERM;
508                                 if (table->strategy) {
509                                         error = table->strategy(
510                                                 table, name, nlen,
511                                                 oldval, oldlenp,
512                                                 newval, newlen, context);
513                                         if (error)
514                                                 return error;
515                                 }
516                                 name++;
517                                 nlen--;
518                                 table = table->child;
519                                 goto repeat;
520                         }
521                         error = do_sysctl_strategy(table, name, nlen,
522                                                    oldval, oldlenp,
523                                                    newval, newlen, context);
524                         return error;
525                 }
526         }
527         return -ENOTDIR;
528 }
529
530 /* Perform the actual read/write of a sysctl table entry. */
531 int do_sysctl_strategy (ctl_table *table, 
532                         int *name, int nlen,
533                         void *oldval, size_t *oldlenp,
534                         void *newval, size_t newlen, void **context)
535 {
536         int op = 0, rc;
537         size_t len;
538
539         if (oldval)
540                 op |= 004;
541         if (newval) 
542                 op |= 002;
543         if (ctl_perm(table, op))
544                 return -EPERM;
545
546         if (table->strategy) {
547                 rc = table->strategy(table, name, nlen, oldval, oldlenp,
548                                      newval, newlen, context);
549                 if (rc < 0)
550                         return rc;
551                 if (rc > 0)
552                         return 0;
553         }
554
555         /* If there is no strategy routine, or if the strategy returns
556          * zero, proceed with automatic r/w */
557         if (table->data && table->maxlen) {
558                 if (oldval && oldlenp) {
559                         if (get_user(len, oldlenp))
560                                 return -EFAULT;
561                         if (len) {
562                                 if (len > table->maxlen)
563                                         len = table->maxlen;
564                                 if(copy_to_user(oldval, table->data, len))
565                                         return -EFAULT;
566                                 if(put_user(len, oldlenp))
567                                         return -EFAULT;
568                         }
569                 }
570                 if (newval && newlen) {
571                         len = newlen;
572                         if (len > table->maxlen)
573                                 len = table->maxlen;
574                         if(copy_from_user(table->data, newval, len))
575                                 return -EFAULT;
576                 }
577         }
578         return 0;
579 }
580
581 /**
582  * register_sysctl_table - register a sysctl hierarchy
583  * @table: the top-level table structure
584  * @insert_at_head: whether the entry should be inserted in front or at the end
585  *
586  * Register a sysctl table hierarchy. @table should be a filled in ctl_table
587  * array. An entry with a ctl_name of 0 terminates the table. 
588  *
589  * The members of the &ctl_table structure are used as follows:
590  *
591  * ctl_name - This is the numeric sysctl value used by sysctl(2). The number
592  *            must be unique within that level of sysctl
593  *
594  * procname - the name of the sysctl file under /proc/sys. Set to %NULL to not
595  *            enter a sysctl file
596  *
597  * data - a pointer to data for use by proc_handler
598  *
599  * maxlen - the maximum size in bytes of the data
600  *
601  * mode - the file permissions for the /proc/sys file, and for sysctl(2)
602  *
603  * child - a pointer to the child sysctl table if this entry is a directory, or
604  *         %NULL.
605  *
606  * proc_handler - the text handler routine (described below)
607  *
608  * strategy - the strategy routine (described below)
609  *
610  * de - for internal use by the sysctl routines
611  *
612  * extra1, extra2 - extra pointers usable by the proc handler routines
613  *
614  * Leaf nodes in the sysctl tree will be represented by a single file
615  * under /proc; non-leaf nodes will be represented by directories.
616  *
617  * sysctl(2) can automatically manage read and write requests through
618  * the sysctl table.  The data and maxlen fields of the ctl_table
619  * struct enable minimal validation of the values being written to be
620  * performed, and the mode field allows minimal authentication.
621  *
622  * More sophisticated management can be enabled by the provision of a
623  * strategy routine with the table entry.  This will be called before
624  * any automatic read or write of the data is performed.
625  *
626  * The strategy routine may return
627  *
628  * < 0 - Error occurred (error is passed to user process)
629  *
630  * 0   - OK - proceed with automatic read or write.
631  *
632  * > 0 - OK - read or write has been done by the strategy routine, so
633  *       return immediately.
634  *
635  * There must be a proc_handler routine for any terminal nodes
636  * mirrored under /proc/sys (non-terminals are handled by a built-in
637  * directory handler).  Several default handlers are available to
638  * cover common cases -
639  *
640  * proc_dostring(), proc_dointvec(), proc_dointvec_jiffies(),
641  * proc_dointvec_minmax(), proc_doulongvec_ms_jiffies_minmax(),
642  * proc_doulongvec_minmax()
643  *
644  * It is the handler's job to read the input buffer from user memory
645  * and process it. The handler should return 0 on success.
646  *
647  * This routine returns %NULL on a failure to register, and a pointer
648  * to the table header on success.
649  */
650 struct ctl_table_header *register_sysctl_table(ctl_table * table, 
651                                                int insert_at_head)
652 {
653         struct ctl_table_header *tmp;
654         tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL);
655         if (!tmp)
656                 return NULL;
657         tmp->ctl_table = table;
658         INIT_LIST_HEAD(&tmp->ctl_entry);
659         tmp->used = 0;
660         tmp->unregistering = NULL;
661         spin_lock(&sysctl_lock);
662         if (insert_at_head)
663                 list_add(&tmp->ctl_entry, &root_table_header.ctl_entry);
664         else
665                 list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
666         spin_unlock(&sysctl_lock);
667 #ifdef CONFIG_PROC_FS
668         register_proc_table(table, proc_sys_root, tmp);
669 #endif
670         return tmp;
671 }
672
673 /**
674  * unregister_sysctl_table - unregister a sysctl table hierarchy
675  * @header: the header returned from register_sysctl_table
676  *
677  * Unregisters the sysctl table and all children. proc entries may not
678  * actually be removed until they are no longer used by anyone.
679  */
680 void unregister_sysctl_table(struct ctl_table_header * header)
681 {
682         spin_lock(&sysctl_lock);
683         start_unregistering(header);
684 #ifdef CONFIG_PROC_FS
685         unregister_proc_table(header->ctl_table, proc_sys_root);
686 #endif
687         spin_unlock(&sysctl_lock);
688         kfree(header);
689 }
690
691 /*
692  * /proc/sys support
693  */
694
695 #ifdef CONFIG_PROC_FS
696
697 /* Scan the sysctl entries in table and add them all into /proc */
698 static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, void *set)
699 {
700         struct proc_dir_entry *de;
701         int len;
702         mode_t mode;
703         
704         for (; table->ctl_name; table++) {
705                 /* Can't do anything without a proc name. */
706                 if (!table->procname)
707                         continue;
708                 /* Maybe we can't do anything with it... */
709                 if (!table->proc_handler && !table->child) {
710                         printk(KERN_WARNING "SYSCTL: Can't register %s\n",
711                                 table->procname);
712                         continue;
713                 }
714
715                 len = strlen(table->procname);
716                 mode = table->mode;
717
718                 de = NULL;
719                 if (table->proc_handler)
720                         mode |= S_IFREG;
721                 else {
722                         mode |= S_IFDIR;
723                         for (de = root->subdir; de; de = de->next) {
724                                 if (proc_match(len, table->procname, de))
725                                         break;
726                         }
727                         /* If the subdir exists already, de is non-NULL */
728                 }
729
730                 if (!de) {
731                         de = create_proc_entry(table->procname, mode, root);
732                         if (!de)
733                                 continue;
734                         de->set = set;
735                         de->data = (void *) table;
736                         if (table->proc_handler) {
737                                 de->proc_fops = &proc_sys_file_operations;
738                                 de->proc_iops = &proc_sys_inode_operations;
739                         }
740                 }
741                 table->de = de;
742                 if (de->mode & S_IFDIR)
743                         register_proc_table(table->child, de, set);
744         }
745 }
746
747 /*
748  * Unregister a /proc sysctl table and any subdirectories.
749  */
750 static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root)
751 {
752         struct proc_dir_entry *de;
753         for (; table->ctl_name; table++) {
754                 if (!(de = table->de))
755                         continue;
756                 if (de->mode & S_IFDIR) {
757                         if (!table->child) {
758                                 printk (KERN_ALERT "Help - malformed sysctl tree on free\n");
759                                 continue;
760                         }
761                         unregister_proc_table(table->child, de);
762
763                         /* Don't unregister directories which still have entries.. */
764                         if (de->subdir)
765                                 continue;
766                 }
767
768                 /*
769                  * In any case, mark the entry as goner; we'll keep it
770                  * around if it's busy, but we'll know to do nothing with
771                  * its fields.  We are under sysctl_lock here.
772                  */
773                 de->data = NULL;
774
775                 /* Don't unregister proc entries that are still being used.. */
776                 if (atomic_read(&de->count))
777                         continue;
778
779                 table->de = NULL;
780                 remove_proc_entry(table->procname, root);
781         }
782 }
783
784 static ssize_t do_rw_proc(int write, struct file * file, char * buf,
785                           size_t count, loff_t *ppos)
786 {
787         int op;
788         struct proc_dir_entry *de =
789           (struct proc_dir_entry*) file->f_dentry->d_inode->u.generic_ip;
790         struct ctl_table *table;
791         size_t res;
792         ssize_t error = -ENOTDIR;
793
794         spin_lock(&sysctl_lock);
795         if (de && de->data && use_table(de->set)) {
796                 /*
797                  * at that point we know that sysctl was not unregistered
798                  * and won't be until we finish
799                  */
800                 spin_unlock(&sysctl_lock);
801                 table = (struct ctl_table *) de->data;
802                 if (!table || !table->proc_handler)
803                         goto out;
804                 error = -EPERM;
805                 op = (write ? 002 : 004);
806                 if (ctl_perm(table, op))
807                         goto out;
808                 
809                 /* careful: calling conventions are nasty here */
810                 res = count;
811
812                 /*
813                  * FIXME: we need to pass on ppos to the handler.
814                  */
815
816                 error = (*table->proc_handler)(table, write, file,
817                                                 buf, &res);
818                 if (!error)
819                         error = res;
820         out:
821                 spin_lock(&sysctl_lock);
822                 unuse_table(de->set);
823         }
824         spin_unlock(&sysctl_lock);
825         return error;
826 }
827
828 static ssize_t proc_readsys(struct file * file, char * buf,
829                             size_t count, loff_t *ppos)
830 {
831         return do_rw_proc(0, file, buf, count, ppos);
832 }
833
834 static ssize_t proc_writesys(struct file * file, const char * buf,
835                              size_t count, loff_t *ppos)
836 {
837         return do_rw_proc(1, file, (char *) buf, count, ppos);
838 }
839
840 static int proc_sys_permission(struct inode *inode, int op)
841 {
842         return test_perm(inode->i_mode, op);
843 }
844
845 /**
846  * proc_dostring - read a string sysctl
847  * @table: the sysctl table
848  * @write: %TRUE if this is a write to the sysctl file
849  * @filp: the file structure
850  * @buffer: the user buffer
851  * @lenp: the size of the user buffer
852  *
853  * Reads/writes a string from/to the user buffer. If the kernel
854  * buffer provided is not large enough to hold the string, the
855  * string is truncated. The copied string is %NULL-terminated.
856  * If the string is being read by the user process, it is copied
857  * and a newline '\n' is added. It is truncated if the buffer is
858  * not large enough.
859  *
860  * Returns 0 on success.
861  */
862 int proc_dostring(ctl_table *table, int write, struct file *filp,
863                   void *buffer, size_t *lenp)
864 {
865         size_t len;
866         char *p, c;
867         
868         if (!table->data || !table->maxlen || !*lenp ||
869             (filp->f_pos && !write)) {
870                 *lenp = 0;
871                 return 0;
872         }
873         
874         if (write) {
875                 len = 0;
876                 p = buffer;
877                 while (len < *lenp) {
878                         if (get_user(c, p++))
879                                 return -EFAULT;
880                         if (c == 0 || c == '\n')
881                                 break;
882                         len++;
883                 }
884                 if (len >= table->maxlen)
885                         len = table->maxlen-1;
886                 if(copy_from_user(table->data, buffer, len))
887                         return -EFAULT;
888                 ((char *) table->data)[len] = 0;
889                 filp->f_pos += *lenp;
890         } else {
891                 len = strlen(table->data);
892                 if (len > table->maxlen)
893                         len = table->maxlen;
894                 if (len > *lenp)
895                         len = *lenp;
896                 if (len)
897                         if(copy_to_user(buffer, table->data, len))
898                                 return -EFAULT;
899                 if (len < *lenp) {
900                         if(put_user('\n', ((char *) buffer) + len))
901                                 return -EFAULT;
902                         len++;
903                 }
904                 *lenp = len;
905                 filp->f_pos += len;
906         }
907         return 0;
908 }
909
910 /*
911  *      Special case of dostring for the UTS structure. This has locks
912  *      to observe. Should this be in kernel/sys.c ????
913  */
914  
915 static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
916                   void *buffer, size_t *lenp)
917 {
918         int r;
919
920         if (!write) {
921                 down_read(&uts_sem);
922                 r=proc_dostring(table,0,filp,buffer,lenp);
923                 up_read(&uts_sem);
924         } else {
925                 down_write(&uts_sem);
926                 r=proc_dostring(table,1,filp,buffer,lenp);
927                 up_write(&uts_sem);
928         }
929         return r;
930 }
931
932 #define OP_SET  0
933 #define OP_AND  1
934 #define OP_OR   2
935 #define OP_MAX  3
936 #define OP_MIN  4
937
938 static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
939                   void *buffer, size_t *lenp, int conv, int op)
940 {
941         int *i, vleft, first=1, neg, val;
942         size_t left, len;
943         
944         #define TMPBUFLEN 20
945         char buf[TMPBUFLEN], *p;
946         
947         if (!table->data || !table->maxlen || !*lenp ||
948             (filp->f_pos && !write)) {
949                 *lenp = 0;
950                 return 0;
951         }
952         
953         i = (int *) table->data;
954         vleft = table->maxlen / sizeof(int);
955         left = *lenp;
956         
957         for (; left && vleft--; i++, first=0) {
958                 if (write) {
959                         while (left) {
960                                 char c;
961                                 if (get_user(c, (char *) buffer))
962                                         return -EFAULT;
963                                 if (!isspace(c))
964                                         break;
965                                 left--;
966                                 buffer++;
967                         }
968                         if (!left)
969                                 break;
970                         neg = 0;
971                         len = left;
972                         if (len > TMPBUFLEN-1)
973                                 len = TMPBUFLEN-1;
974                         if(copy_from_user(buf, buffer, len))
975                                 return -EFAULT;
976                         buf[len] = 0;
977                         p = buf;
978                         if (*p == '-' && left > 1) {
979                                 neg = 1;
980                                 left--, p++;
981                         }
982                         if (*p < '0' || *p > '9')
983                                 break;
984                         val = simple_strtoul(p, &p, 0) * conv;
985                         len = p-buf;
986                         if ((len < left) && *p && !isspace(*p))
987                                 break;
988                         if (neg)
989                                 val = -val;
990                         buffer += len;
991                         left -= len;
992                         switch(op) {
993                         case OP_SET:    *i = val; break;
994                         case OP_AND:    *i &= val; break;
995                         case OP_OR:     *i |= val; break;
996                         case OP_MAX:    if(*i < val)
997                                                 *i = val;
998                                         break;
999                         case OP_MIN:    if(*i > val)
1000                                                 *i = val;
1001                                         break;
1002                         }
1003                 } else {
1004                         p = buf;
1005                         if (!first)
1006                                 *p++ = '\t';
1007                         sprintf(p, "%d", (*i) / conv);
1008                         len = strlen(buf);
1009                         if (len > left)
1010                                 len = left;
1011                         if(copy_to_user(buffer, buf, len))
1012                                 return -EFAULT;
1013                         left -= len;
1014                         buffer += len;
1015                 }
1016         }
1017
1018         if (!write && !first && left) {
1019                 if(put_user('\n', (char *) buffer))
1020                         return -EFAULT;
1021                 left--, buffer++;
1022         }
1023         if (write) {
1024                 p = (char *) buffer;
1025                 while (left) {
1026                         char c;
1027                         if (get_user(c, p++))
1028                                 return -EFAULT;
1029                         if (!isspace(c))
1030                                 break;
1031                         left--;
1032                 }
1033         }
1034         if (write && first)
1035                 return -EINVAL;
1036         *lenp -= left;
1037         filp->f_pos += *lenp;
1038         return 0;
1039 }
1040
1041 /**
1042  * proc_dointvec - read a vector of integers
1043  * @table: the sysctl table
1044  * @write: %TRUE if this is a write to the sysctl file
1045  * @filp: the file structure
1046  * @buffer: the user buffer
1047  * @lenp: the size of the user buffer
1048  *
1049  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1050  * values from/to the user buffer, treated as an ASCII string. 
1051  *
1052  * Returns 0 on success.
1053  */
1054 int proc_dointvec(ctl_table *table, int write, struct file *filp,
1055                      void *buffer, size_t *lenp)
1056 {
1057     return do_proc_dointvec(table,write,filp,buffer,lenp,1,OP_SET);
1058 }
1059
1060 /*
1061  *      init may raise the set.
1062  */
1063  
1064 int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
1065                         void *buffer, size_t *lenp)
1066 {
1067         if (!capable(CAP_SYS_MODULE)) {
1068                 return -EPERM;
1069         }
1070         return do_proc_dointvec(table,write,filp,buffer,lenp,1,
1071                                 (current->pid == 1) ? OP_SET : OP_AND);
1072 }
1073
1074 /**
1075  * proc_dointvec_minmax - read a vector of integers with min/max values
1076  * @table: the sysctl table
1077  * @write: %TRUE if this is a write to the sysctl file
1078  * @filp: the file structure
1079  * @buffer: the user buffer
1080  * @lenp: the size of the user buffer
1081  *
1082  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1083  * values from/to the user buffer, treated as an ASCII string.
1084  *
1085  * This routine will ensure the values are within the range specified by
1086  * table->extra1 (min) and table->extra2 (max).
1087  *
1088  * Returns 0 on success.
1089  */
1090 int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
1091                   void *buffer, size_t *lenp)
1092 {
1093         int *i, *min, *max, vleft, first=1, neg, val;
1094         size_t len, left;
1095         #define TMPBUFLEN 20
1096         char buf[TMPBUFLEN], *p;
1097         
1098         if (!table->data || !table->maxlen || !*lenp ||
1099             (filp->f_pos && !write)) {
1100                 *lenp = 0;
1101                 return 0;
1102         }
1103         
1104         i = (int *) table->data;
1105         min = (int *) table->extra1;
1106         max = (int *) table->extra2;
1107         vleft = table->maxlen / sizeof(int);
1108         left = *lenp;
1109         
1110         for (; left && vleft--; i++, min++, max++, first=0) {
1111                 if (write) {
1112                         while (left) {
1113                                 char c;
1114                                 if (get_user(c, (char *) buffer))
1115                                         return -EFAULT;
1116                                 if (!isspace(c))
1117                                         break;
1118                                 left--;
1119                                 buffer++;
1120                         }
1121                         if (!left)
1122                                 break;
1123                         neg = 0;
1124                         len = left;
1125                         if (len > TMPBUFLEN-1)
1126                                 len = TMPBUFLEN-1;
1127                         if(copy_from_user(buf, buffer, len))
1128                                 return -EFAULT;
1129                         buf[len] = 0;
1130                         p = buf;
1131                         if (*p == '-' && left > 1) {
1132                                 neg = 1;
1133                                 left--, p++;
1134                         }
1135                         if (*p < '0' || *p > '9')
1136                                 break;
1137                         val = simple_strtoul(p, &p, 0);
1138                         len = p-buf;
1139                         if ((len < left) && *p && !isspace(*p))
1140                                 break;
1141                         if (neg)
1142                                 val = -val;
1143                         buffer += len;
1144                         left -= len;
1145
1146                         if ((min && val < *min) || (max && val > *max))
1147                                 continue;
1148                         *i = val;
1149                 } else {
1150                         p = buf;
1151                         if (!first)
1152                                 *p++ = '\t';
1153                         sprintf(p, "%d", *i);
1154                         len = strlen(buf);
1155                         if (len > left)
1156                                 len = left;
1157                         if(copy_to_user(buffer, buf, len))
1158                                 return -EFAULT;
1159                         left -= len;
1160                         buffer += len;
1161                 }
1162         }
1163
1164         if (!write && !first && left) {
1165                 if(put_user('\n', (char *) buffer))
1166                         return -EFAULT;
1167                 left--, buffer++;
1168         }
1169         if (write) {
1170                 p = (char *) buffer;
1171                 while (left) {
1172                         char c;
1173                         if (get_user(c, p++))
1174                                 return -EFAULT;
1175                         if (!isspace(c))
1176                                 break;
1177                         left--;
1178                 }
1179         }
1180         if (write && first)
1181                 return -EINVAL;
1182         *lenp -= left;
1183         filp->f_pos += *lenp;
1184         return 0;
1185 }
1186
1187 static int do_proc_doulongvec_minmax(ctl_table *table, int write,
1188                                      struct file *filp,
1189                                      void *buffer, size_t *lenp,
1190                                      unsigned long convmul,
1191                                      unsigned long convdiv)
1192 {
1193 #define TMPBUFLEN 20
1194         unsigned long *i, *min, *max, val;
1195         int vleft, first=1, neg;
1196         size_t len, left;
1197         char buf[TMPBUFLEN], *p;
1198         
1199         if (!table->data || !table->maxlen || !*lenp ||
1200             (filp->f_pos && !write)) {
1201                 *lenp = 0;
1202                 return 0;
1203         }
1204         
1205         i = (unsigned long *) table->data;
1206         min = (unsigned long *) table->extra1;
1207         max = (unsigned long *) table->extra2;
1208         vleft = table->maxlen / sizeof(unsigned long);
1209         left = *lenp;
1210         
1211         for (; left && vleft--; i++, first=0) {
1212                 if (write) {
1213                         while (left) {
1214                                 char c;
1215                                 if (get_user(c, (char *) buffer))
1216                                         return -EFAULT;
1217                                 if (!isspace(c))
1218                                         break;
1219                                 left--;
1220                                 buffer++;
1221                         }
1222                         if (!left)
1223                                 break;
1224                         neg = 0;
1225                         len = left;
1226                         if (len > TMPBUFLEN-1)
1227                                 len = TMPBUFLEN-1;
1228                         if(copy_from_user(buf, buffer, len))
1229                                 return -EFAULT;
1230                         buf[len] = 0;
1231                         p = buf;
1232                         if (*p == '-' && left > 1) {
1233                                 neg = 1;
1234                                 left--, p++;
1235                         }
1236                         if (*p < '0' || *p > '9')
1237                                 break;
1238                         val = simple_strtoul(p, &p, 0) * convmul / convdiv ;
1239                         len = p-buf;
1240                         if ((len < left) && *p && !isspace(*p))
1241                                 break;
1242                         if (neg)
1243                                 val = -val;
1244                         buffer += len;
1245                         left -= len;
1246
1247                         if(neg)
1248                                 continue;
1249                         if (min && val < *min++)
1250                                 continue;
1251                         if (max && val > *max++)
1252                                 continue;
1253                         *i = val;
1254                 } else {
1255                         p = buf;
1256                         if (!first)
1257                                 *p++ = '\t';
1258                         sprintf(p, "%lu", convdiv * (*i) / convmul);
1259                         len = strlen(buf);
1260                         if (len > left)
1261                                 len = left;
1262                         if(copy_to_user(buffer, buf, len))
1263                                 return -EFAULT;
1264                         left -= len;
1265                         buffer += len;
1266                 }
1267         }
1268
1269         if (!write && !first && left) {
1270                 if(put_user('\n', (char *) buffer))
1271                         return -EFAULT;
1272                 left--, buffer++;
1273         }
1274         if (write) {
1275                 p = (char *) buffer;
1276                 while (left) {
1277                         char c;
1278                         if (get_user(c, p++))
1279                                 return -EFAULT;
1280                         if (!isspace(c))
1281                                 break;
1282                         left--;
1283                 }
1284         }
1285         if (write && first)
1286                 return -EINVAL;
1287         *lenp -= left;
1288         filp->f_pos += *lenp;
1289         return 0;
1290 #undef TMPBUFLEN
1291 }
1292
1293 /**
1294  * proc_doulongvec_minmax - read a vector of long integers with min/max values
1295  * @table: the sysctl table
1296  * @write: %TRUE if this is a write to the sysctl file
1297  * @filp: the file structure
1298  * @buffer: the user buffer
1299  * @lenp: the size of the user buffer
1300  *
1301  * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
1302  * values from/to the user buffer, treated as an ASCII string.
1303  *
1304  * This routine will ensure the values are within the range specified by
1305  * table->extra1 (min) and table->extra2 (max).
1306  *
1307  * Returns 0 on success.
1308  */
1309 int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
1310                            void *buffer, size_t *lenp)
1311 {
1312     return do_proc_doulongvec_minmax(table, write, filp, buffer, lenp, 1l, 1l);
1313 }
1314
1315 /**
1316  * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values
1317  * @table: the sysctl table
1318  * @write: %TRUE if this is a write to the sysctl file
1319  * @filp: the file structure
1320  * @buffer: the user buffer
1321  * @lenp: the size of the user buffer
1322  *
1323  * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
1324  * values from/to the user buffer, treated as an ASCII string. The values
1325  * are treated as milliseconds, and converted to jiffies when they are stored.
1326  *
1327  * This routine will ensure the values are within the range specified by
1328  * table->extra1 (min) and table->extra2 (max).
1329  *
1330  * Returns 0 on success.
1331  */
1332 int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
1333                                       struct file *filp,
1334                                       void *buffer, size_t *lenp)
1335 {
1336     return do_proc_doulongvec_minmax(table, write, filp, buffer,
1337                                      lenp, HZ, 1000l);
1338 }
1339
1340
1341 /**
1342  * proc_dointvec_jiffies - read a vector of integers as seconds
1343  * @table: the sysctl table
1344  * @write: %TRUE if this is a write to the sysctl file
1345  * @filp: the file structure
1346  * @buffer: the user buffer
1347  * @lenp: the size of the user buffer
1348  *
1349  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1350  * values from/to the user buffer, treated as an ASCII string. 
1351  * The values read are assumed to be in seconds, and are converted into
1352  * jiffies.
1353  *
1354  * Returns 0 on success.
1355  */
1356 int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
1357                           void *buffer, size_t *lenp)
1358 {
1359     return do_proc_dointvec(table,write,filp,buffer,lenp,HZ,OP_SET);
1360 }
1361
1362 #else /* CONFIG_PROC_FS */
1363
1364 int proc_dostring(ctl_table *table, int write, struct file *filp,
1365                   void *buffer, size_t *lenp)
1366 {
1367         return -ENOSYS;
1368 }
1369
1370 static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
1371                             void *buffer, size_t *lenp)
1372 {
1373         return -ENOSYS;
1374 }
1375
1376 int proc_dointvec(ctl_table *table, int write, struct file *filp,
1377                   void *buffer, size_t *lenp)
1378 {
1379         return -ENOSYS;
1380 }
1381
1382 int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
1383                         void *buffer, size_t *lenp)
1384 {
1385         return -ENOSYS;
1386 }
1387
1388 int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
1389                     void *buffer, size_t *lenp)
1390 {
1391         return -ENOSYS;
1392 }
1393
1394 int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
1395                     void *buffer, size_t *lenp)
1396 {
1397         return -ENOSYS;
1398 }
1399
1400 int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
1401                     void *buffer, size_t *lenp)
1402 {
1403         return -ENOSYS;
1404 }
1405
1406 int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
1407                                       struct file *filp,
1408                                       void *buffer, size_t *lenp)
1409 {
1410     return -ENOSYS;
1411 }
1412
1413
1414 #endif /* CONFIG_PROC_FS */
1415
1416
1417 /*
1418  * General sysctl support routines 
1419  */
1420
1421 /* The generic string strategy routine: */
1422 int sysctl_string(ctl_table *table, int *name, int nlen,
1423                   void *oldval, size_t *oldlenp,
1424                   void *newval, size_t newlen, void **context)
1425 {
1426         size_t l, len;
1427         
1428         if (!table->data || !table->maxlen) 
1429                 return -ENOTDIR;
1430         
1431         if (oldval && oldlenp) {
1432                 if (get_user(len, oldlenp))
1433                         return -EFAULT;
1434                 if (len) {
1435                         l = strlen(table->data);
1436                         if (len > l) len = l;
1437                         if (len >= table->maxlen)
1438                                 len = table->maxlen;
1439                         if(copy_to_user(oldval, table->data, len))
1440                                 return -EFAULT;
1441                         if(put_user(0, ((char *) oldval) + len))
1442                                 return -EFAULT;
1443                         if(put_user(len, oldlenp))
1444                                 return -EFAULT;
1445                 }
1446         }
1447         if (newval && newlen) {
1448                 len = newlen;
1449                 if (len > table->maxlen)
1450                         len = table->maxlen;
1451                 if(copy_from_user(table->data, newval, len))
1452                         return -EFAULT;
1453                 if (len == table->maxlen)
1454                         len--;
1455                 ((char *) table->data)[len] = 0;
1456         }
1457         return 0;
1458 }
1459
1460 /*
1461  * This function makes sure that all of the integers in the vector
1462  * are between the minimum and maximum values given in the arrays
1463  * table->extra1 and table->extra2, respectively.
1464  */
1465 int sysctl_intvec(ctl_table *table, int *name, int nlen,
1466                 void *oldval, size_t *oldlenp,
1467                 void *newval, size_t newlen, void **context)
1468 {
1469         int i, *vec, *min, *max;
1470         size_t length;
1471
1472         if (newval && newlen) {
1473                 if (newlen % sizeof(int) != 0)
1474                         return -EINVAL;
1475
1476                 if (!table->extra1 && !table->extra2)
1477                         return 0;
1478
1479                 if (newlen > table->maxlen)
1480                         newlen = table->maxlen;
1481                 length = newlen / sizeof(int);
1482
1483                 vec = (int *) newval;
1484                 min = (int *) table->extra1;
1485                 max = (int *) table->extra2;
1486
1487                 for (i = 0; i < length; i++) {
1488                         int value;
1489                         if (get_user(value, vec + i))
1490                                 return -EFAULT;
1491                         if (min && value < min[i])
1492                                 return -EINVAL;
1493                         if (max && value > max[i])
1494                                 return -EINVAL;
1495                 }
1496         }
1497         return 0;
1498 }
1499
1500 /* Strategy function to convert jiffies to seconds */ 
1501 int sysctl_jiffies(ctl_table *table, int *name, int nlen,
1502                 void *oldval, size_t *oldlenp,
1503                 void *newval, size_t newlen, void **context)
1504 {
1505         if (oldval) {
1506                 size_t olen;
1507                 if (oldlenp) { 
1508                         if (get_user(olen, oldlenp))
1509                                 return -EFAULT;
1510                         if (olen!=sizeof(int))
1511                                 return -EINVAL; 
1512                 }
1513                 if (put_user(*(int *)(table->data) / HZ, (int *)oldval) || 
1514                     (oldlenp && put_user(sizeof(int),oldlenp)))
1515                         return -EFAULT;
1516         }
1517         if (newval && newlen) { 
1518                 int new;
1519                 if (newlen != sizeof(int))
1520                         return -EINVAL; 
1521                 if (get_user(new, (int *)newval))
1522                         return -EFAULT;
1523                 *(int *)(table->data) = new*HZ; 
1524         }
1525         return 1;
1526 }
1527
1528
1529 #else /* CONFIG_SYSCTL */
1530
1531
1532 extern asmlinkage long sys_sysctl(struct __sysctl_args *args)
1533 {
1534         return -ENOSYS;
1535 }
1536
1537 int sysctl_string(ctl_table *table, int *name, int nlen,
1538                   void *oldval, size_t *oldlenp,
1539                   void *newval, size_t newlen, void **context)
1540 {
1541         return -ENOSYS;
1542 }
1543
1544 int sysctl_intvec(ctl_table *table, int *name, int nlen,
1545                 void *oldval, size_t *oldlenp,
1546                 void *newval, size_t newlen, void **context)
1547 {
1548         return -ENOSYS;
1549 }
1550
1551 int sysctl_jiffies(ctl_table *table, int *name, int nlen,
1552                 void *oldval, size_t *oldlenp,
1553                 void *newval, size_t newlen, void **context)
1554 {
1555         return -ENOSYS;
1556 }
1557
1558 int proc_dostring(ctl_table *table, int write, struct file *filp,
1559                   void *buffer, size_t *lenp)
1560 {
1561         return -ENOSYS;
1562 }
1563
1564 int proc_dointvec(ctl_table *table, int write, struct file *filp,
1565                   void *buffer, size_t *lenp)
1566 {
1567         return -ENOSYS;
1568 }
1569
1570 int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
1571                         void *buffer, size_t *lenp)
1572 {
1573         return -ENOSYS;
1574 }
1575
1576 int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
1577                     void *buffer, size_t *lenp)
1578 {
1579         return -ENOSYS;
1580 }
1581
1582 int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
1583                           void *buffer, size_t *lenp)
1584 {
1585         return -ENOSYS;
1586 }
1587
1588 int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
1589                     void *buffer, size_t *lenp)
1590 {
1591         return -ENOSYS;
1592 }
1593
1594 int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
1595                                       struct file *filp,
1596                                       void *buffer, size_t *lenp)
1597 {
1598     return -ENOSYS;
1599 }
1600
1601 struct ctl_table_header * register_sysctl_table(ctl_table * table, 
1602                                                 int insert_at_head)
1603 {
1604         return 0;
1605 }
1606
1607 void unregister_sysctl_table(struct ctl_table_header * table)
1608 {
1609 }
1610
1611 #endif /* CONFIG_SYSCTL */