Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

inotify: Fix reporting of cookies for inotify events

My rework of handling of notification events (namely commit 7053aee26a35
"fsnotify: do not share events between notification groups") broke
sending of cookies with inotify events. We didn't propagate the value
passed to fsnotify() properly and passed 4 uninitialized bytes to
userspace instead (so it is also an information leak). Sadly I didn't
notice this during my testing because inotify cookies aren't used very
much and LTP inotify tests ignore them.

Fix the problem by passing the cookie value properly.

Fixes: 7053aee26a3548ebaba046ae2e52396ccf56ac6c
Reported-by: Vegard Nossum <vegard.nossum@oracle.com>
Signed-off-by: Jan Kara <jack@suse.cz>

Jan Kara 45a22f4c 6d0abeca

+10 -9
+1 -1
fs/notify/dnotify/dnotify.c
··· 86 86 struct fsnotify_mark *inode_mark, 87 87 struct fsnotify_mark *vfsmount_mark, 88 88 u32 mask, void *data, int data_type, 89 - const unsigned char *file_name) 89 + const unsigned char *file_name, u32 cookie) 90 90 { 91 91 struct dnotify_mark *dn_mark; 92 92 struct dnotify_struct *dn;
+1 -1
fs/notify/fanotify/fanotify.c
··· 147 147 struct fsnotify_mark *inode_mark, 148 148 struct fsnotify_mark *fanotify_mark, 149 149 u32 mask, void *data, int data_type, 150 - const unsigned char *file_name) 150 + const unsigned char *file_name, u32 cookie) 151 151 { 152 152 int ret = 0; 153 153 struct fanotify_event_info *event;
+1 -1
fs/notify/fsnotify.c
··· 179 179 180 180 return group->ops->handle_event(group, to_tell, inode_mark, 181 181 vfsmount_mark, mask, data, data_is, 182 - file_name); 182 + file_name, cookie); 183 183 } 184 184 185 185 /*
+1 -1
fs/notify/inotify/inotify.h
··· 27 27 struct fsnotify_mark *inode_mark, 28 28 struct fsnotify_mark *vfsmount_mark, 29 29 u32 mask, void *data, int data_type, 30 - const unsigned char *file_name); 30 + const unsigned char *file_name, u32 cookie); 31 31 32 32 extern const struct fsnotify_ops inotify_fsnotify_ops;
+2 -1
fs/notify/inotify/inotify_fsnotify.c
··· 67 67 struct fsnotify_mark *inode_mark, 68 68 struct fsnotify_mark *vfsmount_mark, 69 69 u32 mask, void *data, int data_type, 70 - const unsigned char *file_name) 70 + const unsigned char *file_name, u32 cookie) 71 71 { 72 72 struct inotify_inode_mark *i_mark; 73 73 struct inotify_event_info *event; ··· 103 103 fsn_event = &event->fse; 104 104 fsnotify_init_event(fsn_event, inode, mask); 105 105 event->wd = i_mark->wd; 106 + event->sync_cookie = cookie; 106 107 event->name_len = len; 107 108 if (len) 108 109 strcpy(event->name, file_name);
+1 -1
fs/notify/inotify/inotify_user.c
··· 495 495 496 496 /* Queue ignore event for the watch */ 497 497 inotify_handle_event(group, NULL, fsn_mark, NULL, FS_IN_IGNORED, 498 - NULL, FSNOTIFY_EVENT_NONE, NULL); 498 + NULL, FSNOTIFY_EVENT_NONE, NULL, 0); 499 499 500 500 i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark); 501 501 /* remove this mark from the idr */
+1 -1
include/linux/fsnotify_backend.h
··· 99 99 struct fsnotify_mark *inode_mark, 100 100 struct fsnotify_mark *vfsmount_mark, 101 101 u32 mask, void *data, int data_type, 102 - const unsigned char *file_name); 102 + const unsigned char *file_name, u32 cookie); 103 103 void (*free_group_priv)(struct fsnotify_group *group); 104 104 void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group); 105 105 void (*free_event)(struct fsnotify_event *event);
+1 -1
kernel/audit_tree.c
··· 916 916 struct fsnotify_mark *inode_mark, 917 917 struct fsnotify_mark *vfsmount_mark, 918 918 u32 mask, void *data, int data_type, 919 - const unsigned char *file_name) 919 + const unsigned char *file_name, u32 cookie) 920 920 { 921 921 return 0; 922 922 }
+1 -1
kernel/audit_watch.c
··· 471 471 struct fsnotify_mark *inode_mark, 472 472 struct fsnotify_mark *vfsmount_mark, 473 473 u32 mask, void *data, int data_type, 474 - const unsigned char *dname) 474 + const unsigned char *dname, u32 cookie) 475 475 { 476 476 struct inode *inode; 477 477 struct audit_parent *parent;