> On Jun 29, 2021, at 7:48 AM, Desmond Cheong Zhi Xi <desmondcheongzx@xxxxxxxxx> wrote: > > Syzbot reports a possible recursive lock: > https://syzkaller.appspot.com/bug?id=f007ef1d7a31a469e3be7aeb0fde0769b18585db > > This happens due to missing lock nesting information. From the logs, > we see that a call to hfs_fill_super is made to mount the hfs > filesystem. While searching for the root inode, the lock on the > catalog btree is grabbed. Then, when the parent of the root isn't > found, a call to __hfs_bnode_create is made to create the parent of > the root. This eventually leads to a call to hfs_ext_read_extent which > grabs a lock on the extents btree. > > Since the order of locking is catalog btree -> extents btree, this > lock hierarchy does not lead to a deadlock. > > To tell lockdep that this locking is safe, we add nesting notation to > distinguish between catalog btrees, extents btrees, and attributes > btrees (for HFS+). This has already been done in hfsplus. > > Reported-and-tested-by: syzbot+b718ec84a87b7e73ade4@xxxxxxxxxxxxxxxxxxxxxxxxx > Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@xxxxxxxxx> > --- > fs/hfs/bfind.c | 14 +++++++++++++- > fs/hfs/btree.h | 7 +++++++ > 2 files changed, 20 insertions(+), 1 deletion(-) > > diff --git a/fs/hfs/bfind.c b/fs/hfs/bfind.c > index 4af318fbda77..ef9498a6e88a 100644 > --- a/fs/hfs/bfind.c > +++ b/fs/hfs/bfind.c > @@ -25,7 +25,19 @@ int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd) > fd->key = ptr + tree->max_key_len + 2; > hfs_dbg(BNODE_REFS, "find_init: %d (%p)\n", > tree->cnid, __builtin_return_address(0)); > - mutex_lock(&tree->tree_lock); > + switch (tree->cnid) { > + case HFS_CAT_CNID: > + mutex_lock_nested(&tree->tree_lock, CATALOG_BTREE_MUTEX); > + break; > + case HFS_EXT_CNID: > + mutex_lock_nested(&tree->tree_lock, EXTENTS_BTREE_MUTEX); > + break; > + case HFS_ATTR_CNID: > + mutex_lock_nested(&tree->tree_lock, ATTR_BTREE_MUTEX); > + break; > + default: > + return -EINVAL; > + } > return 0; > } > > diff --git a/fs/hfs/btree.h b/fs/hfs/btree.h > index 4ba45caf5939..0e6baee93245 100644 > --- a/fs/hfs/btree.h > +++ b/fs/hfs/btree.h > @@ -13,6 +13,13 @@ typedef int (*btree_keycmp)(const btree_key *, const btree_key *); > > #define NODE_HASH_SIZE 256 > > +/* B-tree mutex nested subclasses */ > +enum hfs_btree_mutex_classes { > + CATALOG_BTREE_MUTEX, > + EXTENTS_BTREE_MUTEX, > + ATTR_BTREE_MUTEX, > +}; > + > /* A HFS BTree held in memory */ > struct hfs_btree { > struct super_block *sb; > -- > 2.25.1 > Looks good to me. Reviewed-by: Viacheslav Dubeyko <slava@xxxxxxxxxxx> Thanks, Slava.