DragonFlyBSD Kernel Audit
DF-0907 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/vfs/smbfs/smbfs_vfsops.c b/sys/vfs/smbfs/smbfs_vfsops.c
index 0000000..1111111 100644
--- a/sys/vfs/smbfs/smbfs_vfsops.c
+++ b/sys/vfs/smbfs/smbfs_vfsops.c
@@ -162,20 +162,17 @@
 			    (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;
 
 /*	simple_lock_init(&smp->sm_npslock);*/
-	pc = mp->mnt_stat.f_mntfromname;
-	pe = pc + sizeof(mp->mnt_stat.f_mntfromname);
-	bzero(pc, MNAMELEN);
-	*pc++ = '/';
-	*pc++ = '/';
-	pc=index(strncpy(pc, vcp->vc_username, pe - pc - 2), 0);
-	if (pc < pe-1) {
-		*(pc++) = '@';
-		pc = index(strncpy(pc, vcp->vc_srvname, pe - pc - 2), 0);
-		if (pc < pe - 1) {
-			*(pc++) = '/';
-			strncpy(pc, ssp->ss_name, pe - pc - 2);
-		}
-	}
+	/*
+	 * Build f_mntfromname as "//user@server/share", bounded to MNAMELEN.
+	 * The old hand-rolled strncpy+index arithmetic had a signed underflow:
+	 * when strlen(vc_username) >= MNAMELEN-4, pe-pc-2 went negative and
+	 * coerced to size_t became SIZE_MAX, overflowing f_mntfromname into
+	 * the rest of struct statfs / struct mount (DF-0907).
+	 */
+	(void)ksnprintf(mp->mnt_stat.f_mntfromname, sizeof(mp->mnt_stat.f_mntfromname),
+	    "//%s@%s/%s", vcp->vc_username, vcp->vc_srvname, ssp->ss_name);
+	(void)pc;
+	(void)pe;
 	/* protect against invalid mount points */
 	smp->sm_args.mount_point[sizeof(smp->sm_args.mount_point) - 1] = '\0';
 	vfs_getnewfsid(mp);