summaryrefslogtreecommitdiff
path: root/src/libsystemd-network/sd-dhcp-lease.c
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2022-01-31 05:04:52 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2022-02-01 12:23:55 +0900
commit7b868543072bb9073174a4ae46032fdb6eb24c92 (patch)
treeb0f09536ee0d890fb3e8f0483c1e5733e2860e6a /src/libsystemd-network/sd-dhcp-lease.c
parent156d01b9ca4cb6d7b3877a3db7d20ed600dc40c0 (diff)
downloadsystemd-7b868543072bb9073174a4ae46032fdb6eb24c92.tar.gz
sd-dhcp-lease: fix reading unaligned memory
The destination address was read twice, one is for prefixlen, and other is for destination address itself. And for prefixlen, the address might be read from unaligned buffer. This also modernizes the code.
Diffstat (limited to 'src/libsystemd-network/sd-dhcp-lease.c')
-rw-r--r--src/libsystemd-network/sd-dhcp-lease.c45
1 files changed, 26 insertions, 19 deletions
diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c
index 5a40eb94d3..fd5701b118 100644
--- a/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/libsystemd-network/sd-dhcp-lease.c
@@ -468,41 +468,48 @@ static int lease_parse_sip_server(const uint8_t *option, size_t len, struct in_a
}
static int lease_parse_routes(
- const uint8_t *option, size_t len,
- struct sd_dhcp_route **routes, size_t *routes_size) {
+ const uint8_t *option,
+ size_t len,
+ struct sd_dhcp_route **routes,
+ size_t *routes_size) {
- struct in_addr addr;
+ int r;
assert(option || len <= 0);
assert(routes);
assert(routes_size);
- if (len <= 0)
- return 0;
-
if (len % 8 != 0)
return -EINVAL;
- if (!GREEDY_REALLOC(*routes, *routes_size + (len / 8)))
- return -ENOMEM;
-
while (len >= 8) {
- struct sd_dhcp_route *route = *routes + *routes_size;
- int r;
-
- route->option = SD_DHCP_OPTION_STATIC_ROUTE;
- r = in4_addr_default_prefixlen((struct in_addr*) option, &route->dst_prefixlen);
- if (r < 0)
- return -EINVAL;
+ struct in_addr dst, gw;
+ uint8_t prefixlen;
- assert_se(lease_parse_be32(option, 4, &addr.s_addr) >= 0);
- route->dst_addr = inet_makeaddr(inet_netof(addr), 0);
+ assert_se(lease_parse_be32(option, 4, &dst.s_addr) >= 0);
option += 4;
- assert_se(lease_parse_be32(option, 4, &route->gw_addr.s_addr) >= 0);
+ assert_se(lease_parse_be32(option, 4, &gw.s_addr) >= 0);
option += 4;
len -= 8;
+
+ r = in4_addr_default_prefixlen(&dst, &prefixlen);
+ if (r < 0)
+ return -EINVAL;
+
+ (void) in4_addr_mask(&dst, prefixlen);
+
+ if (!GREEDY_REALLOC(*routes, *routes_size + 1))
+ return -ENOMEM;
+
+ (*routes)[*routes_size] = (struct sd_dhcp_route) {
+ .dst_addr = dst,
+ .gw_addr = gw,
+ .dst_prefixlen = prefixlen,
+ .option = SD_DHCP_OPTION_STATIC_ROUTE,
+ };
+
(*routes_size)++;
}