diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2021-03-31 16:20:30 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2021-03-31 16:28:14 +0200 |
commit | 77fac974fe396dbe4fb679b748bfa89db1136e0c (patch) | |
tree | 44c18c114d13d026bc5faafbe467d5010c63baff /src/nss-resolve | |
parent | portabled: add --extension parameter for layered images support (diff) | |
download | systemd-77fac974fe396dbe4fb679b748bfa89db1136e0c.tar.xz systemd-77fac974fe396dbe4fb679b748bfa89db1136e0c.zip |
nss-resolve: fix parsing of io.systemd.Resolve.ResolveAddress reply
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.)
Diffstat (limited to 'src/nss-resolve')
-rw-r--r-- | src/nss-resolve/nss-resolve.c | 49 |
1 files changed, 24 insertions, 25 deletions
diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c index dfc0977c84..e5b5079c16 100644 --- a/src/nss-resolve/nss-resolve.c +++ b/src/nss-resolve/nss-resolve.c @@ -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; |