proc: maps protection
[safe/jmp/linux-2.6] / kernel / sysctl.c
index b240e2c..f0664bd 100644 (file)
  *  Removed it and replaced it with older style, 03/23/00, Bill Wendling
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
 #include <linux/proc_fs.h>
+#include <linux/capability.h>
 #include <linux/ctype.h>
 #include <linux/utsname.h>
 #include <linux/capability.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/net.h>
 #include <linux/sysrq.h>
 #include <linux/highuid.h>
 #include <linux/writeback.h>
 #include <linux/limits.h>
 #include <linux/dcache.h>
 #include <linux/syscalls.h>
+#include <linux/nfs_fs.h>
+#include <linux/acpi.h>
 
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 
-#ifdef CONFIG_ROOT_NFS
-#include <linux/nfs_fs.h>
+extern int proc_nr_files(ctl_table *table, int write, struct file *filp,
+                     void __user *buffer, size_t *lenp, loff_t *ppos);
+
+#ifdef CONFIG_X86
+#include <asm/nmi.h>
+#include <asm/stacktrace.h>
 #endif
 
 #if defined(CONFIG_SYSCTL)
 extern int C_A_D;
 extern int sysctl_overcommit_memory;
 extern int sysctl_overcommit_ratio;
+extern int sysctl_panic_on_oom;
 extern int max_threads;
-extern int sysrq_enabled;
 extern int core_uses_pid;
 extern int suid_dumpable;
 extern char core_pattern[];
-extern int cad_pid;
 extern int pid_max;
 extern int min_free_kbytes;
 extern int printk_ratelimit_jiffies;
 extern int printk_ratelimit_burst;
 extern int pid_max_min, pid_max_max;
-
-#ifdef CONFIG_INOTIFY
-extern int inotify_max_user_devices;
-extern int inotify_max_user_watches;
-extern int inotify_max_queued_events;
-#endif
-
-#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
-int unknown_nmi_panic;
-extern int proc_unknown_nmi_panic(ctl_table *, int, struct file *,
-                                 void __user *, size_t *, loff_t *);
-#endif
+extern int sysctl_drop_caches;
+extern int percpu_pagelist_fraction;
+extern int compat_log;
+extern int maps_protect;
 
 /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
 static int maxolduid = 65535;
 static int minolduid;
+static int min_percpu_pagelist_fract = 8;
 
 static int ngroups_max = NGROUPS_MAX;
 
 #ifdef CONFIG_KMOD
 extern char modprobe_path[];
 #endif
-#ifdef CONFIG_HOTPLUG
-extern char hotplug_path[];
-#endif
 #ifdef CONFIG_CHR_DEV_SG
 extern int sg_big_buff;
 #endif
-#ifdef CONFIG_SYSVIPC
-extern size_t shm_ctlmax;
-extern size_t shm_ctlall;
-extern int shm_ctlmni;
-extern int msg_ctlmax;
-extern int msg_ctlmnb;
-extern int msg_ctlmni;
-extern int sem_ctls[];
-#endif
 
 #ifdef __sparc__
 extern char reboot_command [];
@@ -115,11 +103,12 @@ extern int pwrsw_enabled;
 extern int unaligned_enabled;
 #endif
 
-#ifdef CONFIG_ARCH_S390
+#ifdef CONFIG_S390
 #ifdef CONFIG_MATHEMU
 extern int sysctl_ieee_emulation_warnings;
 #endif
 extern int sysctl_userprocess_debug;
+extern int spin_retry;
 #endif
 
 extern int sysctl_hz_timer;
@@ -128,12 +117,26 @@ extern int sysctl_hz_timer;
 extern int acct_parm[];
 #endif
 
-int randomize_va_space = 1;
+#ifdef CONFIG_IA64
+extern int no_unaligned_warning;
+#endif
+
+#ifdef CONFIG_RT_MUTEXES
+extern int max_lock_depth;
+#endif
+
+#ifdef CONFIG_SYSCTL_SYSCALL
+static int parse_table(int __user *, int, void __user *, size_t __user *,
+               void __user *, size_t, ctl_table *);
+#endif
+
 
-static int parse_table(int __user *, int, void __user *, size_t __user *, void __user *, size_t,
-                      ctl_table *, void **);
-static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
+#ifdef CONFIG_PROC_SYSCTL
+static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
                  void __user *buffer, size_t *lenp, loff_t *ppos);
+static int proc_dointvec_taint(ctl_table *table, int write, struct file *filp,
+                              void __user *buffer, size_t *lenp, loff_t *ppos);
+#endif
 
 static ctl_table root_table[];
 static struct ctl_table_header root_table_header =
@@ -141,10 +144,6 @@ static struct ctl_table_header root_table_header =
 
 static ctl_table kern_table[];
 static ctl_table vm_table[];
-#ifdef CONFIG_NET
-extern ctl_table net_table[];
-#endif
-static ctl_table proc_table[];
 static ctl_table fs_table[];
 static ctl_table debug_table[];
 static ctl_table dev_table[];
@@ -152,30 +151,14 @@ extern ctl_table random_table[];
 #ifdef CONFIG_UNIX98_PTYS
 extern ctl_table pty_table[];
 #endif
+#ifdef CONFIG_INOTIFY_USER
+extern ctl_table inotify_table[];
+#endif
 
 #ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
 int sysctl_legacy_va_layout;
 #endif
 
-/* /proc declarations: */
-
-#ifdef CONFIG_PROC_FS
-
-static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *);
-static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *);
-static int proc_opensys(struct inode *, struct file *);
-
-struct file_operations proc_sys_file_operations = {
-       .open           = proc_opensys,
-       .read           = proc_readsys,
-       .write          = proc_writesys,
-};
-
-extern struct proc_dir_entry *proc_sys_root;
-
-static void register_proc_table(ctl_table *, struct proc_dir_entry *);
-static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
-#endif
 
 /* The default sysctl tables: */
 
@@ -201,12 +184,6 @@ static ctl_table root_table[] = {
        },
 #endif
        {
-               .ctl_name       = CTL_PROC,
-               .procname       = "proc",
-               .mode           = 0555,
-               .child          = proc_table,
-       },
-       {
                .ctl_name       = CTL_FS,
                .procname       = "fs",
                .mode           = 0555,
@@ -230,51 +207,6 @@ static ctl_table root_table[] = {
 
 static ctl_table kern_table[] = {
        {
-               .ctl_name       = KERN_OSTYPE,
-               .procname       = "ostype",
-               .data           = system_utsname.sysname,
-               .maxlen         = sizeof(system_utsname.sysname),
-               .mode           = 0444,
-               .proc_handler   = &proc_doutsstring,
-               .strategy       = &sysctl_string,
-       },
-       {
-               .ctl_name       = KERN_OSRELEASE,
-               .procname       = "osrelease",
-               .data           = system_utsname.release,
-               .maxlen         = sizeof(system_utsname.release),
-               .mode           = 0444,
-               .proc_handler   = &proc_doutsstring,
-               .strategy       = &sysctl_string,
-       },
-       {
-               .ctl_name       = KERN_VERSION,
-               .procname       = "version",
-               .data           = system_utsname.version,
-               .maxlen         = sizeof(system_utsname.version),
-               .mode           = 0444,
-               .proc_handler   = &proc_doutsstring,
-               .strategy       = &sysctl_string,
-       },
-       {
-               .ctl_name       = KERN_NODENAME,
-               .procname       = "hostname",
-               .data           = system_utsname.nodename,
-               .maxlen         = sizeof(system_utsname.nodename),
-               .mode           = 0644,
-               .proc_handler   = &proc_doutsstring,
-               .strategy       = &sysctl_string,
-       },
-       {
-               .ctl_name       = KERN_DOMAINNAME,
-               .procname       = "domainname",
-               .data           = system_utsname.domainname,
-               .maxlen         = sizeof(system_utsname.domainname),
-               .mode           = 0644,
-               .proc_handler   = &proc_doutsstring,
-               .strategy       = &sysctl_string,
-       },
-       {
                .ctl_name       = KERN_PANIC,
                .procname       = "panic",
                .data           = &panic_timeout,
@@ -294,19 +226,21 @@ static ctl_table kern_table[] = {
                .ctl_name       = KERN_CORE_PATTERN,
                .procname       = "core_pattern",
                .data           = core_pattern,
-               .maxlen         = 64,
+               .maxlen         = 128,
                .mode           = 0644,
                .proc_handler   = &proc_dostring,
                .strategy       = &sysctl_string,
        },
+#ifdef CONFIG_PROC_SYSCTL
        {
                .ctl_name       = KERN_TAINTED,
                .procname       = "tainted",
                .data           = &tainted,
                .maxlen         = sizeof(int),
-               .mode           = 0444,
-               .proc_handler   = &proc_dointvec,
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_taint,
        },
+#endif
        {
                .ctl_name       = KERN_CAP_BSET,
                .procname       = "cap-bound",
@@ -397,12 +331,12 @@ static ctl_table kern_table[] = {
                .strategy       = &sysctl_string,
        },
 #endif
-#ifdef CONFIG_HOTPLUG
+#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
        {
                .ctl_name       = KERN_HOTPLUG,
                .procname       = "hotplug",
-               .data           = &hotplug_path,
-               .maxlen         = HOTPLUG_PATH_LEN,
+               .data           = &uevent_helper,
+               .maxlen         = UEVENT_HELPER_PATH_LEN,
                .mode           = 0644,
                .proc_handler   = &proc_dostring,
                .strategy       = &sysctl_string,
@@ -428,82 +362,26 @@ static ctl_table kern_table[] = {
                .proc_handler   = &proc_dointvec,
        },
 #endif
-#ifdef CONFIG_SYSVIPC
-       {
-               .ctl_name       = KERN_SHMMAX,
-               .procname       = "shmmax",
-               .data           = &shm_ctlmax,
-               .maxlen         = sizeof (size_t),
-               .mode           = 0644,
-               .proc_handler   = &proc_doulongvec_minmax,
-       },
-       {
-               .ctl_name       = KERN_SHMALL,
-               .procname       = "shmall",
-               .data           = &shm_ctlall,
-               .maxlen         = sizeof (size_t),
-               .mode           = 0644,
-               .proc_handler   = &proc_doulongvec_minmax,
-       },
-       {
-               .ctl_name       = KERN_SHMMNI,
-               .procname       = "shmmni",
-               .data           = &shm_ctlmni,
-               .maxlen         = sizeof (int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec,
-       },
-       {
-               .ctl_name       = KERN_MSGMAX,
-               .procname       = "msgmax",
-               .data           = &msg_ctlmax,
-               .maxlen         = sizeof (int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec,
-       },
-       {
-               .ctl_name       = KERN_MSGMNI,
-               .procname       = "msgmni",
-               .data           = &msg_ctlmni,
-               .maxlen         = sizeof (int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec,
-       },
-       {
-               .ctl_name       = KERN_MSGMNB,
-               .procname       =  "msgmnb",
-               .data           = &msg_ctlmnb,
-               .maxlen         = sizeof (int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec,
-       },
-       {
-               .ctl_name       = KERN_SEM,
-               .procname       = "sem",
-               .data           = &sem_ctls,
-               .maxlen         = 4*sizeof (int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec,
-       },
-#endif
 #ifdef CONFIG_MAGIC_SYSRQ
        {
                .ctl_name       = KERN_SYSRQ,
                .procname       = "sysrq",
-               .data           = &sysrq_enabled,
+               .data           = &__sysrq_enabled,
                .maxlen         = sizeof (int),
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
        },
 #endif
+#ifdef CONFIG_PROC_SYSCTL
        {
                .ctl_name       = KERN_CADPID,
                .procname       = "cad_pid",
-               .data           = &cad_pid,
+               .data           = NULL,
                .maxlen         = sizeof (int),
                .mode           = 0600,
-               .proc_handler   = &proc_dointvec,
+               .proc_handler   = &proc_do_cad_pid,
        },
+#endif
        {
                .ctl_name       = KERN_MAX_THREADS,
                .procname       = "threads-max",
@@ -548,7 +426,7 @@ static ctl_table kern_table[] = {
                .extra1         = &minolduid,
                .extra2         = &maxolduid,
        },
-#ifdef CONFIG_ARCH_S390
+#ifdef CONFIG_S390
 #ifdef CONFIG_MATHEMU
        {
                .ctl_name       = KERN_IEEE_EMULATION_WARNINGS,
@@ -629,11 +507,27 @@ static ctl_table kern_table[] = {
                .data           = &unknown_nmi_panic,
                .maxlen         = sizeof (int),
                .mode           = 0644,
-               .proc_handler   = &proc_unknown_nmi_panic,
+               .proc_handler   = &proc_dointvec,
+       },
+       {
+               .ctl_name       = KERN_NMI_WATCHDOG,
+               .procname       = "nmi_watchdog",
+               .data           = &nmi_watchdog_enabled,
+               .maxlen         = sizeof (int),
+               .mode           = 0644,
+               .proc_handler   = &proc_nmi_enabled,
        },
 #endif
 #if defined(CONFIG_X86)
        {
+               .ctl_name       = KERN_PANIC_ON_NMI,
+               .procname       = "panic_on_unrecovered_nmi",
+               .data           = &panic_on_unrecovered_nmi,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
+       {
                .ctl_name       = KERN_BOOTLOADER_TYPE,
                .procname       = "bootloader_type",
                .data           = &bootloader_type,
@@ -641,7 +535,16 @@ static ctl_table kern_table[] = {
                .mode           = 0444,
                .proc_handler   = &proc_dointvec,
        },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "kstack_depth_to_print",
+               .data           = &kstack_depth_to_print,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
 #endif
+#if defined(CONFIG_MMU)
        {
                .ctl_name       = KERN_RANDOMIZE,
                .procname       = "randomize_va_space",
@@ -650,6 +553,67 @@ static ctl_table kern_table[] = {
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
        },
+#endif
+#if defined(CONFIG_S390) && defined(CONFIG_SMP)
+       {
+               .ctl_name       = KERN_SPIN_RETRY,
+               .procname       = "spin_retry",
+               .data           = &spin_retry,
+               .maxlen         = sizeof (int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
+#endif
+#ifdef CONFIG_ACPI_SLEEP
+       {
+               .ctl_name       = KERN_ACPI_VIDEO_FLAGS,
+               .procname       = "acpi_video_flags",
+               .data           = &acpi_video_flags,
+               .maxlen         = sizeof (unsigned long),
+               .mode           = 0644,
+               .proc_handler   = &proc_doulongvec_minmax,
+       },
+#endif
+#ifdef CONFIG_IA64
+       {
+               .ctl_name       = KERN_IA64_UNALIGNED,
+               .procname       = "ignore-unaligned-usertrap",
+               .data           = &no_unaligned_warning,
+               .maxlen         = sizeof (int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
+#endif
+#ifdef CONFIG_COMPAT
+       {
+               .ctl_name       = KERN_COMPAT_LOG,
+               .procname       = "compat-log",
+               .data           = &compat_log,
+               .maxlen         = sizeof (int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
+#endif
+#ifdef CONFIG_RT_MUTEXES
+       {
+               .ctl_name       = KERN_MAX_LOCK_DEPTH,
+               .procname       = "max_lock_depth",
+               .data           = &max_lock_depth,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
+#endif
+#ifdef CONFIG_PROC_FS
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "maps_protect",
+               .data           = &maps_protect,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
+#endif
 
        { .ctl_name = 0 }
 };
@@ -670,6 +634,14 @@ static ctl_table vm_table[] = {
                .proc_handler   = &proc_dointvec,
        },
        {
+               .ctl_name       = VM_PANIC_ON_OOM,
+               .procname       = "panic_on_oom",
+               .data           = &sysctl_panic_on_oom,
+               .maxlen         = sizeof(sysctl_panic_on_oom),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
+       {
                .ctl_name       = VM_OVERCOMMIT_RATIO,
                .procname       = "overcommit_ratio",
                .data           = &sysctl_overcommit_ratio,
@@ -710,18 +682,18 @@ static ctl_table vm_table[] = {
        {
                .ctl_name       = VM_DIRTY_WB_CS,
                .procname       = "dirty_writeback_centisecs",
-               .data           = &dirty_writeback_centisecs,
-               .maxlen         = sizeof(dirty_writeback_centisecs),
+               .data           = &dirty_writeback_interval,
+               .maxlen         = sizeof(dirty_writeback_interval),
                .mode           = 0644,
                .proc_handler   = &dirty_writeback_centisecs_handler,
        },
        {
                .ctl_name       = VM_DIRTY_EXPIRE_CS,
                .procname       = "dirty_expire_centisecs",
-               .data           = &dirty_expire_centisecs,
-               .maxlen         = sizeof(dirty_expire_centisecs),
+               .data           = &dirty_expire_interval,
+               .maxlen         = sizeof(dirty_expire_interval),
                .mode           = 0644,
-               .proc_handler   = &proc_dointvec,
+               .proc_handler   = &proc_dointvec_userhz_jiffies,
        },
        {
                .ctl_name       = VM_NR_PDFLUSH_THREADS,
@@ -772,6 +744,15 @@ static ctl_table vm_table[] = {
                .strategy       = &sysctl_intvec,
        },
        {
+               .ctl_name       = VM_DROP_PAGECACHE,
+               .procname       = "drop_caches",
+               .data           = &sysctl_drop_caches,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = drop_caches_sysctl_handler,
+               .strategy       = &sysctl_intvec,
+       },
+       {
                .ctl_name       = VM_MIN_FREE_KBYTES,
                .procname       = "min_free_kbytes",
                .data           = &min_free_kbytes,
@@ -781,6 +762,16 @@ static ctl_table vm_table[] = {
                .strategy       = &sysctl_intvec,
                .extra1         = &zero,
        },
+       {
+               .ctl_name       = VM_PERCPU_PAGELIST_FRACTION,
+               .procname       = "percpu_pagelist_fraction",
+               .data           = &percpu_pagelist_fraction,
+               .maxlen         = sizeof(percpu_pagelist_fraction),
+               .mode           = 0644,
+               .proc_handler   = &percpu_pagelist_fraction_sysctl_handler,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &min_percpu_pagelist_fract,
+       },
 #ifdef CONFIG_MMU
        {
                .ctl_name       = VM_MAX_MAP_COUNT,
@@ -797,9 +788,8 @@ static ctl_table vm_table[] = {
                .data           = &laptop_mode,
                .maxlen         = sizeof(laptop_mode),
                .mode           = 0644,
-               .proc_handler   = &proc_dointvec,
-               .strategy       = &sysctl_intvec,
-               .extra1         = &zero,
+               .proc_handler   = &proc_dointvec_jiffies,
+               .strategy       = &sysctl_jiffies,
        },
        {
                .ctl_name       = VM_BLOCK_DUMP,
@@ -833,23 +823,61 @@ static ctl_table vm_table[] = {
                .extra1         = &zero,
        },
 #endif
-#ifdef CONFIG_SWAP
+#ifdef CONFIG_NUMA
        {
-               .ctl_name       = VM_SWAP_TOKEN_TIMEOUT,
-               .procname       = "swap_token_timeout",
-               .data           = &swap_token_default_timeout,
-               .maxlen         = sizeof(swap_token_default_timeout),
+               .ctl_name       = VM_ZONE_RECLAIM_MODE,
+               .procname       = "zone_reclaim_mode",
+               .data           = &zone_reclaim_mode,
+               .maxlen         = sizeof(zone_reclaim_mode),
                .mode           = 0644,
-               .proc_handler   = &proc_dointvec_jiffies,
-               .strategy       = &sysctl_jiffies,
+               .proc_handler   = &proc_dointvec,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &zero,
+       },
+       {
+               .ctl_name       = VM_MIN_UNMAPPED,
+               .procname       = "min_unmapped_ratio",
+               .data           = &sysctl_min_unmapped_ratio,
+               .maxlen         = sizeof(sysctl_min_unmapped_ratio),
+               .mode           = 0644,
+               .proc_handler   = &sysctl_min_unmapped_ratio_sysctl_handler,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &zero,
+               .extra2         = &one_hundred,
+       },
+       {
+               .ctl_name       = VM_MIN_SLAB,
+               .procname       = "min_slab_ratio",
+               .data           = &sysctl_min_slab_ratio,
+               .maxlen         = sizeof(sysctl_min_slab_ratio),
+               .mode           = 0644,
+               .proc_handler   = &sysctl_min_slab_ratio_sysctl_handler,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &zero,
+               .extra2         = &one_hundred,
+       },
+#endif
+#if defined(CONFIG_X86_32) || \
+   (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL))
+       {
+               .ctl_name       = VM_VDSO_ENABLED,
+               .procname       = "vdso_enabled",
+               .data           = &vdso_enabled,
+               .maxlen         = sizeof(vdso_enabled),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &zero,
        },
 #endif
        { .ctl_name = 0 }
 };
 
-static ctl_table proc_table[] = {
+#if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
+static ctl_table binfmt_misc_table[] = {
        { .ctl_name = 0 }
 };
+#endif
 
 static ctl_table fs_table[] = {
        {
@@ -874,7 +902,7 @@ static ctl_table fs_table[] = {
                .data           = &files_stat,
                .maxlen         = 3*sizeof(int),
                .mode           = 0444,
-               .proc_handler   = &proc_dointvec,
+               .proc_handler   = &proc_nr_files,
        },
        {
                .ctl_name       = FS_MAXFILE,
@@ -947,7 +975,7 @@ static ctl_table fs_table[] = {
                .data           = &aio_nr,
                .maxlen         = sizeof(aio_nr),
                .mode           = 0444,
-               .proc_handler   = &proc_dointvec,
+               .proc_handler   = &proc_doulongvec_minmax,
        },
        {
                .ctl_name       = FS_AIO_MAX_NR,
@@ -955,8 +983,16 @@ static ctl_table fs_table[] = {
                .data           = &aio_max_nr,
                .maxlen         = sizeof(aio_max_nr),
                .mode           = 0644,
-               .proc_handler   = &proc_dointvec,
+               .proc_handler   = &proc_doulongvec_minmax,
        },
+#ifdef CONFIG_INOTIFY_USER
+       {
+               .ctl_name       = FS_INOTIFY,
+               .procname       = "inotify",
+               .mode           = 0555,
+               .child          = inotify_table,
+       },
+#endif 
 #endif
        {
                .ctl_name       = KERN_SETUID_DUMPABLE,
@@ -966,38 +1002,12 @@ static ctl_table fs_table[] = {
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
        },
-#ifdef CONFIG_INOTIFY
-       {
-               .ctl_name       = INOTIFY_MAX_USER_DEVICES,
-               .procname       = "max_user_devices",
-               .data           = &inotify_max_user_devices,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec_minmax,
-               .strategy       = &sysctl_intvec,
-               .extra1         = &zero,
-       },
-
-       {
-               .ctl_name       = INOTIFY_MAX_USER_WATCHES,
-               .procname       = "max_user_watches",
-               .data           = &inotify_max_user_watches,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = &proc_dointvec_minmax,
-               .strategy       = &sysctl_intvec,
-               .extra1         = &zero, 
-       },
-
+#if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)
        {
-               .ctl_name       = INOTIFY_MAX_QUEUED_EVENTS,
-               .procname       = "max_queued_events",
-               .data           = &inotify_max_queued_events,
-               .maxlen         = sizeof(int),
-               .mode           = 0644, 
-               .proc_handler   = &proc_dointvec_minmax,
-               .strategy       = &sysctl_intvec, 
-               .extra1         = &zero
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "binfmt_misc",
+               .mode           = 0555,
+               .child          = binfmt_misc_table,
        },
 #endif
        { .ctl_name = 0 }
@@ -1011,20 +1021,89 @@ static ctl_table dev_table[] = {
        { .ctl_name = 0 }
 };
 
-extern void init_irq_proc (void);
+static DEFINE_SPINLOCK(sysctl_lock);
 
-void __init sysctl_init(void)
+/* called under sysctl_lock */
+static int use_table(struct ctl_table_header *p)
 {
-#ifdef CONFIG_PROC_FS
-       register_proc_table(root_table, proc_sys_root);
-       init_irq_proc();
-#endif
+       if (unlikely(p->unregistering))
+               return 0;
+       p->used++;
+       return 1;
+}
+
+/* called under sysctl_lock */
+static void unuse_table(struct ctl_table_header *p)
+{
+       if (!--p->used)
+               if (unlikely(p->unregistering))
+                       complete(p->unregistering);
+}
+
+/* called under sysctl_lock, will reacquire if has to wait */
+static void start_unregistering(struct ctl_table_header *p)
+{
+       /*
+        * if p->used is 0, nobody will ever touch that entry again;
+        * we'll eliminate all paths to it before dropping sysctl_lock
+        */
+       if (unlikely(p->used)) {
+               struct completion wait;
+               init_completion(&wait);
+               p->unregistering = &wait;
+               spin_unlock(&sysctl_lock);
+               wait_for_completion(&wait);
+               spin_lock(&sysctl_lock);
+       }
+       /*
+        * do not remove from the list until nobody holds it; walking the
+        * list in do_sysctl() relies on that.
+        */
+       list_del_init(&p->ctl_entry);
 }
 
+void sysctl_head_finish(struct ctl_table_header *head)
+{
+       if (!head)
+               return;
+       spin_lock(&sysctl_lock);
+       unuse_table(head);
+       spin_unlock(&sysctl_lock);
+}
+
+struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev)
+{
+       struct ctl_table_header *head;
+       struct list_head *tmp;
+       spin_lock(&sysctl_lock);
+       if (prev) {
+               tmp = &prev->ctl_entry;
+               unuse_table(prev);
+               goto next;
+       }
+       tmp = &root_table_header.ctl_entry;
+       for (;;) {
+               head = list_entry(tmp, struct ctl_table_header, ctl_entry);
+
+               if (!use_table(head))
+                       goto next;
+               spin_unlock(&sysctl_lock);
+               return head;
+       next:
+               tmp = tmp->next;
+               if (tmp == &root_table_header.ctl_entry)
+                       break;
+       }
+       spin_unlock(&sysctl_lock);
+       return NULL;
+}
+
+#ifdef CONFIG_SYSCTL_SYSCALL
 int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
               void __user *newval, size_t newlen)
 {
-       struct list_head *tmp;
+       struct ctl_table_header *head;
+       int error = -ENOTDIR;
 
        if (nlen <= 0 || nlen >= CTL_MAXNAME)
                return -ENOTDIR;
@@ -1033,20 +1112,17 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol
                if (!oldlenp || get_user(old_len, oldlenp))
                        return -EFAULT;
        }
-       tmp = &root_table_header.ctl_entry;
-       do {
-               struct ctl_table_header *head =
-                       list_entry(tmp, struct ctl_table_header, ctl_entry);
-               void *context = NULL;
-               int error = parse_table(name, nlen, oldval, oldlenp, 
-                                       newval, newlen, head->ctl_table,
-                                       &context);
-               kfree(context);
-               if (error != -ENOTDIR)
-                       return error;
-               tmp = tmp->next;
-       } while (tmp != &root_table_header.ctl_entry);
-       return -ENOTDIR;
+
+       for (head = sysctl_head_next(NULL); head;
+                       head = sysctl_head_next(head)) {
+               error = parse_table(name, nlen, oldval, oldlenp, 
+                                       newval, newlen, head->ctl_table);
+               if (error != -ENOTDIR) {
+                       sysctl_head_finish(head);
+                       break;
+               }
+       }
+       return error;
 }
 
 asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
@@ -1063,9 +1139,10 @@ asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
        unlock_kernel();
        return error;
 }
+#endif /* CONFIG_SYSCTL_SYSCALL */
 
 /*
- * ctl_perm does NOT grant the superuser all rights automatically, because
+ * sysctl_perm does NOT grant the superuser all rights automatically, because
  * some sysctl variables are readonly even to root.
  */
 
@@ -1080,7 +1157,7 @@ static int test_perm(int mode, int op)
        return -EACCES;
 }
 
-static inline int ctl_perm(ctl_table *table, int op)
+int sysctl_perm(ctl_table *table, int op)
 {
        int error;
        error = security_sysctl(table, op);
@@ -1089,10 +1166,11 @@ static inline int ctl_perm(ctl_table *table, int op)
        return test_perm(table->mode, op);
 }
 
+#ifdef CONFIG_SYSCTL_SYSCALL
 static int parse_table(int __user *name, int nlen,
                       void __user *oldval, size_t __user *oldlenp,
                       void __user *newval, size_t newlen,
-                      ctl_table *table, void **context)
+                      ctl_table *table)
 {
        int n;
 repeat:
@@ -1100,20 +1178,14 @@ repeat:
                return -ENOTDIR;
        if (get_user(n, name))
                return -EFAULT;
-       for ( ; table->ctl_name; table++) {
-               if (n == table->ctl_name || table->ctl_name == CTL_ANY) {
+       for ( ; table->ctl_name || table->procname; table++) {
+               if (!table->ctl_name)
+                       continue;
+               if (n == table->ctl_name) {
                        int error;
                        if (table->child) {
-                               if (ctl_perm(table, 001))
+                               if (sysctl_perm(table, 001))
                                        return -EPERM;
-                               if (table->strategy) {
-                                       error = table->strategy(
-                                               table, name, nlen,
-                                               oldval, oldlenp,
-                                               newval, newlen, context);
-                                       if (error)
-                                               return error;
-                               }
                                name++;
                                nlen--;
                                table = table->child;
@@ -1121,7 +1193,7 @@ repeat:
                        }
                        error = do_sysctl_strategy(table, name, nlen,
                                                   oldval, oldlenp,
-                                                  newval, newlen, context);
+                                                  newval, newlen);
                        return error;
                }
        }
@@ -1132,7 +1204,7 @@ repeat:
 int do_sysctl_strategy (ctl_table *table, 
                        int __user *name, int nlen,
                        void __user *oldval, size_t __user *oldlenp,
-                       void __user *newval, size_t newlen, void **context)
+                       void __user *newval, size_t newlen)
 {
        int op = 0, rc;
        size_t len;
@@ -1141,12 +1213,12 @@ int do_sysctl_strategy (ctl_table *table,
                op |= 004;
        if (newval) 
                op |= 002;
-       if (ctl_perm(table, op))
+       if (sysctl_perm(table, op))
                return -EPERM;
 
        if (table->strategy) {
                rc = table->strategy(table, name, nlen, oldval, oldlenp,
-                                    newval, newlen, context);
+                                    newval, newlen);
                if (rc < 0)
                        return rc;
                if (rc > 0)
@@ -1178,11 +1250,28 @@ int do_sysctl_strategy (ctl_table *table,
        }
        return 0;
 }
+#endif /* CONFIG_SYSCTL_SYSCALL */
+
+static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table)
+{
+       for (; table->ctl_name || table->procname; table++) {
+               table->parent = parent;
+               if (table->child)
+                       sysctl_set_parent(table, table->child);
+       }
+}
+
+static __init int sysctl_init(void)
+{
+       sysctl_set_parent(NULL, root_table);
+       return 0;
+}
+
+core_initcall(sysctl_init);
 
 /**
  * register_sysctl_table - register a sysctl hierarchy
  * @table: the top-level table structure
- * @insert_at_head: whether the entry should be inserted in front or at the end
  *
  * Register a sysctl table hierarchy. @table should be a filled in ctl_table
  * array. An entry with a ctl_name of 0 terminates the table. 
@@ -1248,8 +1337,7 @@ int do_sysctl_strategy (ctl_table *table,
  * This routine returns %NULL on a failure to register, and a pointer
  * to the table header on success.
  */
-struct ctl_table_header *register_sysctl_table(ctl_table * table, 
-                                              int insert_at_head)
+struct ctl_table_header *register_sysctl_table(ctl_table * table)
 {
        struct ctl_table_header *tmp;
        tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL);
@@ -1257,13 +1345,12 @@ struct ctl_table_header *register_sysctl_table(ctl_table * table,
                return NULL;
        tmp->ctl_table = table;
        INIT_LIST_HEAD(&tmp->ctl_entry);
-       if (insert_at_head)
-               list_add(&tmp->ctl_entry, &root_table_header.ctl_entry);
-       else
-               list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
-#ifdef CONFIG_PROC_FS
-       register_proc_table(table, proc_sys_root);
-#endif
+       tmp->used = 0;
+       tmp->unregistering = NULL;
+       sysctl_set_parent(NULL, table);
+       spin_lock(&sysctl_lock);
+       list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
+       spin_unlock(&sysctl_lock);
        return tmp;
 }
 
@@ -1276,180 +1363,44 @@ struct ctl_table_header *register_sysctl_table(ctl_table * table,
  */
 void unregister_sysctl_table(struct ctl_table_header * header)
 {
-       list_del(&header->ctl_entry);
-#ifdef CONFIG_PROC_FS
-       unregister_proc_table(header->ctl_table, proc_sys_root);
-#endif
+       might_sleep();
+       spin_lock(&sysctl_lock);
+       start_unregistering(header);
+       spin_unlock(&sysctl_lock);
        kfree(header);
 }
 
-/*
- * /proc/sys support
- */
-
-#ifdef CONFIG_PROC_FS
-
-/* Scan the sysctl entries in table and add them all into /proc */
-static void register_proc_table(ctl_table * table, struct proc_dir_entry *root)
-{
-       struct proc_dir_entry *de;
-       int len;
-       mode_t mode;
-       
-       for (; table->ctl_name; table++) {
-               /* Can't do anything without a proc name. */
-               if (!table->procname)
-                       continue;
-               /* Maybe we can't do anything with it... */
-               if (!table->proc_handler && !table->child) {
-                       printk(KERN_WARNING "SYSCTL: Can't register %s\n",
-                               table->procname);
-                       continue;
-               }
-
-               len = strlen(table->procname);
-               mode = table->mode;
-
-               de = NULL;
-               if (table->proc_handler)
-                       mode |= S_IFREG;
-               else {
-                       mode |= S_IFDIR;
-                       for (de = root->subdir; de; de = de->next) {
-                               if (proc_match(len, table->procname, de))
-                                       break;
-                       }
-                       /* If the subdir exists already, de is non-NULL */
-               }
-
-               if (!de) {
-                       de = create_proc_entry(table->procname, mode, root);
-                       if (!de)
-                               continue;
-                       de->data = (void *) table;
-                       if (table->proc_handler)
-                               de->proc_fops = &proc_sys_file_operations;
-               }
-               table->de = de;
-               if (de->mode & S_IFDIR)
-                       register_proc_table(table->child, de);
-       }
-}
-
-/*
- * Unregister a /proc sysctl table and any subdirectories.
- */
-static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root)
+#else /* !CONFIG_SYSCTL */
+struct ctl_table_header *register_sysctl_table(ctl_table * table)
 {
-       struct proc_dir_entry *de;
-       for (; table->ctl_name; table++) {
-               if (!(de = table->de))
-                       continue;
-               if (de->mode & S_IFDIR) {
-                       if (!table->child) {
-                               printk (KERN_ALERT "Help - malformed sysctl tree on free\n");
-                               continue;
-                       }
-                       unregister_proc_table(table->child, de);
-
-                       /* Don't unregister directories which still have entries.. */
-                       if (de->subdir)
-                               continue;
-               }
-
-               /* Don't unregister proc entries that are still being used.. */
-               if (atomic_read(&de->count))
-                       continue;
-
-               table->de = NULL;
-               remove_proc_entry(table->procname, root);
-       }
+       return NULL;
 }
 
-static ssize_t do_rw_proc(int write, struct file * file, char __user * buf,
-                         size_t count, loff_t *ppos)
+void unregister_sysctl_table(struct ctl_table_header * table)
 {
-       int op;
-       struct proc_dir_entry *de;
-       struct ctl_table *table;
-       size_t res;
-       ssize_t error;
-       
-       de = PDE(file->f_dentry->d_inode);
-       if (!de || !de->data)
-               return -ENOTDIR;
-       table = (struct ctl_table *) de->data;
-       if (!table || !table->proc_handler)
-               return -ENOTDIR;
-       op = (write ? 002 : 004);
-       if (ctl_perm(table, op))
-               return -EPERM;
-       
-       res = count;
-
-       error = (*table->proc_handler) (table, write, file, buf, &res, ppos);
-       if (error)
-               return error;
-       return res;
 }
 
-static int proc_opensys(struct inode *inode, struct file *file)
-{
-       if (file->f_mode & FMODE_WRITE) {
-               /*
-                * sysctl entries that are not writable,
-                * are _NOT_ writable, capabilities or not.
-                */
-               if (!(inode->i_mode & S_IWUSR))
-                       return -EPERM;
-       }
-
-       return 0;
-}
+#endif /* CONFIG_SYSCTL */
 
-static ssize_t proc_readsys(struct file * file, char __user * buf,
-                           size_t count, loff_t *ppos)
-{
-       return do_rw_proc(0, file, buf, count, ppos);
-}
+/*
+ * /proc/sys support
+ */
 
-static ssize_t proc_writesys(struct file * file, const char __user * buf,
-                            size_t count, loff_t *ppos)
-{
-       return do_rw_proc(1, file, (char __user *) buf, count, ppos);
-}
+#ifdef CONFIG_PROC_SYSCTL
 
-/**
- * proc_dostring - read a string sysctl
- * @table: the sysctl table
- * @write: %TRUE if this is a write to the sysctl file
- * @filp: the file structure
- * @buffer: the user buffer
- * @lenp: the size of the user buffer
- * @ppos: file position
- *
- * Reads/writes a string from/to the user buffer. If the kernel
- * buffer provided is not large enough to hold the string, the
- * string is truncated. The copied string is %NULL-terminated.
- * If the string is being read by the user process, it is copied
- * and a newline '\n' is added. It is truncated if the buffer is
- * not large enough.
- *
- * Returns 0 on success.
- */
-int proc_dostring(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp, loff_t *ppos)
+static int _proc_do_string(void* data, int maxlen, int write,
+                          struct file *filp, void __user *buffer,
+                          size_t *lenp, loff_t *ppos)
 {
        size_t len;
        char __user *p;
        char c;
-       
-       if (!table->data || !table->maxlen || !*lenp ||
-           (*ppos && !write)) {
+
+       if (!data || !maxlen || !*lenp) {
                *lenp = 0;
                return 0;
        }
-       
+
        if (write) {
                len = 0;
                p = buffer;
@@ -1460,20 +1411,29 @@ int proc_dostring(ctl_table *table, int write, struct file *filp,
                                break;
                        len++;
                }
-               if (len >= table->maxlen)
-                       len = table->maxlen-1;
-               if(copy_from_user(table->data, buffer, len))
+               if (len >= maxlen)
+                       len = maxlen-1;
+               if(copy_from_user(data, buffer, len))
                        return -EFAULT;
-               ((char *) table->data)[len] = 0;
+               ((char *) data)[len] = 0;
                *ppos += *lenp;
        } else {
-               len = strlen(table->data);
-               if (len > table->maxlen)
-                       len = table->maxlen;
+               len = strlen(data);
+               if (len > maxlen)
+                       len = maxlen;
+
+               if (*ppos > len) {
+                       *lenp = 0;
+                       return 0;
+               }
+
+               data += *ppos;
+               len  -= *ppos;
+
                if (len > *lenp)
                        len = *lenp;
                if (len)
-                       if(copy_to_user(buffer, table->data, len))
+                       if(copy_to_user(buffer, data, len))
                                return -EFAULT;
                if (len < *lenp) {
                        if(put_user('\n', ((char __user *) buffer) + len))
@@ -1486,28 +1446,32 @@ int proc_dostring(ctl_table *table, int write, struct file *filp,
        return 0;
 }
 
-/*
- *     Special case of dostring for the UTS structure. This has locks
- *     to observe. Should this be in kernel/sys.c ????
+/**
+ * proc_dostring - read a string sysctl
+ * @table: the sysctl table
+ * @write: %TRUE if this is a write to the sysctl file
+ * @filp: the file structure
+ * @buffer: the user buffer
+ * @lenp: the size of the user buffer
+ * @ppos: file position
+ *
+ * Reads/writes a string from/to the user buffer. If the kernel
+ * buffer provided is not large enough to hold the string, the
+ * string is truncated. The copied string is %NULL-terminated.
+ * If the string is being read by the user process, it is copied
+ * and a newline '\n' is added. It is truncated if the buffer is
+ * not large enough.
+ *
+ * Returns 0 on success.
  */
-static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
+int proc_dostring(ctl_table *table, int write, struct file *filp,
                  void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-       int r;
-
-       if (!write) {
-               down_read(&uts_sem);
-               r=proc_dostring(table,0,filp,buffer,lenp, ppos);
-               up_read(&uts_sem);
-       } else {
-               down_write(&uts_sem);
-               r=proc_dostring(table,1,filp,buffer,lenp, ppos);
-               up_write(&uts_sem);
-       }
-       return r;
+       return _proc_do_string(table->data, table->maxlen, write, filp,
+                              buffer, lenp, ppos);
 }
 
+
 static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp,
                                 int *valp,
                                 int write, void *data)
@@ -1527,8 +1491,9 @@ static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp,
        return 0;
 }
 
-static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp, loff_t *ppos,
+static int __do_proc_dointvec(void *tbl_data, ctl_table *table,
+                 int write, struct file *filp, void __user *buffer,
+                 size_t *lenp, loff_t *ppos,
                  int (*conv)(int *negp, unsigned long *lvalp, int *valp,
                              int write, void *data),
                  void *data)
@@ -1541,13 +1506,13 @@ static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
        char buf[TMPBUFLEN], *p;
        char __user *s = buffer;
        
-       if (!table->data || !table->maxlen || !*lenp ||
+       if (!tbl_data || !table->maxlen || !*lenp ||
            (*ppos && !write)) {
                *lenp = 0;
                return 0;
        }
        
-       i = (int *) table->data;
+       i = (int *) tbl_data;
        vleft = table->maxlen / sizeof(*i);
        left = *lenp;
 
@@ -1577,7 +1542,7 @@ static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
                        p = buf;
                        if (*p == '-' && left > 1) {
                                neg = 1;
-                               left--, p++;
+                               p++;
                        }
                        if (*p < '0' || *p > '9')
                                break;
@@ -1636,6 +1601,16 @@ static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
 #undef TMPBUFLEN
 }
 
+static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
+                 void __user *buffer, size_t *lenp, loff_t *ppos,
+                 int (*conv)(int *negp, unsigned long *lvalp, int *valp,
+                             int write, void *data),
+                 void *data)
+{
+       return __do_proc_dointvec(table->data, table, write, filp,
+                       buffer, lenp, ppos, conv, data);
+}
+
 /**
  * proc_dointvec - read a vector of integers
  * @table: the sysctl table
@@ -1660,8 +1635,6 @@ int proc_dointvec(ctl_table *table, int write, struct file *filp,
 #define OP_SET 0
 #define OP_AND 1
 #define OP_OR  2
-#define OP_MAX 3
-#define OP_MIN 4
 
 static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
                                      int *valp,
@@ -1674,12 +1647,6 @@ static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
                case OP_SET:    *valp = val; break;
                case OP_AND:    *valp &= val; break;
                case OP_OR:     *valp |= val; break;
-               case OP_MAX:    if(*valp < val)
-                                       *valp = val;
-                               break;
-               case OP_MIN:    if(*valp > val)
-                               *valp = val;
-                               break;
                }
        } else {
                int val = *valp;
@@ -1703,11 +1670,27 @@ int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
 {
        int op;
 
-       if (!capable(CAP_SYS_MODULE)) {
+       if (write && !capable(CAP_SYS_MODULE)) {
                return -EPERM;
        }
 
-       op = (current->pid == 1) ? OP_SET : OP_AND;
+       op = is_init(current) ? OP_SET : OP_AND;
+       return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
+                               do_proc_dointvec_bset_conv,&op);
+}
+
+/*
+ *     Taint values can only be increased
+ */
+static int proc_dointvec_taint(ctl_table *table, int write, struct file *filp,
+                              void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       int op;
+
+       if (write && !capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       op = OP_OR;
        return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
                                do_proc_dointvec_bset_conv,&op);
 }
@@ -1769,7 +1752,7 @@ int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
                                do_proc_dointvec_minmax_conv, &param);
 }
 
-static int do_proc_doulongvec_minmax(ctl_table *table, int write,
+static int __do_proc_doulongvec_minmax(void *data, ctl_table *table, int write,
                                     struct file *filp,
                                     void __user *buffer,
                                     size_t *lenp, loff_t *ppos,
@@ -1783,13 +1766,13 @@ static int do_proc_doulongvec_minmax(ctl_table *table, int write,
        char buf[TMPBUFLEN], *p;
        char __user *s = buffer;
        
-       if (!table->data || !table->maxlen || !*lenp ||
+       if (!data || !table->maxlen || !*lenp ||
            (*ppos && !write)) {
                *lenp = 0;
                return 0;
        }
        
-       i = (unsigned long *) table->data;
+       i = (unsigned long *) data;
        min = (unsigned long *) table->extra1;
        max = (unsigned long *) table->extra2;
        vleft = table->maxlen / sizeof(unsigned long);
@@ -1818,7 +1801,7 @@ static int do_proc_doulongvec_minmax(ctl_table *table, int write,
                        p = buf;
                        if (*p == '-' && left > 1) {
                                neg = 1;
-                               left--, p++;
+                               p++;
                        }
                        if (*p < '0' || *p > '9')
                                break;
@@ -1874,6 +1857,17 @@ static int do_proc_doulongvec_minmax(ctl_table *table, int write,
 #undef TMPBUFLEN
 }
 
+static int do_proc_doulongvec_minmax(ctl_table *table, int write,
+                                    struct file *filp,
+                                    void __user *buffer,
+                                    size_t *lenp, loff_t *ppos,
+                                    unsigned long convmul,
+                                    unsigned long convdiv)
+{
+       return __do_proc_doulongvec_minmax(table->data, table, write,
+                       filp, buffer, lenp, ppos, convmul, convdiv);
+}
+
 /**
  * proc_doulongvec_minmax - read a vector of long integers with min/max values
  * @table: the sysctl table
@@ -1930,6 +1924,8 @@ static int do_proc_dointvec_jiffies_conv(int *negp, unsigned long *lvalp,
                                         int write, void *data)
 {
        if (write) {
+               if (*lvalp > LONG_MAX / HZ)
+                       return 1;
                *valp = *negp ? -(*lvalp*HZ) : (*lvalp*HZ);
        } else {
                int val = *valp;
@@ -1951,6 +1947,8 @@ static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp,
                                                int write, void *data)
 {
        if (write) {
+               if (USER_HZ < HZ && *lvalp > (LONG_MAX / HZ) * USER_HZ)
+                       return 1;
                *valp = clock_t_to_jiffies(*negp ? -*lvalp : *lvalp);
        } else {
                int val = *valp;
@@ -2018,6 +2016,7 @@ int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
  * @filp: the file structure
  * @buffer: the user buffer
  * @lenp: the size of the user buffer
+ * @ppos: pointer to the file position
  *
  * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
  * values from/to the user buffer, treated as an ASCII string. 
@@ -2057,6 +2056,28 @@ int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
                                do_proc_dointvec_ms_jiffies_conv, NULL);
 }
 
+static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
+                          void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       struct pid *new_pid;
+       pid_t tmp;
+       int r;
+
+       tmp = pid_nr(cad_pid);
+
+       r = __do_proc_dointvec(&tmp, table, write, filp, buffer,
+                              lenp, ppos, NULL, NULL);
+       if (r || !write)
+               return r;
+
+       new_pid = find_get_pid(tmp);
+       if (!new_pid)
+               return -ESRCH;
+
+       put_pid(xchg(&cad_pid, new_pid));
+       return 0;
+}
+
 #else /* CONFIG_PROC_FS */
 
 int proc_dostring(ctl_table *table, int write, struct file *filp,
@@ -2065,12 +2086,6 @@ int proc_dostring(ctl_table *table, int write, struct file *filp,
        return -ENOSYS;
 }
 
-static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
-                           void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
 int proc_dointvec(ctl_table *table, int write, struct file *filp,
                  void __user *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -2125,6 +2140,7 @@ int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
 #endif /* CONFIG_PROC_FS */
 
 
+#ifdef CONFIG_SYSCTL_SYSCALL
 /*
  * General sysctl support routines 
  */
@@ -2132,31 +2148,34 @@ int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
 /* The generic string strategy routine: */
 int sysctl_string(ctl_table *table, int __user *name, int nlen,
                  void __user *oldval, size_t __user *oldlenp,
-                 void __user *newval, size_t newlen, void **context)
+                 void __user *newval, size_t newlen)
 {
-       size_t l, len;
-       
        if (!table->data || !table->maxlen) 
                return -ENOTDIR;
        
        if (oldval && oldlenp) {
-               if (get_user(len, oldlenp))
+               size_t bufsize;
+               if (get_user(bufsize, oldlenp))
                        return -EFAULT;
-               if (len) {
-                       l = strlen(table->data);
-                       if (len > l) len = l;
-                       if (len >= table->maxlen)
+               if (bufsize) {
+                       size_t len = strlen(table->data), copied;
+
+                       /* This shouldn't trigger for a well-formed sysctl */
+                       if (len > table->maxlen)
                                len = table->maxlen;
-                       if(copy_to_user(oldval, table->data, len))
-                               return -EFAULT;
-                       if(put_user(0, ((char __user *) oldval) + len))
+
+                       /* Copy up to a max of bufsize-1 bytes of the string */
+                       copied = (len >= bufsize) ? bufsize - 1 : len;
+
+                       if (copy_to_user(oldval, table->data, copied) ||
+                           put_user(0, (char __user *)(oldval + copied)))
                                return -EFAULT;
-                       if(put_user(len, oldlenp))
+                       if (put_user(len, oldlenp))
                                return -EFAULT;
                }
        }
        if (newval && newlen) {
-               len = newlen;
+               size_t len = newlen;
                if (len > table->maxlen)
                        len = table->maxlen;
                if(copy_from_user(table->data, newval, len))
@@ -2165,7 +2184,7 @@ int sysctl_string(ctl_table *table, int __user *name, int nlen,
                        len--;
                ((char *) table->data)[len] = 0;
        }
-       return 0;
+       return 1;
 }
 
 /*
@@ -2175,7 +2194,7 @@ int sysctl_string(ctl_table *table, int __user *name, int nlen,
  */
 int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context)
+               void __user *newval, size_t newlen)
 {
 
        if (newval && newlen) {
@@ -2211,19 +2230,25 @@ int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
 /* Strategy function to convert jiffies to seconds */ 
 int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context)
+               void __user *newval, size_t newlen)
 {
-       if (oldval) {
+       if (oldval && oldlenp) {
                size_t olen;
-               if (oldlenp) { 
-                       if (get_user(olen, oldlenp))
+
+               if (get_user(olen, oldlenp))
+                       return -EFAULT;
+               if (olen) {
+                       int val;
+
+                       if (olen < sizeof(int))
+                               return -EINVAL;
+
+                       val = *(int *)(table->data) / HZ;
+                       if (put_user(val, (int __user *)oldval))
+                               return -EFAULT;
+                       if (put_user(sizeof(int), oldlenp))
                                return -EFAULT;
-                       if (olen!=sizeof(int))
-                               return -EINVAL; 
                }
-               if (put_user(*(int *)(table->data)/HZ, (int __user *)oldval) ||
-                   (oldlenp && put_user(sizeof(int),oldlenp)))
-                       return -EFAULT;
        }
        if (newval && newlen) { 
                int new;
@@ -2239,19 +2264,25 @@ int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
 /* Strategy function to convert jiffies to seconds */ 
 int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context)
+               void __user *newval, size_t newlen)
 {
-       if (oldval) {
+       if (oldval && oldlenp) {
                size_t olen;
-               if (oldlenp) { 
-                       if (get_user(olen, oldlenp))
+
+               if (get_user(olen, oldlenp))
+                       return -EFAULT;
+               if (olen) {
+                       int val;
+
+                       if (olen < sizeof(int))
+                               return -EINVAL;
+
+                       val = jiffies_to_msecs(*(int *)(table->data));
+                       if (put_user(val, (int __user *)oldval))
+                               return -EFAULT;
+                       if (put_user(sizeof(int), oldlenp))
                                return -EFAULT;
-                       if (olen!=sizeof(int))
-                               return -EINVAL; 
                }
-               if (put_user(jiffies_to_msecs(*(int *)(table->data)), (int __user *)oldval) ||
-                   (oldlenp && put_user(sizeof(int),oldlenp)))
-                       return -EFAULT;
        }
        if (newval && newlen) { 
                int new;
@@ -2264,109 +2295,73 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
        return 1;
 }
 
-#else /* CONFIG_SYSCTL */
+
+
+#else /* CONFIG_SYSCTL_SYSCALL */
 
 
 asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
 {
+       static int msg_count;
+       struct __sysctl_args tmp;
+       int name[CTL_MAXNAME];
+       int i;
+
+       /* Read in the sysctl name for better debug message logging */
+       if (copy_from_user(&tmp, args, sizeof(tmp)))
+               return -EFAULT;
+       if (tmp.nlen <= 0 || tmp.nlen >= CTL_MAXNAME)
+               return -ENOTDIR;
+       for (i = 0; i < tmp.nlen; i++)
+               if (get_user(name[i], tmp.name + i))
+                       return -EFAULT;
+
+       /* Ignore accesses to kernel.version */
+       if ((tmp.nlen == 2) && (name[0] == CTL_KERN) && (name[1] == KERN_VERSION))
+               goto out;
+
+       if (msg_count < 5) {
+               msg_count++;
+               printk(KERN_INFO
+                       "warning: process `%s' used the removed sysctl "
+                       "system call with ", current->comm);
+               for (i = 0; i < tmp.nlen; i++)
+                       printk("%d.", name[i]);
+               printk("\n");
+       }
+out:
        return -ENOSYS;
 }
 
 int sysctl_string(ctl_table *table, int __user *name, int nlen,
                  void __user *oldval, size_t __user *oldlenp,
-                 void __user *newval, size_t newlen, void **context)
+                 void __user *newval, size_t newlen)
 {
        return -ENOSYS;
 }
 
 int sysctl_intvec(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context)
+               void __user *newval, size_t newlen)
 {
        return -ENOSYS;
 }
 
 int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context)
+               void __user *newval, size_t newlen)
 {
        return -ENOSYS;
 }
 
 int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
                void __user *oldval, size_t __user *oldlenp,
-               void __user *newval, size_t newlen, void **context)
-{
-       return -ENOSYS;
-}
-
-int proc_dostring(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_dointvec(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
-                       void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
-                   void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
-                         void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
-                         void __user *buffer, size_t *lenp, loff_t *ppos)
+               void __user *newval, size_t newlen)
 {
        return -ENOSYS;
 }
 
-int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
-                            void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
-                   void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
-                                     struct file *filp,
-                                     void __user *buffer,
-                                     size_t *lenp, loff_t *ppos)
-{
-    return -ENOSYS;
-}
-
-struct ctl_table_header * register_sysctl_table(ctl_table * table, 
-                                               int insert_at_head)
-{
-       return NULL;
-}
-
-void unregister_sysctl_table(struct ctl_table_header * table)
-{
-}
-
-#endif /* CONFIG_SYSCTL */
+#endif /* CONFIG_SYSCTL_SYSCALL */
 
 /*
  * No sense putting this after each symbol definition, twice,