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.
This commit is contained in:
cinap_lenrek 2024-10-20 12:12:42 +00:00
parent fcdfb151e2
commit c1c4d40def
18 changed files with 49 additions and 255 deletions

View file

@ -282,33 +282,6 @@ rts(Uart*, int)
{
}
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 @@ PhysUart qemuphysuart = {
.modemctl = donothing,
.rts = rts,
.dtr = donothing,
.status = status,
.fifo = donothing,
.getc = getc,
.putc = putc,

View file

@ -225,33 +225,6 @@ rts(Uart *uart, int on)
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 @@ PhysUart miniphysuart = {
.modemctl = donothing,
.rts = rts,
.dtr = donothing,
.status = status,
.fifo = donothing,
.getc = getc,
.putc = putc,

View file

@ -282,33 +282,6 @@ rts(Uart*, int)
{
}
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 @@ PhysUart pl011physuart = {
.modemctl = donothing,
.rts = rts,
.dtr = donothing,
.status = status,
.fifo = donothing,
.getc = getc,
.putc = putc,

View file

@ -273,33 +273,6 @@ dobreak(Uart*, int)
{
}
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 @@ PhysUart imxphysuart = {
.modemctl = donothing,
.rts = rts,
.dtr = donothing,
.status = status,
.fifo = donothing,
.getc = getc,
.putc = putc,

View file

@ -255,13 +255,6 @@ kw_dtr(Uart* uart, int on)
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 @@ PhysUart kwphysuart = {
.modemctl = kw_modemctl,
.rts = kw_rts,
.dtr = kw_dtr,
.status = kw_status,
.fifo = kw_fifo,
.getc = kw_getc,
.putc = kw_putc,

View file

@ -284,33 +284,6 @@ rts(Uart*, int)
{
}
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 @@ PhysUart lx2kphysuart = {
.modemctl = donothing,
.rts = rts,
.dtr = donothing,
.status = status,
.fifo = donothing,
.getc = getc,
.putc = putc,

View file

@ -145,20 +145,18 @@ static Uart i8250uart[] = {
#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 @@ i8250status(Uart* uart, void* buf, long n, long offset)
(msr & Dcd) ? " dcd": "",
(msr & Ri) ? " ring": ""
);
n = readstr(offset, buf, n, p);
free(p);
return n;
}
static void

View file

@ -149,20 +149,18 @@ static Uart i8250uart[2] = {
#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 @@ i8250status(Uart* uart, void* buf, long n, long offset)
(msr & Dcd) ? " dcd": "",
(msr & Ri) ? " ring": ""
);
n = readstr(offset, buf, n, p);
free(p);
return n;
}
static void

View file

@ -174,20 +174,18 @@ static Uart i8250uart[] = {
#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 @@ i8250status(Uart* uart, void* buf, long n, long offset)
(msr & Dcd) ? " dcd": "",
(msr & Ri) ? " ring": ""
);
n = readstr(offset, buf, n, p);
free(p);
return n;
}
static void

View file

@ -254,21 +254,19 @@ axpcc(Cc* cc, int cmd)
}
}
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 @@ axpstatus(Uart* uart, void* buf, long n, long offset)
(ms & Sdcd) ? " dcd" : "",
(ms & Sri) ? " ring" : ""
);
n = readstr(offset, buf, n, p);
free(p);
return n;
}
static void

View file

@ -150,20 +150,18 @@ static Uart i8250uart[2] = {
#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 @@ i8250status(Uart* uart, void* buf, long n, long offset)
(msr & Dcd) ? " dcd": "",
(msr & Ri) ? " ring": ""
);
n = readstr(offset, buf, n, p);
free(p);
return n;
}
static void

View file

@ -399,6 +399,7 @@ static long
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 @@ uartread(Chan *c, void *buf, long n, vlong off)
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;

View file

@ -881,7 +881,7 @@ struct PhysUart
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 */

View file

@ -132,14 +132,13 @@ suenable(Uart*uart, int ie)
}
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 @@ sustatus(Uart* uart, void* buf, long n, long offset)
uart->type,
uart->ferr,
uart->oerr);
n = readstr(offset, buf, n, p);
free(p);
return n;
}
static void

View file

@ -212,14 +212,13 @@ smcenable(Uart *uart, int intenb)
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 @@ smcstatus(Uart* uart, void* buf, long n, long offset)
uart->ferr,
uart->oerr
);
n = readstr(offset, buf, n, p);
free(p);
return n;
}
static void

View file

@ -159,12 +159,6 @@ parity(Uart *uart, int n)
return 0;
}
static long
status(Uart *, void *, long, long)
{
return 0;
}
void
uartarcsputc(Uart*, int c)
{
@ -192,7 +186,6 @@ PhysUart arcsphysuart = {
.modemctl = donothing,
.rts = donothing,
.dtr = donothing,
.status = status,
.fifo = donothing,
.getc = uartarcsgetc,

View file

@ -145,20 +145,18 @@ static Uart i8250uart[] = {
#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 @@ i8250status(Uart* uart, void* buf, long n, long offset)
(msr & Dcd) ? " dcd": "",
(msr & Ri) ? " ring": ""
);
n = readstr(offset, buf, n, p);
free(p);
return n;
}
static void

View file

@ -199,33 +199,6 @@ parity(Uart *uart, int n)
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 @@ PhysUart xenphysuart = {
.modemctl = donothing,
.rts = donothing,
.dtr = donothing,
.status = status,
.fifo = donothing,
.getc = xengetc,