mirror of
https://github.com/systemd/systemd.git
synced 2026-08-10 01:48:09 +00:00
shared: fix DNS RR wire cache and EFI boot option bounds checks (#42926)
Invalidate cached DNS RR wire format when `dns_resource_record_clamp_ttl()` updates `rr->ttl` in place. Validate each EFI `Boot####` device-path node length before reading subtype-specific fields.
This commit is contained in:
@@ -554,7 +554,12 @@ static void dnssec_fix_rrset_ttl(
|
||||
/* Pick the TTL as the minimum of the RR's TTL, the
|
||||
* RR's original TTL according to the RRSIG and the
|
||||
* RRSIG's own TTL, see RFC 4035, Section 5.3.3 */
|
||||
rr->ttl = MIN3(rr->ttl, rrsig->rrsig.original_ttl, rrsig->ttl);
|
||||
uint32_t ttl = MIN3(rr->ttl, rrsig->rrsig.original_ttl, rrsig->ttl);
|
||||
if (ttl != rr->ttl) {
|
||||
rr->ttl = ttl;
|
||||
dns_resource_record_clear_wire_format(rr);
|
||||
}
|
||||
|
||||
rr->expiry = rrsig->rrsig.expiration * USEC_PER_SEC;
|
||||
|
||||
/* Copy over information about the signer and wildcard source of synthesis */
|
||||
|
||||
@@ -2467,18 +2467,29 @@ TEST(dns_resource_record_is_synthetic) {
|
||||
* ================================================================ */
|
||||
|
||||
TEST(dns_resource_record_clamp_ttl_in_place) {
|
||||
_cleanup_free_ void *wire_format = NULL;
|
||||
DnsResourceRecord *rr = NULL, *orig = NULL;
|
||||
size_t wire_format_size;
|
||||
|
||||
rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, "www.example.com");
|
||||
ASSERT_NOT_NULL(rr);
|
||||
orig = rr;
|
||||
rr->ttl = 3600;
|
||||
rr->a.in_addr.s_addr = htobe32(0xc0a8017f);
|
||||
|
||||
ASSERT_FALSE(dns_resource_record_clamp_ttl(&rr, 4800));
|
||||
ASSERT_EQ(rr->ttl, 3600u);
|
||||
|
||||
ASSERT_OK(dns_resource_record_to_wire_format(rr, false));
|
||||
ASSERT_NOT_NULL(rr->wire_format);
|
||||
wire_format_size = rr->wire_format_size;
|
||||
ASSERT_NOT_NULL(wire_format = memdup(rr->wire_format, wire_format_size));
|
||||
|
||||
ASSERT_TRUE(dns_resource_record_clamp_ttl(&rr, 2400));
|
||||
ASSERT_EQ(rr->ttl, 2400u);
|
||||
ASSERT_OK(dns_resource_record_to_wire_format(rr, false));
|
||||
ASSERT_EQ(rr->wire_format_size, wire_format_size);
|
||||
ASSERT_NE(memcmp(rr->wire_format, wire_format, wire_format_size), 0);
|
||||
|
||||
ASSERT_TRUE(rr == orig);
|
||||
|
||||
|
||||
@@ -1466,6 +1466,15 @@ int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dns_resource_record_clear_wire_format(DnsResourceRecord *rr) {
|
||||
assert(rr);
|
||||
|
||||
rr->wire_format = mfree(rr->wire_format);
|
||||
rr->wire_format_size = 0;
|
||||
rr->wire_format_rdata_offset = 0;
|
||||
rr->wire_format_canonical = false;
|
||||
}
|
||||
|
||||
int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret) {
|
||||
const char *n;
|
||||
int r;
|
||||
@@ -1977,6 +1986,7 @@ int dns_resource_record_clamp_ttl(DnsResourceRecord **rr, uint32_t max_ttl) {
|
||||
if (old_rr->n_ref == 1) {
|
||||
/* Patch in place */
|
||||
old_rr->ttl = new_ttl;
|
||||
dns_resource_record_clear_wire_format(old_rr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -392,6 +392,7 @@ const char* dns_resource_record_to_string(DnsResourceRecord *rr);
|
||||
DnsResourceRecord *dns_resource_record_copy(DnsResourceRecord *rr);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceRecord*, dns_resource_record_unref);
|
||||
|
||||
void dns_resource_record_clear_wire_format(DnsResourceRecord *rr);
|
||||
int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical);
|
||||
|
||||
int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret);
|
||||
|
||||
@@ -283,19 +283,23 @@ int efi_get_boot_option(
|
||||
|
||||
if (header->path_len > 0) {
|
||||
uint8_t *dbuf;
|
||||
size_t dnext, doff;
|
||||
size_t dnext, doff, path_len;
|
||||
|
||||
doff = offsetof(struct boot_option, title) + title_size;
|
||||
dbuf = buf + doff;
|
||||
if (header->path_len > l - doff)
|
||||
return -EINVAL;
|
||||
path_len = MIN((size_t) header->path_len, l - doff);
|
||||
|
||||
dnext = 0;
|
||||
while (dnext < header->path_len) {
|
||||
while (dnext < path_len) {
|
||||
struct device_path *dpath;
|
||||
size_t remaining = path_len - dnext;
|
||||
|
||||
if (remaining < offsetof(struct device_path, path))
|
||||
break;
|
||||
|
||||
dpath = (struct device_path *)(dbuf + dnext);
|
||||
if (dpath->length < 4)
|
||||
if (dpath->length < offsetof(struct device_path, path) ||
|
||||
dpath->length > remaining)
|
||||
break;
|
||||
|
||||
/* Type 0x7F – End of Hardware Device Path, Sub-Type 0xFF – End Entire Device Path */
|
||||
@@ -310,6 +314,9 @@ int efi_get_boot_option(
|
||||
|
||||
/* Sub-Type 1 – Hard Drive */
|
||||
if (dpath->sub_type == MEDIA_HARDDRIVE_DP) {
|
||||
if (dpath->length < offsetof(struct device_path, drive) + sizeof(struct drive_path))
|
||||
break;
|
||||
|
||||
/* 0x02 – GUID Partition Table */
|
||||
if (dpath->drive.mbr_type != MBR_TYPE_EFI_PARTITION_TABLE_HEADER)
|
||||
continue;
|
||||
@@ -325,9 +332,9 @@ int efi_get_boot_option(
|
||||
|
||||
/* Sub-Type 4 – File Path */
|
||||
if (dpath->sub_type == MEDIA_FILEPATH_DP && !p && ret_path) {
|
||||
p = utf16_to_utf8(dpath->path, dpath->length-4);
|
||||
p = utf16_to_utf8(dpath->path, dpath->length - offsetof(struct device_path, path));
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
return -ENOMEM;
|
||||
|
||||
efi_tilt_backslashes(p);
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user