]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Check snprintf doesn't overflow in dhcp_vendor and that a -1
authorRoy Marples <roy@marples.name>
Tue, 5 Aug 2014 17:03:04 +0000 (17:03 +0000)
committerRoy Marples <roy@marples.name>
Tue, 5 Aug 2014 17:03:04 +0000 (17:03 +0000)
return is correctly handled.

Thanks to Tobias Stoeckmann.

dhcp-common.c
dhcp-common.h
dhcp.c
dhcp6.c
if-options.c

index d8ffc5dd30e3dad16fb64a4c50a31e7a796654f2..f2e1b5e012aa826a6751fd4d4f10dd9998626193 100644 (file)
@@ -63,7 +63,7 @@ vivso_find(uint32_t iana_en, const void *arg)
        return NULL;
 }
 
-size_t
+ssize_t
 dhcp_vendor(char *str, size_t len)
 {
        struct utsname utn;
@@ -71,17 +71,21 @@ dhcp_vendor(char *str, size_t len)
        int l;
 
        if (uname(&utn) != 0)
-               return (size_t)snprintf(str, len, "%s-%s",
+               return (ssize_t)snprintf(str, len, "%s-%s",
                    PACKAGE, VERSION);
        p = str;
        l = snprintf(p, len,
            "%s-%s:%s-%s:%s", PACKAGE, VERSION,
            utn.sysname, utn.release, utn.machine);
+       if (l == -1 || (size_t)(l + 1) > len)
+               return -1;
        p += l;
        len -= (size_t)l;
        l = if_machinearch(p, len);
+       if (l == -1 || (size_t)(l + 1) > len)
+               return -1;
        p += l;
-       return (size_t)(p - str);
+       return p - str;
 }
 
 int
index e0994bf8f1b02ea93d7abfe9e5e9276bf222f51f..5519edaca83b580d923bb9400e532817f0b93c3f 100644 (file)
@@ -82,7 +82,7 @@ struct dhcp_opt {
 
 struct dhcp_opt *vivso_find(uint32_t, const void *);
 
-size_t dhcp_vendor(char *, size_t);
+ssize_t dhcp_vendor(char *, size_t);
 
 #define add_option_mask(var, val) (var[val >> 3] |= 1 << (val & 7))
 #define del_option_mask(var, val) (var[val >> 3] &= ~(1 << (val & 7)))
diff --git a/dhcp.c b/dhcp.c
index 13a5759272475c05ab5162adce95b3a2a493be36..4b63e178536df2da9307f825ff1ffddc7c750df4 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -828,7 +828,6 @@ make_message(struct dhcp_message **message,
                        p += ifo->vendorclassid[0] + 1;
                }
 
-
                if (type != DHCP_INFORM) {
                        if (ifo->leasetime != 0) {
                                *p++ = DHO_LEASETIME;
diff --git a/dhcp6.c b/dhcp6.c
index b1f814aa17fc8bdbecfc94c1e7c888fa2dd643c7..86337cd0e1b1dcff50014ba92cab65ce3da184df 100644 (file)
--- a/dhcp6.c
+++ b/dhcp6.c
@@ -156,11 +156,11 @@ static size_t
 dhcp6_makevendor(struct dhcp6_option *o, const struct interface *ifp)
 {
        const struct if_options *ifo;
-       size_t len;
+       size_t len, i;
        uint8_t *p;
        uint16_t u16;
        uint32_t u32;
-       size_t vlen, i;
+       ssize_t vlen;
        const struct vivco *vivco;
        char vendor[VENDORCLASSID_MAX_LEN];
 
@@ -174,7 +174,10 @@ dhcp6_makevendor(struct dhcp6_option *o, const struct interface *ifp)
                vlen = 0; /* silence bogus gcc warning */
        } else {
                vlen = dhcp_vendor(vendor, sizeof(vendor));
-               len += sizeof(uint16_t) + vlen;
+               if (vlen == -1)
+                       vlen = 0;
+               else
+                       len += sizeof(uint16_t) + (size_t)vlen;
        }
 
        if (len > UINT16_MAX) {
@@ -200,11 +203,11 @@ dhcp6_makevendor(struct dhcp6_option *o, const struct interface *ifp)
                                memcpy(p, vivco->data, vivco->len);
                                p += vivco->len;
                        }
-               } else {
+               } else if (vlen) {
                        u16 = htons(vlen);
                        memcpy(p, &u16, sizeof(u16));
                        p += sizeof(u16);
-                       memcpy(p, vendor, vlen);
+                       memcpy(p, vendor, (size_t)vlen);
                }
        }
 
index 4e921ba812ef98ba56deefe285998e9e6bab6402..d8bb8beed3a885613d00496cff2629f92d72eea7 100644 (file)
@@ -1981,6 +1981,7 @@ read_config(struct dhcpcd_ctx *ctx,
        FILE *fp;
        char *line, *buf, *option, *p;
        size_t buflen;
+       ssize_t vlen;
        int skip = 0, have_profile = 0;
 #ifndef EMBEDDED_CONFIG
        const char * const *e;
@@ -2016,9 +2017,9 @@ read_config(struct dhcpcd_ctx *ctx,
        ifo->auth.options |= DHCPCD_AUTH_REQUIRE;
        TAILQ_INIT(&ifo->auth.tokens);
 
-       ifo->vendorclassid[0] =
-           (uint8_t)dhcp_vendor((char *)ifo->vendorclassid + 1,
-           sizeof(ifo->vendorclassid) - 1);
+       vlen = dhcp_vendor((char *)ifo->vendorclassid + 1,
+                   sizeof(ifo->vendorclassid) - 1);
+       ifo->vendorclassid[0] = vlen == -1 ? 0 : (uint8_t)vlen;
 
        buf = NULL;
        buflen = 0;