Descripción
In the Linux kernel, following vulnerability has been resolved:
hfsplus: fix missing hfs_bnode_get() in __hfs_bnode_create
When sync() and link() are called concurrently, both threads may
enter hfs_bnode_find() without finding node hash table
and proceed to create it.
Thread A:
hfsplus_write_inode()
-> hfsplus_write_system_inode()
hfs_btree_write()
hfs_bnode_find(tree, 0)
__hfs_bnode_create(tree, 0)
Thread B:
hfsplus_create_cat()
hfs_brec_insert()
hfs_bnode_split()
hfs_bmap_alloc()
0)
In this case, thread A creates bnode, sets refcnt=1, hashes it.
Thread B also tries same notices it already
been inserted, drops its own instance, uses hashed one without
getting node.
```
node2 = hfs_bnode_findhash(tree, cnid);
if (!node2) { <- Thread A
hash hfs_bnode_hash(cnid);
node->next_hash tree->node_hash[hash];
tree->node_hash[hash] node;
tree->node_hash_cnt++;
} else B
spin_unlock(&tree->hash_lock);
kfree(node);
wait_event(node2->lock_wq,
!test_bit(HFS_BNODE_NEW, &node2->flags));
return node2;
}
```
However, requires each call take a reference.
Here end up setting refcnt=1. When they later put node,
this triggers:
BUG_ON(!atomic_read(&node->refcnt))
In scenario, fact finds table
rather than creating new one, thus must reference.
Fix by calling when reusing bnode newly created by
another ensure refcount is updated correctly.
A similar bug was fixed HFS long ago commit
a9dc087fd3c4 ("fix __hfs_bnode_create")
but issue remained HFS+ until now.
https://git.kernel.org/stable/c/152af114287851583cf7e0abc10129941f19466a
https://git.kernel.org/stable/c/457f795e7abd7770de10216d7f9994a3f12a56d6
https://git.kernel.org/stable/c/5882e7c8cdbb5e254a69628b780acff89c78071e
https://git.kernel.org/stable/c/b68dc4134b18a3922cd33439ec614aad4172bc86
https://git.kernel.org/stable/c/b9d1c6bb5f19460074ce9862cb80be86b5fb0a50