[67/99] fsnotify: do not set group for a mark before it is on the i_list

From: Greg KH
Date: Fri Nov 06 2009 - 17:30:56 EST

2.6.31-stable review patch. If anyone has any objections, please let us know.

From: Eric Paris <eparis@xxxxxxxxxx>

commit 9f0d793b52eb2266359661369ef6303838904855 upstream.

fsnotify_add_mark is supposed to add a mark to the g_list and i_list and to
set the group and inode for the mark. fsnotify_destroy_mark_by_entry uses
the fact that ->group != NULL to know if this group should be destroyed or
if it's already been done.

But fsnotify_add_mark sets the group and inode before it actually adds the
mark to the i_list and g_list. This can result in a race in inotify, it
requires 3 threads.

sys_inotify_add_watch("file") sys_inotify_add_watch("file") sys_inotify_rm_watch([a])
^--- returns wd = [a]
^--- returns wd = [b]
returns to userspace;
^--- gives us the pointer from task 1
^--- this is going to set the mark->group and mark->inode fields, but will
return -EEXIST because of the race with [b].
^--- since ->group != NULL we call back
into inotify_freeing_mark() which calls

since fsnotify_add_mark() failed we call:
inotify_remove_from_idr([a]) <------WHOOPS it's not in the idr, this could
have been any entry added later!

The fix is to make sure we don't set mark->group until we are sure the mark is
on the inode and fsnotify_add_mark will return success.

Signed-off-by: Eric Paris <eparis@xxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>

fs/notify/inode_mark.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

--- a/fs/notify/inode_mark.c
+++ b/fs/notify/inode_mark.c
@@ -324,11 +324,11 @@ int fsnotify_add_mark(struct fsnotify_ma

- entry->group = group;
- entry->inode = inode;
lentry = fsnotify_find_mark_entry(group, inode);
if (!lentry) {
+ entry->group = group;
+ entry->inode = inode;
hlist_add_head(&entry->i_list, &inode->i_fsnotify_mark_entries);
list_add(&entry->g_list, &group->mark_entries);

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/