diff options
author | Eric Paris <eparis@redhat.com> | 2010-08-18 18:25:49 +0200 |
---|---|---|
committer | Eric Paris <eparis@redhat.com> | 2010-08-23 02:09:41 +0200 |
commit | faa9560ae76ef50a3cbfb1a6afc0343fd8172374 (patch) | |
tree | b62dcdece22b214d0e0c75848b4d02b8e9923d0c | |
parent | Merge branch 'kvm-updates/2.6.36' of git://git.kernel.org/pub/scm/virt/kvm/kvm (diff) | |
download | linux-faa9560ae76ef50a3cbfb1a6afc0343fd8172374.tar.xz linux-faa9560ae76ef50a3cbfb1a6afc0343fd8172374.zip |
fanotify: do not dereference inode_mark when it is unset
The fanotify code is supposed to get the group from the mark. It accidentally
only used the inode_mark. If the vfsmount_mark was set but not the inode_mark
it would deref the NULL inode_mark. Get the group from the correct place.
Reported-by: Tvrtko Ursulin <tvrtko.ursulin@sophos.com>
Signed-off-by: Eric Paris <eparis@redhat.com>
-rw-r--r-- | fs/notify/fsnotify.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 3970392b2722..f3e3b355ba7f 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -148,13 +148,14 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt, const unsigned char *file_name, struct fsnotify_event **event) { - struct fsnotify_group *group = inode_mark->group; + struct fsnotify_group *group = NULL; __u32 inode_test_mask = (mask & ~FS_EVENT_ON_CHILD); __u32 vfsmount_test_mask = (mask & ~FS_EVENT_ON_CHILD); - pr_debug("%s: group=%p to_tell=%p mnt=%p mark=%p mask=%x data=%p" - " data_is=%d cookie=%d event=%p\n", __func__, group, to_tell, - mnt, inode_mark, mask, data, data_is, cookie, *event); + if (unlikely(!inode_mark && !vfsmount_mark)) { + BUG(); + return 0; + } /* clear ignored on inode modification */ if (mask & FS_MODIFY) { @@ -168,18 +169,24 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt, /* does the inode mark tell us to do something? */ if (inode_mark) { + group = inode_mark->group; inode_test_mask &= inode_mark->mask; inode_test_mask &= ~inode_mark->ignored_mask; } /* does the vfsmount_mark tell us to do something? */ if (vfsmount_mark) { + group = vfsmount_mark->group; vfsmount_test_mask &= vfsmount_mark->mask; vfsmount_test_mask &= ~vfsmount_mark->ignored_mask; if (inode_mark) vfsmount_test_mask &= ~inode_mark->ignored_mask; } + pr_debug("%s: group=%p to_tell=%p mnt=%p mark=%p mask=%x data=%p" + " data_is=%d cookie=%d event=%p\n", __func__, group, to_tell, + mnt, inode_mark, mask, data, data_is, cookie, *event); + if (!inode_test_mask && !vfsmount_test_mask) return 0; |