]> nv-tegra.nvidia Code Review - linux-3.10.git/blobdiff - kernel/sysctl_binary.c
cgroup: fix to break the while loop in cgroup_attach_task() correctly
[linux-3.10.git] / kernel / sysctl_binary.c
index 8cd50d8f9bde4c2d2ce403736aa33c9b769f35c9..aea4a9ea6fc845b884f84a367589a5945703e761 100644 (file)
@@ -1,6 +1,6 @@
 #include <linux/stat.h>
 #include <linux/sysctl.h>
-#include "../fs/xfs/linux-2.6/xfs_sysctl.h"
+#include "../fs/xfs/xfs_sysctl.h"
 #include <linux/sunrpc/debug.h>
 #include <linux/string.h>
 #include <net/ip_vs.h>
@@ -13,6 +13,9 @@
 #include <linux/file.h>
 #include <linux/ctype.h>
 #include <linux/netdevice.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/compat.h>
 
 #ifdef CONFIG_SYSCTL_SYSCALL
 
@@ -134,7 +137,6 @@ static const struct bin_table bin_kern_table[] = {
        { CTL_INT,      KERN_IA64_UNALIGNED,            "ignore-unaligned-usertrap" },
        { CTL_INT,      KERN_COMPAT_LOG,                "compat-log" },
        { CTL_INT,      KERN_MAX_LOCK_DEPTH,            "max_lock_depth" },
-       { CTL_INT,      KERN_NMI_WATCHDOG,              "nmi_watchdog" },
        { CTL_INT,      KERN_PANIC_ON_NMI,              "panic_on_unrecovered_nmi" },
        {}
 };
@@ -146,7 +148,7 @@ static const struct bin_table bin_vm_table[] = {
        { CTL_INT,      VM_DIRTY_RATIO,                 "dirty_ratio" },
        /* VM_DIRTY_WB_CS "dirty_writeback_centisecs" no longer used */
        /* VM_DIRTY_EXPIRE_CS "dirty_expire_centisecs" no longer used */
-       { CTL_INT,      VM_NR_PDFLUSH_THREADS,          "nr_pdflush_threads" },
+       /* VM_NR_PDFLUSH_THREADS "nr_pdflush_threads" no longer used */
        { CTL_INT,      VM_OVERCOMMIT_RATIO,            "overcommit_ratio" },
        /* VM_PAGEBUF unused */
        /* VM_HUGETLB_PAGES "nr_hugepages" no longer used */
@@ -213,7 +215,7 @@ static const struct bin_table bin_net_ipv4_route_table[] = {
        { CTL_INT,      NET_IPV4_ROUTE_GC_MIN_INTERVAL,         "gc_min_interval" },
        { CTL_INT,      NET_IPV4_ROUTE_GC_MIN_INTERVAL_MS,      "gc_min_interval_ms" },
        { CTL_INT,      NET_IPV4_ROUTE_GC_TIMEOUT,              "gc_timeout" },
-       { CTL_INT,      NET_IPV4_ROUTE_GC_INTERVAL,             "gc_interval" },
+       /* NET_IPV4_ROUTE_GC_INTERVAL "gc_interval" no longer used */
        { CTL_INT,      NET_IPV4_ROUTE_REDIRECT_LOAD,           "redirect_load" },
        { CTL_INT,      NET_IPV4_ROUTE_REDIRECT_NUMBER,         "redirect_number" },
        { CTL_INT,      NET_IPV4_ROUTE_REDIRECT_SILENCE,        "redirect_silence" },
@@ -223,7 +225,6 @@ static const struct bin_table bin_net_ipv4_route_table[] = {
        { CTL_INT,      NET_IPV4_ROUTE_MTU_EXPIRES,             "mtu_expires" },
        { CTL_INT,      NET_IPV4_ROUTE_MIN_PMTU,                "min_pmtu" },
        { CTL_INT,      NET_IPV4_ROUTE_MIN_ADVMSS,              "min_adv_mss" },
-       { CTL_INT,      NET_IPV4_ROUTE_SECRET_INTERVAL,         "secret_interval" },
        {}
 };
 
@@ -387,7 +388,6 @@ static const struct bin_table bin_net_ipv4_table[] = {
        { CTL_INT,      NET_TCP_MODERATE_RCVBUF,                "tcp_moderate_rcvbuf" },
        { CTL_INT,      NET_TCP_TSO_WIN_DIVISOR,                "tcp_tso_win_divisor" },
        { CTL_STR,      NET_TCP_CONG_CONTROL,                   "tcp_congestion_control" },
-       { CTL_INT,      NET_TCP_ABC,                            "tcp_abc" },
        { CTL_INT,      NET_TCP_MTU_PROBING,                    "tcp_mtu_probing" },
        { CTL_INT,      NET_TCP_BASE_MSS,                       "tcp_base_mss" },
        { CTL_INT,      NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS, "tcp_workaround_signed_windows" },
@@ -971,7 +971,6 @@ out:
 static ssize_t bin_intvec(struct file *file,
        void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
 {
-       mm_segment_t old_fs = get_fs();
        ssize_t copied = 0;
        char *buffer;
        ssize_t result;
@@ -984,13 +983,10 @@ static ssize_t bin_intvec(struct file *file,
        if (oldval && oldlen) {
                unsigned __user *vec = oldval;
                size_t length = oldlen / sizeof(*vec);
-               loff_t pos = 0;
                char *str, *end;
                int i;
 
-               set_fs(KERNEL_DS);
-               result = vfs_read(file, buffer, BUFSZ - 1, &pos);
-               set_fs(old_fs);
+               result = kernel_read(file, 0, buffer, BUFSZ - 1);
                if (result < 0)
                        goto out_kfree;
 
@@ -1017,7 +1013,6 @@ static ssize_t bin_intvec(struct file *file,
        if (newval && newlen) {
                unsigned __user *vec = newval;
                size_t length = newlen / sizeof(*vec);
-               loff_t pos = 0;
                char *str, *end;
                int i;
 
@@ -1033,9 +1028,7 @@ static ssize_t bin_intvec(struct file *file,
                        str += snprintf(str, end - str, "%lu\t", value);
                }
 
-               set_fs(KERNEL_DS);
-               result = vfs_write(file, buffer, str - buffer, &pos);
-               set_fs(old_fs);
+               result = kernel_write(file, buffer, str - buffer, 0);
                if (result < 0)
                        goto out_kfree;
        }
@@ -1049,7 +1042,6 @@ out:
 static ssize_t bin_ulongvec(struct file *file,
        void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
 {
-       mm_segment_t old_fs = get_fs();
        ssize_t copied = 0;
        char *buffer;
        ssize_t result;
@@ -1062,13 +1054,10 @@ static ssize_t bin_ulongvec(struct file *file,
        if (oldval && oldlen) {
                unsigned long __user *vec = oldval;
                size_t length = oldlen / sizeof(*vec);
-               loff_t pos = 0;
                char *str, *end;
                int i;
 
-               set_fs(KERNEL_DS);
-               result = vfs_read(file, buffer, BUFSZ - 1, &pos);
-               set_fs(old_fs);
+               result = kernel_read(file, 0, buffer, BUFSZ - 1);
                if (result < 0)
                        goto out_kfree;
 
@@ -1095,7 +1084,6 @@ static ssize_t bin_ulongvec(struct file *file,
        if (newval && newlen) {
                unsigned long __user *vec = newval;
                size_t length = newlen / sizeof(*vec);
-               loff_t pos = 0;
                char *str, *end;
                int i;
 
@@ -1111,9 +1099,7 @@ static ssize_t bin_ulongvec(struct file *file,
                        str += snprintf(str, end - str, "%lu\t", value);
                }
 
-               set_fs(KERNEL_DS);
-               result = vfs_write(file, buffer, str - buffer, &pos);
-               set_fs(old_fs);
+               result = kernel_write(file, buffer, str - buffer, 0);
                if (result < 0)
                        goto out_kfree;
        }
@@ -1124,27 +1110,18 @@ out:
        return result;
 }
 
-static unsigned hex_value(int ch)
-{
-       return isdigit(ch) ? ch - '0' : ((ch | 0x20) - 'a') + 10;
-}
-
 static ssize_t bin_uuid(struct file *file,
        void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
 {
-       mm_segment_t old_fs = get_fs();
        ssize_t result, copied = 0;
 
        /* Only supports reads */
        if (oldval && oldlen) {
-               loff_t pos = 0;
                char buf[40], *str = buf;
                unsigned char uuid[16];
                int i;
 
-               set_fs(KERNEL_DS);
-               result = vfs_read(file, buf, sizeof(buf) - 1, &pos);
-               set_fs(old_fs);
+               result = kernel_read(file, 0, buf, sizeof(buf) - 1);
                if (result < 0)
                        goto out;
 
@@ -1156,7 +1133,8 @@ static ssize_t bin_uuid(struct file *file,
                        if (!isxdigit(str[0]) || !isxdigit(str[1]))
                                goto out;
 
-                       uuid[i] = (hex_value(str[0]) << 4) | hex_value(str[1]);
+                       uuid[i] = (hex_to_bin(str[0]) << 4) |
+                                       hex_to_bin(str[1]);
                        str += 2;
                        if (*str == '-')
                                str++;
@@ -1179,28 +1157,25 @@ out:
 static ssize_t bin_dn_node_address(struct file *file,
        void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
 {
-       mm_segment_t old_fs = get_fs();
        ssize_t result, copied = 0;
 
        if (oldval && oldlen) {
-               loff_t pos = 0;
                char buf[15], *nodep;
                unsigned long area, node;
                __le16 dnaddr;
 
-               set_fs(KERNEL_DS);
-               result = vfs_read(file, buf, sizeof(buf) - 1, &pos);
-               set_fs(old_fs);
+               result = kernel_read(file, 0, buf, sizeof(buf) - 1);
                if (result < 0)
                        goto out;
 
                buf[result] = '\0';
 
-               /* Convert the decnet addresss to binary */
+               /* Convert the decnet address to binary */
                result = -EIO;
-               nodep = strchr(buf, '.') + 1;
+               nodep = strchr(buf, '.');
                if (!nodep)
                        goto out;
+               ++nodep;
 
                area = simple_strtoul(buf, NULL, 10);
                node = simple_strtoul(nodep, NULL, 10);
@@ -1219,7 +1194,6 @@ static ssize_t bin_dn_node_address(struct file *file,
        }
 
        if (newval && newlen) {
-               loff_t pos = 0;
                __le16 dnaddr;
                char buf[15];
                int len;
@@ -1236,9 +1210,7 @@ static ssize_t bin_dn_node_address(struct file *file,
                                le16_to_cpu(dnaddr) >> 10,
                                le16_to_cpu(dnaddr) & 0x3ff);
 
-               set_fs(KERNEL_DS);
-               result = vfs_write(file, buf, len, &pos);
-               set_fs(old_fs);
+               result = kernel_write(file, buf, len, 0);
                if (result < 0)
                        goto out;
        }
@@ -1325,13 +1297,11 @@ static ssize_t binary_sysctl(const int *name, int nlen,
        void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
 {
        const struct bin_table *table = NULL;
-       struct nameidata nd;
        struct vfsmount *mnt;
        struct file *file;
        ssize_t result;
        char *pathname;
        int flags;
-       int acc_mode;
 
        pathname = sysctl_getname(name, nlen, &table);
        result = PTR_ERR(pathname);
@@ -1341,28 +1311,17 @@ static ssize_t binary_sysctl(const int *name, int nlen,
        /* How should the sysctl be accessed? */
        if (oldval && oldlen && newval && newlen) {
                flags = O_RDWR;
-               acc_mode = MAY_READ | MAY_WRITE;
        } else if (newval && newlen) {
                flags = O_WRONLY;
-               acc_mode = MAY_WRITE;
        } else if (oldval && oldlen) {
                flags = O_RDONLY;
-               acc_mode = MAY_READ;
        } else {
                result = 0;
                goto out_putname;
        }
 
-       mnt = current->nsproxy->pid_ns->proc_mnt;
-       result = vfs_path_lookup(mnt->mnt_root, mnt, pathname, 0, &nd);
-       if (result)
-               goto out_putname;
-
-       result = may_open(&nd.path, acc_mode, flags);
-       if (result)
-               goto out_putpath;
-
-       file = dentry_open(nd.path.dentry, nd.path.mnt, flags, current_cred());
+       mnt = task_active_pid_ns(current)->proc_mnt;
+       file = file_open_root(mnt->mnt_root, mnt, pathname, flags);
        result = PTR_ERR(file);
        if (IS_ERR(file))
                goto out_putname;
@@ -1371,13 +1330,9 @@ static ssize_t binary_sysctl(const int *name, int nlen,
 
        fput(file);
 out_putname:
-       putname(pathname);
+       __putname(pathname);
 out:
        return result;
-
-out_putpath:
-       path_put(&nd.path);
-       goto out_putname;
 }
 
 
@@ -1493,7 +1448,6 @@ SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args)
 
 
 #ifdef CONFIG_COMPAT
-#include <asm/compat.h>
 
 struct compat_sysctl_args {
        compat_uptr_t   name;
@@ -1505,7 +1459,7 @@ struct compat_sysctl_args {
        compat_ulong_t  __unused[4];
 };
 
-asmlinkage long compat_sys_sysctl(struct compat_sysctl_args __user *args)
+COMPAT_SYSCALL_DEFINE1(sysctl, struct compat_sysctl_args __user *, args)
 {
        struct compat_sysctl_args tmp;
        compat_size_t __user *compat_oldlenp;