From 87df842410ce5a86fdca9fbec0dba80d2aa88b6f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 17 Mar 2010 23:06:02 +0100 Subject: procfs: Kill BKL in llseek on proc base We don't use the BKL elsewhere, so use generic_file_llseek so we can avoid default_llseek taking the BKL. Signed-off-by: Arnd Bergmann [restore proc_fdinfo_file_operations as non-seekable] Signed-off-by: Frederic Weisbecker Cc: Thomas Gleixner Cc: Andrew Morton Cc: Ingo Molnar Cc: John Kacur Cc: KAMEZAWA Hiroyuki Cc: Al Viro diff --git a/fs/proc/base.c b/fs/proc/base.c index a731084..95d91cf 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -728,6 +728,7 @@ out_no_task: static const struct file_operations proc_info_file_operations = { .read = proc_info_read, + .llseek = generic_file_llseek, }; static int proc_single_show(struct seq_file *m, void *v) @@ -985,6 +986,7 @@ out_no_task: static const struct file_operations proc_environ_operations = { .read = environ_read, + .llseek = generic_file_llseek, }; static ssize_t oom_adjust_read(struct file *file, char __user *buf, @@ -1058,6 +1060,7 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, static const struct file_operations proc_oom_adjust_operations = { .read = oom_adjust_read, .write = oom_adjust_write, + .llseek = generic_file_llseek, }; #ifdef CONFIG_AUDITSYSCALL @@ -1129,6 +1132,7 @@ out_free_page: static const struct file_operations proc_loginuid_operations = { .read = proc_loginuid_read, .write = proc_loginuid_write, + .llseek = generic_file_llseek, }; static ssize_t proc_sessionid_read(struct file * file, char __user * buf, @@ -1149,6 +1153,7 @@ static ssize_t proc_sessionid_read(struct file * file, char __user * buf, static const struct file_operations proc_sessionid_operations = { .read = proc_sessionid_read, + .llseek = generic_file_llseek, }; #endif @@ -1200,6 +1205,7 @@ static ssize_t proc_fault_inject_write(struct file * file, static const struct file_operations proc_fault_inject_operations = { .read = proc_fault_inject_read, .write = proc_fault_inject_write, + .llseek = generic_file_llseek, }; #endif @@ -1941,7 +1947,7 @@ static ssize_t proc_fdinfo_read(struct file *file, char __user *buf, } static const struct file_operations proc_fdinfo_file_operations = { - .open = nonseekable_open, + .open = nonseekable_open, .read = proc_fdinfo_read, }; @@ -2225,6 +2231,7 @@ out_no_task: static const struct file_operations proc_pid_attr_operations = { .read = proc_pid_attr_read, .write = proc_pid_attr_write, + .llseek = generic_file_llseek, }; static const struct pid_entry attr_dir_stuff[] = { @@ -2345,6 +2352,7 @@ static ssize_t proc_coredump_filter_write(struct file *file, static const struct file_operations proc_coredump_filter_operations = { .read = proc_coredump_filter_read, .write = proc_coredump_filter_write, + .llseek = generic_file_llseek, }; #endif -- cgit v0.10.2 From 34aacb2920667d405a8df15968b7f71ba46c8f18 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 30 Mar 2010 02:14:26 +0200 Subject: procfs: Use generic_file_llseek in /proc/kcore /proc/kcore has no llseek and then falls down to use default_llseek. This is racy against read_kcore() that directly manipulates fpos but it doesn't hold the bkl there so using it in llseek doesn't protect anything. Let's use generic_file_llseek() instead. Signed-off-by: Frederic Weisbecker Acked-by: Arnd Bergmann Cc: Thomas Gleixner Cc: Andrew Morton Cc: Ingo Molnar Cc: John Kacur Cc: KAMEZAWA Hiroyuki Cc: Al Viro diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index b442dac..3964532 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c @@ -557,6 +557,7 @@ static int open_kcore(struct inode *inode, struct file *filp) static const struct file_operations proc_kcore_operations = { .read = read_kcore, .open = open_kcore, + .llseek = generic_file_llseek, }; #ifdef CONFIG_MEMORY_HOTPLUG -- cgit v0.10.2 From 41775e29a74ed825496c975ba19c7661e15f0523 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 30 Mar 2010 02:24:54 +0200 Subject: procfs: Use generic_file_llseek in /proc/kmsg No need to hold the bkl to seek here, none of the other fops callbacks use it. Use generic_file_llseek explicitly. Signed-off-by: Frederic Weisbecker Acked-by: Arnd Bergmann Cc: Thomas Gleixner Cc: Andrew Morton Cc: Ingo Molnar Cc: John Kacur Cc: KAMEZAWA Hiroyuki Cc: Al Viro diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c index cfe90a4..bd4b5a7 100644 --- a/fs/proc/kmsg.c +++ b/fs/proc/kmsg.c @@ -53,6 +53,7 @@ static const struct file_operations proc_kmsg_operations = { .poll = kmsg_poll, .open = kmsg_open, .release = kmsg_release, + .llseek = generic_file_llseek, }; static int __init proc_kmsg_init(void) -- cgit v0.10.2 From 73296bc611cee009f3be6b451e827d1425b9c10f Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 30 Mar 2010 02:33:36 +0200 Subject: procfs: Use generic_file_llseek in /proc/vmcore /proc/vmcore has no llseek and then falls down to use default_llseek. This is racy against read_vmcore() that directly manipulates fpos but it doesn't hold the bkl there so using it in llseek doesn't protect anything. Let's use generic_file_llseek() instead. Signed-off-by: Frederic Weisbecker Acked-by: Arnd Bergmann Cc: Thomas Gleixner Cc: Andrew Morton Cc: Ingo Molnar Cc: John Kacur Cc: KAMEZAWA Hiroyuki Cc: Al Viro diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 0872afa..00ef604 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c @@ -162,6 +162,7 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer, static const struct file_operations proc_vmcore_operations = { .read = read_vmcore, + .llseek = generic_file_llseek, }; static struct vmcore* __init get_new_element(void) -- cgit v0.10.2 From d79b6f4de5db0103ceb4734e42ad101d836d61d9 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 30 Mar 2010 07:27:50 +0200 Subject: procfs: Push down the bkl from ioctl Push down the bkl from procfs's ioctl main handler to its users. Only three procfs users implement an ioctl (non unlocked) handler. Turn them into unlocked_ioctl and push down the Devil inside. v2: PDE(inode)->data doesn't need to be under bkl v3: And don't forget to git-add the result v4: Use wrappers to pushdown instead of an invasive and error prone handlers surgery. Signed-off-by: Frederic Weisbecker Acked-by: Arnd Bergmann Cc: Thomas Gleixner Cc: Andrew Morton Cc: Ingo Molnar Cc: John Kacur Cc: KAMEZAWA Hiroyuki Cc: Al Viro Cc: Alexey Dobriyan diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index fc8cf7a..4cd8b22 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -82,8 +83,7 @@ module_param(fan_mult, int, 0); MODULE_PARM_DESC(fan_mult, "Factor to multiply fan speed with"); static int i8k_open_fs(struct inode *inode, struct file *file); -static int i8k_ioctl(struct inode *, struct file *, unsigned int, - unsigned long); +static long i8k_ioctl(struct file *, unsigned int, unsigned long); static const struct file_operations i8k_fops = { .owner = THIS_MODULE, @@ -91,7 +91,7 @@ static const struct file_operations i8k_fops = { .read = seq_read, .llseek = seq_lseek, .release = single_release, - .ioctl = i8k_ioctl, + .unlocked_ioctl = i8k_ioctl, }; struct smm_regs { @@ -307,8 +307,8 @@ static int i8k_get_dell_signature(int req_fn) return regs.eax == 1145651527 && regs.edx == 1145392204 ? 0 : -1; } -static int i8k_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, - unsigned long arg) +static int +i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg) { int val = 0; int speed; @@ -395,6 +395,17 @@ static int i8k_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, return 0; } +static long i8k_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) +{ + long ret; + + lock_kernel(); + ret = i8k_ioctl_unlocked(fp, cmd, arg); + unlock_kernel(); + + return ret; +} + /* * Print the information for /proc/i8k. */ diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c index 3697c40..724693c 100644 --- a/drivers/isdn/divert/divert_procfs.c +++ b/drivers/isdn/divert/divert_procfs.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "isdn_divert.h" @@ -176,9 +177,7 @@ isdn_divert_close(struct inode *ino, struct file *filep) /*********/ /* IOCTL */ /*********/ -static int -isdn_divert_ioctl(struct inode *inode, struct file *file, - uint cmd, ulong arg) +static int isdn_divert_ioctl_unlocked(struct file *file, uint cmd, ulong arg) { divert_ioctl dioctl; int i; @@ -257,6 +256,17 @@ isdn_divert_ioctl(struct inode *inode, struct file *file, return copy_to_user((void __user *)arg, &dioctl, sizeof(dioctl)) ? -EFAULT : 0; } /* isdn_divert_ioctl */ +static long isdn_divert_ioctl(struct file *file, uint cmd, ulong arg) +{ + long ret; + + lock_kernel(); + ret = isdn_divert_ioctl_unlocked(file, cmd, arg); + unlock_kernel(); + + return ret; +} + static const struct file_operations isdn_fops = { .owner = THIS_MODULE, @@ -264,7 +274,7 @@ static const struct file_operations isdn_fops = .read = isdn_divert_read, .write = isdn_divert_write, .poll = isdn_divert_poll, - .ioctl = isdn_divert_ioctl, + .unlocked_ioctl = isdn_divert_ioctl, .open = isdn_divert_open, .release = isdn_divert_close, }; diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 39bddba..95690a8 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1331,12 +1331,18 @@ static unsigned int cache_poll_procfs(struct file *filp, poll_table *wait) return cache_poll(filp, wait, cd); } -static int cache_ioctl_procfs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static long cache_ioctl_procfs(struct file *filp, + unsigned int cmd, unsigned long arg) { + long ret; + struct inode *inode = filp->f_path.dentry->d_inode; struct cache_detail *cd = PDE(inode)->data; - return cache_ioctl(inode, filp, cmd, arg, cd); + lock_kernel(); + ret = cache_ioctl(inode, filp, cmd, arg, cd); + unlock_kernel(); + + return ret; } static int cache_open_procfs(struct inode *inode, struct file *filp) @@ -1359,7 +1365,7 @@ static const struct file_operations cache_file_operations_procfs = { .read = cache_read_procfs, .write = cache_write_procfs, .poll = cache_poll_procfs, - .ioctl = cache_ioctl_procfs, /* for FIONREAD */ + .unlocked_ioctl = cache_ioctl_procfs, /* for FIONREAD */ .open = cache_open_procfs, .release = cache_release_procfs, }; -- cgit v0.10.2 From c2f980500a81006173daf3048284b28832858616 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 30 Mar 2010 07:32:50 +0200 Subject: procfs: Kill the bkl in ioctl There are no more users of procfs that implement the ioctl callback. Drop the bkl from this path and warn on any use of this callback. Signed-off-by: Frederic Weisbecker Cc: Arnd Bergmann Cc: Thomas Gleixner Cc: Andrew Morton Cc: Ingo Molnar Cc: John Kacur Cc: KAMEZAWA Hiroyuki Cc: Al Viro diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 445a02b..afcda85 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -231,9 +231,9 @@ static long proc_reg_unlocked_ioctl(struct file *file, unsigned int cmd, unsigne if (rv == -ENOIOCTLCMD) rv = -EINVAL; } else if (ioctl) { - lock_kernel(); + WARN_ONCE(1, "Procfs ioctl handlers must use unlocked_ioctl, " + "%pf will be called without the Bkl held\n", ioctl); rv = ioctl(file->f_path.dentry->d_inode, file, cmd, arg); - unlock_kernel(); } pde_users_dec(pde); -- cgit v0.10.2 From 99df95a22f7cfcf85405d4edc07c2d953542f0dd Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 13 Apr 2010 22:46:36 +0200 Subject: sunrpc: Include missing smp_lock.h Now that cache_ioctl_procfs() calls the bkl explicitly, we need to include the relevant header as well. This fixes the following build error: net/sunrpc/cache.c: In function 'cache_ioctl_procfs': net/sunrpc/cache.c:1355: error: implicit declaration of function 'lock_kernel' net/sunrpc/cache.c:1359: error: implicit declaration of function 'unlock_kernel' Reported-by: Stephen Rothwell Signed-off-by: Frederic Weisbecker diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 95690a8..77970fe 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include -- cgit v0.10.2