Skip to content

Fix DNS keyword ACI test failures on RHEL 9.x (IPv4-mapped address) - #7703

Open
mmatsuya wants to merge 1 commit into
389ds:389-ds-base-2.2from
mmatsuya:389-ds-base-2.2-fix-dns-aci-keywords
Open

mmatsuya wants to merge 1 commit into
389ds:389-ds-base-2.2from
mmatsuya:389-ds-base-2.2-fix-dns-aci-keywords

Conversation

@mmatsuya

@mmatsuya mmatsuya commented Aug 11, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

The acl/keywords_test.py DNS keyword tests (test_user_can_access_the_data_when_connecting_from_internal_ds_network_only etc.) fail in idm-ci on RHEL 9.x with:

INSUFFICIENT_ACCESS

Root Cause

When 389-ds binds on :: (dual-stack), IPv4 clients appear as ::ffff:x.x.x.x at the socket layer (accept() returns the IPv4-mapped form). The ACL engine calls PR_GetHostByAddr() → gethostbyaddr_r(::ffff:x.x.x.x, 16, AF_INET6) (confirmed via objdump of libnspr4.so).

On glibc-2.34 (RHEL 9.x), gethostbyaddr_r with AF_INET6 and an IPv4-mapped address does not auto-unmap it, so the plain IPv4 entry in /etc/hosts is not found → hostname lookup returns NULL → DNS keyword ACI fails.

On glibc-2.39 (RHEL 10.x), the auto-unmap happens and the lookup succeeds, so the tests pass there without this fix.

Fix

Add a module-scoped autouse fixture to conftest.py that registers ::ffff:<ip> <hostname> in /etc/hosts before the keywords test module runs. This ensures gethostbyaddr_r finds the hostname regardless of glibc version.

Verification

Validated with trigger-test-suite #15591 on RHEL 9.2: all 16 acl/keywords_test.py tests pass with this fixture in place.

Summary by Sourcery

Ensure DNS keyword ACL tests handle IPv4-mapped client addresses on RHEL 9.x by normalizing host resolution in the ACL test suite.

Enhancements:

  • Add a module-scoped autouse fixture to register IPv4-mapped IPv6 addresses for the test directory server host so reverse DNS lookups succeed on glibc versions without auto-unmapping.

Tests:

  • Stabilize acl/keywords DNS keyword tests across platforms by guaranteeing hostname resolution for IPv4-mapped connections.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The configure_ipv4_mapped_hosts fixture appends directly to /etc/hosts without any cleanup or idempotency checks, which can lead to repeated entries or persistent file mutations across test runs—consider checking for an existing ::ffff:<ip> <host> entry and/or restoring the original file content after the module finishes.
  • Because this workaround is targeting a glibc/OS-specific behavior, you may want to guard the fixture so it only runs when the resolved address is IPv4 and the platform actually exhibits the problem (e.g., RHEL 9.x), avoiding unnecessary /etc/hosts modifications on newer systems.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `configure_ipv4_mapped_hosts` fixture appends directly to `/etc/hosts` without any cleanup or idempotency checks, which can lead to repeated entries or persistent file mutations across test runs—consider checking for an existing `::ffff:<ip> <host>` entry and/or restoring the original file content after the module finishes.
- Because this workaround is targeting a glibc/OS-specific behavior, you may want to guard the fixture so it only runs when the resolved address is IPv4 and the platform actually exhibits the problem (e.g., RHEL 9.x), avoiding unnecessary `/etc/hosts` modifications on newer systems.

## Individual Comments

### Comment 1
<location path="dirsrvtests/tests/suites/acl/conftest.py" line_range="25-34" />
<code_context>
 from lib389.idm.domain import Domain


+@pytest.fixture(scope="module", autouse=True)
+def configure_ipv4_mapped_hosts(topo):
+    """Register the IPv4-mapped IPv6 address in /etc/hosts.
+
+    When DS binds on :: (dual-stack), IPv4 clients appear as ::ffff:x.x.x.x
+    at the socket layer. NSPR's PR_GetHostByAddr calls gethostbyaddr_r with
+    AF_INET6, and glibc-2.34 (RHEL 9.x) does not auto-unmap IPv4-mapped
+    addresses, so the plain IPv4 entry in /etc/hosts is not found and the
+    DNS keyword ACI evaluation fails with INSUFFICIENT_ACCESS.
+    Adding the ::ffff:<ip> form ensures the reverse lookup succeeds.
+    """
+    host = topo.standalone.host
+    ip = socket.gethostbyname(host)
+    with open("/etc/hosts", "a") as f:
+        f.write(f"::ffff:{ip}   {host}\n")
+
+
</code_context>
<issue_to_address>
**issue (bug_risk):** Fixture mutates /etc/hosts but never restores it, which can leave persistent state across tests and runs

Because this autouse fixture appends directly to `/etc/hosts`, every test run (and each test process) will keep adding duplicate `::ffff:<ip> <hostname>` lines and never clean them up, leaving persistent state and an ever-growing hosts file. Please either (1) check whether the exact mapping already exists before writing, and/or (2) add teardown logic to remove the entry that was added. At minimum, a guard that no-ops when the mapping is present would prevent unbounded growth of `/etc/hosts`.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread dirsrvtests/tests/suites/acl/conftest.py
Comment thread dirsrvtests/tests/suites/acl/conftest.py
Removes and Restores ACIs after the test.
"""
aci_list = Domain(topo.standalone, DEFAULT_SUFFIX).get_attr_vals_utf8('aci')
aci_list = Domain(topo.standalone, DEFAULT_SUFFIX).get_attr_vals_utf8("aci")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, for other PR, try to avoid such cosmetic changes as they are making the review harder
( half of the changes are pure noise )

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the change. Thanks!

When DS listens on :: (dual-stack), IPv4 clients appear as ::ffff:x.x.x.x
at the socket layer. NSPR's PR_GetHostByAddr calls gethostbyaddr_r with
AF_INET6, and glibc-2.34 (RHEL 9.x) does not auto-unmap IPv4-mapped
addresses, so the plain IPv4 entry in /etc/hosts is not found and the
DNS keyword ACI evaluation fails with INSUFFICIENT_ACCESS.

Add a module-scoped autouse fixture to conftest.py that registers the
::ffff:<ip> form in /etc/hosts before the test suite runs and removes
it on teardown. The duplicate check uses token-based comparison to
avoid false negatives from spacing differences.

Signed-off-by: Masahiro Matsuya <mmatsuya@redhat.com>
@mmatsuya
mmatsuya force-pushed the 389-ds-base-2.2-fix-dns-aci-keywords branch from d649cb9 to 00f5c04 Compare August 12, 2026 05:27
with open("/etc/hosts", "w") as f:
f.writelines(line for line in lines if line != entry)

request.addfinalizer(remove_entry)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tear down seems still present.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the 54-63 lines to avoid risking /etc/hosts corruption if the process get somehow killed while rewriting it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants