Re: [RFC PATCH 00/11] output a valid shell script when running 'make -n'

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Aug 19, 2024 at 06:02:57PM +0200 Vegard Nossum wrote:
> This patch series lets 'make -n' output a shell script that can be
> used to build the kernel without any further use of make. For example:
> 
>     make defconfig
> 
>     # ensure some build prerequisites are built
>     make prepare
> 
>     # generate build script
>     make -n | tee build.sh
> 
>     # excecute build script
>     bash -eux build.sh
> 
> The purpose of this is to take a step towards defeating the insertion of
> backdoors at build time (see [1]). Some of the benefits of separating the
> build script from the build system are:
> 
>  - we can invoke make in a restricted environment (e.g. mostly read-only
>    kernel tree),
> 
>  - we have an audit log of the exact commands that run during the build
>    process; although it's true that the build script wouldn't be useful
>    for either production or development builds (as it doesn't support
>    incremental rebuilds or parallel builds), it would allow you to
>    rebuild an existing kernel and compare the resulting binary for
>    discrepancies to the original build,
> 
>  - the audit log can be stored (e.g. in git) and changes to it over time
>    can themselves be audited (e.g. by looking at diffs),
> 
>  - there's a lot fewer places to hide malicious code in a straight-line
>    shell script that makes minimal use of variables and helper functions.
>    You also cannot inject fragments of Makefile code through environment
>    variables (again, see [1]).
> 
> Alternative ways to achieve some of the same things would be:
> 
>  - the existing compile_commands.json infrastructure; unfortunately this
>    does not include most of the steps performed during a build (such as
>    linking vmlinux) and does not really allow you to reproduce/verify the
>    full build,
> 
>  - simply running something like strace -f -e trace=execve make; however,
>    this also does not result in something that can be easily played back;
>    at the very least it would need to be heavily filtered and processed
>    to account for data passed in environment variables and things like
>    temporary files used by the compiler.
> 
> This implementation works as follows:
> 
>  - 'make -n' (AKA --dry-run) by default prints out the commands that make
>    runs; this output is modified to be usable as a shell script,
> 
>  - we output 'make() { :; }' at the start of the script in order to make
>    all 'make' invocations in the resulting build script no-ops (GNU Make
>    will actually execute -- and print -- all recipe lines that include
>    $(MAKE), even when invoked with -n).
> 
>  - we simplify the makefile rules in some cases to make the shell script
>    more readable; for example, we don't need the logic that extracts
>    dependencies from .c files (since that is only used by 'make' itself
>    when determining what to rebuild) or the logic that generates .cmd
>    files,
> 
> This patch is WIP and may not produce a working shell script in all
> circumstances. For example, while plain 'make -n' works for me, other
> make targets (e.g. 'make -n htmldocs') are not at all guaranteed to
> produce meaningful output; certain kernel configs may also not work,
> especially those that rely on external tools like e.g. Rust.

Thanks for this patch set and all the thoughts laid out here in detail,
especially for the write-up in [1], too!

I think it is a good idea to work towards hardening the build system against
known and difficult to spot attacks.  As the patch set integration needs a
complete 'make -n' script (at least for a "simple", defined config) to be
successful, I expect that it might become quite some work and patience, but I
think it is a meaningful goal.

In order to prevent "degradation" of Make rules after a possible integration,
we need some (automated) testers, otherwise we will loose all the efforts again.

Please give me yet some days for a first rough round through the patches.

Kind regards
Nicolas



> 
> [1]: https://www.openwall.com/lists/oss-security/2024/04/17/3
> [2]: https://www.gnu.org/software/make/manual/make.html#Testing-Flags
> 
> 
> Vegard
> 
> ---
> 
> Vegard Nossum (11):
>   kbuild: ignore .config rule for make --always-make
>   kbuild: document some prerequisites
>   kbuild: pass KERNELVERSION and LOCALVERSION explicitly to
>     setlocalversion
>   kbuild: don't execute .ko recipe in --dry-run mode
>   kbuild: execute modules.order recipe in --dry-run mode
>   kbuild: set $dry_run when running in --dry-run mode
>   kbuild: define 'make' as a no-op in --dry-run mode
>   kbuild: make link-vmlinux.sh respect $dry_run
>   kbuild: simplify commands in --dry-run mode
>   kbuild: don't test for file presence in --dry-run mode
>   kbuild: suppress echoing of commands in --dry-run mode
> 
>  Makefile                          | 28 +++++++++++++++++---
>  arch/x86/boot/compressed/Makefile |  6 +++++
>  scripts/Kbuild.include            | 27 +++++++++++++++++++
>  scripts/Makefile.build            |  2 +-
>  scripts/Makefile.modfinal         |  9 +++++--
>  scripts/Makefile.modpost          |  8 ++++--
>  scripts/Makefile.vmlinux          | 22 ++++++++++++++--
>  scripts/Makefile.vmlinux_o        |  3 +++
>  scripts/link-vmlinux.sh           | 44 ++++++++++++++++++++-----------
>  9 files changed, 123 insertions(+), 26 deletions(-)
> 
> -- 
> 2.34.1
> 

-- 
epost|xmpp: nicolas@xxxxxxxxx          irc://oftc.net/nsc
↳ gpg: 18ed 52db e34f 860e e9fb  c82b 7d97 0932 55a0 ce7f
     -- frykten for herren er opphav til kunnskap --

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux&nblp;USB Development]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite Secrets]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux