lkml.org 
[lkml]   [2008]   [Apr]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subjectinotify: fix race
    -stable review patch.  If anyone has any objections, please let us know.
    ---------------------

    From: Nick Piggin <npiggin@suse.de>

    upstream commit: d599e36a9ea85432587f4550acc113cd7549d12a

    There is a race between setting an inode's children's "parent watched" flag
    when placing the first watch on a parent, and instantiating new children of
    that parent: a child could miss having its flags set by
    set_dentry_child_flags, but then inotify_d_instantiate might still see
    !inotify_inode_watched.

    The solution is to set_dentry_child_flags after adding the watch. Locking is
    taken care of, because both set_dentry_child_flags and inotify_d_instantiate
    hold dcache_lock and child->d_locks.

    Signed-off-by: Nick Piggin <npiggin@suse.de>
    Cc: Robert Love <rlove@google.com>
    Cc: John McCutchan <ttb@tentacle.dhs.org>
    Cc: Jan Kara <jack@ucw.cz>
    Cc: Yan Zheng <yanzheng@21cn.com>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Christian Lamparter <chunkeey@web.de>
    Signed-off-by: Chris Wright <chrisw@sous-sol.org>
    ---
    fs/inotify.c | 13 ++++++++++---
    1 file changed, 10 insertions(+), 3 deletions(-)

    --- a/fs/inotify.c
    +++ b/fs/inotify.c
    @@ -627,6 +627,7 @@ s32 inotify_add_watch(struct inotify_han
    struct inode *inode, u32 mask)
    {
    int ret = 0;
    + int newly_watched;

    /* don't allow invalid bits: we don't want flags set */
    mask &= IN_ALL_EVENTS | IN_ONESHOT;
    @@ -653,12 +654,18 @@ s32 inotify_add_watch(struct inotify_han
    */
    watch->inode = igrab(inode);

    - if (!inotify_inode_watched(inode))
    - set_dentry_child_flags(inode, 1);
    -
    /* Add the watch to the handle's and the inode's list */
    + newly_watched = !inotify_inode_watched(inode);
    list_add(&watch->h_list, &ih->watches);
    list_add(&watch->i_list, &inode->inotify_watches);
    + /*
    + * Set child flags _after_ adding the watch, so there is no race
    + * windows where newly instantiated children could miss their parent's
    + * watched flag.
    + */
    + if (newly_watched)
    + set_dentry_child_flags(inode, 1);
    +
    out:
    mutex_unlock(&ih->mutex);
    mutex_unlock(&inode->inotify_mutex);
    --


    \
     
     \ /
      Last update: 2008-04-17 03:17    [W:0.022 / U:30.816 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site