Hello community, here is the log from the commit of package tftp for openSUSE:11.4 checked in at Fri Jun 24 16:16:50 CEST 2011.
-------- --- old-versions/11.4/all/tftp/tftp.changes 2010-12-11 01:00:45.000000000 +0100 +++ 11.4/tftp/tftp.changes 2011-06-24 09:16:04.000000000 +0200 @@ -1,0 +2,8 @@ +Wed Jun 22 13:15:44 UTC 2011 - [email protected] + +- fix buffer overflow (bnc#699714) + - tftp-hpa-CVE-2011-2199.patch +- unbreak tftp by changing to user to run as in tftpd itself, + not via xinetd (bnc#682340) + +------------------------------------------------------------------- Package does not exist at destination yet. Using Fallback old-versions/11.4/all/tftp Destination is old-versions/11.4/UPDATES/all/tftp calling whatdependson for 11.4-i586 New: ---- tftp-hpa-CVE-2011-2199.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ tftp.spec ++++++ --- /var/tmp/diff_new_pack.pjaHqg/_old 2011-06-24 16:13:55.000000000 +0200 +++ /var/tmp/diff_new_pack.pjaHqg/_new 2011-06-24 16:13:55.000000000 +0200 @@ -1,7 +1,7 @@ # -# spec file for package tftp (Version 5.0) +# spec file for package tftp # -# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ Name: tftp Version: 5.0 -Release: 1 +Release: 113.<RELEASE114> License: BSD3c Summary: Trivial File Transfer Protocol (TFTP) Url: http://www.kernel.org/pub/software/network/tftp/ @@ -30,6 +30,7 @@ Patch1: tftp-hpa-0.46_colon_check.patch Patch4: tftp-hpa-0.49-fortify-strcpy-crash.patch Patch5: tftp-hpa-0.48-tzfix.patch +Patch6: tftp-hpa-CVE-2011-2199.patch Patch42: tftp-hpa-0.43_old-autoconf.diff BuildRequires: pwdutils BuildRequires: tcpd-devel @@ -52,6 +53,7 @@ %patch1 %patch4 -p1 %patch5 -p1 +%patch6 -p1 %if 0%{?suse_version} < 1030 %patch42 %endif ++++++ tftp-hpa-CVE-2011-2199.patch ++++++ >From f3035c45bc50bb5cac87ca01e7ef6a12485184f8 Mon Sep 17 00:00:00 2001 From: H. Peter Anvin <[email protected]> Date: Fri, 10 Jun 2011 11:47:02 -0700 Subject: [PATCH] tftpd: simplify option parsing Simplify the option parsing to make use of the fact that all the options we support are integer options. This fixes a buffer overflow in the utimeout option. Reported-by: Timo Warns <[email protected]> Signed-off-by: H. Peter Anvin <[email protected]> Signed-off-by: Petr Uzel <[email protected]> --- tftpd/tftpd.c | 154 +++++++++++++++++++++++++++------------------------------ 1 files changed, 73 insertions(+), 81 deletions(-) Index: tftp-hpa-5.0/tftpd/tftpd.c =================================================================== --- tftp-hpa-5.0.orig/tftpd/tftpd.c +++ tftp-hpa-5.0/tftpd/tftpd.c @@ -113,18 +113,18 @@ static struct rule *rewrite_rules = NULL int tftp(struct tftphdr *, int); static void nak(int, const char *); static void timer(int); -static void do_opt(char *, char *, char **); +static void do_opt(const char *, const char *, char **); -static int set_blksize(char *, char **); -static int set_blksize2(char *, char **); -static int set_tsize(char *, char **); -static int set_timeout(char *, char **); -static int set_utimeout(char *, char **); -static int set_rollover(char *, char **); +static int set_blksize(uintmax_t *); +static int set_blksize2(uintmax_t *); +static int set_tsize(uintmax_t *); +static int set_timeout(uintmax_t *); +static int set_utimeout(uintmax_t *); +static int set_rollover(uintmax_t *); struct options { const char *o_opt; - int (*o_fnc) (char *, char **); + int (*o_fnc)(uintmax_t *); } options[] = { {"blksize", set_blksize}, {"blksize2", set_blksize2}, @@ -1111,48 +1111,38 @@ static int blksize_set; /* * Set a non-standard block size (c.f. RFC2348) */ -static int set_blksize(char *val, char **ret) +static int set_blksize(uintmax_t *vp) { - static char b_ret[6]; - unsigned int sz; - char *vend; - - sz = (unsigned int)strtoul(val, &vend, 10); + uintmax_t sz = *vp; - if (blksize_set || *vend) + if (blksize_set) return 0; if (sz < 8) - return (0); + return 0; else if (sz > max_blksize) sz = max_blksize; - segsize = sz; - sprintf(*ret = b_ret, "%u", sz); - + *vp = segsize = sz; blksize_set = 1; - - return (1); + return 1; } /* * Set a power-of-two block size (nonstandard) */ -static int set_blksize2(char *val, char **ret) +static int set_blksize2(uintmax_t *vp) { - static char b_ret[6]; - unsigned int sz; - char *vend; - - sz = (unsigned int)strtoul(val, &vend, 10); + uintmax_t sz = *vp; - if (blksize_set || *vend) + if (blksize_set) return 0; if (sz < 8) return (0); else if (sz > max_blksize) sz = max_blksize; + else /* Convert to a power of two */ if (sz & (sz - 1)) { @@ -1163,28 +1153,22 @@ static int set_blksize2(char *val, char sz = sz1; } - segsize = sz; - sprintf(*ret = b_ret, "%u", sz); - + *vp = segsize = sz; blksize_set = 1; - - return (1); + return 1; } /* * Set the block number rollover value */ -static int set_rollover(char *val, char **ret) +static int set_rollover(uintmax_t *vp) { - uintmax_t ro; - char *vend; + uintmax_t ro = *vp; - ro = strtoumax(val, &vend, 10); - if (ro > 65535 || *vend) + if (ro > 65535) return 0; rollover_val = (uint16_t)ro; - *ret = val; return 1; } @@ -1193,22 +1177,18 @@ static int set_rollover(char *val, char * For netascii mode, we don't know the size ahead of time; * so reject the option. */ -static int set_tsize(char *val, char **ret) +static int set_tsize(uintmax_t *vp) { - static char b_ret[sizeof(uintmax_t) * CHAR_BIT / 3 + 2]; - uintmax_t sz; - char *vend; + uintmax_t sz = *vp; - sz = strtoumax(val, &vend, 10); - - if (!tsize_ok || *vend) + if (!tsize_ok) return 0; if (sz == 0) - sz = (uintmax_t) tsize; + sz = tsize; - sprintf(*ret = b_ret, "%" PRIuMAX, sz); - return (1); + *vp = sz; + return 1; } /* @@ -1216,74 +1196,86 @@ static int set_tsize(char *val, char **r * to be the (default) retransmission timeout, but being an * integer in seconds it seems a bit limited. */ -static int set_timeout(char *val, char **ret) +static int set_timeout(uintmax_t *vp) { - static char b_ret[4]; - unsigned long to; - char *vend; - - to = strtoul(val, &vend, 10); + uintmax_t to = *vp; - if (to < 1 || to > 255 || *vend) + if (to < 1 || to > 255) return 0; rexmtval = timeout = to * 1000000UL; maxtimeout = rexmtval * TIMEOUT_LIMIT; - sprintf(*ret = b_ret, "%lu", to); - return (1); + return 1; } /* Similar, but in microseconds. We allow down to 10 ms. */ -static int set_utimeout(char *val, char **ret) +static int set_utimeout(uintmax_t *vp) { - static char b_ret[4]; - unsigned long to; - char *vend; + uintmax_t to = *vp; - to = strtoul(val, &vend, 10); - - if (to < 10000UL || to > 255000000UL || *vend) + if (to < 10000UL || to > 255000000UL) return 0; rexmtval = timeout = to; maxtimeout = rexmtval * TIMEOUT_LIMIT; - sprintf(*ret = b_ret, "%lu", to); - return (1); + return 1; } /* - * Parse RFC2347 style options + * Conservative calculation for the size of a buffer which can hold an + * arbitrary integer + */ +#define OPTBUFSIZE (sizeof(uintmax_t) * CHAR_BIT / 3 + 3) + +/* + * Parse RFC2347 style options; we limit the arguments to positive + * integers which matches all our current options. */ -static void do_opt(char *opt, char *val, char **ap) +static void do_opt(const char *opt, const char *val, char **ap) { struct options *po; - char *ret; + char retbuf[OPTBUFSIZE]; + char *p = *ap; + size_t optlen, retlen; + char *vend; + uintmax_t v; /* Global option-parsing variables initialization */ blksize_set = 0; - if (!*opt) + if (!*opt || !*val) + return; + + errno = 0; + v = strtoumax(val, &vend, 10); + if (*vend || errno == ERANGE) return; for (po = options; po->o_opt; po++) if (!strcasecmp(po->o_opt, opt)) { - if (po->o_fnc(val, &ret)) { - if (*ap + strlen(opt) + strlen(ret) + 2 >= - ackbuf + sizeof(ackbuf)) { + if (po->o_fnc(&v)) { + optlen = strlen(opt); + retlen = sprintf(retbuf, "%"PRIuMAX, v); + + if (p + optlen + retlen + 2 >= ackbuf + sizeof(ackbuf)) { nak(EOPTNEG, "Insufficient space for options"); exit(0); } - *ap = strrchr(strcpy(strrchr(strcpy(*ap, opt), '\0') + 1, - ret), '\0') + 1; + + memcpy(p, opt, optlen+1); + p += optlen+1; + memcpy(p, retbuf, retlen+1); + p += retlen+1; } else { nak(EOPTNEG, "Unsupported option(s) requested"); exit(0); } break; } - return; + + *ap = p; } #ifdef WITH_REGEX ++++++ tftp.xinetd ++++++ --- /var/tmp/diff_new_pack.pjaHqg/_old 2011-06-24 16:13:55.000000000 +0200 +++ /var/tmp/diff_new_pack.pjaHqg/_new 2011-06-24 16:13:55.000000000 +0200 @@ -11,9 +11,9 @@ protocol = udp wait = yes flags = IPv6 IPv4 - user = tftp + user = root server = /usr/sbin/in.tftpd - server_args = -s /srv/tftpboot + server_args = -u tftp -s /srv/tftpboot # per_source = 11 # cps = 100 2 disable = yes ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Remember to have fun... -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
