diff options
author | Bjoern A. Zeeb <bz@FreeBSD.org> | 2011-09-28 08:47:17 +0000 |
---|---|---|
committer | Bjoern A. Zeeb <bz@FreeBSD.org> | 2011-09-28 08:47:17 +0000 |
commit | 261d4022db3351b55685fed4b18a98ed32aa203f (patch) | |
tree | fc72ee1dd1ac0829c819d8bfb5512d16db03fb5c | |
parent | 01d430d6b0150e4f123ebb67bdb27f53bf679c36 (diff) | |
download | src-261d4022db3351b55685fed4b18a98ed32aa203f.tar.gz src-261d4022db3351b55685fed4b18a98ed32aa203f.zip |
Fix handling of corrupt compress(1)ed data. [11:04]
Add missing length checks on unix socket addresses. [11:05]
Approved by: so (cperciva)
Approved by: re (kensmith)
Security: FreeBSD-SA-11:04.compress
Security: CVE-2011-2895 [11:04]
Security: FreeBSD-SA-11:05.unix
Notes
Notes:
svn path=/releng/7.4/; revision=225827
-rw-r--r-- | UPDATING | 5 | ||||
-rw-r--r-- | sys/conf/newvers.sh | 2 | ||||
-rw-r--r-- | sys/kern/uipc_usrreq.c | 4 | ||||
-rw-r--r-- | usr.bin/compress/zopen.c | 23 | ||||
-rw-r--r-- | usr.bin/gzip/zuncompress.c | 31 |
5 files changed, 46 insertions, 19 deletions
@@ -8,6 +8,11 @@ Items affecting the ports and packages system can be found in /usr/ports/UPDATING. Please read that file before running portupgrade. +20110928: p3 FreeBSD-SA-11:04.compress, FreeBSD-SA-11:05.unix + Fix handling of corrupt compress(1)ed data. [11:04] + + Add missing length checks on unix socket addresses. [11:05] + 20110528: p2 FreeBSD-SA-11:02.bind Fix BIND remote DoS with large RRSIG RRsets and negative caching. diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh index 59b31a50b3dd..95ac9aa52177 100644 --- a/sys/conf/newvers.sh +++ b/sys/conf/newvers.sh @@ -32,7 +32,7 @@ TYPE="FreeBSD" REVISION="7.4" -BRANCH="RELEASE-p2" +BRANCH="RELEASE-p3" if [ "X${BRANCH_OVERRIDE}" != "X" ]; then BRANCH=${BRANCH_OVERRIDE} fi diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 395b677da2f5..385fce628624 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -395,6 +395,8 @@ uipc_bind(struct socket *so, struct sockaddr *nam, struct thread *td) unp = sotounpcb(so); KASSERT(unp != NULL, ("uipc_bind: unp == NULL")); + if (soun->sun_len > sizeof(struct sockaddr_un)) + return (EINVAL); namelen = soun->sun_len - offsetof(struct sockaddr_un, sun_path); if (namelen <= 0) return (EINVAL); @@ -1141,6 +1143,8 @@ unp_connect(struct socket *so, struct sockaddr *nam, struct thread *td) unp = sotounpcb(so); KASSERT(unp != NULL, ("unp_connect: unp == NULL")); + if (nam->sa_len > sizeof(struct sockaddr_un)) + return (EINVAL); len = nam->sa_len - offsetof(struct sockaddr_un, sun_path); if (len <= 0) return (EINVAL); diff --git a/usr.bin/compress/zopen.c b/usr.bin/compress/zopen.c index f0ec8871cd81..751103ae656a 100644 --- a/usr.bin/compress/zopen.c +++ b/usr.bin/compress/zopen.c @@ -490,7 +490,7 @@ zread(void *cookie, char *rbp, int num) block_compress = maxbits & BLOCK_MASK; maxbits &= BIT_MASK; maxmaxcode = 1L << maxbits; - if (maxbits > BITS) { + if (maxbits > BITS || maxbits < 12) { errno = EFTYPE; return (-1); } @@ -517,17 +517,28 @@ zread(void *cookie, char *rbp, int num) for (code = 255; code >= 0; code--) tab_prefixof(code) = 0; clear_flg = 1; - free_ent = FIRST - 1; - if ((code = getcode(zs)) == -1) /* O, untimely death! */ - break; + free_ent = FIRST; + oldcode = -1; + continue; } incode = code; - /* Special case for KwKwK string. */ + /* Special case for kWkWk string. */ if (code >= free_ent) { + if (code > free_ent || oldcode == -1) { + /* Bad stream. */ + errno = EINVAL; + return (-1); + } *stackp++ = finchar; code = oldcode; } + /* + * The above condition ensures that code < free_ent. + * The construction of tab_prefixof in turn guarantees that + * each iteration decreases code and therefore stack usage is + * bound by 1 << BITS - 256. + */ /* Generate output characters in reverse order. */ while (code >= 256) { @@ -544,7 +555,7 @@ middle: do { } while (stackp > de_stack); /* Generate the new entry. */ - if ((code = free_ent) < maxmaxcode) { + if ((code = free_ent) < maxmaxcode && oldcode != -1) { tab_prefixof(code) = (u_short) oldcode; tab_suffixof(code) = finchar; free_ent = code + 1; diff --git a/usr.bin/gzip/zuncompress.c b/usr.bin/gzip/zuncompress.c index dd0f249d223e..1642584835af 100644 --- a/usr.bin/gzip/zuncompress.c +++ b/usr.bin/gzip/zuncompress.c @@ -247,7 +247,7 @@ zread(void *cookie, char *rbp, int num) zs->zs_block_compress = zs->zs_maxbits & BLOCK_MASK; zs->zs_maxbits &= BIT_MASK; zs->zs_maxmaxcode = 1L << zs->zs_maxbits; - if (zs->zs_maxbits > BITS) { + if (zs->zs_maxbits > BITS || zs->zs_maxbits < 12) { errno = EFTYPE; return (-1); } @@ -259,13 +259,7 @@ zread(void *cookie, char *rbp, int num) } zs->zs_free_ent = zs->zs_block_compress ? FIRST : 256; - zs->u.r.zs_finchar = zs->u.r.zs_oldcode = getcode(zs); - if (zs->u.r.zs_oldcode == -1) /* EOF already? */ - return (0); /* Get out of here */ - - /* First code must be 8 bits = char. */ - *bp++ = (u_char)zs->u.r.zs_finchar; - count--; + zs->u.r.zs_oldcode = -1; zs->u.r.zs_stackp = de_stack; while ((zs->u.r.zs_code = getcode(zs)) > -1) { @@ -275,17 +269,29 @@ zread(void *cookie, char *rbp, int num) zs->u.r.zs_code--) tab_prefixof(zs->u.r.zs_code) = 0; zs->zs_clear_flg = 1; - zs->zs_free_ent = FIRST - 1; - if ((zs->u.r.zs_code = getcode(zs)) == -1) /* O, untimely death! */ - break; + zs->zs_free_ent = FIRST; + zs->u.r.zs_oldcode = -1; + continue; } zs->u.r.zs_incode = zs->u.r.zs_code; /* Special case for KwKwK string. */ if (zs->u.r.zs_code >= zs->zs_free_ent) { + if (zs->u.r.zs_code > zs->zs_free_ent || + zs->u.r.zs_oldcode == -1) { + /* Bad stream. */ + errno = EINVAL; + return (-1); + } *zs->u.r.zs_stackp++ = zs->u.r.zs_finchar; zs->u.r.zs_code = zs->u.r.zs_oldcode; } + /* + * The above condition ensures that code < free_ent. + * The construction of tab_prefixof in turn guarantees that + * each iteration decreases code and therefore stack usage is + * bound by 1 << BITS - 256. + */ /* Generate output characters in reverse order. */ while (zs->u.r.zs_code >= 256) { @@ -302,7 +308,8 @@ middle: do { } while (zs->u.r.zs_stackp > de_stack); /* Generate the new entry. */ - if ((zs->u.r.zs_code = zs->zs_free_ent) < zs->zs_maxmaxcode) { + if ((zs->u.r.zs_code = zs->zs_free_ent) < zs->zs_maxmaxcode && + zs->u.r.zs_oldcode != -1) { tab_prefixof(zs->u.r.zs_code) = (u_short) zs->u.r.zs_oldcode; tab_suffixof(zs->u.r.zs_code) = zs->u.r.zs_finchar; zs->zs_free_ent = zs->u.r.zs_code + 1; |