kernel/sysctl.c
30179 /*
30180 * sysctl.c: General linux system control interface
30181 *
30182 * Begun 24 March 1995, Stephen Tweedie
30183 * Added /proc support, Dec 1995
30184 * Added bdflush entry and intvec min/max checking,
30185 * 2/23/96, Tom Dyas.
30186 * Added hooks for /proc/sys/net (minor, minor patch),
30187 * 96/4/1, Mike Shaver.
30188 * Added kernel/java-{interpreter,appletviewer}, 96/5/10,
30189 * Mike Shaver.
30190 * Dynamic registration fixes, Stephen Tweedie.
30191 * Added kswapd-interval, ctrl-alt-del, printk stuff,
30192 * 1/8/97, Chris Horn.
30193 * Made sysctl support optional via CONFIG_SYSCTL,
30194 * 1/10/97, Chris Horn. */
30195
30196 #include <linux/config.h>
30197 #include <linux/malloc.h>
30198 #include <linux/sysctl.h>
30199 #include <linux/swapctl.h>
30200 #include <linux/proc_fs.h>
30201 #include <linux/ctype.h>
30202 #include <linux/utsname.h>
30203 #include <linux/swapctl.h>
30204 #include <linux/smp_lock.h>
30205 #include <linux/init.h>
30206
30207 #include <asm/uaccess.h>
30208
30209 #ifdef CONFIG_ROOT_NFS
30210 #include <linux/nfs_fs.h>
30211 #endif
30212
30213 #if defined(CONFIG_SYSCTL)
30214
30215 /* External variables not in a header file. */
30216 extern int panic_timeout;
30217 extern int console_loglevel, C_A_D;
30218 extern int bdf_prm[], bdflush_min[], bdflush_max[];
30219 extern char binfmt_java_interpreter[],
30220 binfmt_java_appletviewer[];
30221 extern int sysctl_overcommit_memory;
30222 extern int nr_queued_signals, max_queued_signals;
30223
30224 #ifdef CONFIG_KMOD
30225 extern char modprobe_path[];
30226 #endif
30227 #ifdef CONFIG_CHR_DEV_SG
30228 extern int sg_big_buff;
30229 #endif
30230 #ifdef CONFIG_SYSVIPC
30231 extern int shmmax;
30232 #endif
30233
30234 #ifdef __sparc__
30235 extern char reboot_command [];
30236 #endif
30237 #ifdef __powerpc__
30238 extern unsigned long htab_reclaim_on, zero_paged_on,
30239 powersave_nap;
30240 int proc_dol2crvec(ctl_table *table, int write,
30241 struct file *filp, void *buffer, size_t *lenp);
30242 #endif
30243
30244 #ifdef CONFIG_BSD_PROCESS_ACCT
30245 extern int acct_parm[];
30246 #endif
30247
30248 extern int pgt_cache_water[];
30249
30250 static int parse_table(int *, int, void *, size_t *,
30251 void *, size_t, ctl_table *, void **);
30252 static int proc_doutsstring(ctl_table *table, int write,
30253 struct file *filp, void *buffer, size_t *lenp);
30254
30255 static ctl_table root_table[];
30256 static struct ctl_table_header root_table_header =
30257 {root_table, DNODE_SINGLE(&root_table_header)};
30258
30259 static ctl_table kern_table[];
30260 static ctl_table vm_table[];
30261 #ifdef CONFIG_NET
30262 extern ctl_table net_table[];
30263 #endif
30264 static ctl_table proc_table[];
30265 static ctl_table fs_table[];
30266 static ctl_table debug_table[];
30267 static ctl_table dev_table[];
30268
30269
30270 /* /proc declarations: */
30271
30272 #ifdef CONFIG_PROC_FS
30273
30274 static ssize_t proc_readsys(struct file *, char *,
30275 size_t, loff_t *);
30276 static ssize_t proc_writesys(struct file *, const char *,
30277 size_t, loff_t *);
30278 static int proc_sys_permission(struct inode *, int);
30279
30280 struct file_operations proc_sys_file_operations =
30281 {
30282 NULL, /* lseek */
30283 proc_readsys, /* read */
30284 proc_writesys, /* write */
30285 NULL, /* readdir */
30286 NULL, /* poll */
30287 NULL, /* ioctl */
30288 NULL, /* mmap */
30289 NULL, /* no special open code */
30290 NULL, /* no special flush code */
30291 NULL, /* no special release code */
30292 NULL /* can't fsync */
30293 };
30294
30295 struct inode_operations proc_sys_inode_operations =
30296 {
30297 &proc_sys_file_operations,
30298 NULL, /* create */
30299 NULL, /* lookup */
30300 NULL, /* link */
30301 NULL, /* unlink */
30302 NULL, /* symlink */
30303 NULL, /* mkdir */
30304 NULL, /* rmdir */
30305 NULL, /* mknod */
30306 NULL, /* rename */
30307 NULL, /* readlink */
30308 NULL, /* follow_link */
30309 NULL, /* readpage */
30310 NULL, /* writepage */
30311 NULL, /* bmap */
30312 NULL, /* truncate */
30313 proc_sys_permission
30314 };
30315
30316 extern struct proc_dir_entry proc_sys_root;
30317
30318 static void register_proc_table(ctl_table *,
30319 struct proc_dir_entry *);
30320 static void unregister_proc_table(ctl_table *,
30321 struct proc_dir_entry *);
30322 #endif
30323 extern int inodes_stat[];
30324 extern int dentry_stat[];
30325
30326 /* The default sysctl tables: */
30327
30328 static ctl_table root_table[] = {
30329 {CTL_KERN, "kernel", NULL, 0, 0555, kern_table},
30330 {CTL_VM, "vm", NULL, 0, 0555, vm_table},
30331 #ifdef CONFIG_NET
30332 {CTL_NET, "net", NULL, 0, 0555, net_table},
30333 #endif
30334 {CTL_PROC, "proc", NULL, 0, 0555, proc_table},
30335 {CTL_FS, "fs", NULL, 0, 0555, fs_table},
30336 {CTL_DEBUG, "debug", NULL, 0, 0555, debug_table},
30337 {CTL_DEV, "dev", NULL, 0, 0555, dev_table},
30338 {0}
30339 };
30340
30341 static ctl_table kern_table[] = {
30342 {KERN_OSTYPE, "ostype", system_utsname.sysname, 64,
30343 0444, NULL, &proc_doutsstring, &sysctl_string},
30344 {KERN_OSRELEASE, "osrelease", system_utsname.release,
30345 64, 0444, NULL, &proc_doutsstring, &sysctl_string},
30346 {KERN_VERSION, "version", system_utsname.version, 64,
30347 0444, NULL, &proc_doutsstring, &sysctl_string},
30348 {KERN_NODENAME, "hostname", system_utsname.nodename,
30349 64, 0644, NULL, &proc_doutsstring, &sysctl_string},
30350 {KERN_DOMAINNAME, "domainname",
30351 system_utsname.domainname, 64,
30352 0644, NULL, &proc_doutsstring, &sysctl_string},
30353 {KERN_PANIC, "panic", &panic_timeout, sizeof(int),
30354 0644, NULL, &proc_dointvec},
30355 #ifdef CONFIG_BLK_DEV_INITRD
30356 {KERN_REALROOTDEV, "real-root-dev", &real_root_dev,
30357 sizeof(int), 0644, NULL, &proc_dointvec},
30358 #endif
30359 #ifdef CONFIG_BINFMT_JAVA
30360 {KERN_JAVA_INTERPRETER, "java-interpreter",
30361 binfmt_java_interpreter,
30362 64, 0644, NULL, &proc_dostring, &sysctl_string },
30363 {KERN_JAVA_APPLETVIEWER, "java-appletviewer",
30364 binfmt_java_appletviewer,
30365 64, 0644, NULL, &proc_dostring, &sysctl_string },
30366 #endif
30367 #ifdef __sparc__
30368 {KERN_SPARC_REBOOT, "reboot-cmd", reboot_command,
30369 256, 0644, NULL, &proc_dostring, &sysctl_string },
30370 #endif
30371 #ifdef __powerpc__
30372 {KERN_PPC_HTABRECLAIM, "htab-reclaim",
30373 &htab_reclaim_on, sizeof(int),
30374 0644, NULL, &proc_dointvec},
30375 {KERN_PPC_ZEROPAGED, "zero-paged", &zero_paged_on,
30376 sizeof(int), 0644, NULL, &proc_dointvec},
30377 {KERN_PPC_POWERSAVE_NAP, "powersave-nap",
30378 &powersave_nap, sizeof(int),
30379 0644, NULL, &proc_dointvec},
30380 {KERN_PPC_L2CR, "l2cr", NULL, 0,
30381 0644, NULL, &proc_dol2crvec},
30382 #endif
30383 {KERN_CTLALTDEL, "ctrl-alt-del", &C_A_D, sizeof(int),
30384 0644, NULL, &proc_dointvec},
30385 {KERN_PRINTK, "printk", &console_loglevel,
30386 4*sizeof(int), 0644, NULL, &proc_dointvec},
30387 #ifdef CONFIG_KMOD
30388 {KERN_MODPROBE, "modprobe", &modprobe_path, 256,
30389 0644, NULL, &proc_dostring, &sysctl_string },
30390 #endif
30391 #ifdef CONFIG_CHR_DEV_SG
30392 {KERN_SG_BIG_BUFF, "sg-big-buff", &sg_big_buff,
30393 sizeof (int), 0444, NULL, &proc_dointvec},
30394 #endif
30395 #ifdef CONFIG_BSD_PROCESS_ACCT
30396 {KERN_ACCT, "acct", &acct_parm, 3*sizeof(int),
30397 0644, NULL, &proc_dointvec},
30398 #endif
30399 {KERN_RTSIGNR, "rtsig-nr", &nr_queued_signals,
30400 sizeof(int), 0444, NULL, &proc_dointvec},
30401 {KERN_RTSIGMAX, "rtsig-max", &max_queued_signals,
30402 sizeof(int), 0644, NULL, &proc_dointvec},
30403 #ifdef CONFIG_SYSVIPC
30404 {KERN_SHMMAX, "shmmax", &shmmax, sizeof (int),
30405 0644, NULL, &proc_dointvec},
30406 #endif
30407 {0}
30408 };
30409
30410 static ctl_table vm_table[] = {
30411 {VM_FREEPG, "freepages", &freepages,
30412 sizeof(freepages_t), 0644, NULL, &proc_dointvec},
30413 {VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0600,
30414 NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
30415 &bdflush_min, &bdflush_max},
30416 {VM_OVERCOMMIT_MEMORY, "overcommit_memory",
30417 &sysctl_overcommit_memory,
30418 sizeof(sysctl_overcommit_memory), 0644, NULL,
30419 &proc_dointvec},
30420 {VM_BUFFERMEM, "buffermem", &buffer_mem,
30421 sizeof(buffer_mem_t), 0644, NULL, &proc_dointvec},
30422 {VM_PAGECACHE, "pagecache", &page_cache,
30423 sizeof(buffer_mem_t), 0644, NULL, &proc_dointvec},
30424 {VM_PAGERDAEMON, "kswapd", &pager_daemon,
30425 sizeof(pager_daemon_t), 0644, NULL, &proc_dointvec},
30426 {VM_PGT_CACHE, "pagetable_cache", &pgt_cache_water,
30427 2*sizeof(int), 0600, NULL, &proc_dointvec},
30428 {VM_PAGE_CLUSTER, "page-cluster", &page_cluster,
30429 sizeof(int), 0600, NULL, &proc_dointvec},
30430 {0}
30431 };
30432
30433 static ctl_table proc_table[] = { {0} };
30434
30435 static ctl_table fs_table[] = {
30436 {FS_NRINODE, "inode-nr", &inodes_stat, 2*sizeof(int),
30437 0444, NULL, &proc_dointvec},
30438 {FS_STATINODE, "inode-state", &inodes_stat,
30439 7*sizeof(int), 0444, NULL, &proc_dointvec},
30440 {FS_MAXINODE, "inode-max", &max_inodes, sizeof(int),
30441 0644, NULL, &proc_dointvec},
30442 {FS_NRFILE, "file-nr", &nr_files, 3*sizeof(int),
30443 0444, NULL, &proc_dointvec},
30444 {FS_MAXFILE, "file-max", &max_files, sizeof(int),
30445 0644, NULL, &proc_dointvec},
30446 {FS_NRSUPER, "super-nr", &nr_super_blocks, sizeof(int),
30447 0444, NULL, &proc_dointvec},
30448 {FS_MAXSUPER, "super-max", &max_super_blocks,
30449 sizeof(int), 0644, NULL, &proc_dointvec},
30450 {FS_NRDQUOT, "dquot-nr", &nr_dquots, 2*sizeof(int),
30451 0444, NULL, &proc_dointvec},
30452 {FS_MAXDQUOT, "dquot-max", &max_dquots, sizeof(int),
30453 0644, NULL, &proc_dointvec},
30454 {FS_DENTRY, "dentry-state", &dentry_stat,
30455 6*sizeof(int), 0444, NULL, &proc_dointvec},
30456 {0}
30457 };
30458
30459 static ctl_table debug_table[] = { {0} };
30460
30461 static ctl_table dev_table[] = { {0} };
30462
30463 void __init sysctl_init(void)
30464 {
30465 #ifdef CONFIG_PROC_FS
30466 register_proc_table(root_table, &proc_sys_root);
30467 #endif
30468 }
30469
30470
30471 int do_sysctl (int *name, int nlen,
30472 void *oldval, size_t *oldlenp,
30473 void *newval, size_t newlen)
30474 {
30475 int error;
30476 struct ctl_table_header *tmp;
30477 void *context;
30478
30479 if (nlen == 0 || nlen >= CTL_MAXNAME)
30480 return -ENOTDIR;
30481
30482 if (oldval)
30483 {
30484 int old_len;
30485 if (!oldlenp)
30486 return -EFAULT;
30487 if(get_user(old_len, oldlenp))
30488 return -EFAULT;
30489 }
30490 tmp = &root_table_header;
30491 do {
30492 context = NULL;
30493 error = parse_table(name, nlen, oldval, oldlenp,
30494 newval, newlen, tmp->ctl_table, &context);
30495 if (context)
30496 kfree(context);
30497 if (error != -ENOTDIR)
30498 return error;
30499 tmp = tmp->DLIST_NEXT(ctl_entry);
30500 } while (tmp != &root_table_header);
30501 return -ENOTDIR;
30502 }
30503
30504 extern asmlinkage int sys_sysctl(
30505 struct __sysctl_args *args)
30506 {
30507 struct __sysctl_args tmp;
30508 int error;
30509
30510 if (copy_from_user(&tmp, args, sizeof(tmp)))
30511 return -EFAULT;
30512
30513 lock_kernel();
30514 error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval,
30515 tmp.oldlenp, tmp.newval, tmp.newlen);
30516 unlock_kernel();
30517 return error;
30518 }
30519
30520 /* Like in_group_p, but testing against egid,
30521 * not fsgid */
30522 static int in_egroup_p(gid_t grp)
30523 {
30524 if (grp != current->egid) {
30525 int i = current->ngroups;
30526 if (i) {
30527 gid_t *groups = current->groups;
30528 do {
30529 if (*groups == grp)
30530 goto out;
30531 groups++;
30532 i--;
30533 } while (i);
30534 }
30535 return 0;
30536 }
30537 out:
30538 return 1;
30539 }
30540
30541 /* ctl_perm does NOT grant the superuser all rights
30542 * automatically, because some sysctl variables are
30543 * readonly even to root. */
30544 static int test_perm(int mode, int op)
30545 {
30546 if (!current->euid)
30547 mode >>= 6;
30548 else if (in_egroup_p(0))
30549 mode >>= 3;
30550 if ((mode & op & 0007) == op)
30551 return 0;
30552 return -EACCES;
30553 }
30554
30555 static inline int ctl_perm(ctl_table *table, int op)
30556 {
30557 return test_perm(table->mode, op);
30558 }
30559
30560 static int parse_table(int *name, int nlen,
30561 void *oldval, size_t *oldlenp,
30562 void *newval, size_t newlen,
30563 ctl_table *table, void **context)
30564 {
30565 int error;
30566 repeat:
30567 if (!nlen)
30568 return -ENOTDIR;
30569
30570 for ( ; table->ctl_name; table++) {
30571 int n;
30572 if(get_user(n,name))
30573 return -EFAULT;
30574 if (n == table->ctl_name ||
30575 table->ctl_name == CTL_ANY) {
30576 if (table->child) {
30577 if (ctl_perm(table, 001))
30578 return -EPERM;
30579 if (table->strategy) {
30580 error = table->strategy(
30581 table, name, nlen,
30582 oldval, oldlenp,
30583 newval, newlen, context);
30584 if (error)
30585 return error;
30586 }
30587 name++;
30588 nlen--;
30589 table = table->child;
30590 goto repeat;
30591 }
30592 error = do_sysctl_strategy(table, name, nlen,
30593 oldval, oldlenp,
30594 newval, newlen, context);
30595 return error;
30596 }
30597 };
30598 return -ENOTDIR;
30599 }
30600
30601 /* Perform the actual read/write of a sysctl table
30602 * entry. */
30603 int do_sysctl_strategy (ctl_table *table,
30604 int *name, int nlen,
30605 void *oldval, size_t *oldlenp,
30606 void *newval, size_t newlen, void **context)
30607 {
30608 int op = 0, rc, len;
30609
30610 if (oldval)
30611 op |= 004;
30612 if (newval)
30613 op |= 002;
30614 if (ctl_perm(table, op))
30615 return -EPERM;
30616
30617 if (table->strategy) {
30618 rc = table->strategy(table, name, nlen, oldval,
30619 oldlenp, newval, newlen, context);
30620 if (rc < 0)
30621 return rc;
30622 if (rc > 0)
30623 return 0;
30624 }
30625
30626 /* If there is no strategy routine, or if the strategy
30627 * returns zero, proceed with automatic r/w */
30628 if (table->data && table->maxlen) {
30629 if (oldval && oldlenp) {
30630 get_user(len, oldlenp);
30631 if (len) {
30632 if (len > table->maxlen)
30633 len = table->maxlen;
30634 if(copy_to_user(oldval, table->data, len))
30635 return -EFAULT;
30636 if(put_user(len, oldlenp))
30637 return -EFAULT;
30638 }
30639 }
30640 if (newval && newlen) {
30641 len = newlen;
30642 if (len > table->maxlen)
30643 len = table->maxlen;
30644 if(copy_from_user(table->data, newval, len))
30645 return -EFAULT;
30646 }
30647 }
30648 return 0;
30649 }
30650
30651 struct ctl_table_header *register_sysctl_table(
30652 ctl_table * table, int insert_at_head)
30653 {
30654 struct ctl_table_header *tmp;
30655 tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
30656 if (!tmp)
30657 return 0;
30658 *tmp = ((struct ctl_table_header) {table, DNODE_NULL});
30659 if (insert_at_head)
30660 DLIST_INSERT_AFTER(&root_table_header, tmp,
30661 ctl_entry);
30662 else
30663 DLIST_INSERT_BEFORE(&root_table_header, tmp,
30664 ctl_entry);
30665 #ifdef CONFIG_PROC_FS
30666 register_proc_table(table, &proc_sys_root);
30667 #endif
30668 return tmp;
30669 }
30670
30671 /* Unlink and free a ctl_table. */
30672 void unregister_sysctl_table(
30673 struct ctl_table_header * header)
30674 {
30675 DLIST_DELETE(header, ctl_entry);
30676 #ifdef CONFIG_PROC_FS
30677 unregister_proc_table(header->ctl_table,
30678 &proc_sys_root);
30679 #endif
30680 kfree(header);
30681 }
30682
30683 /* /proc/sys support */
30684
30685 #ifdef CONFIG_PROC_FS
30686
30687 /* Scan the sysctl entries in table and add them all into
30688 * /proc */
30689 static void register_proc_table(ctl_table * table,
30690 struct proc_dir_entry *root)
30691 {
30692 struct proc_dir_entry *de;
30693 int len;
30694 mode_t mode;
30695
30696 for (; table->ctl_name; table++) {
30697 /* Can't do anything without a proc name. */
30698 if (!table->procname)
30699 continue;
30700 /* Maybe we can't do anything with it... */
30701 if (!table->proc_handler && !table->child) {
30702 printk(KERN_WARNING "SYSCTL: Can't register %s\n",
30703 table->procname);
30704 continue;
30705 }
30706
30707 len = strlen(table->procname);
30708 mode = table->mode;
30709
30710 de = NULL;
30711 if (table->proc_handler)
30712 mode |= S_IFREG;
30713 else {
30714 mode |= S_IFDIR;
30715 for (de = root->subdir; de; de = de->next) {
30716 if (proc_match(len, table->procname, de))
30717 break;
30718 }
30719 /* If the subdir exists already, de is non-NULL */
30720 }
30721
30722 if (!de) {
30723 de = create_proc_entry(table->procname, mode,root);
30724 if (!de)
30725 continue;
30726 de->data = (void *) table;
30727 if (table->proc_handler)
30728 de->ops = &proc_sys_inode_operations;
30729
30730 }
30731 table->de = de;
30732 if (de->mode & S_IFDIR)
30733 register_proc_table(table->child, de);
30734 }
30735 }
30736
30737 /* Unregister a /proc sysctl table and any
30738 * subdirectories. */
30739 static void unregister_proc_table(ctl_table * table,
30740 struct proc_dir_entry *root)
30741 {
30742 struct proc_dir_entry *de;
30743 for (; table->ctl_name; table++) {
30744 if (!(de = table->de))
30745 continue;
30746 if (de->mode & S_IFDIR) {
30747 if (!table->child) {
30748 printk(KERN_ALERT
30749 "Help - malformed sysctl tree on free\n");
30750 continue;
30751 }
30752 unregister_proc_table(table->child, de);
30753
30754 /* Don't unregister directories which still have
30755 * entries.. */
30756 if (de->subdir)
30757 continue;
30758 }
30759
30760 /* Don't unregister proc entries that are still being
30761 * used.. */
30762 if (de->count)
30763 continue;
30764
30765 proc_unregister(root, de->low_ino);
30766 table->de = NULL;
30767 kfree(de);
30768 }
30769 }
30770
30771 static ssize_t do_rw_proc(int write, struct file * file,
30772 char * buf, size_t count, loff_t *ppos)
30773 {
30774 int op;
30775 struct proc_dir_entry *de;
30776 struct ctl_table *table;
30777 size_t res;
30778 ssize_t error;
30779
30780 de = (struct proc_dir_entry *)
30781 file->f_dentry->d_inode->u.generic_ip;
30782 if (!de || !de->data)
30783 return -ENOTDIR;
30784 table = (struct ctl_table *) de->data;
30785 if (!table || !table->proc_handler)
30786 return -ENOTDIR;
30787 op = (write ? 002 : 004);
30788 if (ctl_perm(table, op))
30789 return -EPERM;
30790
30791 res = count;
30792
30793 /* FIXME: we need to pass on ppos to the handler. */
30794
30795 error =
30796 (*table->proc_handler)(table, write, file, buf,&res);
30797 if (error)
30798 return error;
30799 return res;
30800 }
30801
30802 static ssize_t proc_readsys(struct file * file,
30803 char * buf, size_t count, loff_t *ppos)
30804 {
30805 return do_rw_proc(0, file, buf, count, ppos);
30806 }
30807
30808 static ssize_t proc_writesys(struct file * file,
30809 const char * buf, size_t count, loff_t *ppos)
30810 {
30811 return do_rw_proc(1, file, (char *) buf, count, ppos);
30812 }
30813
30814 static int proc_sys_permission(struct inode *inode,
30815 int op)
30816 {
30817 return test_perm(inode->i_mode, op);
30818 }
30819
30820 int proc_dostring(ctl_table *table, int write,
30821 struct file *filp, void *buffer, size_t *lenp)
30822 {
30823 int len;
30824 char *p, c;
30825
30826 if (!table->data || !table->maxlen || !*lenp ||
30827 (filp->f_pos && !write)) {
30828 *lenp = 0;
30829 return 0;
30830 }
30831
30832 if (write) {
30833 len = 0;
30834 p = buffer;
30835 while (len < *lenp) {
30836 if(get_user(c, p++))
30837 return -EFAULT;
30838 if (c == 0 || c == '\n')
30839 break;
30840 len++;
30841 }
30842 if (len >= table->maxlen)
30843 len = table->maxlen-1;
30844 if(copy_from_user(table->data, buffer, len))
30845 return -EFAULT;
30846 ((char *) table->data)[len] = 0;
30847 filp->f_pos += *lenp;
30848 } else {
30849 len = strlen(table->data);
30850 if (len > table->maxlen)
30851 len = table->maxlen;
30852 if (len > *lenp)
30853 len = *lenp;
30854 if (len)
30855 if(copy_to_user(buffer, table->data, len))
30856 return -EFAULT;
30857 if (len < *lenp) {
30858 if(put_user('\n', ((char *) buffer) + len))
30859 return -EFAULT;
30860 len++;
30861 }
30862 *lenp = len;
30863 filp->f_pos += len;
30864 }
30865 return 0;
30866 }
30867
30868 /* Special case of dostring for the UTS structure. This
30869 * has locks to observe. Should this be in kernel/sys.c
30870 * ???? */
30871 static int proc_doutsstring(ctl_table *table, int write,
30872 struct file *filp, void *buffer, size_t *lenp)
30873 {
30874 int r;
30875 down(&uts_sem);
30876 r=proc_dostring(table,write,filp,buffer,lenp);
30877 up(&uts_sem);
30878 return r;
30879 }
30880
30881 static int do_proc_dointvec(ctl_table *table, int write,
30882 struct file *filp, void *buffer, size_t *lenp, int conv)
30883 {
30884 int *i, vleft, first=1, len, left, neg, val;
30885 #define TMPBUFLEN 20
30886 char buf[TMPBUFLEN], *p;
30887
30888 if (!table->data || !table->maxlen || !*lenp ||
30889 (filp->f_pos && !write)) {
30890 *lenp = 0;
30891 return 0;
30892 }
30893
30894 i = (int *) table->data;
30895 vleft = table->maxlen / sizeof(int);
30896 left = *lenp;
30897
30898 for (; left && vleft--; i++, first=0) {
30899 if (write) {
30900 while (left) {
30901 char c;
30902 if(get_user(c,(char *) buffer))
30903 return -EFAULT;
30904 if (!isspace(c))
30905 break;
30906 left--;
30907 ((char *) buffer)++;
30908 }
30909 if (!left)
30910 break;
30911 neg = 0;
30912 len = left;
30913 if (len > TMPBUFLEN-1)
30914 len = TMPBUFLEN-1;
30915 if(copy_from_user(buf, buffer, len))
30916 return -EFAULT;
30917 buf[len] = 0;
30918 p = buf;
30919 if (*p == '-' && left > 1) {
30920 neg = 1;
30921 left--, p++;
30922 }
30923 if (*p < '0' || *p > '9')
30924 break;
30925 val = simple_strtoul(p, &p, 0) * conv;
30926 len = p-buf;
30927 if ((len < left) && *p && !isspace(*p))
30928 break;
30929 if (neg)
30930 val = -val;
30931 buffer += len;
30932 left -= len;
30933 *i = val;
30934 } else {
30935 p = buf;
30936 if (!first)
30937 *p++ = '\t';
30938 sprintf(p, "%d", (*i) / conv);
30939 len = strlen(buf);
30940 if (len > left)
30941 len = left;
30942 if(copy_to_user(buffer, buf, len))
30943 return -EFAULT;
30944 left -= len;
30945 buffer += len;
30946 }
30947 }
30948
30949 if (!write && !first && left) {
30950 if(put_user('\n', (char *) buffer))
30951 return -EFAULT;
30952 left--, buffer++;
30953 }
30954 if (write) {
30955 p = (char *) buffer;
30956 while (left) {
30957 char c;
30958 if(get_user(c, p++))
30959 return -EFAULT;
30960 if (!isspace(c))
30961 break;
30962 left--;
30963 }
30964 }
30965 if (write && first)
30966 return -EINVAL;
30967 *lenp -= left;
30968 filp->f_pos += *lenp;
30969 return 0;
30970 }
30971
30972 int proc_dointvec(ctl_table *table, int write,
30973 struct file *filp, void *buf, size_t *lenp)
30974 {
30975 return do_proc_dointvec(table,write,filp,buf,lenp,1);
30976 }
30977
30978 int proc_dointvec_minmax(ctl_table *table, int write,
30979 struct file *filp, void *buffer, size_t *lenp)
30980 {
30981 int *i, *min, *max, vleft, first=1, len, left, neg,val;
30982 #define TMPBUFLEN 20
30983 char buf[TMPBUFLEN], *p;
30984
30985 if (!table->data || !table->maxlen || !*lenp ||
30986 (filp->f_pos && !write)) {
30987 *lenp = 0;
30988 return 0;
30989 }
30990
30991 i = (int *) table->data;
30992 min = (int *) table->extra1;
30993 max = (int *) table->extra2;
30994 vleft = table->maxlen / sizeof(int);
30995 left = *lenp;
30996
30997 for (; left && vleft--; i++, first=0) {
30998 if (write) {
30999 while (left) {
31000 char c;
31001 if(get_user(c, (char *) buffer))
31002 return -EFAULT;
31003 if (!isspace(c))
31004 break;
31005 left--;
31006 ((char *) buffer)++;
31007 }
31008 if (!left)
31009 break;
31010 neg = 0;
31011 len = left;
31012 if (len > TMPBUFLEN-1)
31013 len = TMPBUFLEN-1;
31014 if(copy_from_user(buf, buffer, len))
31015 return -EFAULT;
31016 buf[len] = 0;
31017 p = buf;
31018 if (*p == '-' && left > 1) {
31019 neg = 1;
31020 left--, p++;
31021 }
31022 if (*p < '0' || *p > '9')
31023 break;
31024 val = simple_strtoul(p, &p, 0);
31025 len = p-buf;
31026 if ((len < left) && *p && !isspace(*p))
31027 break;
31028 if (neg)
31029 val = -val;
31030 buffer += len;
31031 left -= len;
31032
31033 if (min && val < *min++)
31034 continue;
31035 if (max && val > *max++)
31036 continue;
31037 *i = val;
31038 } else {
31039 p = buf;
31040 if (!first)
31041 *p++ = '\t';
31042 sprintf(p, "%d", *i);
31043 len = strlen(buf);
31044 if (len > left)
31045 len = left;
31046 if(copy_to_user(buffer, buf, len))
31047 return -EFAULT;
31048 left -= len;
31049 buffer += len;
31050 }
31051 }
31052
31053 if (!write && !first && left) {
31054 if(put_user('\n', (char *) buffer))
31055 return -EFAULT;
31056 left--, buffer++;
31057 }
31058 if (write) {
31059 p = (char *) buffer;
31060 while (left) {
31061 char c;
31062 if(get_user(c, p++))
31063 return -EFAULT;
31064 if (!isspace(c))
31065 break;
31066 left--;
31067 }
31068 }
31069 if (write && first)
31070 return -EINVAL;
31071 *lenp -= left;
31072 filp->f_pos += *lenp;
31073 return 0;
31074 }
31075
31076 /* Like proc_dointvec, but converts seconds to jiffies */
31077 int proc_dointvec_jiffies(ctl_table *tbl, int write,
31078 struct file *filp, void *buf, size_t *lenp)
31079 {
31080 return do_proc_dointvec(tbl,write,filp,buf,lenp,HZ);
31081 }
31082
31083 #else /* CONFIG_PROC_FS */
31084
31085 int proc_dostring(ctl_table *table, int write,
31086 struct file *filp, void *buffer, size_t *lenp)
31087 {
31088 return -ENOSYS;
31089 }
31090
31091 static int proc_doutsstring(ctl_table *table, int write,
31092 struct file *filp, void *buffer, size_t *lenp)
31093 {
31094 return -ENOSYS;
31095 }
31096
31097 int proc_dointvec(ctl_table *table, int write,
31098 struct file *filp, void *buffer, size_t *lenp)
31099 {
31100 return -ENOSYS;
31101 }
31102
31103 int proc_dointvec_minmax(ctl_table *table, int write,
31104 struct file *filp, void *buffer, size_t *lenp)
31105 {
31106 return -ENOSYS;
31107 }
31108
31109 int proc_dointvec_jiffies(ctl_table *table, int write,
31110 struct file *filp, void *buffer, size_t *lenp)
31111 {
31112 return -ENOSYS;
31113 }
31114
31115 #endif /* CONFIG_PROC_FS */
31116
31117
31118 /* General sysctl support routines */
31119
31120 /* The generic string strategy routine: */
31121 int sysctl_string(ctl_table *table, int *name, int nlen,
31122 void *oldval, size_t *oldlenp,
31123 void *newval, size_t newlen, void **context)
31124 {
31125 int l, len;
31126
31127 if (!table->data || !table->maxlen)
31128 return -ENOTDIR;
31129
31130 if (oldval && oldlenp) {
31131 if (get_user(len, oldlenp))
31132 return -EFAULT;
31133 if (len) {
31134 l = strlen(table->data);
31135 if (len > l) len = l;
31136 if (len >= table->maxlen)
31137 len = table->maxlen;
31138 if (copy_to_user(oldval, table->data, len))
31139 return -EFAULT;
31140 if (put_user(0, ((char *) oldval) + len))
31141 return -EFAULT;
31142 if (put_user(len, oldlenp))
31143 return -EFAULT;
31144 }
31145 }
31146 if (newval && newlen) {
31147 len = newlen;
31148 if (len > table->maxlen)
31149 len = table->maxlen;
31150 if (copy_from_user(table->data, newval, len))
31151 return -EFAULT;
31152 if (len == table->maxlen)
31153 len--;
31154 ((char *) table->data)[len] = 0;
31155 }
31156 return 0;
31157 }
31158
31159 /* This function makes sure that all of the integers in
31160 * the vector are between the minimum and maximum values
31161 * given in the arrays table->extra1 and table->extra2,
31162 * respectively. */
31163 int sysctl_intvec(ctl_table *table, int *name, int nlen,
31164 void *oldval, size_t *oldlenp,
31165 void *newval, size_t newlen, void **context)
31166 {
31167 int i, length, *vec, *min, *max;
31168
31169 if (newval && newlen) {
31170 if (newlen % sizeof(int) != 0)
31171 return -EINVAL;
31172
31173 if (!table->extra1 && !table->extra2)
31174 return 0;
31175
31176 if (newlen > table->maxlen)
31177 newlen = table->maxlen;
31178 length = newlen / sizeof(int);
31179
31180 vec = (int *) newval;
31181 min = (int *) table->extra1;
31182 max = (int *) table->extra2;
31183
31184 for (i = 0; i < length; i++) {
31185 int value;
31186 get_user(value, vec + i);
31187 if (min && value < min[i])
31188 return -EINVAL;
31189 if (max && value > max[i])
31190 return -EINVAL;
31191 }
31192 }
31193 return 0;
31194 }
31195
31196 int do_string (void *oldval, size_t *oldlenp,
31197 void *newval, size_t newlen,
31198 int rdwr, char *data, size_t max)
31199 {
31200 int l = strlen(data) + 1;
31201 if (newval && !rdwr)
31202 return -EPERM;
31203 if (newval && newlen >= max)
31204 return -EINVAL;
31205 if (oldval) {
31206 int old_l;
31207 if (get_user(old_l, oldlenp))
31208 return -EFAULT;
31209 if (l > old_l)
31210 return -ENOMEM;
31211 if (put_user(l, oldlenp) ||
31212 copy_to_user(oldval, data, l))
31213 return -EFAULT;
31214 }
31215 if (newval) {
31216 if (copy_from_user(data, newval, newlen))
31217 return -EFAULT;
31218 data[newlen] = 0;
31219 }
31220 return 0;
31221 }
31222
31223 int do_int (void *oldval, size_t *oldlenp,
31224 void *newval, size_t newlen,
31225 int rdwr, int *data)
31226 {
31227 if (newval && !rdwr)
31228 return -EPERM;
31229 if (newval && newlen != sizeof(int))
31230 return -EINVAL;
31231 if (oldval) {
31232 int old_l;
31233 if (get_user(old_l, oldlenp))
31234 return -EFAULT;
31235 if (old_l < sizeof(int))
31236 return -ENOMEM;
31237 if (put_user(sizeof(int), oldlenp) ||
31238 copy_to_user(oldval, data, sizeof(int)))
31239 return -EFAULT;
31240 }
31241 if (newval)
31242 if (copy_from_user(data, newval, sizeof(int)))
31243 return -EFAULT;
31244 return 0;
31245 }
31246
31247 int do_struct (void *oldval, size_t *oldlenp,
31248 void *newval, size_t newlen,
31249 int rdwr, void *data, size_t len)
31250 {
31251 if (newval && !rdwr)
31252 return -EPERM;
31253 if (newval && newlen != len)
31254 return -EINVAL;
31255 if (oldval) {
31256 int old_l;
31257 if (get_user(old_l, oldlenp))
31258 return -EFAULT;
31259 if (old_l < len)
31260 return -ENOMEM;
31261 if (put_user(len, oldlenp) ||
31262 copy_to_user(oldval, data, len))
31263 return -EFAULT;
31264 }
31265 if (newval)
31266 if (copy_from_user(data, newval, len))
31267 return -EFAULT;
31268 return 0;
31269 }
31270
31271
31272 #else /* CONFIG_SYSCTL */
31273
31274
31275 extern asmlinkage int sys_sysctl(
31276 struct __sysctl_args *args)
31277 {
31278 return -ENOSYS;
31279 }
31280
31281 int sysctl_string(ctl_table *table, int *name, int nlen,
31282 void *oldval, size_t *oldlenp,
31283 void *newval, size_t newlen, void **context)
31284 {
31285 return -ENOSYS;
31286 }
31287
31288 int sysctl_intvec(ctl_table *table, int *name, int nlen,
31289 void *oldval, size_t *oldlenp,
31290 void *newval, size_t newlen, void **context)
31291 {
31292 return -ENOSYS;
31293 }
31294
31295 int proc_dostring(ctl_table *table, int write,
31296 struct file *filp, void *buffer, size_t *lenp)
31297 {
31298 return -ENOSYS;
31299 }
31300
31301 int proc_dointvec(ctl_table *table, int write,
31302 struct file *filp, void *buffer, size_t *lenp)
31303 {
31304 return -ENOSYS;
31305 }
31306
31307 int proc_dointvec_minmax(ctl_table *table, int write,
31308 struct file *filp, void *buffer, size_t *lenp)
31309 {
31310 return -ENOSYS;
31311 }
31312
31313 int proc_dointvec_jiffies(ctl_table *table, int write,
31314 struct file *filp, void *buffer, size_t *lenp)
31315 {
31316 return -ENOSYS;
31317 }
31318
31319 struct ctl_table_header *
31320 register_sysctl_table(ctl_table *tbl, int insert_at_head)
31321 {
31322 return 0;
31323 }
31324
31325 void unregister_sysctl_table(
31326 struct ctl_table_header * table)
31327 {
31328 }
31329
31330 #endif /* CONFIG_SYSCTL */
Сайт управляется системой
uCoz