@@ -284,8 +284,9 @@ static int fanotify_get_response(struct fsnotify_group *group,
284284 */
285285static u32 fanotify_group_event_mask (struct fsnotify_group * group ,
286286 struct fsnotify_iter_info * iter_info ,
287- u32 event_mask , const void * data ,
288- int data_type , struct inode * dir )
287+ u32 * match_mask , u32 event_mask ,
288+ const void * data , int data_type ,
289+ struct inode * dir )
289290{
290291 __u32 marks_mask = 0 , marks_ignored_mask = 0 ;
291292 __u32 test_mask , user_mask = FANOTIFY_OUTGOING_EVENTS |
@@ -335,6 +336,9 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group,
335336 continue ;
336337
337338 marks_mask |= mark -> mask ;
339+
340+ /* Record the mark types of this group that matched the event */
341+ * match_mask |= 1U << type ;
338342 }
339343
340344 test_mask = event_mask & marks_mask & ~marks_ignored_mask ;
@@ -701,11 +705,11 @@ static struct fanotify_event *fanotify_alloc_error_event(
701705 return & fee -> fae ;
702706}
703707
704- static struct fanotify_event * fanotify_alloc_event (struct fsnotify_group * group ,
705- u32 mask , const void * data ,
706- int data_type , struct inode * dir ,
707- const struct qstr * file_name ,
708- __kernel_fsid_t * fsid )
708+ static struct fanotify_event * fanotify_alloc_event (
709+ struct fsnotify_group * group ,
710+ u32 mask , const void * data , int data_type ,
711+ struct inode * dir , const struct qstr * file_name ,
712+ __kernel_fsid_t * fsid , u32 match_mask )
709713{
710714 struct fanotify_event * event = NULL ;
711715 gfp_t gfp = GFP_KERNEL_ACCOUNT ;
@@ -753,13 +757,36 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
753757 }
754758
755759 /*
756- * In the special case of FAN_RENAME event, we record both
757- * old and new parent+name.
760+ * In the special case of FAN_RENAME event, use the match_mask
761+ * to determine if we need to report only the old parent+name,
762+ * only the new parent+name or both.
758763 * 'dirid' and 'file_name' are the old parent+name and
759764 * 'moved' has the new parent+name.
760765 */
761- if (mask & FAN_RENAME )
762- moved = fsnotify_data_dentry (data , data_type );
766+ if (mask & FAN_RENAME ) {
767+ bool report_old , report_new ;
768+
769+ if (WARN_ON_ONCE (!match_mask ))
770+ return NULL ;
771+
772+ /* Report both old and new parent+name if sb watching */
773+ report_old = report_new =
774+ match_mask & (1U << FSNOTIFY_ITER_TYPE_SB );
775+ report_old |=
776+ match_mask & (1U << FSNOTIFY_ITER_TYPE_INODE );
777+ report_new |=
778+ match_mask & (1U << FSNOTIFY_ITER_TYPE_INODE2 );
779+
780+ if (!report_old ) {
781+ /* Do not report old parent+name */
782+ dirid = NULL ;
783+ file_name = NULL ;
784+ }
785+ if (report_new ) {
786+ /* Report new parent+name */
787+ moved = fsnotify_data_dentry (data , data_type );
788+ }
789+ }
763790 }
764791
765792 /*
@@ -872,6 +899,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,
872899 struct fanotify_event * event ;
873900 struct fsnotify_event * fsn_event ;
874901 __kernel_fsid_t fsid = {};
902+ u32 match_mask = 0 ;
875903
876904 BUILD_BUG_ON (FAN_ACCESS != FS_ACCESS );
877905 BUILD_BUG_ON (FAN_MODIFY != FS_MODIFY );
@@ -897,12 +925,13 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,
897925
898926 BUILD_BUG_ON (HWEIGHT32 (ALL_FANOTIFY_EVENT_BITS ) != 20 );
899927
900- mask = fanotify_group_event_mask (group , iter_info , mask , data ,
901- data_type , dir );
928+ mask = fanotify_group_event_mask (group , iter_info , & match_mask ,
929+ mask , data , data_type , dir );
902930 if (!mask )
903931 return 0 ;
904932
905- pr_debug ("%s: group=%p mask=%x\n" , __func__ , group , mask );
933+ pr_debug ("%s: group=%p mask=%x report_mask=%x\n" , __func__ ,
934+ group , mask , match_mask );
906935
907936 if (fanotify_is_perm_event (mask )) {
908937 /*
@@ -921,7 +950,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,
921950 }
922951
923952 event = fanotify_alloc_event (group , mask , data , data_type , dir ,
924- file_name , & fsid );
953+ file_name , & fsid , match_mask );
925954 ret = - ENOMEM ;
926955 if (unlikely (!event )) {
927956 /*
0 commit comments