summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2019-06-19 06:34:44 -0400
committerJan Kara <jack@suse.cz>2019-06-19 09:53:58 -0400
commitc285a2f01d692ef48d7243cf1072897bbd237407 (patch)
treed6959488584787c33c90c971805e48920831289f
parentc6d9c35d16f1bafd3fec64b865e569e48cbcb514 (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.c4
-rw-r--r--fs/notify/mark.c14
-rw-r--r--include/linux/fsnotify_backend.h4
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 */
293struct fsnotify_mark_connector { 293struct 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] */