]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dhcp: length of each user class field must be positive
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 12 Jan 2021 12:47:23 +0000 (21:47 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 12 Jan 2021 15:00:56 +0000 (00:00 +0900)
This also fixes an memory leak when sd_dhcp_client_set_user_class()
is called multiple times.

src/libsystemd-network/dhcp-option.c
src/libsystemd-network/sd-dhcp-client.c
src/network/networkd-dhcp4.c
src/systemd/sd-dhcp-client.h

index 70753c68d847a160ef334eb9a0b6f2a427a8c3eb..7e3fe4348bb4ebd54c4d73f88ea0a37a06c3080d 100644 (file)
@@ -38,11 +38,14 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
                 size_t total = 0;
                 char **s;
 
+                if (strv_isempty((char **) optval))
+                        return -EINVAL;
+
                 STRV_FOREACH(s, (char **) optval) {
                         size_t len = strlen(*s);
 
-                        if (len > 255)
-                                return -ENAMETOOLONG;
+                        if (len > 255 || len == 0)
+                                return -EINVAL;
 
                         total += 1 + len;
                 }
@@ -51,14 +54,13 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
                         return -ENOBUFS;
 
                 options[*offset] = code;
-                options[*offset + 1] =  total;
+                options[*offset + 1] = total;
                 *offset += 2;
 
                 STRV_FOREACH(s, (char **) optval) {
                         size_t len = strlen(*s);
 
                         options[*offset] = len;
-
                         memcpy(&options[*offset + 1], *s, len);
                         *offset += 1 + len;
                 }
index 7604aafd6f8ae9b5a24cb300e6c9c87fce063eae..5cf3637d68b4af9976de1ca9c6ab84bf1df7e7f8 100644 (file)
@@ -573,22 +573,26 @@ int sd_dhcp_client_set_mud_url(
 
 int sd_dhcp_client_set_user_class(
                 sd_dhcp_client *client,
-                const char* const* user_class) {
+                char * const *user_class) {
 
-        _cleanup_strv_free_ char **s = NULL;
-        char **p;
+        char * const *p;
+        char **s = NULL;
 
-        STRV_FOREACH(p, (char **) user_class)
-                if (strlen(*p) > 255)
-                        return -ENAMETOOLONG;
+        assert_return(client, -EINVAL);
+        assert_return(!strv_isempty(user_class), -EINVAL);
+
+        STRV_FOREACH(p, user_class) {
+                size_t n = strlen(*p);
 
-        s = strv_copy((char **) user_class);
+                if (n > 255 || n == 0)
+                        return -EINVAL;
+        }
+
+        s = strv_copy(user_class);
         if (!s)
                 return -ENOMEM;
 
-        client->user_class = TAKE_PTR(s);
-
-        return 0;
+        return strv_free_and_replace(client->user_class, s);
 }
 
 int sd_dhcp_client_set_client_port(
index 080dcedab54dc93af09ebd6e66c8e66daeed903f..d5c1c507bf971e55e6efd50a7c9d13797b6a9900 100644 (file)
@@ -1417,7 +1417,7 @@ int dhcp4_configure(Link *link) {
         }
 
         if (link->network->dhcp_user_class) {
-                r = sd_dhcp_client_set_user_class(link->dhcp_client, (const char **) link->network->dhcp_user_class);
+                r = sd_dhcp_client_set_user_class(link->dhcp_client, link->network->dhcp_user_class);
                 if (r < 0)
                         return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set user class: %m");
         }
index c35328a9a6fc6d87e615c5bb894c3fb560da9a98..822286919ea9c29657801c62f45062c279da1e29 100644 (file)
@@ -181,7 +181,7 @@ int sd_dhcp_client_set_mud_url(
                 const char *mudurl);
 int sd_dhcp_client_set_user_class(
                 sd_dhcp_client *client,
-                const char* const *user_class);
+                char * const *user_class);
 int sd_dhcp_client_get_lease(
                 sd_dhcp_client *client,
                 sd_dhcp_lease **ret);