git: 9front

Download patch

ref: 2e6fb00af4fae7afd8d6bc9767b89ff0da5670dd
parent: 8b5e8084fc7b57e847f1f850374d110f84ba532b
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Nov 1 15:21:14 EDT 2025

lib9p: fix Rstat issues (thanks nposting)

For one, our respond() handler would abort the
file-server when the reply wont fit into msize.

This can happen with Rstat, as it contains
variable-sized strings which can exceed small
msize.

To fix this, we have rstat() handler ensure that the
resulting stat buffeer will fit into the response,
converting the response into an Rerror otherise.

The following script can reproduce the issue:

ramfs -D -S ram
@{syscall fversion 0 300 buf 256; mount -c /fd/0 /n/ram} <>[0] /srv/ram
a='a'
for(i in `{seq 1 300}){
	a=$a^a
	touch /n/ram/$a && ls -l /n/ram/$a
}

On a second note, there was also a double-free,
as freeing r->ofcall.stat buffer depends only on
r->ifcall.type == Tstat. But rstat() would keep
r->ofcall.stat pointing to allocated statbuf,
on error.

--- a/sys/src/lib9p/srv.c
+++ b/sys/src/lib9p/srv.c
@@ -674,14 +674,18 @@
 		return;
 	}
 	n = GBIT16(tmp)+BIT16SZ;
+	if(n+BIT32SZ+BIT8SZ+BIT16SZ+BIT16SZ > r->srv->msize){
+		r->error = "rstat: message size too small";
+		return;
+	}
 	statbuf = emalloc9p(n);
 	r->ofcall.nstat = convD2M(&r->d, statbuf, n);
-	r->ofcall.stat = statbuf;	/* freed in closereq */
 	if(r->ofcall.nstat <= BIT16SZ){
 		r->error = "convD2M fails";
 		free(statbuf);
 		return;
 	}
+	r->ofcall.stat = statbuf;	/* freed in closereq */
 }
 
 static void
--