17
17
18
18
#include "fanotify.h"
19
19
20
+ static bool fanotify_path_equal (struct path * p1 , struct path * p2 )
21
+ {
22
+ return p1 -> mnt == p2 -> mnt && p1 -> dentry == p2 -> dentry ;
23
+ }
24
+
25
+ static inline bool fanotify_fsid_equal (__kernel_fsid_t * fsid1 ,
26
+ __kernel_fsid_t * fsid2 )
27
+ {
28
+ return fsid1 -> val [0 ] == fsid1 -> val [0 ] && fsid2 -> val [1 ] == fsid2 -> val [1 ];
29
+ }
30
+
31
+ static bool fanotify_fh_equal (struct fanotify_fh * fh1 ,
32
+ struct fanotify_fh * fh2 )
33
+ {
34
+ if (fh1 -> type != fh2 -> type || fh1 -> len != fh2 -> len )
35
+ return false;
36
+
37
+ /* Do not merge events if we failed to encode fh */
38
+ if (fh1 -> type == FILEID_INVALID )
39
+ return false;
40
+
41
+ return !fh1 -> len ||
42
+ !memcmp (fanotify_fh_buf (fh1 ), fanotify_fh_buf (fh2 ), fh1 -> len );
43
+ }
44
+
20
45
static bool should_merge (struct fsnotify_event * old_fsn ,
21
46
struct fsnotify_event * new_fsn )
22
47
{
@@ -27,12 +52,12 @@ static bool should_merge(struct fsnotify_event *old_fsn,
27
52
new = FANOTIFY_E (new_fsn );
28
53
29
54
if (old_fsn -> objectid != new_fsn -> objectid || old -> pid != new -> pid ||
30
- old -> fh_type != new -> fh_type || old -> fh_len != new -> fh_len )
55
+ old -> fh . type != new -> fh . type )
31
56
return false;
32
57
33
58
if (fanotify_event_has_path (old )) {
34
- return old -> path . mnt == new -> path . mnt &&
35
- old -> path . dentry == new -> path . dentry ;
59
+ return fanotify_path_equal ( fanotify_event_path ( old ),
60
+ fanotify_event_path ( new )) ;
36
61
} else if (fanotify_event_has_fid (old )) {
37
62
/*
38
63
* We want to merge many dirent events in the same dir (i.e.
@@ -42,8 +67,11 @@ static bool should_merge(struct fsnotify_event *old_fsn,
42
67
* mask FAN_CREATE|FAN_DELETE|FAN_ONDIR if it describes mkdir+
43
68
* unlink pair or rmdir+create pair of events.
44
69
*/
45
- return (old -> mask & FS_ISDIR ) == (new -> mask & FS_ISDIR ) &&
46
- fanotify_fid_equal (& old -> fid , & new -> fid , old -> fh_len );
70
+ if ((old -> mask & FS_ISDIR ) != (new -> mask & FS_ISDIR ))
71
+ return false;
72
+
73
+ return fanotify_fsid_equal (& old -> fsid , & new -> fsid ) &&
74
+ fanotify_fh_equal (& old -> fh , & new -> fh );
47
75
}
48
76
49
77
/* Do not merge events if we failed to encode fid */
@@ -213,15 +241,14 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group,
213
241
return test_mask & user_mask ;
214
242
}
215
243
216
- static int fanotify_encode_fid (struct fanotify_event * event ,
217
- struct inode * inode , gfp_t gfp ,
218
- __kernel_fsid_t * fsid )
244
+ static void fanotify_encode_fh (struct fanotify_fh * fh , struct inode * inode ,
245
+ gfp_t gfp )
219
246
{
220
- struct fanotify_fid * fid = & event -> fid ;
221
- int dwords , bytes = 0 ;
222
- int err , type ;
247
+ int dwords , type , bytes = 0 ;
248
+ char * ext_buf = NULL ;
249
+ void * buf = fh -> buf ;
250
+ int err ;
223
251
224
- fid -> ext_fh = NULL ;
225
252
dwords = 0 ;
226
253
err = - ENOENT ;
227
254
type = exportfs_encode_inode_fh (inode , NULL , & dwords , NULL );
@@ -232,31 +259,32 @@ static int fanotify_encode_fid(struct fanotify_event *event,
232
259
if (bytes > FANOTIFY_INLINE_FH_LEN ) {
233
260
/* Treat failure to allocate fh as failure to allocate event */
234
261
err = - ENOMEM ;
235
- fid -> ext_fh = kmalloc (bytes , gfp );
236
- if (!fid -> ext_fh )
262
+ ext_buf = kmalloc (bytes , gfp );
263
+ if (!ext_buf )
237
264
goto out_err ;
265
+
266
+ * fanotify_fh_ext_buf_ptr (fh ) = ext_buf ;
267
+ buf = ext_buf ;
238
268
}
239
269
240
- type = exportfs_encode_inode_fh (inode , fanotify_fid_fh (fid , bytes ),
241
- & dwords , NULL );
270
+ type = exportfs_encode_inode_fh (inode , buf , & dwords , NULL );
242
271
err = - EINVAL ;
243
272
if (!type || type == FILEID_INVALID || bytes != dwords << 2 )
244
273
goto out_err ;
245
274
246
- fid -> fsid = * fsid ;
247
- event -> fh_len = bytes ;
275
+ fh -> type = type ;
276
+ fh -> len = bytes ;
248
277
249
- return type ;
278
+ return ;
250
279
251
280
out_err :
252
- pr_warn_ratelimited ("fanotify: failed to encode fid (fsid=%x.%x, "
253
- "type=%d, bytes=%d, err=%i)\n" ,
254
- fsid -> val [0 ], fsid -> val [1 ], type , bytes , err );
255
- kfree (fid -> ext_fh );
256
- fid -> ext_fh = NULL ;
257
- event -> fh_len = 0 ;
258
-
259
- return FILEID_INVALID ;
281
+ pr_warn_ratelimited ("fanotify: failed to encode fid (type=%d, len=%d, err=%i)\n" ,
282
+ type , bytes , err );
283
+ kfree (ext_buf );
284
+ * fanotify_fh_ext_buf_ptr (fh ) = NULL ;
285
+ /* Report the event without a file identifier on encode error */
286
+ fh -> type = FILEID_INVALID ;
287
+ fh -> len = 0 ;
260
288
}
261
289
262
290
/*
@@ -326,16 +354,17 @@ init: __maybe_unused
326
354
event -> pid = get_pid (task_pid (current ));
327
355
else
328
356
event -> pid = get_pid (task_tgid (current ));
329
- event -> fh_len = 0 ;
357
+ event -> fh . len = 0 ;
330
358
if (id && FAN_GROUP_FLAG (group , FAN_REPORT_FID )) {
331
- /* Report the event without a file identifier on encode error */
332
- event -> fh_type = fanotify_encode_fid (event , id , gfp , fsid );
359
+ event -> fsid = * fsid ;
360
+ if (id )
361
+ fanotify_encode_fh (& event -> fh , id , gfp );
333
362
} else if (path ) {
334
- event -> fh_type = FILEID_ROOT ;
363
+ event -> fh . type = FILEID_ROOT ;
335
364
event -> path = * path ;
336
365
path_get (path );
337
366
} else {
338
- event -> fh_type = FILEID_INVALID ;
367
+ event -> fh . type = FILEID_INVALID ;
339
368
event -> path .mnt = NULL ;
340
369
event -> path .dentry = NULL ;
341
370
}
@@ -483,8 +512,8 @@ static void fanotify_free_event(struct fsnotify_event *fsn_event)
483
512
event = FANOTIFY_E (fsn_event );
484
513
if (fanotify_event_has_path (event ))
485
514
path_put (& event -> path );
486
- else if (fanotify_event_has_ext_fh ( event ))
487
- kfree (event -> fid . ext_fh );
515
+ else if (fanotify_fh_has_ext_buf ( & event -> fh ))
516
+ kfree (fanotify_fh_ext_buf ( & event -> fh ) );
488
517
put_pid (event -> pid );
489
518
if (fanotify_is_perm_event (event -> mask )) {
490
519
kmem_cache_free (fanotify_perm_event_cachep ,
0 commit comments