git: 9front

Download patch

ref: 9a5bb5c4fbd1405d6e6f4e4deb0181f6404082a4
parent: 913cf047adb28f0d9484cdf3bea246f2589d5002
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Oct 20 08:12:42 EDT 2024

devuart: Fix memory leak when reading status file

Drivers where allocating a READSTR size buffer,
then readstr() it. But readstr() can raise an
error on pagefault, resulting in the buffer to
be leaked.

Instead, we change the interface and allocate
the buffer in devuart read handler, passing
the driver start and end pointers into it.

Also, provide a default implementation (when
status == nil), avoiding some duplication.

--- a/sys/src/9/arm64/uartqemu.c
+++ b/sys/src/9/arm64/uartqemu.c
@@ -282,33 +282,6 @@
 {
 }
 
-static long
-status(Uart *uart, void *buf, long n, long offset)
-{
-	char *p;
-
-	p = malloc(READSTR);
-	if(p == nil)
-		error(Enomem);
-	snprint(p, READSTR,
-		"b%d\n"
-		"dev(%d) type(%d) framing(%d) overruns(%d) "
-		"berr(%d) serr(%d)\n",
-
-		uart->baud,
-		uart->dev,
-		uart->type,
-		uart->ferr,
-		uart->oerr,
-		uart->berr,
-		uart->serr
-	);
-	n = readstr(offset, buf, n, p);
-	free(p);
-
-	return n;
-}
-
 static void
 donothing(Uart*, int)
 {
@@ -356,7 +329,6 @@
 	.modemctl	= donothing,
 	.rts		= rts,
 	.dtr		= donothing,
-	.status		= status,
 	.fifo		= donothing,
 	.getc		= getc,
 	.putc		= putc,
--- a/sys/src/9/bcm/uartmini.c
+++ b/sys/src/9/bcm/uartmini.c
@@ -225,33 +225,6 @@
 		ap[MuMcr] |= RtsN;
 }
 
-static long
-status(Uart *uart, void *buf, long n, long offset)
-{
-	char *p;
-
-	p = malloc(READSTR);
-	if(p == nil)
-		error(Enomem);
-	snprint(p, READSTR,
-		"b%d\n"
-		"dev(%d) type(%d) framing(%d) overruns(%d) "
-		"berr(%d) serr(%d)\n",
-
-		uart->baud,
-		uart->dev,
-		uart->type,
-		uart->ferr,
-		uart->oerr,
-		uart->berr,
-		uart->serr
-	);
-	n = readstr(offset, buf, n, p);
-	free(p);
-
-	return n;
-}
-
 static void
 donothing(Uart*, int)
 {
@@ -295,7 +268,6 @@
 	.modemctl	= donothing,
 	.rts		= rts,
 	.dtr		= donothing,
-	.status		= status,
 	.fifo		= donothing,
 	.getc		= getc,
 	.putc		= putc,
--- a/sys/src/9/bcm/uartpl011.c
+++ b/sys/src/9/bcm/uartpl011.c
@@ -282,33 +282,6 @@
 {
 }
 
-static long
-status(Uart *uart, void *buf, long n, long offset)
-{
-	char *p;
-
-	p = malloc(READSTR);
-	if(p == nil)
-		error(Enomem);
-	snprint(p, READSTR,
-		"b%d\n"
-		"dev(%d) type(%d) framing(%d) overruns(%d) "
-		"berr(%d) serr(%d)\n",
-
-		uart->baud,
-		uart->dev,
-		uart->type,
-		uart->ferr,
-		uart->oerr,
-		uart->berr,
-		uart->serr
-	);
-	n = readstr(offset, buf, n, p);
-	free(p);
-
-	return n;
-}
-
 static void
 donothing(Uart*, int)
 {
@@ -348,7 +321,6 @@
 	.modemctl	= donothing,
 	.rts		= rts,
 	.dtr		= donothing,
-	.status		= status,
 	.fifo		= donothing,
 	.getc		= getc,
 	.putc		= putc,
--- a/sys/src/9/imx8/uartimx.c
+++ b/sys/src/9/imx8/uartimx.c
@@ -273,33 +273,6 @@
 {
 }
 
-static long
-status(Uart *uart, void *buf, long n, long offset)
-{
-	char *p;
-
-	p = malloc(READSTR);
-	if(p == nil)
-		error(Enomem);
-	snprint(p, READSTR,
-		"b%d\n"
-		"dev(%d) type(%d) framing(%d) overruns(%d) "
-		"berr(%d) serr(%d)\n",
-
-		uart->baud,
-		uart->dev,
-		uart->type,
-		uart->ferr,
-		uart->oerr,
-		uart->berr,
-		uart->serr
-	);
-	n = readstr(offset, buf, n, p);
-	free(p);
-
-	return n;
-}
-
 static void
 interrupt(Ureg*, void *arg)
 {
@@ -393,7 +366,6 @@
 	.modemctl	= donothing,
 	.rts		= rts,
 	.dtr		= donothing,
-	.status		= status,
 	.fifo		= donothing,
 	.getc		= getc,
 	.putc		= putc,
--- a/sys/src/9/kw/uartkw.c
+++ b/sys/src/9/kw/uartkw.c
@@ -255,13 +255,6 @@
 	USED(uart, on);
 }
 
-static long
-kw_status(Uart* uart, void* buf, long n, long offset)
-{
-	USED(uart, buf, n, offset);
-	return 0;
-}
-
 static void
 kw_fifo(Uart* uart, int level)
 {
@@ -318,7 +311,6 @@
 	.modemctl	= kw_modemctl,
 	.rts		= kw_rts,
 	.dtr		= kw_dtr,
-	.status		= kw_status,
 	.fifo		= kw_fifo,
 	.getc		= kw_getc,
 	.putc		= kw_putc,
--- a/sys/src/9/lx2k/uartlx2k.c
+++ b/sys/src/9/lx2k/uartlx2k.c
@@ -284,33 +284,6 @@
 {
 }
 
-static long
-status(Uart *uart, void *buf, long n, long offset)
-{
-	char *p;
-
-	p = malloc(READSTR);
-	if(p == nil)
-		error(Enomem);
-	snprint(p, READSTR,
-		"b%d\n"
-		"dev(%d) type(%d) framing(%d) overruns(%d) "
-		"berr(%d) serr(%d)\n",
-
-		uart->baud,
-		uart->dev,
-		uart->type,
-		uart->ferr,
-		uart->oerr,
-		uart->berr,
-		uart->serr
-	);
-	n = readstr(offset, buf, n, p);
-	free(p);
-
-	return n;
-}
-
 static void
 donothing(Uart*, int)
 {
@@ -359,7 +332,6 @@
 	.modemctl	= donothing,
 	.rts		= rts,
 	.dtr		= donothing,
-	.status		= status,
 	.fifo		= donothing,
 	.getc		= getc,
 	.putc		= putc,
--- a/sys/src/9/mt7688/uarti8250.c
+++ b/sys/src/9/mt7688/uarti8250.c
@@ -145,20 +145,18 @@
 #define csr8w(c, r, v)	((c)->io[r] = (c)->sticky[r] | (v))
 #define csr8o(c, r, v)	((c)->io[r] = (v))
 
-static long
-i8250status(Uart* uart, void* buf, long n, long offset)
+static char*
+i8250status(Uart* uart, char *p, char *e)
 {
-	char *p;
 	Ctlr *ctlr;
 	uchar ier, lcr, mcr, msr;
 
 	ctlr = uart->regs;
-	p = malloc(READSTR);
 	mcr = ctlr->sticky[Mcr];
 	msr = csr8r(ctlr, Msr);
 	ier = ctlr->sticky[Ier];
 	lcr = ctlr->sticky[Lcr];
-	snprint(p, READSTR,
+	return seprint(p, e,
 		"b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
 		"dev(%d) type(%d) framing(%d) overruns(%d) "
 		"berr(%d) serr(%d)%s%s%s%s\n",
@@ -185,10 +183,6 @@
 		(msr & Dcd) ? " dcd": "",
 		(msr & Ri) ? " ring": ""
 	);
-	n = readstr(offset, buf, n, p);
-	free(p);
-
-	return n;
 }
 
 static void
--- a/sys/src/9/mtx/uarti8250.c
+++ b/sys/src/9/mtx/uarti8250.c
@@ -149,20 +149,18 @@
 #define csr8r(c, r)	inb((c)->io+(r))
 #define csr8w(c, r, v)	outb((c)->io+(r), (c)->sticky[(r)]|(v))
 
-static long
-i8250status(Uart* uart, void* buf, long n, long offset)
+static char*
+i8250status(Uart* uart, char *p, char *e)
 {
-	char *p;
 	Ctlr *ctlr;
 	uchar ier, lcr, mcr, msr;
 
 	ctlr = uart->regs;
-	p = malloc(READSTR);
 	mcr = ctlr->sticky[Mcr];
 	msr = csr8r(ctlr, Msr);
 	ier = ctlr->sticky[Ier];
 	lcr = ctlr->sticky[Lcr];
-	snprint(p, READSTR,
+	return seprint(p, e,
 		"b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
 		"dev(%d) type(%d) framing(%d) overruns(%d)%s%s%s%s\n",
 
@@ -186,10 +184,6 @@
 		(msr & Dcd) ? " dcd": "",
 		(msr & Ri) ? " ring": ""
 	);
-	n = readstr(offset, buf, n, p);
-	free(p);
-
-	return n;
 }
 
 static void
--- a/sys/src/9/omap/uarti8250.c
+++ b/sys/src/9/omap/uarti8250.c
@@ -174,20 +174,18 @@
 #define csr8w(c, r, v)	((c)->io[r] = (c)->sticky[r] | (v), coherence())
 #define csr8o(c, r, v)	((c)->io[r] = (v), coherence())
 
-static long
-i8250status(Uart* uart, void* buf, long n, long offset)
+static char*
+i8250status(Uart* uart, char *p, char *e)
 {
-	char *p;
 	Ctlr *ctlr;
 	uchar ier, lcr, mcr, msr;
 
 	ctlr = uart->regs;
-	p = malloc(READSTR);
 	mcr = ctlr->sticky[Mcr];
 	msr = csr8r(ctlr, Msr);
 	ier = ctlr->sticky[Ier];
 	lcr = ctlr->sticky[Lcr];
-	snprint(p, READSTR,
+	return seprint(p, e,
 		"b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
 		"dev(%d) type(%d) framing(%d) overruns(%d) "
 		"berr(%d) serr(%d)%s%s%s%s\n",
@@ -214,10 +212,6 @@
 		(msr & Dcd) ? " dcd": "",
 		(msr & Ri) ? " ring": ""
 	);
-	n = readstr(offset, buf, n, p);
-	free(p);
-
-	return n;
 }
 
 static void
--- a/sys/src/9/pc/uartaxp.c
+++ b/sys/src/9/pc/uartaxp.c
@@ -254,21 +254,19 @@
 	}
 }
 
-static long
-axpstatus(Uart* uart, void* buf, long n, long offset)
+static char*
+axpstatus(Uart* uart, char *p, char *e)
 {
-	char *p;
 	Ccb *ccb;
 	u16int bs, fstat, ms;
 
 	ccb = ((Cc*)(uart->regs))->ccb;
 
-	p = smalloc(READSTR);
 	bs = ccb->bs;
 	fstat = ccb->df;
 	ms = ccb->ms;
 
-	snprint(p, READSTR,
+	return seprint(p, e,
 		"b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
 		"dev(%d) type(%d) framing(%d) overruns(%d) "
 		"berr(%d) serr(%d)%s%s%s%s\n",
@@ -295,10 +293,6 @@
 		(ms & Sdcd) ? " dcd"  : "",
 		(ms & Sri) ? " ring" : ""
 	);
-	n = readstr(offset, buf, n, p);
-	free(p);
-
-	return n;
 }
 
 static void
--- a/sys/src/9/pc/uarti8250.c
+++ b/sys/src/9/pc/uarti8250.c
@@ -150,20 +150,18 @@
 #define csr8r(c, r)	inb((c)->io+(r))
 #define csr8w(c, r, v)	outb((c)->io+(r), (c)->sticky[(r)]|(v))
 
-static long
-i8250status(Uart* uart, void* buf, long n, long offset)
+static char*
+i8250status(Uart* uart, char *p, char *e)
 {
-	char *p;
 	Ctlr *ctlr;
 	uchar ier, lcr, mcr, msr;
 
 	ctlr = uart->regs;
-	p = smalloc(READSTR);
 	mcr = ctlr->sticky[Mcr];
 	msr = csr8r(ctlr, Msr);
 	ier = ctlr->sticky[Ier];
 	lcr = ctlr->sticky[Lcr];
-	snprint(p, READSTR,
+	return seprint(p, e,
 		"b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
 		"dev(%d) type(%d) framing(%d) overruns(%d) "
 		"berr(%d) serr(%d)%s%s%s%s\n",
@@ -190,10 +188,6 @@
 		(msr & Dcd) ? " dcd": "",
 		(msr & Ri) ? " ring": ""
 	);
-	n = readstr(offset, buf, n, p);
-	free(p);
-
-	return n;
 }
 
 static void
--- a/sys/src/9/port/devuart.c
+++ b/sys/src/9/port/devuart.c
@@ -399,6 +399,7 @@
 uartread(Chan *c, void *buf, long n, vlong off)
 {
 	Uart *p;
+	char *s;
 	ulong offset = off;
 
 	if(c->qid.type & QTDIR){
@@ -413,7 +414,29 @@
 	case Nctlqid:
 		return readnum(offset, buf, n, NETID(c->qid.path), NUMSIZE);
 	case Nstatqid:
-		return (*p->phys->status)(p, buf, n, offset);
+		if(off >= READSTR)
+			return 0;
+		s = smalloc(READSTR);
+		if(waserror()){
+			free(s);
+			nexterror();
+		}
+		if(p->phys->status == nil)
+			seprint(s, s + READSTR,
+				"b%d\n"
+				"dev(%d) type(%d) framing(%d) overruns(%d) "
+				"berr(%d) serr(%d)\n",
+				p->baud,
+				p->dev, p->type, p->ferr, p->oerr,
+				p->berr, p->serr);
+		else {
+			s[0] = '\0';
+			(*p->phys->status)(p, s, s + READSTR);
+		}
+		n = readstr(offset, buf, n, s);
+		free(s);
+		poperror();
+		return n;
 	}
 
 	return 0;
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -881,7 +881,7 @@
 	void	(*modemctl)(Uart*, int);
 	void	(*rts)(Uart*, int);
 	void	(*dtr)(Uart*, int);
-	long	(*status)(Uart*, void*, long, long);
+	char*	(*status)(Uart*, char*, char*);
 	void	(*fifo)(Uart*, int);
 	void	(*power)(Uart*, int);
 	int	(*getc)(Uart*);	/* polling versions, for iprint, rdb */
--- a/sys/src/9/ppc/uartsaturn.c
+++ b/sys/src/9/ppc/uartsaturn.c
@@ -132,14 +132,13 @@
 }
 
 
-static long
-sustatus(Uart* uart, void* buf, long n, long offset)
+static char*
+sustatus(Uart* uart, char *p, char *e)
 {
 	Saturnuart *su;
-	char p[128];
 
 	su = ((UartData*)uart->regs)->su;
-	snprint(p, sizeof p, "b%d c%d e%d l%d m0 p%c s%d i1\n"
+	return seprint(p, e, "b%d c%d e%d l%d m0 p%c s%d i1\n"
 		"dev(%d) type(%d) framing(%d) overruns(%d)\n",
 
 		uart->baud,
@@ -153,10 +152,6 @@
 		uart->type,
 		uart->ferr,
 		uart->oerr);
-	n = readstr(offset, buf, n, p);
-	free(p);
-
-	return n;
 }
 
 static void
--- a/sys/src/9/ppc/uartsmc.c
+++ b/sys/src/9/ppc/uartsmc.c
@@ -212,14 +212,13 @@
 	ud->enabled = 1;
 }
 
-static long
-smcstatus(Uart* uart, void* buf, long n, long offset)
+static char*
+smcstatus(Uart* uart, char *p, char *e)
 {
 	SMC *sp;
-	char p[128];
 
 	sp = ((UartData*)uart->regs)->smc;
-	snprint(p, sizeof p, "b%d c%d e%d l%d m0 p%c s%d i1\n"
+	return seprint(p, e, "b%d c%d e%d l%d m0 p%c s%d i1\n"
 		"dev(%d) type(%d) framing(%d) overruns(%d)\n",
 
 		uart->baud,
@@ -234,10 +233,6 @@
 		uart->ferr,
 		uart->oerr 
 	);
-	n = readstr(offset, buf, n, p);
-	free(p);
-
-	return n;
 }
 
 static void
--- a/sys/src/9/sgi/uartarcs.c
+++ b/sys/src/9/sgi/uartarcs.c
@@ -159,12 +159,6 @@
 	return 0;
 }
 
-static long
-status(Uart *, void *, long, long)
-{
-	return 0;
-}
-
 void
 uartarcsputc(Uart*, int c)
 {
@@ -192,7 +186,6 @@
 	.modemctl	= donothing,
 	.rts		= donothing,
 	.dtr		= donothing,
-	.status		= status,
 	.fifo		= donothing,
 
 	.getc		= uartarcsgetc,
--- a/sys/src/9/teg2/uarti8250.c
+++ b/sys/src/9/teg2/uarti8250.c
@@ -145,20 +145,18 @@
 #define csr8w(c, r, v)	((c)->io[r] = (c)->sticky[r] | (v), coherence())
 #define csr8o(c, r, v)	((c)->io[r] = (v), coherence())
 
-static long
-i8250status(Uart* uart, void* buf, long n, long offset)
+static char*
+i8250status(Uart* uart, char *p, char *e)
 {
-	char *p;
 	Ctlr *ctlr;
 	uchar ier, lcr, mcr, msr;
 
 	ctlr = uart->regs;
-	p = malloc(READSTR);
 	mcr = ctlr->sticky[Mcr];
 	msr = csr8r(ctlr, Msr);
 	ier = ctlr->sticky[Ier];
 	lcr = ctlr->sticky[Lcr];
-	snprint(p, READSTR,
+	return seprint(p, e,
 		"b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
 		"dev(%d) type(%d) framing(%d) overruns(%d) "
 		"berr(%d) serr(%d)%s%s%s%s\n",
@@ -185,10 +183,6 @@
 		(msr & Dcd) ? " dcd": "",
 		(msr & Ri) ? " ring": ""
 	);
-	n = readstr(offset, buf, n, p);
-	free(p);
-
-	return n;
 }
 
 static void
--- a/sys/src/9/xen/uartxen.c
+++ b/sys/src/9/xen/uartxen.c
@@ -199,33 +199,6 @@
 	return 0;
 }
 
-static long
-status(Uart *uart, void *buf, long n, long offset)
-{
-	char *p;
-
-	p = malloc(READSTR);
-	if(p == nil)
-		error(Enomem);
-	snprint(p, READSTR,
-		"b%d\n"
-		"dev(%d) type(%d) framing(%d) overruns(%d) "
-		"berr(%d) serr(%d)\n",
-
-		uart->baud,
-		uart->dev,
-		uart->type,
-		uart->ferr,
-		uart->oerr,
-		uart->berr,
-		uart->serr
-	);
-	n = readstr(offset, buf, n, p);
-	free(p);
-
-	return n;
-}
-
 void
 xenputc(Uart*, int c)
 {
@@ -279,7 +252,6 @@
 	.modemctl	= donothing,
 	.rts		= donothing,
 	.dtr		= donothing,
-	.status		= status,
 	.fifo		= donothing,
 
 	.getc		= xengetc,
--