Commit afa588b2651a03da4bc601a17a244b1cd97264f2

Authored by Eric W. Biederman
1 parent b419148e56

sysctl: Separate the binary sysctl logic into it's own file.

In preparation for more invasive cleanups separate the core
binary sysctl logic into it's own file.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>

Showing 3 changed files with 186 additions and 166 deletions Side-by-side Diff

... ... @@ -4,7 +4,7 @@
4 4  
5 5 obj-y = sched.o fork.o exec_domain.o panic.o printk.o \
6 6 cpu.o exit.o itimer.o time.o softirq.o resource.o \
7   - sysctl.o capability.o ptrace.o timer.o user.o \
  7 + sysctl.o sysctl_binary.o capability.o ptrace.o timer.o user.o \
8 8 signal.o sys.o kmod.o workqueue.o pid.o \
9 9 rcupdate.o extable.o params.o posix-timers.o \
10 10 kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
... ... @@ -27,7 +27,6 @@
27 27 #include <linux/security.h>
28 28 #include <linux/ctype.h>
29 29 #include <linux/kmemcheck.h>
30   -#include <linux/smp_lock.h>
31 30 #include <linux/fs.h>
32 31 #include <linux/init.h>
33 32 #include <linux/kernel.h>
... ... @@ -60,7 +59,6 @@
60 59 #include <asm/io.h>
61 60 #endif
62 61  
63   -static int deprecated_sysctl_warning(struct __sysctl_args *args);
64 62  
65 63 #if defined(CONFIG_SYSCTL)
66 64  
... ... @@ -1766,122 +1764,6 @@
1766 1764 spin_unlock(&sysctl_lock);
1767 1765 }
1768 1766  
1769   -#ifdef CONFIG_SYSCTL_SYSCALL
1770   -/* Perform the actual read/write of a sysctl table entry. */
1771   -static int do_sysctl_strategy(struct ctl_table_root *root,
1772   - struct ctl_table *table,
1773   - void __user *oldval, size_t __user *oldlenp,
1774   - void __user *newval, size_t newlen)
1775   -{
1776   - int op = 0, rc;
1777   -
1778   - if (oldval)
1779   - op |= MAY_READ;
1780   - if (newval)
1781   - op |= MAY_WRITE;
1782   - if (sysctl_perm(root, table, op))
1783   - return -EPERM;
1784   -
1785   - if (table->strategy) {
1786   - rc = table->strategy(table, oldval, oldlenp, newval, newlen);
1787   - if (rc < 0)
1788   - return rc;
1789   - if (rc > 0)
1790   - return 0;
1791   - }
1792   -
1793   - /* If there is no strategy routine, or if the strategy returns
1794   - * zero, proceed with automatic r/w */
1795   - if (table->data && table->maxlen) {
1796   - rc = sysctl_data(table, oldval, oldlenp, newval, newlen);
1797   - if (rc < 0)
1798   - return rc;
1799   - }
1800   - return 0;
1801   -}
1802   -
1803   -static int parse_table(int __user *name, int nlen,
1804   - void __user *oldval, size_t __user *oldlenp,
1805   - void __user *newval, size_t newlen,
1806   - struct ctl_table_root *root,
1807   - struct ctl_table *table)
1808   -{
1809   - int n;
1810   -repeat:
1811   - if (!nlen)
1812   - return -ENOTDIR;
1813   - if (get_user(n, name))
1814   - return -EFAULT;
1815   - for ( ; table->ctl_name || table->procname; table++) {
1816   - if (!table->ctl_name)
1817   - continue;
1818   - if (n == table->ctl_name) {
1819   - int error;
1820   - if (table->child) {
1821   - if (sysctl_perm(root, table, MAY_EXEC))
1822   - return -EPERM;
1823   - name++;
1824   - nlen--;
1825   - table = table->child;
1826   - goto repeat;
1827   - }
1828   - error = do_sysctl_strategy(root, table,
1829   - oldval, oldlenp,
1830   - newval, newlen);
1831   - return error;
1832   - }
1833   - }
1834   - return -ENOTDIR;
1835   -}
1836   -
1837   -int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
1838   - void __user *newval, size_t newlen)
1839   -{
1840   - struct ctl_table_header *head;
1841   - int error = -ENOTDIR;
1842   -
1843   - if (nlen <= 0 || nlen >= CTL_MAXNAME)
1844   - return -ENOTDIR;
1845   - if (oldval) {
1846   - int old_len;
1847   - if (!oldlenp || get_user(old_len, oldlenp))
1848   - return -EFAULT;
1849   - }
1850   -
1851   - for (head = sysctl_head_next(NULL); head;
1852   - head = sysctl_head_next(head)) {
1853   - error = parse_table(name, nlen, oldval, oldlenp,
1854   - newval, newlen,
1855   - head->root, head->ctl_table);
1856   - if (error != -ENOTDIR) {
1857   - sysctl_head_finish(head);
1858   - break;
1859   - }
1860   - }
1861   - return error;
1862   -}
1863   -
1864   -SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)
1865   -{
1866   - struct __sysctl_args tmp;
1867   - int error;
1868   -
1869   - if (copy_from_user(&tmp, args, sizeof(tmp)))
1870   - return -EFAULT;
1871   -
1872   - error = deprecated_sysctl_warning(&tmp);
1873   - if (error)
1874   - goto out;
1875   -
1876   - lock_kernel();
1877   - error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp,
1878   - tmp.newval, tmp.newlen);
1879   - unlock_kernel();
1880   -out:
1881   - return error;
1882   -}
1883   -#endif /* CONFIG_SYSCTL_SYSCALL */
1884   -
1885 1767 /*
1886 1768 * sysctl_perm does NOT grant the superuser all rights automatically, because
1887 1769 * some sysctl variables are readonly even to root.
... ... @@ -3148,23 +3030,6 @@
3148 3030 #else /* CONFIG_SYSCTL_SYSCALL */
3149 3031  
3150 3032  
3151   -SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)
3152   -{
3153   - struct __sysctl_args tmp;
3154   - int error;
3155   -
3156   - if (copy_from_user(&tmp, args, sizeof(tmp)))
3157   - return -EFAULT;
3158   -
3159   - error = deprecated_sysctl_warning(&tmp);
3160   -
3161   - /* If no error reading the parameters then just -ENOSYS ... */
3162   - if (!error)
3163   - error = -ENOSYS;
3164   -
3165   - return error;
3166   -}
3167   -
3168 3033 int sysctl_data(struct ctl_table *table,
3169 3034 void __user *oldval, size_t __user *oldlenp,
3170 3035 void __user *newval, size_t newlen)
... ... @@ -3202,36 +3067,6 @@
3202 3067  
3203 3068 #endif /* CONFIG_SYSCTL_SYSCALL */
3204 3069  
3205   -static int deprecated_sysctl_warning(struct __sysctl_args *args)
3206   -{
3207   - static int msg_count;
3208   - int name[CTL_MAXNAME];
3209   - int i;
3210   -
3211   - /* Check args->nlen. */
3212   - if (args->nlen < 0 || args->nlen > CTL_MAXNAME)
3213   - return -ENOTDIR;
3214   -
3215   - /* Read in the sysctl name for better debug message logging */
3216   - for (i = 0; i < args->nlen; i++)
3217   - if (get_user(name[i], args->name + i))
3218   - return -EFAULT;
3219   -
3220   - /* Ignore accesses to kernel.version */
3221   - if ((args->nlen == 2) && (name[0] == CTL_KERN) && (name[1] == KERN_VERSION))
3222   - return 0;
3223   -
3224   - if (msg_count < 5) {
3225   - msg_count++;
3226   - printk(KERN_INFO
3227   - "warning: process `%s' used the deprecated sysctl "
3228   - "system call with ", current->comm);
3229   - for (i = 0; i < args->nlen; i++)
3230   - printk("%d.", name[i]);
3231   - printk("\n");
3232   - }
3233   - return 0;
3234   -}
3235 3070  
3236 3071 /*
3237 3072 * No sense putting this after each symbol definition, twice,
kernel/sysctl_binary.c
  1 +#include <linux/stat.h>
  2 +#include <linux/sysctl.h>
  3 +#include "../fs/xfs/linux-2.6/xfs_sysctl.h"
  4 +#include <linux/sunrpc/debug.h>
  5 +#include <linux/string.h>
  6 +#include <net/ip_vs.h>
  7 +#include <linux/syscalls.h>
  8 +#include <linux/namei.h>
  9 +#include <linux/mount.h>
  10 +#include <linux/fs.h>
  11 +#include <linux/nsproxy.h>
  12 +#include <linux/pid_namespace.h>
  13 +#include <linux/file.h>
  14 +#include <linux/ctype.h>
  15 +#include <linux/smp_lock.h>
  16 +
  17 +static int deprecated_sysctl_warning(struct __sysctl_args *args);
  18 +
  19 +#ifdef CONFIG_SYSCTL_SYSCALL
  20 +
  21 +/* Perform the actual read/write of a sysctl table entry. */
  22 +static int do_sysctl_strategy(struct ctl_table_root *root,
  23 + struct ctl_table *table,
  24 + void __user *oldval, size_t __user *oldlenp,
  25 + void __user *newval, size_t newlen)
  26 +{
  27 + int op = 0, rc;
  28 +
  29 + if (oldval)
  30 + op |= MAY_READ;
  31 + if (newval)
  32 + op |= MAY_WRITE;
  33 + if (sysctl_perm(root, table, op))
  34 + return -EPERM;
  35 +
  36 + if (table->strategy) {
  37 + rc = table->strategy(table, oldval, oldlenp, newval, newlen);
  38 + if (rc < 0)
  39 + return rc;
  40 + if (rc > 0)
  41 + return 0;
  42 + }
  43 +
  44 + /* If there is no strategy routine, or if the strategy returns
  45 + * zero, proceed with automatic r/w */
  46 + if (table->data && table->maxlen) {
  47 + rc = sysctl_data(table, oldval, oldlenp, newval, newlen);
  48 + if (rc < 0)
  49 + return rc;
  50 + }
  51 + return 0;
  52 +}
  53 +
  54 +static int parse_table(int __user *name, int nlen,
  55 + void __user *oldval, size_t __user *oldlenp,
  56 + void __user *newval, size_t newlen,
  57 + struct ctl_table_root *root,
  58 + struct ctl_table *table)
  59 +{
  60 + int n;
  61 +repeat:
  62 + if (!nlen)
  63 + return -ENOTDIR;
  64 + if (get_user(n, name))
  65 + return -EFAULT;
  66 + for ( ; table->ctl_name || table->procname; table++) {
  67 + if (!table->ctl_name)
  68 + continue;
  69 + if (n == table->ctl_name) {
  70 + int error;
  71 + if (table->child) {
  72 + if (sysctl_perm(root, table, MAY_EXEC))
  73 + return -EPERM;
  74 + name++;
  75 + nlen--;
  76 + table = table->child;
  77 + goto repeat;
  78 + }
  79 + error = do_sysctl_strategy(root, table,
  80 + oldval, oldlenp,
  81 + newval, newlen);
  82 + return error;
  83 + }
  84 + }
  85 + return -ENOTDIR;
  86 +}
  87 +
  88 +int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
  89 + void __user *newval, size_t newlen)
  90 +{
  91 + struct ctl_table_header *head;
  92 + int error = -ENOTDIR;
  93 +
  94 + if (nlen <= 0 || nlen >= CTL_MAXNAME)
  95 + return -ENOTDIR;
  96 + if (oldval) {
  97 + int old_len;
  98 + if (!oldlenp || get_user(old_len, oldlenp))
  99 + return -EFAULT;
  100 + }
  101 +
  102 + for (head = sysctl_head_next(NULL); head;
  103 + head = sysctl_head_next(head)) {
  104 + error = parse_table(name, nlen, oldval, oldlenp,
  105 + newval, newlen,
  106 + head->root, head->ctl_table);
  107 + if (error != -ENOTDIR) {
  108 + sysctl_head_finish(head);
  109 + break;
  110 + }
  111 + }
  112 + return error;
  113 +}
  114 +
  115 +SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)
  116 +{
  117 + struct __sysctl_args tmp;
  118 + int error;
  119 +
  120 + if (copy_from_user(&tmp, args, sizeof(tmp)))
  121 + return -EFAULT;
  122 +
  123 + error = deprecated_sysctl_warning(&tmp);
  124 + if (error)
  125 + goto out;
  126 +
  127 + lock_kernel();
  128 + error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp,
  129 + tmp.newval, tmp.newlen);
  130 + unlock_kernel();
  131 +out:
  132 + return error;
  133 +}
  134 +
  135 +#else /* CONFIG_SYSCTL_SYSCALL */
  136 +
  137 +SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)
  138 +{
  139 + struct __sysctl_args tmp;
  140 + int error;
  141 +
  142 + if (copy_from_user(&tmp, args, sizeof(tmp)))
  143 + return -EFAULT;
  144 +
  145 + error = deprecated_sysctl_warning(&tmp);
  146 +
  147 + /* If no error reading the parameters then just -ENOSYS ... */
  148 + if (!error)
  149 + error = -ENOSYS;
  150 +
  151 + return error;
  152 +}
  153 +
  154 +#endif /* CONFIG_SYSCTL_SYSCALL */
  155 +
  156 +static int deprecated_sysctl_warning(struct __sysctl_args *args)
  157 +{
  158 + static int msg_count;
  159 + int name[CTL_MAXNAME];
  160 + int i;
  161 +
  162 + /* Check args->nlen. */
  163 + if (args->nlen < 0 || args->nlen > CTL_MAXNAME)
  164 + return -ENOTDIR;
  165 +
  166 + /* Read in the sysctl name for better debug message logging */
  167 + for (i = 0; i < args->nlen; i++)
  168 + if (get_user(name[i], args->name + i))
  169 + return -EFAULT;
  170 +
  171 + /* Ignore accesses to kernel.version */
  172 + if ((args->nlen == 2) && (name[0] == CTL_KERN) && (name[1] == KERN_VERSION))
  173 + return 0;
  174 +
  175 + if (msg_count < 5) {
  176 + msg_count++;
  177 + printk(KERN_INFO
  178 + "warning: process `%s' used the deprecated sysctl "
  179 + "system call with ", current->comm);
  180 + for (i = 0; i < args->nlen; i++)
  181 + printk("%d.", name[i]);
  182 + printk("\n");
  183 + }
  184 + return 0;
  185 +}