feat(daemon,transfer): consume fake super = yes module directive (#1904)#3559
Merged
Merged
Conversation
The daemon parsed `fake super = yes` from `rsyncd.conf(5)` into
`ModuleConfig.fake_super` but never threaded it into the transfer
pipeline. Receivers therefore tried real chown() regardless of the
module directive, which silently dropped ownership for non-root
daemons and contradicted upstream's `clientserver.c:1106-1107`
behaviour where `fake super = yes` demotes the receiver's am_root
and forces fake-super semantics on the wire.
Wire-up path:
ModuleConfig.fake_super
-> ServerConfig.fake_super (transfer/config)
-> MetadataOptions.fake_super (receiver/transfer.rs)
-> apply_ownership_via_fake_super (writes user.rsync.%stat)
-> create_*_with_fake_super placeholders for special files
Changes:
- transfer/config/mod.rs: add `pub fake_super: bool` to ServerConfig
with upstream citation and default false.
- transfer/config/builder.rs: add `.fake_super(bool)` builder method
matching the existing `&mut self -> &mut Self` style.
- transfer/config/builder_tests.rs: assert default false and
round-trip through the builder.
- daemon/sections/module_access/client_args.rs: in
`build_server_config`, set `cfg.fake_super = module.fake_super`
after the iconv wire-up. Per upstream, the directive is purely
daemon-config-driven; client `--fake-super` is demoted to
`--super` on the wire and never reaches the server-side parser.
- transfer/receiver/transfer.rs: call `.fake_super(self.config.fake_super)`
on the MetadataOptions builder so the receiver routes ownership
writes into the user.rsync.%stat xattr instead of chown().
- daemon/tests/chunks/daemon_fake_super_module_push.rs: end-to-end
test that pushes a file with `-og` to a daemon module configured
with `fake super = yes` and asserts the destination carries the
user.rsync.%stat xattr.
Upstream references:
- clientserver.c:1106-1107: `fake super = yes` demotes am_root and
rewrites client `--fake-super` to honour the daemon directive.
- loadparm.c: `fake super` module parameter parsing.
- rsync.c:set_file_attrs(): fake-super stores ownership in xattrs.
- xattrs.c:set_stat_xattr(): user.rsync.%stat encoding.
Closes #1904.
oferchen
added a commit
that referenced
this pull request
May 5, 2026
…) (#3559) The daemon parsed `fake super = yes` from `rsyncd.conf(5)` into `ModuleConfig.fake_super` but never threaded it into the transfer pipeline. Receivers therefore tried real chown() regardless of the module directive, which silently dropped ownership for non-root daemons and contradicted upstream's `clientserver.c:1106-1107` behaviour where `fake super = yes` demotes the receiver's am_root and forces fake-super semantics on the wire. Wire-up path: ModuleConfig.fake_super -> ServerConfig.fake_super (transfer/config) -> MetadataOptions.fake_super (receiver/transfer.rs) -> apply_ownership_via_fake_super (writes user.rsync.%stat) -> create_*_with_fake_super placeholders for special files Changes: - transfer/config/mod.rs: add `pub fake_super: bool` to ServerConfig with upstream citation and default false. - transfer/config/builder.rs: add `.fake_super(bool)` builder method matching the existing `&mut self -> &mut Self` style. - transfer/config/builder_tests.rs: assert default false and round-trip through the builder. - daemon/sections/module_access/client_args.rs: in `build_server_config`, set `cfg.fake_super = module.fake_super` after the iconv wire-up. Per upstream, the directive is purely daemon-config-driven; client `--fake-super` is demoted to `--super` on the wire and never reaches the server-side parser. - transfer/receiver/transfer.rs: call `.fake_super(self.config.fake_super)` on the MetadataOptions builder so the receiver routes ownership writes into the user.rsync.%stat xattr instead of chown(). - daemon/tests/chunks/daemon_fake_super_module_push.rs: end-to-end test that pushes a file with `-og` to a daemon module configured with `fake super = yes` and asserts the destination carries the user.rsync.%stat xattr. Upstream references: - clientserver.c:1106-1107: `fake super = yes` demotes am_root and rewrites client `--fake-super` to honour the daemon directive. - loadparm.c: `fake super` module parameter parsing. - rsync.c:set_file_attrs(): fake-super stores ownership in xattrs. - xattrs.c:set_stat_xattr(): user.rsync.%stat encoding. Closes #1904.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
fake super = yesfromModuleConfig.fake_superthroughServerConfig.fake_superand intoMetadataOptions.fake_super, so daemon-side receivers honour the directive end-to-end.fake super = yeswas parsed but never consumed: receivers issued realchown()calls regardless of the directive, which silently dropped ownership for non-root daemons and contradicted upstream'sclientserver.c:1106-1107semantics.-ogto a module configured withfake super = yesand asserts the destination carries theuser.rsync.%statxattr.Wire-up path
Files changed
crates/transfer/src/config/mod.rs(+23): addpub fake_super: boolfield with upstream-cited rustdoc.crates/transfer/src/config/builder.rs(+23): add.fake_super(bool)builder method.crates/transfer/src/config/builder_tests.rs(+21): default-false assertion and round-trip test.crates/daemon/src/daemon/sections/module_access/client_args.rs(+7): setcfg.fake_super = module.fake_superinbuild_server_config.crates/transfer/src/receiver/transfer.rs(+6/-1): chain.fake_super(self.config.fake_super)on the receiver'sMetadataOptions::new()builder.crates/daemon/src/tests/chunks/daemon_fake_super_module_push.rs(+158, new): end-to-end daemon test.crates/daemon/src/tests.rs(+2): wire the new chunk into the test harness.Upstream references
clientserver.c:1106-1107— daemonfake super = yesdemotes the receiver'sam_rootand forces fake-super semantics regardless of client args.loadparm.c—fake supermodule parameter parsing.rsync.c:set_file_attrs()— fake-super stores ownership in xattrs.xattrs.c:set_stat_xattr()—user.rsync.%statencoding format.Per upstream, client
--fake-superis demoted to--superon the wire before reaching the daemon, so the directive is purely daemon-config-driven; we do not parse--fake-superserver-side.Test plan
crates/daemon/src/tests/chunks/daemon_fake_super_module_push.rscovers the end-to-end daemon push case (skips gracefully on filesystems without user.* xattr support).crates/transfer/src/config/builder_tests.rs::fake_super_round_trips_through_buildercovers the builder.crates/transfer/src/config/builder_tests.rs::default_optional_fieldsadds the default-false assertion.crates/daemon/src/rsyncd_config/tests.rs::module_fake_super_yes_parses_to_true_for_am_root_demotioncovers the parser side (unchanged).Closes #1904.