@@ -592,21 +592,28 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *dir,
592
592
__kernel_fsid_t * fsid ,
593
593
const struct qstr * name ,
594
594
struct inode * child ,
595
+ struct dentry * moved ,
595
596
unsigned int * hash ,
596
597
gfp_t gfp )
597
598
{
598
599
struct fanotify_name_event * fne ;
599
600
struct fanotify_info * info ;
600
601
struct fanotify_fh * dfh , * ffh ;
602
+ struct inode * dir2 = moved ? d_inode (moved -> d_parent ) : NULL ;
603
+ const struct qstr * name2 = moved ? & moved -> d_name : NULL ;
601
604
unsigned int dir_fh_len = fanotify_encode_fh_len (dir );
605
+ unsigned int dir2_fh_len = fanotify_encode_fh_len (dir2 );
602
606
unsigned int child_fh_len = fanotify_encode_fh_len (child );
603
607
unsigned long name_len = name ? name -> len : 0 ;
608
+ unsigned long name2_len = name2 ? name2 -> len : 0 ;
604
609
unsigned int len , size ;
605
610
606
611
/* Reserve terminating null byte even for empty name */
607
- size = sizeof (* fne ) + name_len + 1 ;
612
+ size = sizeof (* fne ) + name_len + name2_len + 2 ;
608
613
if (dir_fh_len )
609
614
size += FANOTIFY_FH_HDR_LEN + dir_fh_len ;
615
+ if (dir2_fh_len )
616
+ size += FANOTIFY_FH_HDR_LEN + dir2_fh_len ;
610
617
if (child_fh_len )
611
618
size += FANOTIFY_FH_HDR_LEN + child_fh_len ;
612
619
fne = kmalloc (size , gfp );
@@ -623,6 +630,11 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *dir,
623
630
len = fanotify_encode_fh (dfh , dir , dir_fh_len , hash , 0 );
624
631
fanotify_info_set_dir_fh (info , len );
625
632
}
633
+ if (dir2_fh_len ) {
634
+ dfh = fanotify_info_dir2_fh (info );
635
+ len = fanotify_encode_fh (dfh , dir2 , dir2_fh_len , hash , 0 );
636
+ fanotify_info_set_dir2_fh (info , len );
637
+ }
626
638
if (child_fh_len ) {
627
639
ffh = fanotify_info_file_fh (info );
628
640
len = fanotify_encode_fh (ffh , child , child_fh_len , hash , 0 );
@@ -632,11 +644,22 @@ static struct fanotify_event *fanotify_alloc_name_event(struct inode *dir,
632
644
fanotify_info_copy_name (info , name );
633
645
* hash ^= full_name_hash ((void * )name_len , name -> name , name_len );
634
646
}
647
+ if (name2_len ) {
648
+ fanotify_info_copy_name2 (info , name2 );
649
+ * hash ^= full_name_hash ((void * )name2_len , name2 -> name ,
650
+ name2_len );
651
+ }
635
652
636
653
pr_debug ("%s: size=%u dir_fh_len=%u child_fh_len=%u name_len=%u name='%.*s'\n" ,
637
654
__func__ , size , dir_fh_len , child_fh_len ,
638
655
info -> name_len , info -> name_len , fanotify_info_name (info ));
639
656
657
+ if (dir2_fh_len ) {
658
+ pr_debug ("%s: dir2_fh_len=%u name2_len=%u name2='%.*s'\n" ,
659
+ __func__ , dir2_fh_len , info -> name2_len ,
660
+ info -> name2_len , fanotify_info_name2 (info ));
661
+ }
662
+
640
663
return & fne -> fae ;
641
664
}
642
665
@@ -692,6 +715,7 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
692
715
struct inode * dirid = fanotify_dfid_inode (mask , data , data_type , dir );
693
716
const struct path * path = fsnotify_data_path (data , data_type );
694
717
struct mem_cgroup * old_memcg ;
718
+ struct dentry * moved = NULL ;
695
719
struct inode * child = NULL ;
696
720
bool name_event = false;
697
721
unsigned int hash = 0 ;
@@ -727,6 +751,15 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
727
751
} else if ((mask & ALL_FSNOTIFY_DIRENT_EVENTS ) || !ondir ) {
728
752
name_event = true;
729
753
}
754
+
755
+ /*
756
+ * In the special case of FAN_RENAME event, we record both
757
+ * old and new parent+name.
758
+ * 'dirid' and 'file_name' are the old parent+name and
759
+ * 'moved' has the new parent+name.
760
+ */
761
+ if (mask & FAN_RENAME )
762
+ moved = fsnotify_data_dentry (data , data_type );
730
763
}
731
764
732
765
/*
@@ -748,9 +781,9 @@ static struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
748
781
} else if (fanotify_is_error_event (mask )) {
749
782
event = fanotify_alloc_error_event (group , fsid , data ,
750
783
data_type , & hash );
751
- } else if (name_event && (file_name || child )) {
752
- event = fanotify_alloc_name_event (id , fsid , file_name , child ,
753
- & hash , gfp );
784
+ } else if (name_event && (file_name || moved || child )) {
785
+ event = fanotify_alloc_name_event (dirid , fsid , file_name , child ,
786
+ moved , & hash , gfp );
754
787
} else if (fid_mode ) {
755
788
event = fanotify_alloc_fid_event (id , fsid , & hash , gfp );
756
789
} else {
@@ -860,6 +893,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask,
860
893
BUILD_BUG_ON (FAN_OPEN_EXEC != FS_OPEN_EXEC );
861
894
BUILD_BUG_ON (FAN_OPEN_EXEC_PERM != FS_OPEN_EXEC_PERM );
862
895
BUILD_BUG_ON (FAN_FS_ERROR != FS_ERROR );
896
+ BUILD_BUG_ON (FAN_RENAME != FS_RENAME );
863
897
864
898
BUILD_BUG_ON (HWEIGHT32 (ALL_FANOTIFY_EVENT_BITS ) != 20 );
865
899
0 commit comments