Skip to content

Commit 58ec613

Browse files
author
Fox Snowpatch
committed
1 parent d88a1b4 commit 58ec613

29 files changed

Lines changed: 919 additions & 189 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@
3030
*.gz
3131
*.i
3232
*.ko
33+
*.ko.stripped
3334
*.lex.c
3435
*.ll
3536
*.lst
3637
*.lz4
3738
*.lzma
3839
*.lzo
40+
*.merkle
3941
*.mod
4042
*.mod.c
4143
*.o

Documentation/kbuild/reproducible-builds.rst

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

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

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

Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1650,7 +1650,9 @@ ifdef CONFIG_MODULES
16501650

16511651
# By default, build modules as well
16521652

1653+
ifndef CONFIG_MODULE_HASHES
16531654
all: modules
1655+
endif
16541656

16551657
# When we're building modules with modversions, we need to consider
16561658
# the built-in objects during the descend as well, in order to
@@ -1666,8 +1668,10 @@ endif
16661668
# is an exception.
16671669
ifdef CONFIG_DEBUG_INFO_BTF_MODULES
16681670
KBUILD_BUILTIN := y
1671+
ifndef CONFIG_MODULE_HASHES
16691672
modules: vmlinux
16701673
endif
1674+
endif
16711675

16721676
modules: modules_prepare
16731677

@@ -2068,7 +2072,7 @@ modules.order: $(build-dir)
20682072
# KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
20692073
# This is solely useful to speed up test compiles.
20702074
modules: modpost
2071-
ifneq ($(KBUILD_MODPOST_NOFINAL),1)
2075+
ifneq ($(CONFIG_MODULE_HASHES)|$(KBUILD_MODPOST_NOFINAL),|1)
20722076
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modfinal
20732077
endif
20742078

@@ -2162,6 +2166,7 @@ clean: $(clean-dirs)
21622166
-o -name '*.c.[012]*.*' \
21632167
-o -name '*.ll' \
21642168
-o -name '*.gcno' \
2169+
-o -name '*.merkle' \
21652170
\) -type f -print \
21662171
-o -name '.tmp_*' -print \
21672172
| xargs rm -rf

crypto/algapi.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ static LIST_HEAD(crypto_template_list);
2424

2525
static inline void crypto_check_module_sig(struct module *mod)
2626
{
27-
if (fips_enabled && mod && !module_sig_ok(mod))
28-
panic("Module %s signature verification failed in FIPS mode\n",
27+
if (fips_enabled && mod && !module_auth_ok(mod))
28+
panic("Module %s authentication failed in FIPS mode\n",
2929
module_name(mod));
3030
}
3131

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 */ \
512514
__ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
513515
__start___ksymtab = .; \
@@ -913,6 +915,15 @@
913915
#define PRINTK_INDEX
914916
#endif
915917

918+
#ifdef CONFIG_MODULE_HASHES
919+
#define MODULE_HASHES \
920+
.module_hashes : AT(ADDR(.module_hashes) - LOAD_OFFSET) { \
921+
KEEP(*(SORT(.module_hashes))) \
922+
}
923+
#else
924+
#define MODULE_HASHES
925+
#endif
926+
916927
/*
917928
* Discard .note.GNU-stack, which is emitted as PROGBITS by the compiler.
918929
* Otherwise, the type of .notes section would become PROGBITS instead of NOTES.

include/linux/module.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -437,9 +437,9 @@ struct module {
437437
/* GPL-only exported symbols. */
438438
bool using_gplonly_symbols;
439439

440-
#ifdef CONFIG_MODULE_SIG
441-
/* Signature was verified. */
442-
bool sig_ok;
440+
#ifdef CONFIG_MODULE_AUTH
441+
/* Module was authenticated. */
442+
bool auth_ok;
443443
#endif
444444

445445
bool async_probe_requested;
@@ -918,16 +918,16 @@ static inline bool retpoline_module_ok(bool has_retpoline)
918918
}
919919
#endif
920920

921-
#ifdef CONFIG_MODULE_SIG
921+
#ifdef CONFIG_MODULE_AUTH
922922
bool is_module_sig_enforced(void);
923923

924924
void set_module_sig_enforced(void);
925925

926-
static inline bool module_sig_ok(struct module *module)
926+
static inline bool module_auth_ok(struct module *module)
927927
{
928-
return module->sig_ok;
928+
return module->auth_ok;
929929
}
930-
#else /* !CONFIG_MODULE_SIG */
930+
#else /* !CONFIG_MODULE_AUTH */
931931
static inline bool is_module_sig_enforced(void)
932932
{
933933
return false;
@@ -937,11 +937,11 @@ static inline void set_module_sig_enforced(void)
937937
{
938938
}
939939

940-
static inline bool module_sig_ok(struct module *module)
940+
static inline bool module_auth_ok(struct module *module)
941941
{
942942
return true;
943943
}
944-
#endif /* CONFIG_MODULE_SIG */
944+
#endif /* CONFIG_MODULE_AUTH */
945945

946946
#if defined(CONFIG_MODULES) && defined(CONFIG_KALLSYMS)
947947
int module_kallsyms_on_each_symbol(const char *modname,

include/linux/module_hashes.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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_hash {
14+
u8 h[MODULE_HASHES_HASH_SIZE];
15+
};
16+
17+
struct module_hashes_proof {
18+
__be32 pos;
19+
struct module_hash hash_sigs[];
20+
} __packed;
21+
22+
struct module_hashes_root {
23+
u32 levels;
24+
struct module_hash hash;
25+
};
26+
27+
extern const struct module_hashes_root module_hashes_root;
28+
29+
#endif /* _LINUX_MODULE_HASHES_H */

include/uapi/linux/module_signature.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
enum module_signature_type {
1818
MODULE_SIGNATURE_TYPE_PKCS7 = 2, /* Signature in PKCS#7 message */
19+
MODULE_SIGNATURE_TYPE_MERKLE = 3, /* Merkle proof for modules, opaque structure */
1920
};
2021

2122
/*

kernel/module/Kconfig

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

274+
config MODULE_AUTH
275+
def_bool MODULE_SIG || MODULE_HASHES
276+
274277
config MODULE_SIG_FORCE
275278
bool "Require modules to be validly signed"
276-
depends on MODULE_SIG
279+
depends on MODULE_AUTH
277280
help
278281
Reject unsigned modules or signed modules for which we don't have a
279282
key. Without this, such modules will simply taint the kernel.
@@ -288,7 +291,7 @@ config MODULE_SIG_ALL
288291
modules must be signed manually, using the scripts/sign-file tool.
289292

290293
comment "Do not forget to sign required modules with scripts/sign-file"
291-
depends on MODULE_SIG_FORCE && !MODULE_SIG_ALL
294+
depends on MODULE_SIG_FORCE && !MODULE_SIG_ALL && !MODULE_HASHES
292295

293296
choice
294297
prompt "Hash algorithm to sign modules"
@@ -403,6 +406,28 @@ config MODULE_DECOMPRESS
403406

404407
endif # MODULE_COMPRESS
405408

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

kernel/module/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ obj-y += strict_rwx.o
1212
obj-y += kmod.o
1313
obj-$(CONFIG_MODULE_DEBUG_AUTOLOAD_DUPS) += dups.o
1414
obj-$(CONFIG_MODULE_DECOMPRESS) += decompress.o
15+
obj-$(CONFIG_MODULE_AUTH) += auth.o
1516
obj-$(CONFIG_MODULE_SIG) += signing.o
1617
obj-$(CONFIG_LIVEPATCH) += livepatch.o
1718
obj-$(CONFIG_MODULES_TREE_LOOKUP) += tree_lookup.o
@@ -23,3 +24,4 @@ obj-$(CONFIG_KGDB_KDB) += kdb.o
2324
obj-$(CONFIG_MODVERSIONS) += version.o
2425
obj-$(CONFIG_MODULE_UNLOAD_TAINT_TRACKING) += tracking.o
2526
obj-$(CONFIG_MODULE_STATS) += stats.o
27+
obj-$(CONFIG_MODULE_HASHES) += hashes.o hashes_root.o

0 commit comments

Comments
 (0)