Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Amir Goldstein and committed by
Jan Kara
c285a2f0 c6d9c35d

+18 -4
+4
fs/notify/fanotify/fanotify.c
··· 355 355 /* Mark is just getting destroyed or created? */ 356 356 if (!conn) 357 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 362 fsid = conn->fsid; 359 363 if (WARN_ON_ONCE(!fsid.val[0] && !fsid.val[1])) 360 364 continue;
+11 -3
fs/notify/mark.c
··· 482 482 conn->type = type; 483 483 conn->obj = connp; 484 484 /* Cache fsid of filesystem containing the object */ 485 - if (fsid) 485 + if (fsid) { 486 486 conn->fsid = *fsid; 487 - else 487 + conn->flags = FSNOTIFY_CONN_FLAG_HAS_FSID; 488 + } else { 488 489 conn->fsid.val[0] = conn->fsid.val[1] = 0; 490 + conn->flags = 0; 491 + } 489 492 if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) 490 493 inode = igrab(fsnotify_conn_inode(conn)); 491 494 /* ··· 563 560 if (err) 564 561 return err; 565 562 goto restart; 566 - } else if (fsid && (conn->fsid.val[0] || conn->fsid.val[1]) && 563 + } else if (fsid && !(conn->flags & FSNOTIFY_CONN_FLAG_HAS_FSID)) { 564 + conn->fsid = *fsid; 565 + /* Pairs with smp_rmb() in fanotify_get_fsid() */ 566 + smp_wmb(); 567 + conn->flags |= FSNOTIFY_CONN_FLAG_HAS_FSID; 568 + } else if (fsid && (conn->flags & FSNOTIFY_CONN_FLAG_HAS_FSID) && 567 569 (fsid->val[0] != conn->fsid.val[0] || 568 570 fsid->val[1] != conn->fsid.val[1])) { 569 571 /*
+3 -1
include/linux/fsnotify_backend.h
··· 292 292 */ 293 293 struct fsnotify_mark_connector { 294 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 298 __kernel_fsid_t fsid; /* fsid of filesystem containing object */ 297 299 union { 298 300 /* Object pointer [lock] */