From 528da3e9e237059a84a2625e942811cf824a6efd Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Fri, 12 Jun 2009 16:04:26 -0400 Subject: inotify: inotify_destroy_mark_entry could get called twice inotify_destroy_mark_entry could get called twice for the same mark since it is called directly in inotify_rm_watch and when the mark is being destroyed for another reason. As an example assume that the file being watched was just deleted so inotify_destroy_mark_entry would get called from the path fsnotify_inoderemove() -> fsnotify_destroy_marks_by_inode() -> fsnotify_destroy_mark_entry() -> inotify_destroy_mark_entry(). If this happened at the same time as userspace tried to remove a watch via inotify_rm_watch we could attempt to remove the mark from the idr twice and could thus double dec the ref cnt and potentially could be in a use after free/double free situation. The fix is to have inotify_rm_watch use the generic recursive safe fsnotify_destroy_mark_by_entry() so we are sure the inotify_destroy_mark_entry() function can only be called one. This patch also renames the function to inotify_ingored_remove_idr() so it is clear what is actually going on in the function. Hopefully this fixes: [ 20.342058] idr_remove called for id=20 which is not allocated. [ 20.348000] Pid: 1860, comm: udevd Not tainted 2.6.30-tip #1077 [ 20.353933] Call Trace: [ 20.356410] [] idr_remove+0x115/0x18f [ 20.361737] [] ? _spin_lock+0x6d/0x75 [ 20.367061] [] ? inotify_destroy_mark_entry+0xa3/0xcf [ 20.373771] [] inotify_destroy_mark_entry+0xb7/0xcf [ 20.380306] [] inotify_freeing_mark+0xe/0x10 [ 20.386238] [] fsnotify_destroy_mark_by_entry+0x143/0x170 [ 20.393293] [] inotify_destroy_mark_entry+0x3c/0xcf [ 20.399829] [] sys_inotify_rm_watch+0x9b/0xc6 [ 20.405850] [] system_call_fastpath+0x16/0x1b Reported-by: Peter Zijlstra Signed-off-by: Eric Paris Tested-by: Peter Ziljlstra --- fs/notify/inotify/inotify_fsnotify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/notify/inotify/inotify_fsnotify.c') diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index 7ef75b83247..47cd258fd24 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -81,7 +81,7 @@ static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_ev static void inotify_freeing_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group) { - inotify_destroy_mark_entry(entry, group); + inotify_ignored_and_remove_idr(entry, group); } static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode, __u32 mask) -- cgit v1.2.3