dnsmasq: fix 2 DoS vulnerabilities in TFTP handling - CVE-2009-2957 - CVE-2009-2958
authorNicolas Thill <nico@openwrt.org>
Wed, 2 Sep 2009 00:15:31 +0000 (00:15 +0000)
committerNicolas Thill <nico@openwrt.org>
Wed, 2 Sep 2009 00:15:31 +0000 (00:15 +0000)
SVN-Revision: 17464

package/dnsmasq/Makefile
package/dnsmasq/patches/001-upstream-security.patch [new file with mode: 0644]

index 1b030d1ad0268bbb28046233eda613aa34fd9a61..eaa4fe2a2f312789ffba826deb9a178ef64635f7 100644 (file)
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=dnsmasq
 PKG_VERSION:=2.47
-PKG_RELEASE:=3
+PKG_RELEASE:=3.1
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq
diff --git a/package/dnsmasq/patches/001-upstream-security.patch b/package/dnsmasq/patches/001-upstream-security.patch
new file mode 100644 (file)
index 0000000..f12d61f
--- /dev/null
@@ -0,0 +1,72 @@
+http://www.thekelleys.org.uk/dnsmasq/dnsmasq.security.patch
+http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-2957
+http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-2958
+
+--- a/src/tftp.c
++++ b/src/tftp.c
+@@ -195,20 +195,21 @@ void tftp_request(struct listener *liste
+       
+       while ((opt = next(&p, end)))
+       {
+-        if (strcasecmp(opt, "blksize") == 0 &&
+-            (opt = next(&p, end)) &&
+-            !(daemon->options & OPT_TFTP_NOBLOCK))
++        if (strcasecmp(opt, "blksize") == 0)
+           {
+-            transfer->blocksize = atoi(opt);
+-            if (transfer->blocksize < 1)
+-              transfer->blocksize = 1;
+-            if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4)
+-              transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4;
+-            transfer->opt_blocksize = 1;
+-            transfer->block = 0;
++            if ((opt = next(&p, end)) &&
++                !(daemon->options & OPT_TFTP_NOBLOCK))
++              {
++                transfer->blocksize = atoi(opt);
++                if (transfer->blocksize < 1)
++                  transfer->blocksize = 1;
++                if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4)
++                  transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4;
++                transfer->opt_blocksize = 1;
++                transfer->block = 0;
++              }
+           }
+-        
+-        if (strcasecmp(opt, "tsize") == 0 && next(&p, end) && !transfer->netascii)
++        else if (strcasecmp(opt, "tsize") == 0 && next(&p, end) && !transfer->netascii)
+           {
+             transfer->opt_transize = 1;
+             transfer->block = 0;
+@@ -220,17 +221,17 @@ void tftp_request(struct listener *liste
+       {
+         if (daemon->tftp_prefix[0] == '/')
+           daemon->namebuff[0] = 0;
+-        strncat(daemon->namebuff, daemon->tftp_prefix, MAXDNAME);
++        strncat(daemon->namebuff, daemon->tftp_prefix, (MAXDNAME-1) - strlen(daemon->namebuff));
+         if (daemon->tftp_prefix[strlen(daemon->tftp_prefix)-1] != '/')
+-          strncat(daemon->namebuff, "/", MAXDNAME);
++          strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
+         if (daemon->options & OPT_TFTP_APREF)
+           {
+             size_t oldlen = strlen(daemon->namebuff);
+             struct stat statbuf;
+             
+-            strncat(daemon->namebuff, inet_ntoa(peer.sin_addr), MAXDNAME);
+-            strncat(daemon->namebuff, "/", MAXDNAME);
++            strncat(daemon->namebuff, inet_ntoa(peer.sin_addr), (MAXDNAME-1) - strlen(daemon->namebuff));
++            strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
+             
+             /* remove unique-directory if it doesn't exist */
+             if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode))
+@@ -248,8 +249,7 @@ void tftp_request(struct listener *liste
+       }
+       else if (filename[0] == '/')
+       daemon->namebuff[0] = 0;
+-      strncat(daemon->namebuff, filename, MAXDNAME);
+-      daemon->namebuff[MAXDNAME-1] = 0;
++      strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
+       /* check permissions and open file */
+       if ((transfer->file = check_tftp_fileperm(&len)))