diff options
author | Thomas Haller <thaller@redhat.com> | 2018-11-12 10:34:54 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2018-11-12 11:56:47 +0100 |
commit | 49c11a44e4e901752a81e3942efca64448fa7c53 (patch) | |
tree | d3d0570a0a936f6422704878bbbd36195958d9dd | |
parent | 60cd93612f15d1e5626121e73b08b2e434cac225 (diff) | |
download | NetworkManager-49c11a44e4e901752a81e3942efca64448fa7c53.tar.gz |
dns: avoid truncation of searches list due to 256 char limit in glibc
Before glibc 2.26, glibc's resolver would only honor 6 search entries
and a character limit of 256. This was lifted recently ([1], [2], [3]).
We also lift this limitation in NetworkManager ([4], [5]).
However, older glibc versions would just truncate the string at 255
characters. In particular, it would not only tuncate the list to 6
entries, but the entry which crosses the 256th character boundary would
be mangled. Avoid that, by adding spaces.
[1] https://sourceware.org/ml/libc-alpha/2017-08/msg00010.html
[2] https://sourceware.org/bugzilla/show_bug.cgi?id=19569
[3] https://sourceware.org/bugzilla/show_bug.cgi?id=21475
[4] https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/47
[5] https://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/80
-rw-r--r-- | src/dns/nm-dns-manager.c | 31 | ||||
-rw-r--r-- | src/tests/test-general.c | 2 |
2 files changed, 31 insertions, 2 deletions
diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c index e1c295666b..7542228f54 100644 --- a/src/dns/nm-dns-manager.c +++ b/src/dns/nm-dns-manager.c @@ -581,10 +581,39 @@ create_resolv_conf (const char *const*searches, g_string_append (str, "# Generated by NetworkManager\n"); if (searches && searches[0]) { + gsize search_base_idx; + g_string_append (str, "search"); + search_base_idx = str->len; + for (i = 0; searches[i]; i++) { + const char *s = searches[i]; + gsize l = strlen (s); + + if ( l == 0 + || NM_STRCHAR_ANY (s, ch, NM_IN_SET (ch, ' ', '\t', '\n'))) { + /* there should be no such characters in the search entry. Also, + * because glibc parser would treat them as line/word separator. + * + * Skip the value silently. */ + continue; + } + + if (search_base_idx > 0) { + if (str->len - search_base_idx + 1 + l > 254) { + /* this entry crosses the 256 character boundery. Older glibc versions + * would truncate the entry at this point. + * + * Fill the line with spaces to cross the 256 char boundary and continue + * afterwards. This way, the truncation happens between two search entries. */ + while (str->len - search_base_idx < 257) + g_string_append_c (str, ' '); + search_base_idx = 0; + } + } + g_string_append_c (str, ' '); - g_string_append (str, searches[i]); + g_string_append_len (str, s, l); } g_string_append_c (str, '\n'); } diff --git a/src/tests/test-general.c b/src/tests/test-general.c index 87ff7f8480..2ab5f8f735 100644 --- a/src/tests/test-general.c +++ b/src/tests/test-general.c @@ -1903,7 +1903,7 @@ test_dns_create_resolv_conf (void) NULL, NULL, "# Generated by NetworkManager\n" - "search a2x456789.b2x456789.c2x456789.d2x456789.e2x456789.f2x456789.g2x456789.h2x456789.i2x456789.j2x4567890 a2y456789.b2y456789.c2y456789.d2y456789.e2y456789.f2y456789.g2y456789.h2y456789.i2y456789.j2y4567890 a2z456789.b2z456789.c2z456789.d2z456789.e2z456789.f2z456789.g2z456789.h2z456789.i2z456789.j2z4567890\n" + "search a2x456789.b2x456789.c2x456789.d2x456789.e2x456789.f2x456789.g2x456789.h2x456789.i2x456789.j2x4567890 a2y456789.b2y456789.c2y456789.d2y456789.e2y456789.f2y456789.g2y456789.h2y456789.i2y456789.j2y4567890 a2z456789.b2z456789.c2z456789.d2z456789.e2z456789.f2z456789.g2z456789.h2z456789.i2z456789.j2z4567890\n" ""); } |