fix(p8-security): close review gaps in the ownership gate and copy-as failure propagation

- H3: a daemon module without 'client owner = yes' now also has super-user
  device activity forced off (char/block mknod, --write-devices), so a root
  daemon can no longer be made to create/write raw devices under AUTO.  The
  entries are skipped, preserving ordinary -a pushes.
- H1/H2: propagate a failed required --copy-as chown from symlink metadata
  restore and implicitly-created parent directories, so the entry (and run)
  reports failure instead of a wrong-owner success.
- Docs/help/headers updated for A2/A3 and the device clamp; startup warning
  spells out the client-owner risk.
- Tests: daemon device clamp (skipped without opt-in, created with opt-in),
  updated --super/--fake-super expectations.
This commit is contained in:
2026-09-12 14:18:03 +02:00
parent e3840c8326
commit b216ed31fb
11 changed files with 123 additions and 38 deletions
+9 -5
View File
@@ -357,17 +357,20 @@ void file_restore_metadata(const char* path, const FileMetadata* metadata,
}
}
void file_restore_symlink_metadata(const char* path, const FileMetadata* metadata,
bool file_restore_symlink_metadata(const char* path, const FileMetadata* metadata,
bool omit_link_times) {
if (path == NULL || metadata == NULL)
return;
return true;
char* leaf = NULL;
int parent_fd = file_open_secure_parent(path, &leaf, false);
if (parent_fd < 0)
return;
return !identity_copy_as_active();
/* Ownership (only when the identity policy is active) via lchown semantics:
fchownat with AT_SYMLINK_NOFOLLOW never dereferences the link. */
identity_apply_ownership_link(parent_fd, leaf, (int32_t)metadata->uid, (int32_t)metadata->gid);
fchownat with AT_SYMLINK_NOFOLLOW never dereferences the link. A failed
REQUIRED --copy-as ownership marks the entry failed; every other policy is
best-effort. */
bool owned = identity_apply_ownership_link(parent_fd, leaf, (int32_t)metadata->uid,
(int32_t)metadata->gid);
/* Symlink mode: not settable on Linux (fchmodat AT_SYMLINK_NOFOLLOW returns
EOPNOTSUPP/ENOTSUP); attempt it for platforms that support it and quietly
ignore the unsupported case so the transfer never fails over it. */
@@ -392,6 +395,7 @@ void file_restore_symlink_metadata(const char* path, const FileMetadata* metadat
}
close(parent_fd);
free(leaf);
return owned;
}
bool file_restore_metadata_fd(int fd, const FileMetadata* metadata, bool preserve_executability) {