Ядро Linux в комментариях

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 */


Содержание раздела