git: 0247b4018de2 - main - unionfs: detect common deadlock-producing mount misconfigurations
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 12 Dec 2025 06:32:56 UTC
The branch main has been updated by jah:
URL: https://cgit.FreeBSD.org/src/commit/?id=0247b4018de2c341ac59a585362c10044cea86ad
commit 0247b4018de2c341ac59a585362c10044cea86ad
Author: Jason A. Harmening <jah@FreeBSD.org>
AuthorDate: 2025-11-29 07:53:16 +0000
Commit: Jason A. Harmening <jah@FreeBSD.org>
CommitDate: 2025-12-12 06:32:05 +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ć <karlo98.m@gmail.com>
Reviewed by: kib, olce
Tested by: pho
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D53988
---
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 284b24a604f4..3eb67221ec0e 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,
- NULL, &(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);