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