diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-10-11 17:29:16 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-10-11 17:29:16 +0200 |
commit | 16d61d3c974b1d287db8d548cc13078341019730 (patch) | |
tree | 95bab330a7bee0b37bcf5d1495a76258969a2655 | |
parent | d9394b0d87169ef7aa7796344af421c757bc3749 (diff) |
kernel: try to catch some (rare) mistakes
kstrcpy() did not null terminate for < 4 byte buffers. fixed,
but i dont think there is any case where this can happen in
practice.
always set malloctag in kstrdup(), cleanup.
always use ERRMAX bounded kstrcpy() to set up->errstr, q->err
and note[]->msg. paranoia.
instead of silently truncating interface name in netifinit(),
panic the kernel if interface name is too long as this case
is clearly a mistake.
panic kernel when filename is too long for addbootfile() in
devroot. this might happen if your kernel configuration is
messed up.
-rw-r--r-- | sys/src/9/port/chan.c | 41 | ||||
-rw-r--r-- | sys/src/9/port/devaoe.c | 2 | ||||
-rw-r--r-- | sys/src/9/port/devroot.c | 2 | ||||
-rw-r--r-- | sys/src/9/port/netif.c | 5 | ||||
-rw-r--r-- | sys/src/9/port/proc.c | 2 | ||||
-rw-r--r-- | sys/src/9/port/qio.c | 11 |
6 files changed, 31 insertions, 32 deletions
diff --git a/sys/src/9/port/chan.c b/sys/src/9/port/chan.c index ff3b8e5f3..dd59d370a 100644 --- a/sys/src/9/port/chan.c +++ b/sys/src/9/port/chan.c @@ -114,7 +114,6 @@ decref(Ref *r) unlock(r); if(x < 0) panic("decref pc=%#p", getcallerpc(&r)); - return x; } @@ -130,20 +129,19 @@ kstrcpy(char *s, char *t, int ns) int nt; nt = strlen(t); - if(nt+1 <= ns){ - memmove(s, t, nt+1); - return; - } - /* too long */ - if(ns < 4){ - /* but very short! */ - strncpy(s, t, ns); + if(nt < ns){ + memmove(s, t, nt); + s[nt] = '\0'; return; } - /* truncate with ... at character boundary (very rare case) */ - memmove(s, t, ns-4); + /* too long, truncate */ + nt = ns-1; + memmove(s, t, nt); + s[nt] = '\0'; + /* append ... if there is space */ ns -= 4; - s[ns] = '\0'; + if(ns < 0) + return; /* look for first byte of UTF-8 sequence by skipping continuation bytes */ while(ns>0 && (s[--ns]&0xC0)==0x80) ; @@ -169,17 +167,18 @@ kstrdup(char **p, char *s) int n; char *t, *prev; - n = strlen(s)+1; + n = strlen(s); /* if it's a user, we can wait for memory; if not, something's very wrong */ - if(up){ - t = smalloc(n); - setmalloctag(t, getcallerpc(&p)); - }else{ - t = malloc(n); + if(up != nil) + t = smalloc(n+1); + else{ + t = malloc(n+1); if(t == nil) panic("kstrdup: no memory"); } + setmalloctag(t, getcallerpc(&p)); memmove(t, s, n); + t[n] = '\0'; prev = *p; *p = t; free(prev); @@ -1002,7 +1001,7 @@ walk(Chan **cp, char **names, int nnames, int nomount, int *nerror) *nerror = nhave; pathclose(path); cclose(c); - strcpy(up->errstr, Enotdir); + kstrcpy(up->errstr, Enotdir, ERRMAX); if(mh != nil) putmhead(mh); return -1; @@ -1083,11 +1082,11 @@ walk(Chan **cp, char **names, int nnames, int nomount, int *nerror) if(wq->nqid==0 || (wq->qid[wq->nqid-1].type&QTDIR)){ if(nerror) *nerror = nhave+wq->nqid+1; - strcpy(up->errstr, Edoesnotexist); + kstrcpy(up->errstr, Edoesnotexist, ERRMAX); }else{ if(nerror) *nerror = nhave+wq->nqid; - strcpy(up->errstr, Enotdir); + kstrcpy(up->errstr, Enotdir, ERRMAX); } free(wq); if(mh != nil) diff --git a/sys/src/9/port/devaoe.c b/sys/src/9/port/devaoe.c index 23f621a05..0165558cc 100644 --- a/sys/src/9/port/devaoe.c +++ b/sys/src/9/port/devaoe.c @@ -2168,7 +2168,7 @@ static void netrdaoeproc(void *v) { int idx; - char name[Maxpath+1], *s; + char name[Maxpath], *s; Aoehdr *h; Block *b; Netlink *nl; diff --git a/sys/src/9/port/devroot.c b/sys/src/9/port/devroot.c index e2d3cddcd..338432505 100644 --- a/sys/src/9/port/devroot.c +++ b/sys/src/9/port/devroot.c @@ -63,6 +63,8 @@ addlist(Dirlist *l, char *name, uchar *contents, ulong len, int perm) panic("too many root files"); l->data[l->ndir] = contents; d = &l->dir[l->ndir]; + if(strlen(name) >= sizeof d->name) + panic("root file name too long: %s", name); strcpy(d->name, name); d->length = len; d->perm = perm; diff --git a/sys/src/9/port/netif.c b/sys/src/9/port/netif.c index 444ef3907..3d77f0500 100644 --- a/sys/src/9/port/netif.c +++ b/sys/src/9/port/netif.c @@ -18,8 +18,9 @@ static int parseaddr(uchar*, char*, int); void netifinit(Netif *nif, char *name, int nfile, ulong limit) { - strncpy(nif->name, name, KNAMELEN-1); - nif->name[KNAMELEN-1] = 0; + if(strlen(name) >= sizeof nif->name) + panic("netifinit: name too long: %s", name); + strcpy(nif->name, name); nif->nfile = nfile; nif->f = xalloc(nfile*sizeof(Netfile*)); if (nif->f == nil) diff --git a/sys/src/9/port/proc.c b/sys/src/9/port/proc.c index a64ef4749..3abc16080 100644 --- a/sys/src/9/port/proc.c +++ b/sys/src/9/port/proc.c @@ -913,7 +913,7 @@ postnote(Proc *p, int dolock, char *n, int flag) ret = 0; if(p->nnote < NNOTE && n != nil) { - strcpy(p->note[p->nnote].msg, n); + kstrcpy(p->note[p->nnote].msg, n, ERRMAX); p->note[p->nnote++].flag = flag; ret = 1; } diff --git a/sys/src/9/port/qio.c b/sys/src/9/port/qio.c index a721debf8..a70fa8a31 100644 --- a/sys/src/9/port/qio.c +++ b/sys/src/9/port/qio.c @@ -1391,7 +1391,7 @@ qclose(Queue *q) ilock(q); q->state |= Qclosed; q->state &= ~(Qflow|Qstarve); - strcpy(q->err, Ehungup); + kstrcpy(q->err, Ehungup, ERRMAX); bfirst = q->bfirst; q->bfirst = 0; q->len = 0; @@ -1417,12 +1417,9 @@ qhangup(Queue *q, char *msg) /* mark it */ ilock(q); q->state |= Qclosed; - if(msg == 0 || *msg == 0) - strcpy(q->err, Ehungup); - else { - strncpy(q->err, msg, ERRMAX-1); - q->err[ERRMAX-1] = 0; - } + if(msg == 0 || *msg == '\0') + msg = Ehungup; + kstrcpy(q->err, msg, ERRMAX); iunlock(q); /* wake up readers/writers */ |