[PATCH] inotify: fix race between the kernel and user space

When you rm a watch, an IN_IGNORED event is sent down the event queue
with the watch descriptor that you just rm'd.

If you then add a watch you could get the ignored watch's wd and if you
haven't read the entire event queue, user space will think that it's
newly created watch was just ignored.

To avoid this problem we just use idr_get_new_above instead of
idr_get_new.

Signed-off-by: John McCutchan <ttb@tentacle.dhs.org>
Signed-off-by: Robert Love <rml@novell.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
diff --git a/fs/inotify.c b/fs/inotify.c
index a8a714e..27ebcac 100644
--- a/fs/inotify.c
+++ b/fs/inotify.c
@@ -90,6 +90,7 @@
 	unsigned int		queue_size;	/* size of the queue (bytes) */
 	unsigned int		event_count;	/* number of pending events */
 	unsigned int		max_events;	/* maximum number of events */
+	u32			last_wd;	/* the last wd allocated */
 };
 
 /*
@@ -352,7 +353,7 @@
 	do {
 		if (unlikely(!idr_pre_get(&dev->idr, GFP_KERNEL)))
 			return -ENOSPC;
-		ret = idr_get_new(&dev->idr, watch, &watch->wd);
+		ret = idr_get_new_above(&dev->idr, watch, dev->last_wd, &watch->wd);
 	} while (ret == -EAGAIN);
 
 	return ret;
@@ -401,6 +402,7 @@
 		return ERR_PTR(ret);
 	}
 
+	dev->last_wd = ret;
 	watch->mask = mask;
 	atomic_set(&watch->count, 0);
 	INIT_LIST_HEAD(&watch->d_list);
@@ -899,6 +901,7 @@
 	dev->queue_size = 0;
 	dev->max_events = inotify_max_queued_events;
 	dev->user = user;
+	dev->last_wd = 0;
 	atomic_set(&dev->count, 0);
 
 	get_inotify_dev(dev);