lkml.org 
[lkml]   [2006]   [Apr]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 18/22] Fix file lookup without ref
    From: Dipankar Sarma <dipankar@in.ibm.com>

    [PATCH] Fix file lookup without ref

    There are places in the kernel where we look up files in fd tables and
    access the file structure without holding refereces to the file. So, we
    need special care to avoid the race between looking up files in the fd
    table and tearing down of the file in another CPU. Otherwise, one might
    see a NULL f_dentry or such torn down version of the file. This patch
    fixes those special places where such a race may happen.

    Signed-off-by: Dipankar Sarma <dipankar@in.ibm.com>
    Acked-by: "Paul E. McKenney" <paulmck@us.ibm.com>
    Signed-off-by: Andrew Morton <akpm@osdl.org>
    Signed-off-by: Linus Torvalds <torvalds@osdl.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    drivers/char/tty_io.c | 8 ++++++--
    fs/locks.c | 9 +++++++--
    fs/proc/base.c | 21 +++++++++++++++------
    3 files changed, 28 insertions(+), 10 deletions(-)

    --- linux-2.6.16.9.orig/drivers/char/tty_io.c
    +++ linux-2.6.16.9/drivers/char/tty_io.c
    @@ -2706,7 +2706,11 @@ static void __do_SAK(void *arg)
    }
    task_lock(p);
    if (p->files) {
    - rcu_read_lock();
    + /*
    + * We don't take a ref to the file, so we must
    + * hold ->file_lock instead.
    + */
    + spin_lock(&p->files->file_lock);
    fdt = files_fdtable(p->files);
    for (i=0; i < fdt->max_fds; i++) {
    filp = fcheck_files(p->files, i);
    @@ -2721,7 +2725,7 @@ static void __do_SAK(void *arg)
    break;
    }
    }
    - rcu_read_unlock();
    + spin_unlock(&p->files->file_lock);
    }
    task_unlock(p);
    } while_each_task_pid(session, PIDTYPE_SID, p);
    --- linux-2.6.16.9.orig/fs/locks.c
    +++ linux-2.6.16.9/fs/locks.c
    @@ -2212,7 +2212,12 @@ void steal_locks(fl_owner_t from)

    lock_kernel();
    j = 0;
    - rcu_read_lock();
    +
    + /*
    + * We are not taking a ref to the file structures, so
    + * we need to acquire ->file_lock.
    + */
    + spin_lock(&files->file_lock);
    fdt = files_fdtable(files);
    for (;;) {
    unsigned long set;
    @@ -2230,7 +2235,7 @@ void steal_locks(fl_owner_t from)
    set >>= 1;
    }
    }
    - rcu_read_unlock();
    + spin_unlock(&files->file_lock);
    unlock_kernel();
    }
    EXPORT_SYMBOL(steal_locks);
    --- linux-2.6.16.9.orig/fs/proc/base.c
    +++ linux-2.6.16.9/fs/proc/base.c
    @@ -294,16 +294,20 @@ static int proc_fd_link(struct inode *in

    files = get_files_struct(task);
    if (files) {
    - rcu_read_lock();
    + /*
    + * We are not taking a ref to the file structure, so we must
    + * hold ->file_lock.
    + */
    + spin_lock(&files->file_lock);
    file = fcheck_files(files, fd);
    if (file) {
    *mnt = mntget(file->f_vfsmnt);
    *dentry = dget(file->f_dentry);
    - rcu_read_unlock();
    + spin_unlock(&files->file_lock);
    put_files_struct(files);
    return 0;
    }
    - rcu_read_unlock();
    + spin_unlock(&files->file_lock);
    put_files_struct(files);
    }
    return -ENOENT;
    @@ -1485,7 +1489,12 @@ static struct dentry *proc_lookupfd(stru
    if (!files)
    goto out_unlock;
    inode->i_mode = S_IFLNK;
    - rcu_read_lock();
    +
    + /*
    + * We are not taking a ref to the file structure, so we must
    + * hold ->file_lock.
    + */
    + spin_lock(&files->file_lock);
    file = fcheck_files(files, fd);
    if (!file)
    goto out_unlock2;
    @@ -1493,7 +1502,7 @@ static struct dentry *proc_lookupfd(stru
    inode->i_mode |= S_IRUSR | S_IXUSR;
    if (file->f_mode & 2)
    inode->i_mode |= S_IWUSR | S_IXUSR;
    - rcu_read_unlock();
    + spin_unlock(&files->file_lock);
    put_files_struct(files);
    inode->i_op = &proc_pid_link_inode_operations;
    inode->i_size = 64;
    @@ -1503,7 +1512,7 @@ static struct dentry *proc_lookupfd(stru
    return NULL;

    out_unlock2:
    - rcu_read_unlock();
    + spin_unlock(&files->file_lock);
    put_files_struct(files);
    out_unlock:
    iput(inode);
    --
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2006-04-21 06:51    [W:2.846 / U:0.936 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site