]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
nss-resolve: fix parsing of io.systemd.Resolve.ResolveAddress reply
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 31 Mar 2021 14:20:30 +0000 (16:20 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 31 Mar 2021 14:28:14 +0000 (16:28 +0200)
Since the switch to varlink in 0c73f4f075a2d23f7cabe708b589f19f4bbbec37, the
code wasn't functional. The JSON_VARIANT_UNSIGNED/JSON_VARIANT_STRING mismatch
meant that we'd reject any reply. Once past that, the code would use
unitialized 'c' and 'n' variables, so it's lucky we never got that far ;)

With -Wmaybe-unitialized, gcc would warn.

I think that declaring the huge list of local variables with very short names
at the top of the function was making it harder to understand what is going on
in the function. So let's rename the variables a bit, and initialize them upon
declaration if possible.

$ build/test-nss-hosts resolve 1.1.1.1 1.0.0.1 10.38.5.41
======== resolve ========
_nss_resolve_gethostbyaddr2_r("1.1.1.1") → status=NSS_STATUS_SUCCESS
                   errno=999/--- h_errno=0/Resolver Error 0 (no error) ttl=0
        "one.one.one.one"
        AF_INET 1.1.1.1

_nss_resolve_gethostbyaddr_r("1.1.1.1") → status=NSS_STATUS_SUCCESS
                   errno=999/--- h_errno=0/Resolver Error 0 (no error)
        "one.one.one.one"
        AF_INET 1.1.1.1

_nss_resolve_gethostbyaddr2_r("1.0.0.1") → status=NSS_STATUS_SUCCESS
                   errno=999/--- h_errno=0/Resolver Error 0 (no error) ttl=0
        "one.one.one.one"
        AF_INET 1.0.0.1

_nss_resolve_gethostbyaddr_r("1.0.0.1") → status=NSS_STATUS_SUCCESS
                   errno=999/--- h_errno=0/Resolver Error 0 (no error)
        "one.one.one.one"
        AF_INET 1.0.0.1

_nss_resolve_gethostbyaddr2_r("10.38.5.41") → status=NSS_STATUS_SUCCESS
                   errno=999/--- h_errno=0/Resolver Error 0 (no error) ttl=0
        "squid.redhat.com"
        alias "squid.corp.redhat.com"
        alias "squid2.corp.redhat.com"
        alias "squid3.corp.redhat.com"
        alias "squid4.corp.redhat.com"
        alias "squid5.corp.redhat.com"
        AF_INET 10.38.5.41

_nss_resolve_gethostbyaddr_r("10.38.5.41") → status=NSS_STATUS_SUCCESS
                   errno=999/--- h_errno=0/Resolver Error 0 (no error)
        "squid.redhat.com"
        alias "squid.corp.redhat.com"
        alias "squid2.corp.redhat.com"
        alias "squid3.corp.redhat.com"
        alias "squid4.corp.redhat.com"
        alias "squid5.corp.redhat.com"
        AF_INET 10.38.5.41

(I have 10.38.5.41 squid.redhat.com squid.corp.redhat.com squid2.corp.redhat.com squid3.corp.redhat.com squid4.corp.redhat.com squid5.corp.redhat.com
in /etc/hosts for testing.)

src/nss-resolve/nss-resolve.c

index dfc0977c849c3692479bdc1428fa0bd20da716dd..e5b5079c1687ce2988dcd9321ac7df2772c3f75f 100644 (file)
@@ -540,8 +540,8 @@ static void name_parameters_destroy(NameParameters *p) {
 }
 
 static const JsonDispatch name_parameters_dispatch_table[] = {
-        { "ifindex", JSON_VARIANT_INTEGER,  json_dispatch_ifindex, offsetof(NameParameters, ifindex), 0              },
-        { "name",    JSON_VARIANT_UNSIGNED, json_dispatch_string,  offsetof(NameParameters, name),    JSON_MANDATORY },
+        { "ifindex", JSON_VARIANT_INTEGER, json_dispatch_ifindex, offsetof(NameParameters, ifindex), 0              },
+        { "name",    JSON_VARIANT_STRING,  json_dispatch_string,  offsetof(NameParameters, name),    JSON_MANDATORY },
         {}
 };
 
@@ -555,12 +555,8 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
 
         _cleanup_(resolve_address_reply_destroy) ResolveAddressReply p = {};
         _cleanup_(json_variant_unrefp) JsonVariant *cparams = NULL;
-        char *r_name, *r_aliases, *r_addr, *r_addr_list;
         _cleanup_(varlink_unrefp) Varlink *link = NULL;
-        JsonVariant *entry, *rparams;
-        const char *n, *error_id;
-        unsigned c = 0, i = 0;
-        size_t ms = 0, idx;
+        JsonVariant *rparams, *entry;
         int r;
 
         PROTECT_ERRNO;
@@ -594,6 +590,7 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
         if (r < 0)
                 goto fail;
 
+        const char* error_id;
         r = varlink_call(link, "io.systemd.Resolve.ResolveAddress", cparams, &rparams, &error_id, NULL);
         if (r < 0)
                 goto fail;
@@ -609,6 +606,8 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
         if (json_variant_is_blank_object(p.names))
                 goto not_found;
 
+        size_t ms = 0, idx;
+
         JSON_VARIANT_ARRAY_FOREACH(entry, p.names) {
                 _cleanup_(name_parameters_destroy) NameParameters q = {};
 
@@ -619,9 +618,10 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
                 ms += ALIGN(strlen(q.name) + 1);
         }
 
-        ms += ALIGN(len) +                                           /* the address */
-              2 * sizeof(char*) +                                    /* pointers to the address, plus trailing NULL */
-              json_variant_elements(p.names) * sizeof(char*);        /* pointers to aliases, plus trailing NULL */
+        size_t n_names = json_variant_elements(p.names);
+        ms += ALIGN(len) +                    /* the address */
+              2 * sizeof(char*) +             /* pointer to the address, plus trailing NULL */
+              n_names * sizeof(char*);        /* pointers to aliases, plus trailing NULL */
 
         if (buflen < ms) {
                 UNPROTECT_ERRNO;
@@ -631,44 +631,43 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
         }
 
         /* First, place address */
-        r_addr = buffer;
+        char *r_addr = buffer;
         memcpy(r_addr, addr, len);
         idx = ALIGN(len);
 
         /* Second, place address list */
-        r_addr_list = buffer + idx;
+        char *r_addr_list = buffer + idx;
         ((char**) r_addr_list)[0] = r_addr;
         ((char**) r_addr_list)[1] = NULL;
         idx += sizeof(char*) * 2;
 
-        /* Third, reserve space for the aliases array */
-        r_aliases = buffer + idx;
-        idx += sizeof(char*) * c;
+        /* Third, reserve space for the aliases array, plus trailing NULL */
+        char *r_aliases = buffer + idx;
+        idx += sizeof(char*) * n_names;
 
         /* Fourth, place aliases */
-        i = 0;
-        r_name = buffer + idx;
+        char *r_name = buffer + idx;
+
+        size_t i = 0;
         JSON_VARIANT_ARRAY_FOREACH(entry, p.names) {
                 _cleanup_(name_parameters_destroy) NameParameters q = {};
-                size_t l;
-                char *z;
 
                 r = json_dispatch(entry, name_parameters_dispatch_table, NULL, json_dispatch_flags, &q);
                 if (r < 0)
                         goto fail;
 
-                l = strlen(q.name);
-                z = buffer + idx;
-                memcpy(z, n, l+1);
+                size_t l = strlen(q.name);
+                char *z = buffer + idx;
+                memcpy(z, q.name, l + 1);
 
                 if (i > 0)
-                        ((char**) r_aliases)[i-1] = z;
+                        ((char**) r_aliases)[i - 1] = z;
                 i++;
 
-                idx += ALIGN(l+1);
+                idx += ALIGN(l + 1);
         }
+        ((char**) r_aliases)[n_names - 1] = NULL;
 
-        ((char**) r_aliases)[c-1] = NULL;
         assert(idx == ms);
 
         result->h_name = r_name;