Commit c285a2f0 authored by Amir Goldstein's avatar Amir Goldstein Committed by Jan Kara
Browse files

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: default avatar <syzbot+c277e8e2f46414645508@syzkaller.appspotmail.com>
Fixes: 77115225 ("fanotify: cache fsid in fsnotify_mark_connector")
Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent c6d9c35d
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -355,6 +355,10 @@ static __kernel_fsid_t fanotify_get_fsid(struct fsnotify_iter_info *iter_info)
		/* Mark is just getting destroyed or created? */
		if (!conn)
			continue;
		if (!(conn->flags & FSNOTIFY_CONN_FLAG_HAS_FSID))
			continue;
		/* Pairs with smp_wmb() in fsnotify_add_mark_list() */
		smp_rmb();
		fsid = conn->fsid;
		if (WARN_ON_ONCE(!fsid.val[0] && !fsid.val[1]))
			continue;
+11 −3
Original line number Diff line number Diff line
@@ -482,10 +482,13 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
	conn->type = type;
	conn->obj = connp;
	/* Cache fsid of filesystem containing the object */
	if (fsid)
	if (fsid) {
		conn->fsid = *fsid;
	else
		conn->flags = FSNOTIFY_CONN_FLAG_HAS_FSID;
	} else {
		conn->fsid.val[0] = conn->fsid.val[1] = 0;
		conn->flags = 0;
	}
	if (conn->type == FSNOTIFY_OBJ_TYPE_INODE)
		inode = igrab(fsnotify_conn_inode(conn));
	/*
@@ -560,7 +563,12 @@ restart:
		if (err)
			return err;
		goto restart;
	} else if (fsid && (conn->fsid.val[0] || conn->fsid.val[1]) &&
	} else if (fsid && !(conn->flags & FSNOTIFY_CONN_FLAG_HAS_FSID)) {
		conn->fsid = *fsid;
		/* Pairs with smp_rmb() in fanotify_get_fsid() */
		smp_wmb();
		conn->flags |= FSNOTIFY_CONN_FLAG_HAS_FSID;
	} else if (fsid && (conn->flags & FSNOTIFY_CONN_FLAG_HAS_FSID) &&
		   (fsid->val[0] != conn->fsid.val[0] ||
		    fsid->val[1] != conn->fsid.val[1])) {
		/*
+3 −1
Original line number Diff line number Diff line
@@ -292,7 +292,9 @@ typedef struct fsnotify_mark_connector __rcu *fsnotify_connp_t;
 */
struct fsnotify_mark_connector {
	spinlock_t lock;
	unsigned int type;	/* Type of object [lock] */
	unsigned short type;	/* Type of object [lock] */
#define FSNOTIFY_CONN_FLAG_HAS_FSID	0x01
	unsigned short flags;	/* flags [lock] */
	__kernel_fsid_t fsid;	/* fsid of filesystem containing object */
	union {
		/* Object pointer [lock] */