code: plan9front

Download patch

ref: c512cf16e5e0d40d559688e6706696f82182a693
parent: 88181e1c5c8d19e61c76b93620abcbc7c2e57481
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon May 1 11:17:08 EDT 2023

dossrv: better error handling and sanity checking in dosfs()

check error for devread() and do some sanity checking
on the constants and dont leak the Dosbpb when error.

--- a/sys/src/cmd/dossrv/dosfs.c
+++ b/sys/src/cmd/dossrv/dosfs.c
@@ -45,9 +45,12 @@
 	root->xf = xf = getxfs(req->uname, req->aname);
 	if(!xf)
 		goto error;
-	if(xf->fmt == 0 && dosfs(xf) < 0){
-		errno = Eformat;
-		goto error;
+	if(xf->fmt == 0){
+		if(dosfs(xf) < 0){
+			errno = Eformat;
+			goto error;
+		}
+		xf->fmt = 1;
 	}
 	root->qid.type = QTDIR;
 	root->qid.path = 0;
--- a/sys/src/cmd/dossrv/dossubs.c
+++ b/sys/src/cmd/dossrv/dossubs.c
@@ -41,7 +41,7 @@
 {
 	Iosect *p1;
 	Fatinfo *fi;
-	uchar	buf[512];
+	uchar buf[512];
 	Dosboot *b;
 	Dosboot32 *b32;
 	Dosbpb *bp;
@@ -73,28 +73,31 @@
 		isdos['&'] = 1;
 	}
 
-	/* don't use getsect() before we we determinted real values */
-	xf->sectsize = 512;
-	xf->sect2trk = 9;
-	devread(xf, 0, buf, sizeof(buf));
+	/* don't use getsect() before determining sector size */
+	if(devread(xf, 0, buf, sizeof(buf)) < 0)
+		return -1;
 
 	if(!isdosfs(buf))
 		return -1;
 
-	b = (Dosboot*)buf;
-
-	xf->sectsize = GSHORT(b->sectsize);
-	if(xf->sectsize < 32)
+	bp = malloc(sizeof(Dosbpb));
+	if(bp == nil)
 		return -1;
+	memset(bp, 0, sizeof(Dosbpb));	/* clear lock */
 
+	b = (Dosboot*)buf;
+	xf->sectsize = GSHORT(b->sectsize);
+	if(xf->sectsize < 32){
+		if(chatty)
+			fprint(2, "sectsize %d\n", xf->sectsize);
+		goto badfmt;
+	}
 	xf->sect2trk = GSHORT(b->trksize);
-	if(xf->sect2trk < 1)
-		return -1;
-
-	bp = malloc(sizeof(Dosbpb));
-	memset(bp, 0, sizeof(Dosbpb));	/* clear lock */
-	xf->ptr = bp;
-	xf->fmt = 1;
+	if(xf->sect2trk == 0){
+		if(chatty)
+			fprint(2, "sect2trk %d\n", xf->sect2trk);
+		goto badfmt;
+	}
 	bp->clustsize = b->clustsize;
 	bp->nresrv = GSHORT(b->nresrv);
 	bp->nfats = b->nfats;
@@ -117,7 +120,7 @@
 		if(bp->fatsize == 0){
 			if(chatty)
 				fprint(2, "fatsize 0\n");
-			return -1;
+			goto badfmt;
 		}
 		bp->dataaddr = bp->fataddr + bp->nfats*bp->fatsize;
 		bp->rootaddr = 0;
@@ -164,6 +167,16 @@
 		bp->dataaddr = bp->rootaddr + (bp->rootsize*DOSDIRSIZE + xf->sectsize-1)/xf->sectsize;
 		bp->freeptr = FATRESRV;
 	}
+	if(bp->clustsize == 0){
+		if(chatty)
+			fprint(2, "clustsize 0\n");
+		goto badfmt;
+	}
+	if(bp->volsize < bp->dataaddr){
+		if(chatty)
+			fprint(2, "volsize < dataaddr\n");
+		goto badfmt;
+	}
 	bp->fatclusters = FATRESRV + (bp->volsize - bp->dataaddr)/bp->clustsize;
 
 	if(xf->isfat32)
@@ -178,7 +191,12 @@
 		chat("fat %d: %lld...", i, bp->fataddr+i*bp->fatsize);
 	chat("root: %lld...", bp->rootaddr);
 	chat("data: %lld...", bp->dataaddr);
+
+	xf->ptr = bp;
 	return 0;
+badfmt:
+	free(bp);
+	return -1;
 }
 
 /*
--- a/sys/src/cmd/dossrv/xfile.c
+++ b/sys/src/cmd/dossrv/xfile.c
@@ -109,6 +109,8 @@
 	fxf->qid = dqid;
 	fxf->dev = fd;
 	fxf->fmt = 0;
+	fxf->sectsize = 0;
+	fxf->sect2trk = 0;
 	fxf->offset = offset;
 	fxf->ptr = nil;
 	fxf->isfat32 = 0;