Skip to content

Commit 048f8a6

Browse files
author
Fox Snowpatch
committed
1 parent d5603db commit 048f8a6

File tree

27 files changed

+884
-175
lines changed

27 files changed

+884
-175
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,14 @@
2929
*.gz
3030
*.i
3131
*.ko
32+
*.ko.stripped
3233
*.lex.c
3334
*.ll
3435
*.lst
3536
*.lz4
3637
*.lzma
3738
*.lzo
39+
*.merkle
3840
*.mod
3941
*.mod.c
4042
*.o

Documentation/kbuild/reproducible-builds.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ generate a different temporary key for each build, resulting in the
8282
modules being unreproducible. However, including a signing key with
8383
your source would presumably defeat the purpose of signing modules.
8484

85-
One approach to this is to divide up the build process so that the
85+
Instead ``CONFIG_MODULE_HASHES`` can be used to embed a static list
86+
of valid modules to load.
87+
88+
Another approach to this is to divide up the build process so that the
8689
unreproducible parts can be treated as sources:
8790

8891
1. Generate a persistent signing key. Add the certificate for the key

Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1588,8 +1588,10 @@ endif
15881588
# is an exception.
15891589
ifdef CONFIG_DEBUG_INFO_BTF_MODULES
15901590
KBUILD_BUILTIN := y
1591+
ifndef CONFIG_MODULE_HASHES
15911592
modules: vmlinux
15921593
endif
1594+
endif
15931595

15941596
modules: modules_prepare
15951597

@@ -1981,7 +1983,11 @@ modules.order: $(build-dir)
19811983
# KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
19821984
# This is solely useful to speed up test compiles.
19831985
modules: modpost
1984-
ifneq ($(KBUILD_MODPOST_NOFINAL),1)
1986+
ifdef CONFIG_MODULE_HASHES
1987+
ifeq ($(MODULE_HASHES_MODPOST_FINAL), 1)
1988+
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modfinal
1989+
endif
1990+
else ifneq ($(KBUILD_MODPOST_NOFINAL),1)
19851991
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modfinal
19861992
endif
19871993

arch/powerpc/kernel/ima_arch.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ static const char *const secure_and_trusted_rules[] = {
6363
const char *const *arch_get_ima_policy(void)
6464
{
6565
if (is_ppc_secureboot_enabled()) {
66-
if (IS_ENABLED(CONFIG_MODULE_SIG))
67-
set_module_sig_enforced();
66+
set_module_sig_enforced();
6867

6968
if (is_ppc_trustedboot_enabled())
7069
return secure_and_trusted_rules;

include/asm-generic/vmlinux.lds.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,8 @@
508508
\
509509
PRINTK_INDEX \
510510
\
511+
MODULE_HASHES \
512+
\
511513
/* Kernel symbol table: Normal symbols */ \
512514
__ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
513515
__start___ksymtab = .; \
@@ -918,6 +920,15 @@
918920
#define PRINTK_INDEX
919921
#endif
920922

923+
#ifdef CONFIG_MODULE_HASHES
924+
#define MODULE_HASHES \
925+
.module_hashes : AT(ADDR(.module_hashes) - LOAD_OFFSET) { \
926+
KEEP(*(SORT(.module_hashes))) \
927+
}
928+
#else
929+
#define MODULE_HASHES
930+
#endif
931+
921932
/*
922933
* Discard .note.GNU-stack, which is emitted as PROGBITS by the compiler.
923934
* Otherwise, the type of .notes section would become PROGBITS instead of NOTES.

include/linux/module.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ struct module {
444444
const u32 *gpl_crcs;
445445
bool using_gplonly_symbols;
446446

447-
#ifdef CONFIG_MODULE_SIG
447+
#ifdef CONFIG_MODULE_SIG_POLICY
448448
/* Signature was verified. */
449449
bool sig_ok;
450450
#endif
@@ -770,8 +770,6 @@ static inline bool is_livepatch_module(struct module *mod)
770770
#endif
771771
}
772772

773-
void set_module_sig_enforced(void);
774-
775773
void module_for_each_mod(int(*func)(struct module *mod, void *data), void *data);
776774

777775
#else /* !CONFIG_MODULES... */
@@ -866,10 +864,6 @@ static inline bool module_requested_async_probing(struct module *module)
866864
}
867865

868866

869-
static inline void set_module_sig_enforced(void)
870-
{
871-
}
872-
873867
/* Dereference module function descriptor */
874868
static inline
875869
void *dereference_module_function_descriptor(struct module *mod, void *ptr)
@@ -922,24 +916,30 @@ static inline bool retpoline_module_ok(bool has_retpoline)
922916
}
923917
#endif
924918

925-
#ifdef CONFIG_MODULE_SIG
919+
#ifdef CONFIG_MODULE_SIG_POLICY
926920
bool is_module_sig_enforced(void);
927921

922+
void set_module_sig_enforced(void);
923+
928924
static inline bool module_sig_ok(struct module *module)
929925
{
930926
return module->sig_ok;
931927
}
932-
#else /* !CONFIG_MODULE_SIG */
928+
#else /* !CONFIG_MODULE_SIG_POLICY */
933929
static inline bool is_module_sig_enforced(void)
934930
{
935931
return false;
936932
}
937933

934+
static inline void set_module_sig_enforced(void)
935+
{
936+
}
937+
938938
static inline bool module_sig_ok(struct module *module)
939939
{
940940
return true;
941941
}
942-
#endif /* CONFIG_MODULE_SIG */
942+
#endif /* CONFIG_MODULE_SIG_POLICY */
943943

944944
#if defined(CONFIG_MODULES) && defined(CONFIG_KALLSYMS)
945945
int module_kallsyms_on_each_symbol(const char *modname,

include/linux/module_hashes.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
3+
#ifndef _LINUX_MODULE_HASHES_H
4+
#define _LINUX_MODULE_HASHES_H
5+
6+
#include <linux/compiler_attributes.h>
7+
#include <linux/types.h>
8+
#include <crypto/sha2.h>
9+
10+
#define __module_hashes_section __section(".module_hashes")
11+
#define MODULE_HASHES_HASH_SIZE SHA256_DIGEST_SIZE
12+
13+
struct module_hashes_proof {
14+
__be32 pos;
15+
u8 hash_sigs[][MODULE_HASHES_HASH_SIZE];
16+
} __packed;
17+
18+
struct module_hashes_root {
19+
u32 levels;
20+
u8 hash[MODULE_HASHES_HASH_SIZE];
21+
};
22+
23+
extern const struct module_hashes_root module_hashes_root;
24+
25+
#endif /* _LINUX_MODULE_HASHES_H */

include/linux/module_signature.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ enum pkey_id_type {
1818
PKEY_ID_PGP, /* OpenPGP generated key ID */
1919
PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */
2020
PKEY_ID_PKCS7, /* Signature in PKCS#7 message */
21+
PKEY_ID_MERKLE, /* Merkle proof for modules */
2122
};
2223

2324
/*
@@ -40,7 +41,7 @@ struct module_signature {
4041
__be32 sig_len; /* Length of signature data */
4142
};
4243

43-
int mod_check_sig(const struct module_signature *ms, size_t file_len,
44-
const char *name);
44+
int mod_split_sig(const void *buf, size_t *buf_len, bool mangled,
45+
enum pkey_id_type *sig_type, size_t *sig_len, const u8 **sig, const char *name);
4546

4647
#endif /* _LINUX_MODULE_SIGNATURE_H */

kernel/module/Kconfig

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,12 @@ config MODULE_SIG
270270
debuginfo strip done by some packagers (such as rpmbuild) and
271271
inclusion into an initramfs that wants the module size reduced.
272272

273+
config MODULE_SIG_POLICY
274+
def_bool MODULE_SIG || MODULE_HASHES
275+
273276
config MODULE_SIG_FORCE
274277
bool "Require modules to be validly signed"
275-
depends on MODULE_SIG
278+
depends on MODULE_SIG_POLICY
276279
help
277280
Reject unsigned modules or signed modules for which we don't have a
278281
key. Without this, such modules will simply taint the kernel.
@@ -286,7 +289,7 @@ config MODULE_SIG_ALL
286289
modules must be signed manually, using the scripts/sign-file tool.
287290

288291
comment "Do not forget to sign required modules with scripts/sign-file"
289-
depends on MODULE_SIG_FORCE && !MODULE_SIG_ALL
292+
depends on MODULE_SIG_FORCE && !MODULE_SIG_ALL && !MODULE_HASHES
290293

291294
choice
292295
prompt "Hash algorithm to sign modules"
@@ -405,6 +408,28 @@ config MODULE_DECOMPRESS
405408

406409
If unsure, say N.
407410

411+
config MODULE_HASHES
412+
bool "Module hash validation"
413+
depends on !MODULE_SIG_ALL
414+
depends on !IMA_APPRAISE_MODSIG
415+
select MODULE_SIG_FORMAT
416+
select CRYPTO_LIB_SHA256
417+
help
418+
Validate modules by their hashes.
419+
Only modules built together with the main kernel image can be
420+
validated that way.
421+
422+
This is a reproducible-build compatible alternative to a build-time
423+
generated module keyring, as enabled by
424+
CONFIG_MODULE_SIG_KEY=certs/signing_key.pem.
425+
426+
Also see the warning in MODULE_SIG about stripping modules.
427+
428+
# To validate the consistency of INSTALL_MOD_STRIP for MODULE_HASHES
429+
config MODULE_INSTALL_STRIP
430+
string
431+
default "$(INSTALL_MOD_STRIP)"
432+
408433
config MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS
409434
bool "Allow loading of modules with missing namespace imports"
410435
help

kernel/module/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ obj-$(CONFIG_KGDB_KDB) += kdb.o
2323
obj-$(CONFIG_MODVERSIONS) += version.o
2424
obj-$(CONFIG_MODULE_UNLOAD_TAINT_TRACKING) += tracking.o
2525
obj-$(CONFIG_MODULE_STATS) += stats.o
26+
obj-$(CONFIG_MODULE_HASHES) += hashes.o hashes_root.o

0 commit comments

Comments
 (0)