kern/coredump_vnode.c: avoid dumping to the mount point we suspended

PR:	299095
Reported by:	Rick Richard <[email protected]>
Reviewed by:	markj
Tested by:	Rick Richard <[email protected]> (previous version)
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D60283
This commit is contained in:
Konstantin Belousov committed 2026-10-07 20:00:53 +03:00
1 parent ccd44c5e48
commit bea382f25b
1 file changed
+45 -1
+45 -1
View File
@@ -241,6 +241,42 @@ vfs_check_namedattr(struct vnode *vp)
return (error);
}
/*
* This check is performed when a vnode is opened for dumping the core
* from userspace process. The /dev/ufssuspend device allows userspace
* to suspend the UFS volume, and we must check that the dump does not
* go into the volume the coredumping process suspended.
*
* Taking MNT_ILOCK around checks is not required, because the process
* is single-threaded around dumping core, and we in particular check
* if the current process is the suspension owner.
*/
static int
vn_open_nosuspend(struct vnode *vp, u_int vn_open_flags)
{
struct mount *mp;
struct thread *susp_owner;
int error;
if ((vn_open_flags & VN_OPEN_COREDUMP) == 0)
return (0);
MPASS((curproc->p_flag & P_HADTHREADS) == 0 ||
(curproc->p_flag & (P_SINGLE_BOUNDARY | P_SINGLE_EXIT |
P_STOPPED)) != 0);
mp = NULL;
error = VOP_GETWRITEMOUNT(vp, &mp);
if (error != 0 || mp == NULL)
return (0);
susp_owner = atomic_load_ptr(&mp->mnt_susp_owner);
if ((atomic_load_int(&mp->mnt_kern_flag) & (MNTK_SUSPEND |
MNTK_SUSPENDED)) != 0 && susp_owner != NULL &&
susp_owner->td_proc == curproc)
error = EBUSY;
vfs_rel(mp);
return (error);
}
/*
* Common code for vnode open operations via a name lookup.
* Lookup the vnode and invoke VOP_CREATE if needed.
@@ -295,6 +331,12 @@ restart:
ndp->ni_dvp = NULL;
goto bad;
}
error = vn_open_nosuspend(ndp->ni_dvp, vn_open_flags);
if (error != 0) {
vp = ndp->ni_dvp;
ndp->ni_dvp = NULL;
goto bad;
}
VATTR_NULL(vap);
vap->va_type = VREG;
vap->va_mode = cmode;
@@ -375,7 +417,9 @@ restart:
goto bad;
}
}
error = vn_open_vnode(vp, fmode, cred, curthread, fp);
error = vn_open_nosuspend(vp, vn_open_flags);
if (error == 0)
error = vn_open_vnode(vp, fmode, cred, curthread, fp);
if (first_open) {
VI_LOCK(vp);
vp->v_iflag &= ~VI_FOPENING;