install: Read --root-ssh-authorized-keys before changing mounts - #2476
ericcurtin wants to merge 2 commits into
Conversation
Johan-Liebert1
left a comment
There was a problem hiding this comment.
Logic looks good to me. Could you please sign off your commit as we require a Signed-off-by: <email> line at the end of commit messages
| }); | ||
| } | ||
| let contents = std::fs::read_to_string(p).with_context(|| format!("Reading {p}"))?; | ||
| bootc_utils::reexec::set_reexec_env(ROOT_SSH_AUTHORIZED_KEYS_ENV, &contents); |
There was a problem hiding this comment.
We should make sure it's UTF-8 compatible here itself
There was a problem hiding this comment.
Switched to std::env::var(), so the value is a String (UTF-8 enforced by the type) and a non-UTF-8 value is a proper error. The value we write is also a String from read_to_string, so it is UTF-8 by construction.
|
|
||
| /// Additional environment variables to pass along when we re-execute ourself; | ||
| /// see [`set_reexec_env`]. | ||
| static REEXEC_ENV: Mutex<Vec<(OsString, OsString)>> = Mutex::new(Vec::new()); |
There was a problem hiding this comment.
We only ever call this from one thread so I'm sure if the mutex is required. Also, not a fan of this being a global var. We should only ever re-exec when we are installing, so putting this in prepare_install would make sense and passing in the vector of env vars to reexec_with_guardenv as an extra_args param?
There was a problem hiding this comment.
We need a mutex or equiv around any static, no problem with that from my PoV.
Also, not a fan of this being a global var.
Yes, but doing it differently would require threading this state from the install code into the lsm code...doable but ugly in a different way.
BTW I would generalize this slightly and e.g.:
- Define a struct we can serialize to JSON of stuff we need to save between re-exec
- In the install path, gather that state before we re-exec
- Serialize it to a memfd
- Set an env var
_BOOTC_INSTALL_REEXEC_STATE - Deserialize it early in the install path
There was a problem hiding this comment.
Kept the global per Colin (threading it from install into lsm was the alternative), but folded the env application together with the argv/argv0 setup into a single prepare_reexec() used by both re-exec sites, so the duplication there is gone too, plus a unit test.
On the memfd/JSON generalization: set_reexec_env is already generic over key/value, and the only payload today is a small text file, so I left the env approach for now. Happy to move to a memfd-backed struct if we grow more state to carry across re-exec (or if key files near the 128KiB per-env-string limit turn out to be a real concern).
`podman build` in `just package` pulls the base image itself, and a transient registry error (e.g. an EOF from quay.io mid-blob) fails the whole CI package job. Pull it up front with the same retry settings we already use for LBI images. Assisted-by: AI
prepare_install() mounts a tmpfs over /tmp and mirrors the host's /var/tmp before reading the --root-ssh-authorized-keys file, so a file bind mounted into the install container under /tmp was hidden and the install failed with "No such file or directory" even though the file was visible in the container. Read the file before touching mounts. Since we may re-exec afterwards (unshare, SELinux install_t) and run prepare_install() again with the mounts in place, carry the content to the child via the environment using a small bootc_utils::reexec helper shared by both re-exec sites. Mount the key file under /tmp in the integration test to cover this. Generated-by: AI
06d92ae to
ede527b
Compare
Problem
prepare_install()mounts a tmpfs over/tmpand mirrors the host's/var/tmp, and only afterwards reads the--root-ssh-authorized-keysfile. A file bind mounted into the install container under/tmpis hidden by then:The file is visible via
podman run ... cat /tmp/authorized_keys, so this is confusing.Change
prepare_install()may re-exec (unshare, SELinuxinstall_t) and run again with the tmpfs in place, so carry the content to the child via the environment with a smallbootc_utils::reexechelper used by both re-exec sites. This avoids mutating our own environment, which is not thread safe./tmpto cover this.just packagepulls the base image with retries (fedora-46 job failed on a quay.io EOF).Testing
Fedora 44 aarch64, SELinux enforcing (exercises the
install_tre-exec), key file bind mounted at/tmp/authorized_keys:install to-disk --via-loopback ... --root-ssh-authorized-keys /tmp/authorized_keysfails as above./etc/tmpfiles.d/bootc-root-ssh.confcontains the keys.cargo test -p bootc-lib --lib,cargo test -p bootc-internal-utils --lib,cargo fmt --checkpass.Generated-by: AI
I hit this on real hardware, reviewed the change and tested it end to end as above.