diff --git a/fs/dnotify.c b/fs/dnotify.c index 28d01ed66de0..eaecc4cfe540 100644 --- a/fs/dnotify.c +++ b/fs/dnotify.c @@ -20,6 +20,7 @@ #include #include #include +#include int dir_notify_enable __read_mostly = 1; @@ -66,6 +67,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) struct dnotify_struct **prev; struct inode *inode; fl_owner_t id = current->files; + struct file *f; int error = 0; if ((arg & ~DN_MULTISHOT) == 0) { @@ -92,6 +94,15 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) prev = &odn->dn_next; } + rcu_read_lock(); + f = fcheck(fd); + rcu_read_unlock(); + /* we'd lost the race with close(), sod off silently */ + /* note that inode->i_lock prevents reordering problems + * between accesses to descriptor table and ->i_dnotify */ + if (f != filp) + goto out_free; + error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); if (error) goto out_free;