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