The branch stable/15 has been updated by jah: URL: https://cgit.FreeBSD.org/src/commit/?id=da6f395119a5eb1ed1dad56874c1c55a5721e220
commit da6f395119a5eb1ed1dad56874c1c55a5721e220 Author: Jason A. Harmening <[email protected]> AuthorDate: 2025-11-29 07:53:16 +0000 Commit: Jason A. Harmening <[email protected]> CommitDate: 2025-12-26 06:38:06 +0000 unionfs: detect common deadlock-producing mount misconfigurations When creating a unionfs mount, it's fairly easy to shoot oneself in the foot by specifying upper and lower file hierarchies that resolve back to the same vnodes. This is fairly easy to do if the sameness is not obvious due to aliasing through nullfs or other unionfs mounts (as in the associated PR), and will produce either deadlock or failed locking assertions on any attempt to use the resulting unionfs mount. Leverage VOP_GETLOWVNODE() to detect the most common cases of foot-shooting at mount time and fail the mount with EDEADLK. This is not meant to be an exhaustive check for all possible deadlock-producing scenarios, but it is an extremely cheap and simple approach that, unlike previous proposed fixes, also works in the presence of nullfs aliases. PR: 172334 Reported by: ngie, Karlo Miličević <[email protected]> Reviewed by: kib, olce Tested by: pho Differential Revision: https://reviews.freebsd.org/D53988 (cherry picked from commit 0247b4018de2c341ac59a585362c10044cea86ad) --- sys/fs/unionfs/union_vfsops.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/sys/fs/unionfs/union_vfsops.c b/sys/fs/unionfs/union_vfsops.c index 9342317ad08e..fd48a520f911 100644 --- a/sys/fs/unionfs/union_vfsops.c +++ b/sys/fs/unionfs/union_vfsops.c @@ -73,6 +73,8 @@ unionfs_domount(struct mount *mp) { struct vnode *lowerrootvp; struct vnode *upperrootvp; + struct vnode *lvp1; + struct vnode *lvp2; struct unionfs_mount *ump; char *target; char *tmp; @@ -276,11 +278,32 @@ unionfs_domount(struct mount *mp) */ VOP_UNLOCK(ump->um_uppervp); + /* + * Detect common cases in which constructing a unionfs hierarchy + * would produce deadlock (or failed locking assertions) upon + * use of the resulting unionfs vnodes. This typically happens + * when the requested upper and lower filesytems (which themselves + * may be unionfs instances and/or nullfs aliases) end up resolving + * to the same base-layer files. Note that this is not meant to be + * an exhaustive check of all possible deadlock-producing scenarios. + */ + lvp1 = lvp2 = NULL; + VOP_GETLOWVNODE(ump->um_lowervp, &lvp1, FREAD); + VOP_GETLOWVNODE(ump->um_uppervp, &lvp2, FREAD); + if (lvp1 != NULL && lvp1 == lvp2) + error = EDEADLK; + if (lvp1 != NULL) + vrele(lvp1); + if (lvp2 != NULL) + vrele(lvp2); + /* * Get the unionfs root vnode. */ - error = unionfs_nodeget(mp, ump->um_uppervp, ump->um_lowervp, - NULLVP, &(ump->um_rootvp), NULL); + if (error == 0) { + error = unionfs_nodeget(mp, ump->um_uppervp, ump->um_lowervp, + NULL, &(ump->um_rootvp), NULL); + } if (error != 0) { vrele(upperrootvp); free(ump, M_UNIONFSMNT);
