Skip to content

Commit

Permalink
Merge pull request #31171 from yuwata/sd-ndisc-invalid-dnssl
Browse files Browse the repository at this point in the history
sd-ndisc: handle invalid DNSSL option gracefully
  • Loading branch information
yuwata committed Feb 8, 2024
2 parents 7dc4318 + a39d839 commit 0627b29
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 4 deletions.
17 changes: 13 additions & 4 deletions src/libsystemd-network/ndisc-router.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "alloc-util.h"
#include "dns-domain.h"
#include "escape.h"
#include "hostname-util.h"
#include "memory-util.h"
#include "missing_network.h"
Expand Down Expand Up @@ -716,8 +717,12 @@ int sd_ndisc_router_dnssl_get_domains(sd_ndisc_router *rt, char ***ret) {

e[n] = 0;
r = dns_name_normalize(e, 0, &normalized);
if (r < 0)
return r;
if (r < 0) {
_cleanup_free_ char *escaped = cescape(e);
log_debug_errno(r, "Failed to normalize advertised domain name \"%s\": %m", strna(escaped));
/* Here, do not propagate error code from dns_name_normalize() except for ENOMEM. */
return r == -ENOMEM ? -ENOMEM : -EBADMSG;
}

/* Ignore the root domain name or "localhost" and friends */
if (!is_localhost(normalized) &&
Expand Down Expand Up @@ -753,8 +758,12 @@ int sd_ndisc_router_dnssl_get_domains(sd_ndisc_router *rt, char ***ret) {
e[n++] = '.';

r = dns_label_escape((char*) p+1, *p, e + n, DNS_LABEL_ESCAPED_MAX);
if (r < 0)
return r;
if (r < 0) {
_cleanup_free_ char *escaped = cescape_length((const char*) p+1, *p);
log_debug_errno(r, "Failed to escape advertised domain name \"%s\": %m", strna(escaped));
/* Here, do not propagate error code from dns_label_escape() except for ENOMEM. */
return r == -ENOMEM ? -ENOMEM : -EBADMSG;
}

n += r;

Expand Down
84 changes: 84 additions & 0 deletions src/libsystemd-network/test-ndisc-rs.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ static void router_dump(sd_ndisc_router *rt) {
int n, i;

n = sd_ndisc_router_dnssl_get_domains(rt, &l);
if (n == -EBADMSG) {
log_info("Invalid domain(s).");
break;
}
assert_se(n > 0);

for (i = 0; i < n; i++)
Expand All @@ -167,18 +171,23 @@ static void router_dump(sd_ndisc_router *rt) {

static int send_ra(uint8_t flags) {
uint8_t advertisement[] = {
/* struct nd_router_advert */
0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* type = 0x03 (SD_NDISC_OPTION_PREFIX_INFORMATION), length = 32 */
0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* type = 0x19 (SD_NDISC_OPTION_RDNSS), length = 24 */
0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
/* type = 0x1f (SD_NDISC_OPTION_DNSSL), legnth = 24 */
0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* type = 0x01 (SD_NDISC_OPTION_SOURCE_LL_ADDRESS), legth = 8 */
0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
};

Expand Down Expand Up @@ -224,6 +233,7 @@ static void test_callback(sd_ndisc *nd, sd_ndisc_event_t event, sd_ndisc_router
return;
}

idx = 0;
sd_event_exit(e, 0);
}

Expand Down Expand Up @@ -261,6 +271,80 @@ TEST(rs) {
test_fd[1] = safe_close(test_fd[1]);
}

static int send_ra_invalid_domain(uint8_t flags) {
uint8_t advertisement[] = {
/* struct nd_router_advert */
0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* type = 0x03 (SD_NDISC_OPTION_PREFIX_INFORMATION), length = 32 */
0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4,
0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00,
0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* type = 0x19 (SD_NDISC_OPTION_RDNSS), length = 24 */
0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
/* type = 0x1f (SD_NDISC_OPTION_DNSSL), legnth = 112 */
0x1f, 0x0e, 0xee, 0x68, 0xb0, 0xf4, 0x36, 0x39,
0x2c, 0xbc, 0x0b, 0xbc, 0xa9, 0x97, 0x71, 0x37,
0xad, 0x86, 0x80, 0x14, 0x2e, 0x58, 0xaa, 0x8a,
0xb7, 0xa1, 0xbe, 0x91, 0x59, 0x00, 0xc4, 0xe8,
0xdd, 0xd8, 0x6d, 0xe5, 0x4a, 0x7a, 0x71, 0x42,
0x74, 0x45, 0x9e, 0x2e, 0xfd, 0x9d, 0x71, 0x1d,
0xd0, 0xc0, 0x54, 0x0c, 0x4d, 0x1f, 0xbf, 0x90,
0xd9, 0x79, 0x58, 0xc0, 0x1d, 0xa3, 0x39, 0xcf,
0xb8, 0xec, 0xd2, 0xe4, 0xcd, 0xb6, 0x13, 0x2f,
0xc0, 0x46, 0xe8, 0x07, 0x3f, 0xaa, 0x28, 0xa5,
0x23, 0xf1, 0xf0, 0xca, 0xd3, 0x19, 0x3f, 0xfa,
0x6c, 0x7c, 0xec, 0x1b, 0xcf, 0x71, 0xeb, 0xba,
0x68, 0x1b, 0x8e, 0x7d, 0x93, 0x7e, 0x0b, 0x9f,
0xdb, 0x12, 0x9c, 0x75, 0x22, 0x5f, 0x12, 0x00,
/* type = 0x01 (SD_NDISC_OPTION_SOURCE_LL_ADDRESS), legth = 8 */
0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53,
};

advertisement[5] = flags;

printf("sizeof(nd_router_advert)=%zu\n", sizeof(struct nd_router_advert));

assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) ==
sizeof(advertisement));

if (verbose)
printf(" sent RA with flag 0x%02x\n", flags);

return 0;
}

TEST(invalid_domain) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
_cleanup_(sd_ndisc_unrefp) sd_ndisc *nd = NULL;

send_ra_function = send_ra_invalid_domain;

assert_se(sd_event_new(&e) >= 0);

assert_se(sd_ndisc_new(&nd) >= 0);
assert_se(nd);

assert_se(sd_ndisc_attach_event(nd, e, 0) >= 0);

assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0);
assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
assert_se(sd_ndisc_set_callback(nd, test_callback, e) >= 0);

assert_se(sd_event_add_time_relative(e, NULL, CLOCK_BOOTTIME,
30 * USEC_PER_SEC, 0,
NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);

assert_se(sd_ndisc_start(nd) >= 0);

assert_se(sd_event_loop(e) >= 0);

test_fd[1] = safe_close(test_fd[1]);
}

static int test_timeout_value(uint8_t flags) {
static int count = 0;
static usec_t last = 0;
Expand Down

0 comments on commit 0627b29

Please sign in to comment.