--- zzzz-none-000/linux-2.6.19.2/kernel/sysctl.c 2007-01-10 19:10:37.000000000 +0000 +++ davinci-8020-5505/linux-2.6.19.2/kernel/sysctl.c 2008-04-10 12:21:44.000000000 +0000 @@ -57,6 +57,14 @@ #endif #if defined(CONFIG_SYSCTL) +#include +#include + +extern __u32 gr_handle_sysctl(const ctl_table *table, const void *oldval, + const void *newval); +extern int gr_handle_sysctl_mod(const char *dirname, const char *name, + const int op); +extern int gr_handle_chroot_sysctl(const int op); /* External variables not in a header file. */ extern int C_A_D; @@ -142,8 +150,10 @@ #endif static ctl_table root_table[]; -static struct ctl_table_header root_table_header = - { root_table, LIST_HEAD_INIT(root_table_header.ctl_entry) }; +static struct ctl_table_header root_table_header = { + .ctl_table = root_table, + .ctl_entry = LIST_HEAD_INIT(root_table_header.ctl_entry) +}; static ctl_table kern_table[]; static ctl_table vm_table[]; @@ -161,6 +171,22 @@ #ifdef HAVE_ARCH_PICK_MMAP_LAYOUT int sysctl_legacy_va_layout; #endif +extern ctl_table grsecurity_table[]; + +#ifdef CONFIG_PAX_SOFTMODE +static ctl_table pax_table[] = { + { + .ctl_name = PAX_SOFTMODE, + .procname = "softmode", + .data = &pax_softmode, + .maxlen = sizeof(unsigned int), + .mode = 0600, + .proc_handler = &proc_dointvec, + }, + + { .ctl_name = 0 } +}; +#endif /* /proc declarations: */ @@ -769,6 +795,24 @@ }, #endif +#if defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_MODSTOP) + { + .ctl_name = KERN_GRSECURITY, + .procname = "grsecurity", + .mode = 0500, + .child = grsecurity_table, + }, +#endif + +#ifdef CONFIG_PAX_SOFTMODE + { + .ctl_name = KERN_PAX, + .procname = "pax", + .mode = 0500, + .child = pax_table, + }, +#endif + { .ctl_name = 0 } }; @@ -1297,6 +1341,10 @@ static inline int ctl_perm(ctl_table *table, int op) { int error; + if (table->de && gr_handle_sysctl_mod(table->de->parent->name, table->de->name, op)) + return -EACCES; + if (gr_handle_chroot_sysctl(op)) + return -EACCES; error = security_sysctl(table, op); if (error) return error; @@ -1315,9 +1363,7 @@ return -ENOTDIR; if (get_user(n, name)) return -EFAULT; - for ( ; table->ctl_name || table->procname; table++) { - if (!table->ctl_name) - continue; + for ( ; table->ctl_name; table++) { if (n == table->ctl_name || table->ctl_name == CTL_ANY) { int error; if (table->child) { @@ -1336,6 +1382,10 @@ table = table->child; goto repeat; } + + if (!gr_handle_sysctl(table, oldval, newval)) + return -EPERM; + error = do_sysctl_strategy(table, name, nlen, oldval, oldlenp, newval, newlen, context); @@ -1534,7 +1584,7 @@ int len; mode_t mode; - for (; table->ctl_name || table->procname; table++) { + for (; table->ctl_name; table++) { /* Can't do anything without a proc name. */ if (!table->procname) continue; @@ -1581,7 +1631,7 @@ static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root) { struct proc_dir_entry *de; - for (; table->ctl_name || table->procname; table++) { + for (; table->ctl_name; table++) { if (!(de = table->de)) continue; if (de->mode & S_IFDIR) { @@ -2682,33 +2732,13 @@ 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"); + "system call\n", current->comm); } -out: return -ENOSYS; }