wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

commit e9ce32ed9302b7d25bec918d30fc152f692d9134
parent 6e75d6c765c66b1db43664f797b4b8fbb2f6255b
Author: Kris Maglione <bsdaemon@wmii.de>
Date:   Sun, 18 Jun 2006 21:23:17 -0400

Fixed buffer overflow vulnerabilities in ixp_unpack functions


Diffstat:
cmd/wmiir.c | 6+++---
libixp/convert.c | 138+++++++++++++++++++++++++++++++++++++++++++------------------------------------
libixp/ixp.h | 18+++++++++---------
libixp/message.c | 93++++++++++++++++++++++++++++++++++++++++---------------------------------------
libixp/transport.c | 2+-
5 files changed, 136 insertions(+), 121 deletions(-)

diff --git a/cmd/wmiir.c b/cmd/wmiir.c @@ -155,14 +155,14 @@ xls(void *result, unsigned int msize, int details) static Stat stat; do { - ixp_unpack_stat(&p, &stat); + ixp_unpack_stat(&p, nil, &stat); n++; } while(p - (unsigned char*)result < msize); dir = (Stat *)cext_emallocz(sizeof(Stat) * n); p = result; do { - ixp_unpack_stat(&p, &dir[i++]); + ixp_unpack_stat(&p, nil, &dir[i++]); } while(p - (unsigned char*)result < msize); qsort(dir, n, sizeof(Stat), comp_stat); @@ -189,7 +189,7 @@ xdir(char *file, int details) return -1; } buf = c.fcall.stat; - ixp_unpack_stat(&buf, s); + ixp_unpack_stat(&buf, nil, s); if(!(s->mode & IXP_DMDIR)) { print_stat(s, details); fflush(stdout); diff --git a/libixp/convert.c b/libixp/convert.c @@ -12,36 +12,39 @@ void ixp_pack_u8(unsigned char **msg, int *msize, unsigned char val) { - if((*msize -= 1) >= 0) + if(!msize || (*msize -= 1) >= 0) *(*msg)++ = val; } void -ixp_unpack_u8(unsigned char **msg, unsigned char *val) +ixp_unpack_u8(unsigned char **msg, int *msize, unsigned char *val) { - *val = *(*msg)++; + if(!msize || (*msize -= 1) >= 0) + *val = *(*msg)++; } void ixp_pack_u16(unsigned char **msg, int *msize, unsigned short val) { - if((*msize -= 2) >= 0) { + if(!msize || (*msize -= 2) >= 0) { *(*msg)++ = val; *(*msg)++ = val >> 8; } } void -ixp_unpack_u16(unsigned char **msg, unsigned short *val) +ixp_unpack_u16(unsigned char **msg, int *msize, unsigned short *val) { - *val = *(*msg)++; - *val |= *(*msg)++ << 8; + if(!msize || (*msize -= 2) >= 0) { + *val = *(*msg)++; + *val |= *(*msg)++ << 8; + } } void ixp_pack_u32(unsigned char **msg, int *msize, unsigned int val) { - if((*msize -= 4) >= 0) { + if(!msize || (*msize -= 4) >= 0) { *(*msg)++ = val; *(*msg)++ = val >> 8; *(*msg)++ = val >> 16; @@ -50,18 +53,20 @@ ixp_pack_u32(unsigned char **msg, int *msize, unsigned int val) } void -ixp_unpack_u32(unsigned char **msg, unsigned int *val) +ixp_unpack_u32(unsigned char **msg, int *msize, unsigned int *val) { - *val = *(*msg)++; - *val |= *(*msg)++ << 8; - *val |= *(*msg)++ << 16; - *val |= *(*msg)++ << 24; + if(!msize || (*msize -= 4) >= 0) { + *val = *(*msg)++; + *val |= *(*msg)++ << 8; + *val |= *(*msg)++ << 16; + *val |= *(*msg)++ << 24; + } } void ixp_pack_u64(unsigned char **msg, int *msize, unsigned long long val) { - if((*msize -= 8) >= 0) { + if(!msize || (*msize -= 8) >= 0) { *(*msg)++ = val; *(*msg)++ = val >> 8; *(*msg)++ = val >> 16; @@ -74,12 +79,18 @@ ixp_pack_u64(unsigned char **msg, int *msize, unsigned long long val) } void -ixp_unpack_u64(unsigned char **msg, unsigned long long *val) +ixp_unpack_u64(unsigned char **msg, int *msize, unsigned long long *val) { - int i; - *val = 0; - for (i = 0; i < 8; ++i) - *val |= (unsigned long long) *(*msg)++ << (8 * i); + if(!msize || (*msize -= 8) >= 0) { + *val |= *(*msg)++; + *val |= *(*msg)++ << 8; + *val |= *(*msg)++ << 16; + *val |= *(*msg)++ << 24; + *val |= (unsigned long long)*(*msg)++ << 32; + *val |= (unsigned long long)*(*msg)++ << 40; + *val |= (unsigned long long)*(*msg)++ << 48; + *val |= (unsigned long long)*(*msg)++ << 56; + } } void @@ -92,13 +103,12 @@ ixp_pack_string(unsigned char **msg, int *msize, const char *s) } void -ixp_unpack_strings(unsigned char **msg, unsigned short n, char **strings) { +ixp_unpack_strings(unsigned char **msg, int *msize, unsigned short n, char **strings) { unsigned char *s = *msg; unsigned int i, size = 0; unsigned short len; - /* XXX: a specially crafted packet could make this read past the end of the buffer */ for(i=0; i<n; i++) { - ixp_unpack_u16(&s, &len); + ixp_unpack_u16(&s, msize, &len); s += len; size += len + 1; /* for '\0' */ } @@ -110,7 +120,10 @@ ixp_unpack_strings(unsigned char **msg, unsigned short n, char **strings) { /* XXX: we don't really need mallocz here */ s = cext_emallocz(size); for(i=0; i < n; i++) { - ixp_unpack_u16(msg, &len); + ixp_unpack_u16(msg, msize, &len); + if(!msize || (*msize -= len) < 0) + return; + memcpy(s, *msg, len); s[len] = '\0'; strings[i] = s; @@ -120,55 +133,56 @@ ixp_unpack_strings(unsigned char **msg, unsigned short n, char **strings) { } void -ixp_unpack_string(unsigned char **msg, char **string, unsigned short *len) +ixp_unpack_string(unsigned char **msg, int *msize, char **string, unsigned short *len) { - ixp_unpack_u16(msg, len); + ixp_unpack_u16(msg, msize, len); *string = nil; - if (!*len) - return; - /* XXX we don't really need emallocz here */ - *string = cext_emallocz(*len+1); - memcpy(*string, *msg, *len); - (*string)[*len] = 0; - *msg += *len; + if (*len && (!msize || (*msize -= *len) >= 0)) { + /* XXX we don't really need emallocz here */ + *string = cext_emallocz(*len+1); + memcpy(*string, *msg, *len); + (*string)[*len] = 0; + *msg += *len; + } } void ixp_pack_data(unsigned char **msg, int *msize, unsigned char *data, unsigned int datalen) { - if((*msize -= datalen) >= 0) { + if(!msize || (*msize -= datalen) >= 0) { memcpy(*msg, data, datalen); *msg += datalen; } } void -ixp_unpack_data(unsigned char **msg, unsigned char **data, unsigned int datalen) +ixp_unpack_data(unsigned char **msg, int *msize, unsigned char **data, unsigned int datalen) { - /* XXX: this could be too large a number */ - *data = cext_emallocz(datalen); - memcpy(*data, *msg, datalen); - *msg += datalen; + if(!msize || (*msize -= datalen) >= 0) { + *data = cext_emallocz(datalen); + memcpy(*data, *msg, datalen); + *msg += datalen; + } } void ixp_pack_prefix(unsigned char *msg, unsigned int size, unsigned char id, unsigned short tag) { - int dummy = sizeof(unsigned char) + - sizeof(unsigned short) + sizeof(unsigned int); - ixp_pack_u32(&msg, &dummy, size); - ixp_pack_u8(&msg, &dummy, id); - ixp_pack_u16(&msg, &dummy, tag); + ixp_pack_u32(&msg, 0, size); + ixp_pack_u8(&msg, 0, id); + ixp_pack_u16(&msg, 0, tag); } void ixp_unpack_prefix(unsigned char **msg, unsigned int *size, unsigned char *id, unsigned short *tag) { - ixp_unpack_u32(msg, size); - ixp_unpack_u8(msg, id); - ixp_unpack_u16(msg, tag); + int msize; + ixp_unpack_u32(msg, nil, size); + msize = *size; + ixp_unpack_u8(msg, &msize, id); + ixp_unpack_u16(msg, &msize, tag); } void @@ -180,11 +194,11 @@ ixp_pack_qid(unsigned char **msg, int *msize, Qid * qid) } void -ixp_unpack_qid(unsigned char **msg, Qid * qid) +ixp_unpack_qid(unsigned char **msg, int *msize, Qid * qid) { - ixp_unpack_u8(msg, &qid->type); - ixp_unpack_u32(msg, &qid->version); - ixp_unpack_u64(msg, &qid->path); + ixp_unpack_u8(msg, msize, &qid->type); + ixp_unpack_u32(msg, msize, &qid->version); + ixp_unpack_u64(msg, msize, &qid->path); } void @@ -205,19 +219,19 @@ ixp_pack_stat(unsigned char **msg, int *msize, Stat * stat) } void -ixp_unpack_stat(unsigned char **msg, Stat * stat) +ixp_unpack_stat(unsigned char **msg, int *msize, Stat * stat) { unsigned short dummy; *msg += sizeof(unsigned short); - ixp_unpack_u16(msg, &stat->type); - ixp_unpack_u32(msg, &stat->dev); - ixp_unpack_qid(msg, &stat->qid); - ixp_unpack_u32(msg, &stat->mode); - ixp_unpack_u32(msg, &stat->atime); - ixp_unpack_u32(msg, &stat->mtime); - ixp_unpack_u64(msg, &stat->length); - ixp_unpack_string(msg, &stat->name, &dummy); - ixp_unpack_string(msg, &stat->uid, &dummy); - ixp_unpack_string(msg, &stat->gid, &dummy); - ixp_unpack_string(msg, &stat->muid, &dummy); + ixp_unpack_u16(msg, msize, &stat->type); + ixp_unpack_u32(msg, msize, &stat->dev); + ixp_unpack_qid(msg, msize, &stat->qid); + ixp_unpack_u32(msg, msize, &stat->mode); + ixp_unpack_u32(msg, msize, &stat->atime); + ixp_unpack_u32(msg, msize, &stat->mtime); + ixp_unpack_u64(msg, msize, &stat->length); + ixp_unpack_string(msg, msize, &stat->name, &dummy); + ixp_unpack_string(msg, msize, &stat->uid, &dummy); + ixp_unpack_string(msg, msize, &stat->gid, &dummy); + ixp_unpack_string(msg, msize, &stat->muid, &dummy); } diff --git a/libixp/ixp.h b/libixp/ixp.h @@ -321,28 +321,28 @@ int ixp_client_do_fcall(IXPClient * c); /* convert.c */ void ixp_pack_u8(unsigned char **msg, int *msize, unsigned char val); -void ixp_unpack_u8(unsigned char **msg, unsigned char *val); +void ixp_unpack_u8(unsigned char **msg, int *msize, unsigned char *val); void ixp_pack_u16(unsigned char **msg, int *msize, unsigned short val); -void ixp_unpack_u16(unsigned char **msg, unsigned short *val); +void ixp_unpack_u16(unsigned char **msg, int *msize, unsigned short *val); void ixp_pack_u32(unsigned char **msg, int *msize, unsigned int val); -void ixp_unpack_u32(unsigned char **msg, unsigned int *val); +void ixp_unpack_u32(unsigned char **msg, int *msize, unsigned int *val); void ixp_pack_u64(unsigned char **msg, int *msize, unsigned long long val); -void ixp_unpack_u64(unsigned char **msg, unsigned long long *val); +void ixp_unpack_u64(unsigned char **msg, int *msize, unsigned long long *val); void ixp_pack_string(unsigned char **msg, int *msize, const char *s); -void ixp_unpack_strings(unsigned char **msg, unsigned short n, char **strings); -void ixp_unpack_string(unsigned char **msg, char **string, unsigned short *len); +void ixp_unpack_strings(unsigned char **msg, int *msize, unsigned short n, char **strings); +void ixp_unpack_string(unsigned char **msg, int *msize, char **string, unsigned short *len); void ixp_pack_data(unsigned char **msg, int *msize, unsigned char *data, unsigned int datalen); -void ixp_unpack_data(unsigned char **msg, unsigned char **data, +void ixp_unpack_data(unsigned char **msg, int *msize, unsigned char **data, unsigned int datalen); void ixp_pack_prefix(unsigned char *msg, unsigned int size, unsigned char id, unsigned short tag); void ixp_unpack_prefix(unsigned char **msg, unsigned int *size, unsigned char *id, unsigned short *tag); void ixp_pack_qid(unsigned char **msg, int *msize, Qid *qid); -void ixp_unpack_qid(unsigned char **msg, Qid *qid); +void ixp_unpack_qid(unsigned char **msg, int *msize, Qid *qid); void ixp_pack_stat(unsigned char **msg, int *msize, Stat *stat); -void ixp_unpack_stat(unsigned char **msg, Stat *stat); +void ixp_unpack_stat(unsigned char **msg, int *msize, Stat *stat); /* request.c */ void respond(Req *r, char *error); diff --git a/libixp/message.c b/libixp/message.c @@ -139,103 +139,104 @@ ixp_fcall2msg(void *msg, Fcall *fcall, unsigned int msglen) unsigned int ixp_msg2fcall(Fcall *fcall, void *msg, unsigned int msglen) { - unsigned int i, msize; + unsigned int i, msize, tsize; unsigned short len; unsigned char *p = msg; ixp_unpack_prefix(&p, &msize, &fcall->type, &fcall->tag); + tsize = msize; if(msize > msglen) /* bad message */ return 0; switch (fcall->type) { case TVERSION: case RVERSION: - ixp_unpack_u32(&p, &fcall->msize); - ixp_unpack_string(&p, &fcall->version, &len); + ixp_unpack_u32(&p, &msize, &fcall->msize); + ixp_unpack_string(&p, &msize, &fcall->version, &len); break; case TAUTH: - ixp_unpack_u32(&p, &fcall->afid); - ixp_unpack_string(&p, &fcall->uname, &len); - ixp_unpack_string(&p, &fcall->aname, &len); + ixp_unpack_u32(&p, &msize, &fcall->afid); + ixp_unpack_string(&p, &msize, &fcall->uname, &len); + ixp_unpack_string(&p, &msize, &fcall->aname, &len); break; case RAUTH: - ixp_unpack_qid(&p, &fcall->aqid); + ixp_unpack_qid(&p, &msize, &fcall->aqid); break; case RATTACH: - ixp_unpack_qid(&p, &fcall->qid); + ixp_unpack_qid(&p, &msize, &fcall->qid); break; case TATTACH: - ixp_unpack_u32(&p, &fcall->fid); - ixp_unpack_u32(&p, &fcall->afid); - ixp_unpack_string(&p, &fcall->uname, &len); - ixp_unpack_string(&p, &fcall->aname, &len); + ixp_unpack_u32(&p, &msize, &fcall->fid); + ixp_unpack_u32(&p, &msize, &fcall->afid); + ixp_unpack_string(&p, &msize, &fcall->uname, &len); + ixp_unpack_string(&p, &msize, &fcall->aname, &len); break; case RERROR: - ixp_unpack_string(&p, &fcall->ename, &len); + ixp_unpack_string(&p, &msize, &fcall->ename, &len); break; case TFLUSH: - ixp_unpack_u16(&p, &fcall->oldtag); + ixp_unpack_u16(&p, &msize, &fcall->oldtag); break; case TWALK: - ixp_unpack_u32(&p, &fcall->fid); - ixp_unpack_u32(&p, &fcall->newfid); - ixp_unpack_u16(&p, &fcall->nwname); - ixp_unpack_strings(&p, fcall->nwname, fcall->wname); + ixp_unpack_u32(&p, &msize, &fcall->fid); + ixp_unpack_u32(&p, &msize, &fcall->newfid); + ixp_unpack_u16(&p, &msize, &fcall->nwname); + ixp_unpack_strings(&p, &msize, fcall->nwname, fcall->wname); break; case RWALK: - ixp_unpack_u16(&p, &fcall->nwqid); + ixp_unpack_u16(&p, &msize, &fcall->nwqid); for(i = 0; i < fcall->nwqid; i++) - ixp_unpack_qid(&p, &fcall->wqid[i]); + ixp_unpack_qid(&p, &msize, &fcall->wqid[i]); break; case TOPEN: - ixp_unpack_u32(&p, &fcall->fid); - ixp_unpack_u8(&p, &fcall->mode); + ixp_unpack_u32(&p, &msize, &fcall->fid); + ixp_unpack_u8(&p, &msize, &fcall->mode); break; case ROPEN: case RCREATE: - ixp_unpack_qid(&p, &fcall->qid); - ixp_unpack_u32(&p, &fcall->iounit); + ixp_unpack_qid(&p, &msize, &fcall->qid); + ixp_unpack_u32(&p, &msize, &fcall->iounit); break; case TCREATE: - ixp_unpack_u32(&p, &fcall->fid); - ixp_unpack_string(&p, &fcall->name, &len); - ixp_unpack_u32(&p, &fcall->perm); - ixp_unpack_u8(&p, &fcall->mode); + ixp_unpack_u32(&p, &msize, &fcall->fid); + ixp_unpack_string(&p, &msize, &fcall->name, &len); + ixp_unpack_u32(&p, &msize, &fcall->perm); + ixp_unpack_u8(&p, &msize, &fcall->mode); break; case TREAD: - ixp_unpack_u32(&p, &fcall->fid); - ixp_unpack_u64(&p, &fcall->offset); - ixp_unpack_u32(&p, &fcall->count); + ixp_unpack_u32(&p, &msize, &fcall->fid); + ixp_unpack_u64(&p, &msize, &fcall->offset); + ixp_unpack_u32(&p, &msize, &fcall->count); break; case RREAD: - ixp_unpack_u32(&p, &fcall->count); - ixp_unpack_data(&p, &fcall->data, fcall->count); + ixp_unpack_u32(&p, &msize, &fcall->count); + ixp_unpack_data(&p, &msize, &fcall->data, fcall->count); break; case TWRITE: - ixp_unpack_u32(&p, &fcall->fid); - ixp_unpack_u64(&p, &fcall->offset); - ixp_unpack_u32(&p, &fcall->count); - ixp_unpack_data(&p, &fcall->data, fcall->count); + ixp_unpack_u32(&p, &msize, &fcall->fid); + ixp_unpack_u64(&p, &msize, &fcall->offset); + ixp_unpack_u32(&p, &msize, &fcall->count); + ixp_unpack_data(&p, &msize, &fcall->data, fcall->count); break; case RWRITE: - ixp_unpack_u32(&p, &fcall->count); + ixp_unpack_u32(&p, &msize, &fcall->count); break; case TCLUNK: case TREMOVE: case TSTAT: - ixp_unpack_u32(&p, &fcall->fid); + ixp_unpack_u32(&p, &msize, &fcall->fid); break; case RSTAT: - ixp_unpack_u16(&p, &len); - ixp_unpack_data(&p, &fcall->stat, len); + ixp_unpack_u16(&p, &msize, &len); + ixp_unpack_data(&p, &msize, &fcall->stat, len); break; case TWSTAT: - ixp_unpack_u32(&p, &fcall->fid); - ixp_unpack_u16(&p, &len); - ixp_unpack_data(&p, &fcall->stat, len); + ixp_unpack_u32(&p, &msize, &fcall->fid); + ixp_unpack_u16(&p, &msize, &len); + ixp_unpack_data(&p, &msize, &fcall->stat, len); break; } - if(msg + msize == p) - return msize; + if(msize > 0) + return tsize; return 0; } diff --git a/libixp/transport.c b/libixp/transport.c @@ -64,7 +64,7 @@ ixp_recv_message(int fd, void *msg, unsigned int msglen, char **errstr) if(ixp_recv_data(fd, msg, sizeof(unsigned int), errstr) != sizeof(unsigned int)) return 0; - ixp_unpack_u32((void *)&msg, &msize); + ixp_unpack_u32((void *)&msg, nil, &msize); if(msize > msglen) { *errstr = "invalid message header"; return 0;