@@ -284,8 +284,9 @@ static int fanotify_get_response(struct fsnotify_group *group,
284
284
*/
285
285
static u32 fanotify_group_event_mask (struct fsnotify_group * group ,
286
286
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 )
289
290
{
290
291
__u32 marks_mask = 0 , marks_ignored_mask = 0 ;
291
292
__u32 test_mask , user_mask = FANOTIFY_OUTGOING_EVENTS |
@@ -335,6 +336,9 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group,
335
336
continue ;
336
337
337
338
marks_mask |= mark -> mask ;
339
+
340
+ /* Record the mark types of this group that matched the event */
341
+ * match_mask |= 1U << type ;
338
342
}
339
343
340
344
test_mask = event_mask & marks_mask & ~marks_ignored_mask ;
@@ -701,11 +705,11 @@ static struct fanotify_event *fanotify_alloc_error_event(
701
705
return & fee -> fae ;
702
706
}
703
707
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 )
709
713
{
710
714
struct fanotify_event * event = NULL ;
711
715
gfp_t gfp = GFP_KERNEL_ACCOUNT ;
@@ -753,13 +757,36 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
753
757
}
754
758
755
759
/*
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.
758
763
* 'dirid' and 'file_name' are the old parent+name and
759
764
* 'moved' has the new parent+name.
760
765
*/
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
+ }
763
790
}
764
791
765
792
/*
@@ -872,6 +899,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,
872
899
struct fanotify_event * event ;
873
900
struct fsnotify_event * fsn_event ;
874
901
__kernel_fsid_t fsid = {};
902
+ u32 match_mask = 0 ;
875
903
876
904
BUILD_BUG_ON (FAN_ACCESS != FS_ACCESS );
877
905
BUILD_BUG_ON (FAN_MODIFY != FS_MODIFY );
@@ -897,12 +925,13 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,
897
925
898
926
BUILD_BUG_ON (HWEIGHT32 (ALL_FANOTIFY_EVENT_BITS ) != 20 );
899
927
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 );
902
930
if (!mask )
903
931
return 0 ;
904
932
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 );
906
935
907
936
if (fanotify_is_perm_event (mask )) {
908
937
/*
@@ -921,7 +950,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,
921
950
}
922
951
923
952
event = fanotify_alloc_event (group , mask , data , data_type , dir ,
924
- file_name , & fsid );
953
+ file_name , & fsid , match_mask );
925
954
ret = - ENOMEM ;
926
955
if (unlikely (!event )) {
927
956
/*
0 commit comments