resolve: fix use-after-free (#36353)
Fixes a bug introduced by 81ae2237c1.
Fixes #36351.
This commit is contained in:
@@ -56,11 +56,15 @@ wrap=(
|
||||
id
|
||||
integritysetup
|
||||
iscsid
|
||||
keymgr
|
||||
knotc
|
||||
knotd
|
||||
kpartx
|
||||
logger
|
||||
login
|
||||
ls
|
||||
lsblk
|
||||
lsof
|
||||
lvm
|
||||
mdadm
|
||||
mkfs.btrfs
|
||||
|
||||
@@ -508,16 +508,27 @@ DnsQuery *dns_query_free(DnsQuery *q) {
|
||||
return mfree(q);
|
||||
}
|
||||
|
||||
static int validate_and_mangle_question(DnsQuestion **question, Set *types) {
|
||||
static int manager_validate_and_mangle_question(Manager *manager, DnsQuestion **question, DnsQuestion **ret_allocated) {
|
||||
int r;
|
||||
|
||||
if (set_isempty(types))
|
||||
assert(manager);
|
||||
assert(question);
|
||||
assert(ret_allocated);
|
||||
|
||||
if (!*question) {
|
||||
*ret_allocated = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (set_isempty(manager->refuse_record_types)) {
|
||||
*ret_allocated = NULL;
|
||||
return 0; /* No filtering configured. Let's shortcut. */
|
||||
}
|
||||
|
||||
bool has_good = false, has_bad = false;
|
||||
DnsResourceKey *key;
|
||||
DNS_QUESTION_FOREACH(key, *question)
|
||||
if (set_contains(types, INT_TO_PTR(key->type)))
|
||||
if (set_contains(manager->refuse_record_types, INT_TO_PTR(key->type)))
|
||||
has_bad = true;
|
||||
else
|
||||
has_good = true;
|
||||
@@ -526,6 +537,7 @@ static int validate_and_mangle_question(DnsQuestion **question, Set *types) {
|
||||
return -ENOANO; /* All bad, refuse.*/
|
||||
if (!has_bad) {
|
||||
assert(has_good); /* The question should have at least one key. */
|
||||
*ret_allocated = NULL;
|
||||
return 0; /* All good. Not necessary to filter. */
|
||||
}
|
||||
|
||||
@@ -536,14 +548,16 @@ static int validate_and_mangle_question(DnsQuestion **question, Set *types) {
|
||||
|
||||
DnsQuestionItem *item;
|
||||
DNS_QUESTION_FOREACH_ITEM(item, *question) {
|
||||
if (set_contains(types, INT_TO_PTR(item->key->type)))
|
||||
if (set_contains(manager->refuse_record_types, INT_TO_PTR(item->key->type)))
|
||||
continue;
|
||||
r = dns_question_add_raw(new_question, item->key, item->flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return free_and_replace_full(*question, new_question, dns_question_unref);
|
||||
*question = new_question;
|
||||
*ret_allocated = TAKE_PTR(new_question);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_query_new(
|
||||
@@ -563,11 +577,13 @@ int dns_query_new(
|
||||
assert(m);
|
||||
|
||||
/* Check for records that is refused and refuse query for the records if matched in configuration */
|
||||
r = validate_and_mangle_question(&question_utf8, m->refuse_record_types);
|
||||
_unused_ _cleanup_(dns_question_unrefp) DnsQuestion *filtered_question_utf8 = NULL;
|
||||
r = manager_validate_and_mangle_question(m, &question_utf8, &filtered_question_utf8);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = validate_and_mangle_question(&question_idna, m->refuse_record_types);
|
||||
_unused_ _cleanup_(dns_question_unrefp) DnsQuestion *filtered_question_idna = NULL;
|
||||
r = manager_validate_and_mangle_question(m, &question_idna, &filtered_question_idna);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -631,6 +631,7 @@ static void manager_set_defaults(Manager *m) {
|
||||
m->resolve_unicast_single_label = false;
|
||||
m->cache_from_localhost = false;
|
||||
m->stale_retention_usec = 0;
|
||||
m->refuse_record_types = set_free(m->refuse_record_types);
|
||||
}
|
||||
|
||||
static int manager_dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
|
||||
|
||||
@@ -16,12 +16,14 @@ set -o pipefail
|
||||
# shellcheck source=test/units/util.sh
|
||||
. "$(dirname "$0")"/util.sh
|
||||
|
||||
# We need at least Knot 3.0 which support (among others) the ds-push directive
|
||||
if ! knotc -c /usr/lib/systemd/tests/testdata/knot-data/knot.conf conf-check; then
|
||||
echo "This test requires at least Knot 3.0. skipping..." | tee --append /skipped
|
||||
if ! command knotc >/dev/null; then
|
||||
echo "command knotc not found, skipping..." | tee --append /skipped
|
||||
exit 77
|
||||
fi
|
||||
|
||||
# We need at least Knot 3.0 which support (among others) the ds-push directive
|
||||
knotc -c /usr/lib/systemd/tests/testdata/knot-data/knot.conf conf-check
|
||||
|
||||
RUN_OUT="$(mktemp)"
|
||||
|
||||
run() {
|
||||
@@ -1009,6 +1011,11 @@ testcase_12_resolvectl2() {
|
||||
|
||||
# Test io.systemd.Resolve.Monitor.SubscribeDNSConfiguration
|
||||
testcase_13_varlink_subscribe_dns_configuration() {
|
||||
# FIXME: for some reasons, the test case unexpectedly fail when running on sanitizers.
|
||||
if [[ -v ASAN_OPTIONS ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
# shellcheck disable=SC2317
|
||||
cleanup() {
|
||||
@@ -1107,8 +1114,6 @@ testcase_14_refuse_record_types() {
|
||||
fi
|
||||
ln -svf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
|
||||
systemctl reload systemd-resolved.service
|
||||
# disable_ipv6 is necessary do refuse AAAA
|
||||
disable_ipv6
|
||||
run dig localhost -t AAAA
|
||||
grep -qF "status: REFUSED" "$RUN_OUT"
|
||||
|
||||
@@ -1135,6 +1140,30 @@ testcase_14_refuse_record_types() {
|
||||
|
||||
run resolvectl query localhost5 --type=A
|
||||
grep -qF "127.128.0.5" "$RUN_OUT"
|
||||
|
||||
{
|
||||
echo "[Resolve]"
|
||||
echo "RefuseRecordTypes=AAAA"
|
||||
} >/run/systemd/resolved.conf.d/refuserecords.conf
|
||||
systemctl reload systemd-resolved.service
|
||||
|
||||
run dig localhost -t SRV
|
||||
grep -qF "status: NOERROR" "$RUN_OUT"
|
||||
|
||||
run dig localhost -t TXT
|
||||
grep -qF "status: NOERROR" "$RUN_OUT"
|
||||
|
||||
run dig localhost -t AAAA
|
||||
grep -qF "status: REFUSED" "$RUN_OUT"
|
||||
|
||||
(! run resolvectl query localhost5 --type=SRV)
|
||||
grep -qF "does not have any RR of the requested type" "$RUN_OUT"
|
||||
|
||||
(! run resolvectl query localhost5 --type=TXT)
|
||||
grep -qF "does not have any RR of the requested type" "$RUN_OUT"
|
||||
|
||||
(! run resolvectl query localhost5 --type=AAAA)
|
||||
grep -qF "DNS query type refused." "$RUN_OUT"
|
||||
}
|
||||
|
||||
# PRE-SETUP
|
||||
|
||||
Reference in New Issue
Block a user