⬢ DragonFlyBSD Kernel Audit
DF-5809 / fix.diff
← back to finding ↓ download raw
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -2294,6 +2294,35 @@
 	return (0);
 }
 
+/*
+ * DF-5809: safe variant.  Extract the export flags and snapshot the
+ * anonymous credential while NE_LOCK is still held, so the caller never
+ * dereferences the netcred after the lock is released.  The returned
+ * credential snapshot is a value copy owned by the caller; it must not
+ * be crfree()d (it is not refcounted), mirroring the embedded
+ * netc_anon semantics consumers already expect.
+ *
+ * Returns 0 on success with *exflagsp / *credanonp filled in,
+ * EACCES if no export matched.
+ */
+int
+vfs_export_lookup_locked(struct mount *mp, struct netexport *nep,
+		struct sockaddr *nam, int *exflagsp,
+		struct ucred *credanonp)
+{
+	struct netcred *np;
+
+	np = vfs_export_lookup(mp, nep, nam);
+	if (np == NULL)
+		return (EACCES);
+	NE_LOCK(nep);
+	*exflagsp = np->netc_exflags;
+	if (credanonp)
+		*credanonp = np->netc_anon;
+	NE_UNLOCK(nep);
+	return (0);
+}
+
 struct netcred *
 vfs_export_lookup(struct mount *mp, struct netexport *nep,
 		struct sockaddr *nam)

# NOTE (not part of the patch): every VFS_CHECKEXP consumer must be
# converted to the *_locked() variant, e.g. ufs_vfsops.c:246-251 becomes
#
#	int exflags;
#	struct ucred credanon;
#
#	error = vfs_export_lookup_locked(mp, &ump->um_export, nam,
#					 &exflags, &credanon);
#	if (error)
#		return (error);
#	*exflagsp = exflags;
#	*credanonp = &credanon;	/* caller-owned storage, no netcred deref */
#
# same mechanical change in tmpfs, hammer2, cd9660, nullfs, ntfs,
# msdosfs, udf checkexp implementations.