@@ -64,18 +64,27 @@ static int fanotify_fid_info_len(int fh_len, int name_len)
64
64
return roundup (FANOTIFY_INFO_HDR_LEN + info_len , FANOTIFY_EVENT_ALIGN );
65
65
}
66
66
67
- static int fanotify_event_info_len (struct fanotify_event * event )
67
+ static int fanotify_event_info_len (unsigned int fid_mode ,
68
+ struct fanotify_event * event )
68
69
{
69
70
struct fanotify_info * info = fanotify_event_info (event );
70
71
int dir_fh_len = fanotify_event_dir_fh_len (event );
71
72
int fh_len = fanotify_event_object_fh_len (event );
72
73
int info_len = 0 ;
74
+ int dot_len = 0 ;
73
75
74
- if (dir_fh_len )
76
+ if (dir_fh_len ) {
75
77
info_len += fanotify_fid_info_len (dir_fh_len , info -> name_len );
78
+ } else if ((fid_mode & FAN_REPORT_NAME ) && (event -> mask & FAN_ONDIR )) {
79
+ /*
80
+ * With group flag FAN_REPORT_NAME, if name was not recorded in
81
+ * event on a directory, we will report the name ".".
82
+ */
83
+ dot_len = 1 ;
84
+ }
76
85
77
86
if (fh_len )
78
- info_len += fanotify_fid_info_len (fh_len , 0 );
87
+ info_len += fanotify_fid_info_len (fh_len , dot_len );
79
88
80
89
return info_len ;
81
90
}
@@ -91,15 +100,16 @@ static struct fanotify_event *get_one_event(struct fsnotify_group *group,
91
100
{
92
101
size_t event_size = FAN_EVENT_METADATA_LEN ;
93
102
struct fanotify_event * event = NULL ;
103
+ unsigned int fid_mode = FAN_GROUP_FLAG (group , FANOTIFY_FID_BITS );
94
104
95
105
pr_debug ("%s: group=%p count=%zd\n" , __func__ , group , count );
96
106
97
107
spin_lock (& group -> notification_lock );
98
108
if (fsnotify_notify_queue_is_empty (group ))
99
109
goto out ;
100
110
101
- if (FAN_GROUP_FLAG ( group , FANOTIFY_FID_BITS ) ) {
102
- event_size += fanotify_event_info_len (
111
+ if (fid_mode ) {
112
+ event_size += fanotify_event_info_len (fid_mode ,
103
113
FANOTIFY_E (fsnotify_peek_first_event (group )));
104
114
}
105
115
@@ -325,7 +335,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
325
335
pr_debug ("%s: group=%p event=%p\n" , __func__ , group , event );
326
336
327
337
metadata .event_len = FAN_EVENT_METADATA_LEN +
328
- fanotify_event_info_len (event );
338
+ fanotify_event_info_len (fid_mode , event );
329
339
metadata .metadata_len = FAN_EVENT_METADATA_LEN ;
330
340
metadata .vers = FANOTIFY_METADATA_VERSION ;
331
341
metadata .reserved = 0 ;
@@ -374,12 +384,25 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
374
384
}
375
385
376
386
if (fanotify_event_object_fh_len (event )) {
387
+ const char * dot = NULL ;
388
+ int dot_len = 0 ;
389
+
377
390
if (fid_mode == FAN_REPORT_FID || info_type ) {
378
391
/*
379
392
* With only group flag FAN_REPORT_FID only type FID is
380
393
* reported. Second info record type is always FID.
381
394
*/
382
395
info_type = FAN_EVENT_INFO_TYPE_FID ;
396
+ } else if ((fid_mode & FAN_REPORT_NAME ) &&
397
+ (event -> mask & FAN_ONDIR )) {
398
+ /*
399
+ * With group flag FAN_REPORT_NAME, if name was not
400
+ * recorded in an event on a directory, report the
401
+ * name "." with info type DFID_NAME.
402
+ */
403
+ info_type = FAN_EVENT_INFO_TYPE_DFID_NAME ;
404
+ dot = "." ;
405
+ dot_len = 1 ;
383
406
} else if ((event -> mask & ALL_FSNOTIFY_DIRENT_EVENTS ) ||
384
407
(event -> mask & FAN_ONDIR )) {
385
408
/*
@@ -400,7 +423,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
400
423
401
424
ret = copy_info_to_user (fanotify_event_fsid (event ),
402
425
fanotify_event_object_fh (event ),
403
- info_type , NULL , 0 , buf , count );
426
+ info_type , dot , dot_len , buf , count );
404
427
if (ret < 0 )
405
428
return ret ;
406
429
@@ -932,11 +955,15 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
932
955
if (fid_mode && class != FAN_CLASS_NOTIF )
933
956
return - EINVAL ;
934
957
935
- /* Reporting either object fid or dir fid */
958
+ /*
959
+ * Reporting either object fid or dir fid.
960
+ * Child name is reported with parent fid so requires dir fid.
961
+ */
936
962
switch (fid_mode ) {
937
963
case 0 :
938
964
case FAN_REPORT_FID :
939
965
case FAN_REPORT_DIR_FID :
966
+ case FAN_REPORT_DFID_NAME :
940
967
break ;
941
968
default :
942
969
return - EINVAL ;
@@ -1294,7 +1321,7 @@ COMPAT_SYSCALL_DEFINE6(fanotify_mark,
1294
1321
*/
1295
1322
static int __init fanotify_user_setup (void )
1296
1323
{
1297
- BUILD_BUG_ON (HWEIGHT32 (FANOTIFY_INIT_FLAGS ) != 9 );
1324
+ BUILD_BUG_ON (HWEIGHT32 (FANOTIFY_INIT_FLAGS ) != 10 );
1298
1325
BUILD_BUG_ON (HWEIGHT32 (FANOTIFY_MARK_FLAGS ) != 9 );
1299
1326
1300
1327
fanotify_mark_cache = KMEM_CACHE (fsnotify_mark ,
0 commit comments