From: Dipankar Sarma With the new fdtable locking rules, you have to protect fdtable with either ->file_lock or rcu_read_lock/unlock(). There are some places where we aren't doing either. This patch fixes those places. Signed-off-by: Dipankar Sarma Signed-off-by: Andrew Morton --- arch/alpha/kernel/osf_sys.c | 8 +++++++- arch/ia64/kernel/perfmon.c | 3 ++- fs/locks.c | 3 +++ fs/proc/array.c | 3 +++ kernel/exit.c | 6 ++++++ 5 files changed, 21 insertions(+), 2 deletions(-) diff -puN arch/alpha/kernel/osf_sys.c~files-fix-preemption-issues arch/alpha/kernel/osf_sys.c --- devel/arch/alpha/kernel/osf_sys.c~files-fix-preemption-issues 2005-09-13 18:44:07.000000000 -0700 +++ devel-akpm/arch/alpha/kernel/osf_sys.c 2005-09-13 18:45:22.000000000 -0700 @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -975,6 +976,7 @@ osf_select(int n, fd_set __user *inp, fd long timeout; int ret = -EINVAL; struct fdtable *fdt; + int max_fdset; timeout = MAX_SCHEDULE_TIMEOUT; if (tvp) { @@ -996,9 +998,13 @@ osf_select(int n, fd_set __user *inp, fd } } + rcu_read_lock(); fdt = files_fdtable(current->files); - if (n < 0 || n > fdt->max_fdset) + max_fdset = fdt->max_fdset; + rcu_read_unlock(); + if (n < 0 || n > max_fdset) { goto out_nofds; + } /* * We need 6 bitmaps (in/out/ex for both incoming and outgoing), diff -puN arch/ia64/kernel/perfmon.c~files-fix-preemption-issues arch/ia64/kernel/perfmon.c --- devel/arch/ia64/kernel/perfmon.c~files-fix-preemption-issues 2005-09-13 18:44:07.000000000 -0700 +++ devel-akpm/arch/ia64/kernel/perfmon.c 2005-09-13 18:44:07.000000000 -0700 @@ -2218,12 +2218,13 @@ static void pfm_free_fd(int fd, struct file *file) { struct files_struct *files = current->files; - struct fdtable *fdt = files_fdtable(files); + struct fdtable *fdt; /* * there ie no fd_uninstall(), so we do it here */ spin_lock(&files->file_lock); + fdt = files_fdtable(files); rcu_assign_pointer(fdt->fd[fd], NULL); spin_unlock(&files->file_lock); diff -puN fs/locks.c~files-fix-preemption-issues fs/locks.c --- devel/fs/locks.c~files-fix-preemption-issues 2005-09-13 18:44:07.000000000 -0700 +++ devel-akpm/fs/locks.c 2005-09-13 18:44:07.000000000 -0700 @@ -124,6 +124,7 @@ #include #include #include +#include #include #include @@ -2209,6 +2210,7 @@ void steal_locks(fl_owner_t from) lock_kernel(); j = 0; + rcu_read_lock(); fdt = files_fdtable(files); for (;;) { unsigned long set; @@ -2226,6 +2228,7 @@ void steal_locks(fl_owner_t from) set >>= 1; } } + rcu_read_unlock(); unlock_kernel(); } EXPORT_SYMBOL(steal_locks); diff -puN fs/proc/array.c~files-fix-preemption-issues fs/proc/array.c --- devel/fs/proc/array.c~files-fix-preemption-issues 2005-09-13 18:44:07.000000000 -0700 +++ devel-akpm/fs/proc/array.c 2005-09-13 18:44:07.000000000 -0700 @@ -74,6 +74,7 @@ #include #include #include +#include #include #include @@ -180,12 +181,14 @@ static inline char * task_state(struct t p->gid, p->egid, p->sgid, p->fsgid); read_unlock(&tasklist_lock); task_lock(p); + rcu_read_lock(); if (p->files) fdt = files_fdtable(p->files); buffer += sprintf(buffer, "FDSize:\t%d\n" "Groups:\t", fdt ? fdt->max_fds : 0); + rcu_read_unlock(); group_info = p->group_info; get_group_info(group_info); diff -puN kernel/exit.c~files-fix-preemption-issues kernel/exit.c --- devel/kernel/exit.c~files-fix-preemption-issues 2005-09-13 18:44:07.000000000 -0700 +++ devel-akpm/kernel/exit.c 2005-09-13 18:44:07.000000000 -0700 @@ -371,6 +371,12 @@ static inline void close_files(struct fi struct fdtable *fdt; j = 0; + + /* + * It is safe to dereference the fd table without RCU or + * ->file_lock because this is the last reference to the + * files structure. + */ fdt = files_fdtable(files); for (;;) { unsigned long set; _