fix(p8-security): make --copy-as directory ownership airtight; harden tests/logs
- file_ensure_directory_secure() now chowns a final directory it creates under --copy-as and fails on error; the symlink parent-creation call site propagates it. The is_dir branch fails when the confined parent cannot be opened under --copy-as. Closes the residual wrong-owner gap for synthesized/symlink parent directories. - file_restore_symlink_metadata() early NULL return is copy-as-aware. - Preserve errno across the implicit-parent failure cleanup. - Neutral skip messages (the clamp, not --no-super, may be responsible). - Daemon copy-as test tolerates the non-root privilege refusal; usage text lists --copy-as.
This commit is contained in:
@@ -343,10 +343,13 @@ class TestDaemonRejection:
|
||||
assert result.returncode != 0
|
||||
assert _tree_file_count(AUTH_MODULE) == 0
|
||||
|
||||
def _assert_ownership_refused(self, daemon, module, flags):
|
||||
def _assert_ownership_refused(self, daemon, module, flags,
|
||||
accept=("client-chosen ownership",)):
|
||||
"""A daemon module without `client owner = yes` refuses every
|
||||
client-chosen ownership / super-user request at the config handshake,
|
||||
before any data lands."""
|
||||
before any data lands. `accept` lists the log phrases that count as the
|
||||
refusal (a non-root daemon refuses --copy-as earlier, at the privilege
|
||||
check, so the caller accepts that phrase too)."""
|
||||
log_path = os.path.join(TEST_DATA_DIR, "fastsyncd.log")
|
||||
before = os.path.getsize(log_path) if os.path.exists(log_path) else 0
|
||||
before_files = self._tree_files()
|
||||
@@ -358,7 +361,7 @@ class TestDaemonRejection:
|
||||
with open(log_path, "rb") as f:
|
||||
f.seek(before)
|
||||
tail = f.read().decode("utf-8", "replace")
|
||||
assert "client-chosen ownership" in tail, (
|
||||
assert any(phrase in tail for phrase in accept), (
|
||||
f"daemon did not log the ownership refusal: {tail[-400:]!r}"
|
||||
)
|
||||
|
||||
@@ -368,7 +371,9 @@ class TestDaemonRejection:
|
||||
so even a root daemon must not honor an arbitrary client-selected owner
|
||||
by default. The refusal happens at the config handshake, before any data
|
||||
lands."""
|
||||
self._assert_ownership_refused(daemon, "files", ["--copy-as=@65534:@65534"])
|
||||
self._assert_ownership_refused(
|
||||
daemon, "files", ["--copy-as=@65534:@65534"],
|
||||
accept=("client-chosen ownership", "requires a privileged receiver"))
|
||||
|
||||
def test_super_refused_by_daemon(self, daemon):
|
||||
"""An explicit --super is a super-user activity request, so a daemon
|
||||
|
||||
Reference in New Issue
Block a user