Merge feat/ref-supermode: SuperMode enum

This commit is contained in:
2026-09-12 20:43:42 +02:00
6 changed files with 15 additions and 17 deletions
+1 -1
View File
@@ -458,7 +458,7 @@ void handler(int file_descriptor) {
* device-node creation) sees SUPER_MODE_OFF. The gate never mutated the * device-node creation) sees SUPER_MODE_OFF. The gate never mutated the
* received config. */ * received config. */
if (gate_ctx.super_mode_override != -1) if (gate_ctx.super_mode_override != -1)
config->super_mode = gate_ctx.super_mode_override; config->super_mode = (SuperMode)gate_ctx.super_mode_override;
protocol_set_8_bit_output(config->eight_bit_output); protocol_set_8_bit_output(config->eight_bit_output);
if (!authorized_root) { if (!authorized_root) {
log_message(LOG_LEVEL_ERROR, "No server-side destination root configured"); log_message(LOG_LEVEL_ERROR, "No server-side destination root configured");
+2 -2
View File
@@ -1293,14 +1293,14 @@ static bool receive_iconv_spec(int fd, Config* c) {
* validated to the SUPER_MODE_AUTO..SUPER_MODE_OFF range (also re-checked by * validated to the SUPER_MODE_AUTO..SUPER_MODE_OFF range (also re-checked by
* validate_received_config). */ * validate_received_config). */
static bool send_privilege_options(int fd, const Config* c) { static bool send_privilege_options(int fd, const Config* c) {
return send_int(fd, c->super_mode); return send_int(fd, (int)c->super_mode);
} }
static bool receive_privilege_options(int fd, Config* c) { static bool receive_privilege_options(int fd, Config* c) {
int mode; int mode;
if (!receive_int(fd, &mode) || mode < SUPER_MODE_AUTO || mode > SUPER_MODE_OFF) if (!receive_int(fd, &mode) || mode < SUPER_MODE_AUTO || mode > SUPER_MODE_OFF)
return false; return false;
c->super_mode = mode; c->super_mode = (SuperMode)mode;
return true; return true;
} }
+8 -10
View File
@@ -68,6 +68,13 @@ typedef struct {
int value; /* 0/1 for booleans, byte count for SO_RCVBUF/SO_SNDBUF */ int value; /* 0/1 for booleans, byte count for SO_RCVBUF/SO_SNDBUF */
} SockOptEntry; } SockOptEntry;
/* --super / --no-super tri-state (Config->super_mode). AUTO (default) and ON
* both permit a confined super-user attempt (AUTO preserves FastSync's
* historical best-effort behavior; an unprivileged attempt is refused by the
* kernel and skipped per entry); OFF forbids the attempt even for root. See
* privilege_super_mode_permitted() in identity.h. */
typedef enum SuperMode { SUPER_MODE_AUTO = 0, SUPER_MODE_ON = 1, SUPER_MODE_OFF = 2 } SuperMode;
typedef struct Config { typedef struct Config {
char* version; char* version;
char* send_directory; char* send_directory;
@@ -416,7 +423,7 @@ typedef struct Config {
* as a trailing int so the receiver can enforce the policy. See * as a trailing int so the receiver can enforce the policy. See
* privilege_super_permitted() and identity_ownership_requested() in * privilege_super_permitted() and identity_ownership_requested() in
* identity.h. */ * identity.h. */
int super_mode; SuperMode super_mode;
// Receiver-side runtime staging registry for --delay-updates. Never sent // Receiver-side runtime staging registry for --delay-updates. Never sent
// over the wire and never set on the sender side. // over the wire and never set on the sender side.
@@ -644,15 +651,6 @@ typedef struct Config {
#define IDENTITY_CURRENT (-1) #define IDENTITY_CURRENT (-1)
#define MAX_IDENTITY_MAP 128 #define MAX_IDENTITY_MAP 128
/* --super / --no-super tri-state (Config->super_mode). AUTO (default) and ON
* both permit a confined super-user attempt (AUTO preserves FastSync's
* historical best-effort behavior; an unprivileged attempt is refused by the
* kernel and skipped per entry); OFF forbids the attempt even for root. See
* privilege_super_mode_permitted() in identity.h. */
#define SUPER_MODE_AUTO 0
#define SUPER_MODE_ON 1
#define SUPER_MODE_OFF 2
Config* config_create(void); Config* config_create(void);
void config_delete(Config* config); void config_delete(Config* config);
+2 -2
View File
@@ -30,7 +30,7 @@ typedef struct {
/* --super / --no-super tri-state (SUPER_MODE_AUTO when unset). Snapshotted /* --super / --no-super tri-state (SUPER_MODE_AUTO when unset). Snapshotted
* per connection so privilege_super_permitted() can gate super-user * per connection so privilege_super_permitted() can gate super-user
* activities without a Config argument. */ * activities without a Config argument. */
int super_mode; SuperMode super_mode;
/* --copy-as=USER[:GROUP]: snapshotted so the ownership resolver can force the /* --copy-as=USER[:GROUP]: snapshotted so the ownership resolver can force the
* target ids without a Config argument. */ * target ids without a Config argument. */
bool copy_as_set; bool copy_as_set;
@@ -128,7 +128,7 @@ bool privilege_super_permitted(void) {
return privilege_super_mode_permitted(g_identity.super_mode); return privilege_super_mode_permitted(g_identity.super_mode);
} }
bool privilege_super_mode_permitted(int mode) { bool privilege_super_mode_permitted(SuperMode mode) {
/* AUTO and ON both attempt the confined operation; OFF forbids it even for a /* AUTO and ON both attempt the confined operation; OFF forbids it even for a
* root receiver. AUTO is the historical FastSync behavior (always attempt * root receiver. AUTO is the historical FastSync behavior (always attempt
* and let the kernel refuse an unprivileged call, which the caller skips), so * and let the kernel refuse an unprivileged call, which the caller skips), so
+1 -1
View File
@@ -128,6 +128,6 @@ bool identity_wire_valid(const Config* config);
* best-effort behavior where an unprivileged attempt is refused by the kernel * best-effort behavior where an unprivileged attempt is refused by the kernel
* and skipped. Neither EVER elevates privileges. */ * and skipped. Neither EVER elevates privileges. */
bool privilege_super_permitted(void); bool privilege_super_permitted(void);
bool privilege_super_mode_permitted(int mode); bool privilege_super_mode_permitted(SuperMode mode);
#endif #endif
+1 -1
View File
@@ -1672,7 +1672,7 @@ static void test_config_receive_rejects_invalid_iconv_spec() {
static void test_config_super_mode_wire_roundtrip() { static void test_config_super_mode_wire_roundtrip() {
if (is_running_under_valgrind()) if (is_running_under_valgrind())
return; return;
int modes[] = {SUPER_MODE_AUTO, SUPER_MODE_ON, SUPER_MODE_OFF}; SuperMode modes[] = {SUPER_MODE_AUTO, SUPER_MODE_ON, SUPER_MODE_OFF};
for (size_t i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) { for (size_t i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) {
int p[2]; int p[2];
EXPECT_EQ_INT(socketpair(AF_UNIX, SOCK_STREAM, 0, p), 0); EXPECT_EQ_INT(socketpair(AF_UNIX, SOCK_STREAM, 0, p), 0);