devices: build init binary as part of build script#578
Conversation
1f75a2f to
a4aae9c
Compare
|
As an idea, what if the init binary was its own crate and libkrun's rust api accepted a memory range for the static init binary. The c API would consume the new init crate and pass that as the default init memory range. In this way the c library maintains compatibility while the first release of the rust API doesn't bake in an assumed init. |
Can you sketch out the idea a bit more? Do I assume correctly that the Also, can you elaborate more on how to overwrite the default? Would the idea be that users invoke some C API with a different memory range, thereby swapping out the default init? If so, it would seem to me that this could be done with the approach at hand as well as a Rust crate, right? |
|
Let's say the rust api had a method like For users who don't want to supply their own binary, then we can have an It could even be the default to wire up the init binary with a feature-flag opt-out. So we get:
|
|
@d-e-s-o I like this approach, thanks. It has also highlighted we are no longer building @ggoodman You can already do that by setting |
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request moves the compilation of the init binary from the Makefile to a Rust build script (build.rs). This is a good step towards making the project more cargo-friendly. However, I've found a critical issue where the new build script omits the conditional compilation logic required for SEV and TDX builds, which will result in a broken init binary for those configurations. Additionally, there are some issues in the Makefile regarding a now-undefined variable and incorrect dependencies that should be addressed for build correctness and clarity.
| let mut init_cc_flags = vec!["-O2", "-static", "-Wall"]; | ||
| if std::env::var_os("TIMESYNC").as_deref() == Some(OsStr::new("1")) { | ||
| init_cc_flags.push("-D__TIMESYNC__"); | ||
| } |
There was a problem hiding this comment.
This build script is missing the conditional compilation logic for SEV and TDX builds that was present in the Makefile. The init binary requires different C defines, additional source files, and specific linker flags when built with SEV or TDX support.
Without this logic, the init binary will be incorrect for SEV and TDX builds, leading to runtime failures. You should check for Cargo features like CARGO_FEATURE_AMD_SEV and CARGO_FEATURE_TDX and adjust the compilation command accordingly.
For example, for SEV, you need to:
- Add
-DSEV=1toinit_cc_flags. - Add
init/tee/snp_attest.cand theinit/tee/kbs/*.cfiles to the list of source files to compile. - Add flags like
-lcurl,-lssl, etc., to the linker. - Add
cargo:rerun-if-changedfor all the new source files and headers.
A similar logic is needed for TDX.
There was a problem hiding this comment.
This comment seems wrong. As per my understanding this was dead code, see reasoning in a68a626, but let me know if I missed something.
We shouldn't stringify paths, because not all paths are valid UTF-8 strings, meaning we could fail operations spuriously. Work with proper Rust paths to not run into such issues. Signed-off-by: Daniel Müller <deso@posteo.net>
When the SEV or TDX environment variables are 1, we set BUILD_INIT to 0. Unless BUILD_INIT is 1, we don't actually build the init binary, which is the only part of the Makefile that uses INIT_DEFS and INIT_SRC. As such, there seems to be no point in setting both INIT_DEFS and INIT_SRC from the code paths used when SEV or TDX are 1. Remove these assignments. That in turn also allows us to remove the KBS_INIT_SRC, KBS_LD_FLAGS, and SNP_INIT_SRC variables. TDX_INIT_SRC seems to have been unused all along. Signed-off-by: Daniel Müller <deso@posteo.net>
Build the default init binary automatically from a Rust build script, instead of from the Makefile. Doing so is a stepping stone to consuming the crate from Cargo. We do build the init binary unconditionally compared to before to not duplicate the logic overly much. But I would think that's not an issue. We keep supporting cross-compilation from MacOS when using the Makefile as before. Signed-off-by: Daniel Müller <deso@posteo.net>
a4aae9c to
205dada
Compare
| cd $(DESTDIR)$(PREFIX)/$(LIBDIR_$(OS))/ ; ln -sf $(KRUN_BINARY_$(OS)) $(KRUN_SONAME_$(OS)) ; ln -sf $(KRUN_SONAME_$(OS)) $(KRUN_BASE_$(OS)) | ||
|
|
||
| clean: | ||
| rm -f $(INIT_BINARY) |
There was a problem hiding this comment.
The downside of building in the build script and us storing stuff in the source tree is that cargo clean won't remove the binary. I think we could:
- live with that; I don't think it's the end of the world, but not great either
- just keep removing
init/inithere from theMakefile(it's a bit odd to have two different components create/remove the file) - the proper way would be to move the created
initbinary intoOUT_DIR, which I think is probably the best approach. It would just mean adjustingKRUN_INIT_BINARY_PATHfrom the build script.
Any preferences?
There was a problem hiding this comment.
I prefer doing it the right way, so in my opinion we should do option 3.
I'm not opposed. Especially because the nitro init binary is now different than the standard CoCo init binary. It seems this option would give us the flexibility to add whichever init we want. |
|
I'm also not opposed to moving the CoCo init source code to another repository. IMO it would make the build process much easier allowing us to avoid weird scripts. |
|
@tylerfanelli @jakecorrenti thank you guys, let's then get this one merged then. Could you please take care of moving CoCo's init to another repo? |
Sure I can take care of it. Just to confirm -- you don't want it in something like libkrunfw, but something entirely different? |
As per previous discussion [0], adjust the build script to build the init binary in Cargo's OUT_DIR, which is meant precisely for use cases like this. This way, we don't leak a random binary into the source tree, where it would have to be removed manually. [0] containers#578 (comment) Signed-off-by: Daniel Müller <deso@posteo.net>
As per previous discussion [0], adjust the build script to build the init binary in Cargo's OUT_DIR, which is meant precisely for use cases like this. This way, we don't leak a random binary into the source tree, where it would have to be removed manually. [0] containers#578 (comment) Signed-off-by: Daniel Müller <deso@posteo.net>
libkrunfw could be a good place for it, indeed. We could also add the scripts to generate the initramfs. Thanks! |
As per previous discussion [0], adjust the build script to build the init binary in Cargo's OUT_DIR, which is meant precisely for use cases like this. This way, we don't leak a random binary into the source tree, where it would have to be removed manually. [0] #578 (comment) Signed-off-by: Daniel Müller <deso@posteo.net>
Build the default init binary automatically from a Rust build script, instead of from the Makefile. Doing so is a stepping stone to consuming the crate from Cargo. We do build the init binary unconditionally compared to before to not duplicate the logic overly much. But I would think that's not an issue. We keep supporting cross-compilation from MacOS when using the Makefile as before.
This PR is a necessary first step towards the changes discussed here.