feat(p7-super): implement --super/--no-super safe-subset privilege gate (protocol 2.18.0)

Add the receiver-side --super / --no-super tri-state (Config->super_mode)
under the safe-subset + clear-refusal privilege model: FastSync never
elevates privileges, it only permits super-user attempts that are already
confined fd-relative below the authorized receive root.

- identity: privilege_super_permitted() gate (OFF=false, ON=true, AUTO follows
  geteuid()==0); identity_apply_ownership/_link become no-ops when not
  permitted; --super with no explicit identity policy implies raw numeric-id
  preservation (explicit usermap/groupmap/chown/numeric-ids still win); warn
  exactly once when --super is requested by a non-root receiver.
- file_receive: gate char/block device-node creation on the gate; FIFO/socket
  handling is unchanged.
- wire: trailing super_mode int after the --iconv spec, validated 0..2 in
  receive_privilege_options and validate_received_config; PROTOCOL_VERSION
  2.17.0 -> 2.18.0; version-sensitive tests and docs updated.
- CLI: --super/--no-super parsed explicitly before the generic --no-* branch
  (malformed --super=x rejected); usage text added.
- tests: config wire round-trip + invalid-value rejection, privilege-gate mode
  unit test, CLI parse test, integration transfer + root-gated ownership
  suppression/appliance tests.
- docs: RSYNC_COMPAT --super row + Wave E note, protocol mentions, README.
This commit is contained in:
2026-09-12 12:01:19 +02:00
parent f64d252faf
commit a785ec13c4
13 changed files with 366 additions and 26 deletions
+12
View File
@@ -18,6 +18,7 @@
#include "delay_updates.h"
#include "delta.h"
#include "file.h"
#include "identity.h"
#include "log.h"
#include "metadata.h"
#include "protocol.h"
@@ -355,6 +356,17 @@ static FileSaveResult file_save_special_to_disk(const char* root_directory, cons
if (is_char || is_blk) {
if (!config || !config->preserve_devices)
return FILE_SAVE_SKIPPED;
/* --super / --no-super (P7 Wave E): char/block device-node creation is a
super-user activity. --no-super forbids it even for a root receiver; the
default AUTO only attempts it when already root. Pure FIFO creation is
unprivileged and deliberately NOT gated here. */
if (!privilege_super_permitted()) {
log_message(LOG_LEVEL_WARNING,
"skipping %s: super-user device-node creation is not permitted "
"(--no-super, or the receiver is not privileged)",
file->path);
return FILE_SAVE_SKIPPED;
}
} else if (is_fifo) {
if (!config || !config->preserve_specials)
return FILE_SAVE_SKIPPED;