mirror of
git://git.9front.org/plan9front/plan9front
synced 2025-01-12 11:10:06 +00:00
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:
parent
fcdfb151e2
commit
c1c4d40def
18 changed files with 49 additions and 255 deletions
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue