diff options
author | Amir Goldstein <amir73il@gmail.com> | 2019-06-19 06:34:44 -0400 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2019-06-19 09:53:58 -0400 |
commit | c285a2f01d692ef48d7243cf1072897bbd237407 (patch) | |
tree | d6959488584787c33c90c971805e48920831289f | |
parent | c6d9c35d16f1bafd3fec64b865e569e48cbcb514 (diff) |
fanotify: update connector fsid cache on add mark
When implementing connector fsid cache, we only initialized the cache
when the first mark added to object was added by FAN_REPORT_FID group.
We forgot to update conn->fsid when the second mark is added by
FAN_REPORT_FID group to an already attached connector without fsid
cache.
Reported-and-tested-by: syzbot+c277e8e2f46414645508@syzkaller.appspotmail.com
Fixes: 77115225acc6 ("fanotify: cache fsid in fsnotify_mark_connector")
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
-rw-r--r-- | fs/notify/fanotify/fanotify.c | 4 | ||||
-rw-r--r-- | fs/notify/mark.c | 14 | ||||
-rw-r--r-- | include/linux/fsnotify_backend.h | 4 |
3 files changed, 18 insertions, 4 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index e6fde1a5c072..b428c295d13f 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c | |||
@@ -355,6 +355,10 @@ static __kernel_fsid_t fanotify_get_fsid(struct fsnotify_iter_info *iter_info) | |||
355 | /* Mark is just getting destroyed or created? */ | 355 | /* Mark is just getting destroyed or created? */ |
356 | if (!conn) | 356 | if (!conn) |
357 | continue; | 357 | continue; |
358 | if (!(conn->flags & FSNOTIFY_CONN_FLAG_HAS_FSID)) | ||
359 | continue; | ||
360 | /* Pairs with smp_wmb() in fsnotify_add_mark_list() */ | ||
361 | smp_rmb(); | ||
358 | fsid = conn->fsid; | 362 | fsid = conn->fsid; |
359 | if (WARN_ON_ONCE(!fsid.val[0] && !fsid.val[1])) | 363 | if (WARN_ON_ONCE(!fsid.val[0] && !fsid.val[1])) |
360 | continue; | 364 | continue; |
diff --git a/fs/notify/mark.c b/fs/notify/mark.c index 25eb247ea85a..99ddd126f6f0 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c | |||
@@ -482,10 +482,13 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp, | |||
482 | conn->type = type; | 482 | conn->type = type; |
483 | conn->obj = connp; | 483 | conn->obj = connp; |
484 | /* Cache fsid of filesystem containing the object */ | 484 | /* Cache fsid of filesystem containing the object */ |
485 | if (fsid) | 485 | if (fsid) { |
486 | conn->fsid = *fsid; | 486 | conn->fsid = *fsid; |
487 | else | 487 | conn->flags = FSNOTIFY_CONN_FLAG_HAS_FSID; |
488 | } else { | ||
488 | conn->fsid.val[0] = conn->fsid.val[1] = 0; | 489 | conn->fsid.val[0] = conn->fsid.val[1] = 0; |
490 | conn->flags = 0; | ||
491 | } | ||
489 | if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) | 492 | if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) |
490 | inode = igrab(fsnotify_conn_inode(conn)); | 493 | inode = igrab(fsnotify_conn_inode(conn)); |
491 | /* | 494 | /* |
@@ -560,7 +563,12 @@ restart: | |||
560 | if (err) | 563 | if (err) |
561 | return err; | 564 | return err; |
562 | goto restart; | 565 | goto restart; |
563 | } else if (fsid && (conn->fsid.val[0] || conn->fsid.val[1]) && | 566 | } else if (fsid && !(conn->flags & FSNOTIFY_CONN_FLAG_HAS_FSID)) { |
567 | conn->fsid = *fsid; | ||
568 | /* Pairs with smp_rmb() in fanotify_get_fsid() */ | ||
569 | smp_wmb(); | ||
570 | conn->flags |= FSNOTIFY_CONN_FLAG_HAS_FSID; | ||
571 | } else if (fsid && (conn->flags & FSNOTIFY_CONN_FLAG_HAS_FSID) && | ||
564 | (fsid->val[0] != conn->fsid.val[0] || | 572 | (fsid->val[0] != conn->fsid.val[0] || |
565 | fsid->val[1] != conn->fsid.val[1])) { | 573 | fsid->val[1] != conn->fsid.val[1])) { |
566 | /* | 574 | /* |
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index a9f9dcc1e515..d4844cad2c2b 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h | |||
@@ -292,7 +292,9 @@ typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t; | |||
292 | */ | 292 | */ |
293 | struct fsnotify_mark_connector { | 293 | struct fsnotify_mark_connector { |
294 | spinlock_t lock; | 294 | spinlock_t lock; |
295 | unsigned int type; /* Type of object [lock] */ | 295 | unsigned short type; /* Type of object [lock] */ |
296 | #define FSNOTIFY_CONN_FLAG_HAS_FSID 0x01 | ||
297 | unsigned short flags; /* flags [lock] */ | ||
296 | __kernel_fsid_t fsid; /* fsid of filesystem containing object */ | 298 | __kernel_fsid_t fsid; /* fsid of filesystem containing object */ |
297 | union { | 299 | union { |
298 | /* Object pointer [lock] */ | 300 | /* Object pointer [lock] */ |