From 3dd0fcf0aa26baa4e8e02c7cd298616128c4b980 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 21 May 2012 18:20:58 -0400 Subject: [PATCH] Update the modsign patchset to the most recent version Update to the modsign-20120510 tag in the modsign git tree. We no longer need to generate the GPG key in the spec file, as the kernel makefile will do that for us. We still provide the genkey template though, so we don't get a generic one from upstream. --- genkey | 6 +- kernel.spec | 29 +- ...n-20111207.patch => modsign-20120510.patch | 4608 ++++++++++------- 3 files changed, 2666 insertions(+), 1977 deletions(-) rename modsign-20111207.patch => modsign-20120510.patch (71%) diff --git a/genkey b/genkey index 486850441..fdb7d1f64 100644 --- a/genkey +++ b/genkey @@ -1,5 +1,7 @@ -%pubring kernel.pub -%secring kernel.sec +%pubring modsign.pub +%secring modsign.sec +%no-protection: yes +%transient-key: yes Key-Type: RSA Key-Length: 2048 Name-Real: Fedora Project diff --git a/kernel.spec b/kernel.spec index 204372f7b..a2831a5bf 100644 --- a/kernel.spec +++ b/kernel.spec @@ -675,7 +675,7 @@ Patch700: linux-2.6-e1000-ich9-montevina.patch Patch800: linux-2.6-crash-driver.patch # crypto/ -Patch900: modsign-20111207.patch +Patch900: modsign-20120510.patch # virt + ksm patches Patch1555: fix_xen_guest_on_old_EC2.patch @@ -1382,7 +1382,7 @@ ApplyPatch linux-2.6-crash-driver.patch ApplyPatch linux-2.6-e1000-ich9-montevina.patch # crypto/ -ApplyPatch modsign-20111207.patch +ApplyPatch modsign-20120510.patch # Assorted Virt Fixes ApplyPatch fix_xen_guest_on_old_EC2.patch @@ -1495,27 +1495,7 @@ find . \( -name "*.orig" -o -name "*~" \) -exec rm -f {} \; >/dev/null find . -name .gitignore -exec rm -f {} \; >/dev/null %if %{signmodules} -cat < +- Update the modsign patchset to the most recent version + * Mon May 21 2012 Josh Boyer - 3.5.0-0.rc0.git1.2 - Linux v3.4-1622-g31a6710 diff --git a/modsign-20111207.patch b/modsign-20120510.patch similarity index 71% rename from modsign-20111207.patch rename to modsign-20120510.patch index 5eee17a87..d9aabf83a 100644 --- a/modsign-20111207.patch +++ b/modsign-20120510.patch @@ -1,7 +1,7 @@ -From 5ba13e189c831b8ad2bfb14f4599b9b9d00cc5ae Mon Sep 17 00:00:00 2001 +From d093caa39460495390c94556f0680218223168c2 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Wed, 7 Dec 2011 14:07:04 +0000 -Subject: MPILIB: Export some more symbols +Date: Fri, 4 May 2012 15:55:49 +0100 +Subject: [PATCH 01/36] MPILIB: Export some more symbols Export some more symbols for use by the DSA key subtype. @@ -12,7 +12,7 @@ Signed-off-by: David Howells lib/mpi/mpi-inv.c | 1 + lib/mpi/mpi-mpow.c | 1 + lib/mpi/mpi-mul.c | 1 + - 5 files changed, 6 insertions(+), 0 deletions(-) + 5 files changed, 6 insertions(+) diff --git a/lib/mpi/mpi-cmp.c b/lib/mpi/mpi-cmp.c index 914bc42..1871e7b 100644 @@ -32,7 +32,7 @@ index 914bc42..1871e7b 100644 } +EXPORT_SYMBOL_GPL(mpi_cmp); diff --git a/lib/mpi/mpi-div.c b/lib/mpi/mpi-div.c -index c3087d1..3da9402 100644 +index f68cbbb..fed3405 100644 --- a/lib/mpi/mpi-div.c +++ b/lib/mpi/mpi-div.c @@ -59,6 +59,7 @@ nomem: @@ -53,11 +53,11 @@ index 0951f98..bfc5ca1 100644 } +EXPORT_SYMBOL_GPL(mpi_invm); diff --git a/lib/mpi/mpi-mpow.c b/lib/mpi/mpi-mpow.c -index 4cc7593..5752194 100644 +index 7328d0d..b8b22e5 100644 --- a/lib/mpi/mpi-mpow.c +++ b/lib/mpi/mpi-mpow.c -@@ -131,3 +131,4 @@ nomem: - kfree(G); +@@ -132,3 +132,4 @@ nomem: + err_out: return rc; } +EXPORT_SYMBOL_GPL(mpi_mulpowm); @@ -71,26 +71,26 @@ index 1f3219e..3d514b9 100644 } +EXPORT_SYMBOL_GPL(mpi_mulm); -- -1.7.9.1 +1.7.10.2 -From 7a5782bc39eba97f3499e3d2686fe48d26f261b0 Mon Sep 17 00:00:00 2001 +From 335abcad2d9fa26198c8e99bae2bb9b3185dce22 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Wed, 7 Dec 2011 14:07:06 +0000 -Subject: KEYS: Move the key config into security/keys/Kconfig +Date: Fri, 4 May 2012 15:55:50 +0100 +Subject: [PATCH 02/36] KEYS: Move the key config into security/keys/Kconfig Move the key config into security/keys/Kconfig as there are going to be a lot of key-related options. Signed-off-by: David Howells --- - security/Kconfig | 68 +---------------------------------------------- + security/Kconfig | 68 +--------------------------------------------- security/keys/Kconfig | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 67 deletions(-) create mode 100644 security/keys/Kconfig diff --git a/security/Kconfig b/security/Kconfig -index 51bd5a0..1c5a7a4 100644 +index ccc61f8..e9c6ac7 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -4,73 +4,7 @@ @@ -246,13 +246,13 @@ index 0000000..a90d6d3 + + If you are unsure as to whether this is required, answer N. -- -1.7.9.1 +1.7.10.2 -From f8b45d1f0f1bdd4c29733f462f6f43518ea625d3 Mon Sep 17 00:00:00 2001 +From 6569015cb5801f36324c76dee156a3e880fcf9be Mon Sep 17 00:00:00 2001 From: David Howells -Date: Wed, 7 Dec 2011 14:07:07 +0000 -Subject: KEYS: Announce key type (un)registration +Date: Fri, 4 May 2012 15:55:50 +0100 +Subject: [PATCH 03/36] KEYS: Announce key type (un)registration Announce the (un)registration of a key type in the core key code rather than in the callers. @@ -264,7 +264,7 @@ Signed-off-by: David Howells 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c -index fa000d2..689d7c8 100644 +index c73bba3..14b2c3d 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c @@ -249,9 +249,6 @@ static int __init init_dns_resolver(void) @@ -277,7 +277,7 @@ index fa000d2..689d7c8 100644 /* create an override credential set with a special thread keyring in * which DNS requests are cached * -@@ -300,8 +297,6 @@ static void __exit exit_dns_resolver(void) +@@ -301,8 +298,6 @@ static void __exit exit_dns_resolver(void) key_revoke(dns_resolver_cache->thread_keyring); unregister_key_type(&key_type_dns_resolver); put_cred(dns_resolver_cache); @@ -287,10 +287,10 @@ index fa000d2..689d7c8 100644 module_init(init_dns_resolver) diff --git a/security/keys/key.c b/security/keys/key.c -index 4414abd..a8086a1 100644 +index 06783cf..dc62894 100644 --- a/security/keys/key.c +++ b/security/keys/key.c -@@ -957,6 +957,8 @@ int register_key_type(struct key_type *ktype) +@@ -980,6 +980,8 @@ int register_key_type(struct key_type *ktype) /* store the type */ list_add(&ktype->link, &key_types_list); @@ -299,7 +299,7 @@ index 4414abd..a8086a1 100644 ret = 0; out: -@@ -979,6 +981,7 @@ void unregister_key_type(struct key_type *ktype) +@@ -1002,6 +1004,7 @@ void unregister_key_type(struct key_type *ktype) list_del_init(&ktype->link); downgrade_write(&key_types_sem); key_gc_keytype(ktype); @@ -308,13 +308,13 @@ index 4414abd..a8086a1 100644 } EXPORT_SYMBOL(unregister_key_type); -- -1.7.9.1 +1.7.10.2 -From bc9e72fd7ba0f06b89c2887a2e2eefef0441d92d Mon Sep 17 00:00:00 2001 +From 13628af46a92a030fdb7dc33976b46cfcc4b3f31 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Wed, 7 Dec 2011 14:07:08 +0000 -Subject: KEYS: Reorganise keys Makefile +Date: Fri, 4 May 2012 15:55:51 +0100 +Subject: [PATCH 04/36] KEYS: Reorganise keys Makefile Reorganise the keys directory Makefile to put all the core bits together and the type-specific bits after. @@ -322,7 +322,7 @@ the type-specific bits after. Signed-off-by: David Howells --- security/keys/Makefile | 12 +++++++++--- - 1 files changed, 9 insertions(+), 3 deletions(-) + 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/security/keys/Makefile b/security/keys/Makefile index a56f1ff..504aaa0 100644 @@ -355,14 +355,14 @@ index a56f1ff..504aaa0 100644 +obj-$(CONFIG_TRUSTED_KEYS) += trusted.o +obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ -- -1.7.9.1 +1.7.10.2 -From b78b34f3950b08d1def84449e10e4560d7cee280 Mon Sep 17 00:00:00 2001 +From 8c5366bc5c1c9ecaa1104d769f60c7b83ed342a9 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Wed, 7 Dec 2011 14:07:08 +0000 -Subject: KEYS: Create a key type that can be used for general cryptographic - operations +Date: Fri, 4 May 2012 16:15:09 +0100 +Subject: [PATCH 05/36] KEYS: Create a key type that can be used for general + cryptographic operations Create a key type that can be used for general cryptographic operations, such as encryption, decryption, signature generation and signature verification. @@ -375,16 +375,20 @@ Signed-off-by: David Howells Documentation/security/keys-crypto.txt | 181 +++++++++++++++++++++++++ include/keys/crypto-subtype.h | 56 ++++++++ include/keys/crypto-type.h | 25 ++++ - security/keys/Kconfig | 8 + - security/keys/Makefile | 3 + - security/keys/crypto_keys.h | 28 ++++ - security/keys/crypto_type.c | 228 ++++++++++++++++++++++++++++++++ - 7 files changed, 529 insertions(+), 0 deletions(-) + security/keys/Kconfig | 2 + + security/keys/Makefile | 1 + + security/keys/crypto/Kconfig | 7 + + security/keys/crypto/Makefile | 7 + + security/keys/crypto/crypto_keys.h | 28 ++++ + security/keys/crypto/crypto_type.c | 228 ++++++++++++++++++++++++++++++++ + 9 files changed, 535 insertions(+) create mode 100644 Documentation/security/keys-crypto.txt create mode 100644 include/keys/crypto-subtype.h create mode 100644 include/keys/crypto-type.h - create mode 100644 security/keys/crypto_keys.h - create mode 100644 security/keys/crypto_type.c + create mode 100644 security/keys/crypto/Kconfig + create mode 100644 security/keys/crypto/Makefile + create mode 100644 security/keys/crypto/crypto_keys.h + create mode 100644 security/keys/crypto/crypto_type.c diff --git a/Documentation/security/keys-crypto.txt b/Documentation/security/keys-crypto.txt new file mode 100644 @@ -667,14 +671,30 @@ index 0000000..47c00c7 + +#endif /* _KEYS_CRYPTO_TYPE_H */ diff --git a/security/keys/Kconfig b/security/keys/Kconfig -index a90d6d3..290c9d3 100644 +index a90d6d3..992fe52 100644 --- a/security/keys/Kconfig +++ b/security/keys/Kconfig -@@ -69,3 +69,11 @@ config KEYS_DEBUG_PROC_KEYS +@@ -69,3 +69,5 @@ config KEYS_DEBUG_PROC_KEYS the resulting table. If you are unsure as to whether this is required, answer N. + ++source security/keys/crypto/Kconfig +diff --git a/security/keys/Makefile b/security/keys/Makefile +index 504aaa0..67dae73 100644 +--- a/security/keys/Makefile ++++ b/security/keys/Makefile +@@ -24,3 +24,4 @@ obj-$(CONFIG_SYSCTL) += sysctl.o + # + obj-$(CONFIG_TRUSTED_KEYS) += trusted.o + obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ ++obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto/ +diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig +new file mode 100644 +index 0000000..3d15710 +--- /dev/null ++++ b/security/keys/crypto/Kconfig +@@ -0,0 +1,7 @@ +config CRYPTO_KEY_TYPE + tristate "Cryptographic key type" + depends on KEYS @@ -682,22 +702,24 @@ index a90d6d3..290c9d3 100644 + This option provides support for a type of key that holds the keys + required for cryptographic operations such as encryption, decryption, + signature generation and signature verification. -diff --git a/security/keys/Makefile b/security/keys/Makefile -index 504aaa0..67fceaa 100644 ---- a/security/keys/Makefile -+++ b/security/keys/Makefile -@@ -24,3 +24,6 @@ obj-$(CONFIG_SYSCTL) += sysctl.o - # - obj-$(CONFIG_TRUSTED_KEYS) += trusted.o - obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ +diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile +new file mode 100644 +index 0000000..36db1d5 +--- /dev/null ++++ b/security/keys/crypto/Makefile +@@ -0,0 +1,7 @@ ++# ++# Makefile for cryptographic keys ++# ++ +obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o + +crypto_keys-y := crypto_type.o -diff --git a/security/keys/crypto_keys.h b/security/keys/crypto_keys.h +diff --git a/security/keys/crypto/crypto_keys.h b/security/keys/crypto/crypto_keys.h new file mode 100644 index 0000000..a339ce0 --- /dev/null -+++ b/security/keys/crypto_keys.h ++++ b/security/keys/crypto/crypto_keys.h @@ -0,0 +1,28 @@ +/* Internal crypto type stuff + * @@ -727,11 +749,11 @@ index 0000000..a339ce0 + */ +extern struct list_head crypto_key_parsers; +extern struct rw_semaphore crypto_key_parsers_sem; -diff --git a/security/keys/crypto_type.c b/security/keys/crypto_type.c +diff --git a/security/keys/crypto/crypto_type.c b/security/keys/crypto/crypto_type.c new file mode 100644 index 0000000..33d279b --- /dev/null -+++ b/security/keys/crypto_type.c ++++ b/security/keys/crypto/crypto_type.c @@ -0,0 +1,228 @@ +/* Cryptographic key type + * @@ -962,13 +984,13 @@ index 0000000..33d279b +module_init(crypto_key_init); +module_exit(crypto_key_cleanup); -- -1.7.9.1 +1.7.10.2 -From 9d66ee5300d0d1391367dd002eba6663aaf33760 Mon Sep 17 00:00:00 2001 +From e8d4b12988cd23815f1a5f4654d819f5a0a2194b Mon Sep 17 00:00:00 2001 From: David Howells -Date: Wed, 7 Dec 2011 14:07:09 +0000 -Subject: KEYS: Add signature verification facility +Date: Fri, 4 May 2012 16:15:57 +0100 +Subject: [PATCH 06/36] KEYS: Add signature verification facility Add a facility whereby a key subtype may be asked to verify a signature against the data it is purported to have signed. @@ -1003,10 +1025,10 @@ Signed-off-by: David Howells Documentation/security/keys-crypto.txt | 101 +++++++++++++++++++++++++++++ include/keys/crypto-subtype.h | 21 ++++++ include/keys/crypto-type.h | 9 +++ - security/keys/Makefile | 2 +- - security/keys/crypto_verify.c | 111 ++++++++++++++++++++++++++++++++ - 5 files changed, 243 insertions(+), 1 deletions(-) - create mode 100644 security/keys/crypto_verify.c + security/keys/crypto/Makefile | 2 +- + security/keys/crypto/crypto_verify.c | 111 ++++++++++++++++++++++++++++++++ + 5 files changed, 243 insertions(+), 1 deletion(-) + create mode 100644 security/keys/crypto/crypto_verify.c diff --git a/Documentation/security/keys-crypto.txt b/Documentation/security/keys-crypto.txt index 97dee80..a964717 100644 @@ -1207,21 +1229,21 @@ index 47c00c7..6b93366 100644 /* * The payload is at the discretion of the subtype. */ -diff --git a/security/keys/Makefile b/security/keys/Makefile -index 67fceaa..8462904 100644 ---- a/security/keys/Makefile -+++ b/security/keys/Makefile -@@ -26,4 +26,4 @@ obj-$(CONFIG_TRUSTED_KEYS) += trusted.o - obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ +diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile +index 36db1d5..67001bc 100644 +--- a/security/keys/crypto/Makefile ++++ b/security/keys/crypto/Makefile +@@ -4,4 +4,4 @@ + obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o -crypto_keys-y := crypto_type.o +crypto_keys-y := crypto_type.o crypto_verify.o -diff --git a/security/keys/crypto_verify.c b/security/keys/crypto_verify.c +diff --git a/security/keys/crypto/crypto_verify.c b/security/keys/crypto/crypto_verify.c new file mode 100644 index 0000000..65f734c --- /dev/null -+++ b/security/keys/crypto_verify.c ++++ b/security/keys/crypto/crypto_verify.c @@ -0,0 +1,111 @@ +/* Signature verification with a crypto key + * @@ -1335,32 +1357,33 @@ index 0000000..65f734c +} +EXPORT_SYMBOL_GPL(verify_sig_cancel); -- -1.7.9.1 +1.7.10.2 -From 8842a89fac8ac5a9691fb8ff381cdf98e23e8029 Mon Sep 17 00:00:00 2001 +From db170ec4f4df7d8f188134c9c9a3e2736ec0dbff Mon Sep 17 00:00:00 2001 From: David Howells -Date: Wed, 7 Dec 2011 14:07:10 +0000 -Subject: KEYS: Asymmetric public-key algorithm crypto key subtype +Date: Fri, 4 May 2012 16:16:46 +0100 +Subject: [PATCH 07/36] KEYS: Asymmetric public-key algorithm crypto key + subtype Add a subtype for supporting asymmetric public-key encryption algorithms such as DSA (FIPS-186) and RSA (PKCS#1 / RFC1337). Signed-off-by: David Howells --- - security/keys/Kconfig | 9 ++++ - security/keys/Makefile | 1 + - security/keys/public_key.c | 55 +++++++++++++++++++++++ - security/keys/public_key.h | 106 ++++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 171 insertions(+), 0 deletions(-) - create mode 100644 security/keys/public_key.c - create mode 100644 security/keys/public_key.h + security/keys/crypto/Kconfig | 10 ++++ + security/keys/crypto/Makefile | 3 +- + security/keys/crypto/public_key.c | 55 +++++++++++++++++++ + security/keys/crypto/public_key.h | 106 +++++++++++++++++++++++++++++++++++++ + 4 files changed, 173 insertions(+), 1 deletion(-) + create mode 100644 security/keys/crypto/public_key.c + create mode 100644 security/keys/crypto/public_key.h -diff --git a/security/keys/Kconfig b/security/keys/Kconfig -index 290c9d3..07c7f3b 100644 ---- a/security/keys/Kconfig -+++ b/security/keys/Kconfig -@@ -77,3 +77,12 @@ config CRYPTO_KEY_TYPE +diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig +index 3d15710..5f2b8ac 100644 +--- a/security/keys/crypto/Kconfig ++++ b/security/keys/crypto/Kconfig +@@ -5,3 +5,13 @@ config CRYPTO_KEY_TYPE This option provides support for a type of key that holds the keys required for cryptographic operations such as encryption, decryption, signature generation and signature verification. @@ -1368,27 +1391,29 @@ index 290c9d3..07c7f3b 100644 +config CRYPTO_KEY_PUBLIC_KEY_SUBTYPE + tristate "Asymmetric public-key crypto algorithm subtype" + depends on CRYPTO_KEY_TYPE ++ select MPILIB + help + This option provides support for asymmetric public key type handling. + If signature generation and/or verification are to be used, + appropriate hash algorithms (such as SHA-1) must be available. + ENOPKG will be reported if the requisite algorithm is unavailable. -diff --git a/security/keys/Makefile b/security/keys/Makefile -index 8462904..dc3281f 100644 ---- a/security/keys/Makefile -+++ b/security/keys/Makefile -@@ -25,5 +25,6 @@ obj-$(CONFIG_SYSCTL) += sysctl.o - obj-$(CONFIG_TRUSTED_KEYS) += trusted.o - obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ - obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o -+obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o +diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile +index 67001bc..6384306 100644 +--- a/security/keys/crypto/Makefile ++++ b/security/keys/crypto/Makefile +@@ -3,5 +3,6 @@ + # + obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o +- crypto_keys-y := crypto_type.o crypto_verify.o -diff --git a/security/keys/public_key.c b/security/keys/public_key.c ++ ++obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o +diff --git a/security/keys/crypto/public_key.c b/security/keys/crypto/public_key.c new file mode 100644 index 0000000..c00ddac --- /dev/null -+++ b/security/keys/public_key.c ++++ b/security/keys/crypto/public_key.c @@ -0,0 +1,55 @@ +/* Asymmetric public key crypto subtype + * @@ -1445,11 +1470,11 @@ index 0000000..c00ddac + .destroy = public_key_destroy, +}; +EXPORT_SYMBOL_GPL(public_key_crypto_key_subtype); -diff --git a/security/keys/public_key.h b/security/keys/public_key.h +diff --git a/security/keys/crypto/public_key.h b/security/keys/crypto/public_key.h new file mode 100644 index 0000000..81ed603 --- /dev/null -+++ b/security/keys/public_key.h ++++ b/security/keys/crypto/public_key.h @@ -0,0 +1,106 @@ +/* Asymmetric public-key algorithm definitions + * @@ -1558,13 +1583,13 @@ index 0000000..81ed603 + +#endif /* _LINUX_PUBLIC_KEY_H */ -- -1.7.9.1 +1.7.10.2 -From 6fc88dcf4610907920e8ec8fc9d11610a23b12ae Mon Sep 17 00:00:00 2001 +From 07f1001d10c926d28b92f0a32dbb57131a0f0942 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Wed, 7 Dec 2011 14:07:11 +0000 -Subject: KEYS: RSA signature verification algorithm +Date: Fri, 4 May 2012 16:30:18 +0100 +Subject: [PATCH 08/36] KEYS: RSA signature verification algorithm Implement the RSA algorithm (PKCS#1 / RFC3447). At this time, only signature verification is supported. This uses the asymmetric public key subtype to hold @@ -1572,18 +1597,18 @@ its key data. Signed-off-by: David Howells --- - security/keys/Kconfig | 6 + - security/keys/Makefile | 1 + - security/keys/crypto_rsa.c | 282 ++++++++++++++++++++++++++++++++++++++++++++ - security/keys/public_key.h | 2 + - 4 files changed, 291 insertions(+), 0 deletions(-) - create mode 100644 security/keys/crypto_rsa.c + security/keys/crypto/Kconfig | 7 + + security/keys/crypto/Makefile | 1 + + security/keys/crypto/crypto_rsa.c | 282 +++++++++++++++++++++++++++++++++++++ + security/keys/crypto/public_key.h | 2 + + 4 files changed, 292 insertions(+) + create mode 100644 security/keys/crypto/crypto_rsa.c -diff --git a/security/keys/Kconfig b/security/keys/Kconfig -index 07c7f3b..65d640b 100644 ---- a/security/keys/Kconfig -+++ b/security/keys/Kconfig -@@ -86,3 +86,9 @@ config CRYPTO_KEY_PUBLIC_KEY_SUBTYPE +diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig +index 5f2b8ac..4e3777e 100644 +--- a/security/keys/crypto/Kconfig ++++ b/security/keys/crypto/Kconfig +@@ -15,3 +15,10 @@ config CRYPTO_KEY_PUBLIC_KEY_SUBTYPE If signature generation and/or verification are to be used, appropriate hash algorithms (such as SHA-1) must be available. ENOPKG will be reported if the requisite algorithm is unavailable. @@ -1591,24 +1616,23 @@ index 07c7f3b..65d640b 100644 +config CRYPTO_KEY_PKEY_ALGO_RSA + tristate "RSA public-key algorithm" + depends on CRYPTO_KEY_PUBLIC_KEY_SUBTYPE ++ select MPILIB_EXTRA + help + This option enables support for the RSA algorithm (PKCS#1, RFC3447). -diff --git a/security/keys/Makefile b/security/keys/Makefile -index dc3281f..59e7180 100644 ---- a/security/keys/Makefile -+++ b/security/keys/Makefile -@@ -26,5 +26,6 @@ obj-$(CONFIG_TRUSTED_KEYS) += trusted.o - obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ - obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o +diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile +index 6384306..b6b1a5a 100644 +--- a/security/keys/crypto/Makefile ++++ b/security/keys/crypto/Makefile +@@ -6,3 +6,4 @@ obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o + crypto_keys-y := crypto_type.o crypto_verify.o + obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o +obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o - - crypto_keys-y := crypto_type.o crypto_verify.o -diff --git a/security/keys/crypto_rsa.c b/security/keys/crypto_rsa.c +diff --git a/security/keys/crypto/crypto_rsa.c b/security/keys/crypto/crypto_rsa.c new file mode 100644 index 0000000..beb5181 --- /dev/null -+++ b/security/keys/crypto_rsa.c ++++ b/security/keys/crypto/crypto_rsa.c @@ -0,0 +1,282 @@ +/* RSA asymmetric public-key algorithm [RFC3447] + * @@ -1892,10 +1916,10 @@ index 0000000..beb5181 + .verify = RSA_verify_signature, +}; +EXPORT_SYMBOL_GPL(RSA_public_key_algorithm); -diff --git a/security/keys/public_key.h b/security/keys/public_key.h +diff --git a/security/keys/crypto/public_key.h b/security/keys/crypto/public_key.h index 81ed603..7913615 100644 ---- a/security/keys/public_key.h -+++ b/security/keys/public_key.h +--- a/security/keys/crypto/public_key.h ++++ b/security/keys/crypto/public_key.h @@ -42,6 +42,8 @@ struct public_key_algorithm { const struct public_key_signature *sig); }; @@ -1906,13 +1930,68 @@ index 81ed603..7913615 100644 * Asymmetric public key data */ -- -1.7.9.1 +1.7.10.2 -From 82b8d487e66a5218ca9f91ca406db97b2113da60 Mon Sep 17 00:00:00 2001 +From a1ac402f327ab537a629c4d365b3f5461eaecb82 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Wed, 7 Dec 2011 14:07:11 +0000 -Subject: PGPLIB: PGP definitions (RFC 4880) +Date: Fri, 4 May 2012 16:30:20 +0100 +Subject: [PATCH 09/36] Fix signature verification for shorter signatures + +gpg can produce a signature file where length of signature is less than the +modulus size because the amount of space an MPI takes up is kept as low as +possible by discarding leading zeros. This regularly happens for several +modules during the build. + +Fix it by relaxing check in RSA verification code. + +Thanks to Tomas Mraz and Miloslav Trmac for help. + +Signed-off-by: Milan Broz +Signed-off-by: David Howells +--- + security/keys/crypto/crypto_rsa.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/security/keys/crypto/crypto_rsa.c b/security/keys/crypto/crypto_rsa.c +index beb5181..cc5cd95 100644 +--- a/security/keys/crypto/crypto_rsa.c ++++ b/security/keys/crypto/crypto_rsa.c +@@ -219,15 +219,23 @@ static int RSA_verify_signature(const struct public_key *key, + kenter(""); + + /* (1) Check the signature size against the public key modulus size */ +- k = (mpi_get_nbits(key->rsa.n) + 7) / 8; ++ k = mpi_get_nbits(key->rsa.n); ++ tsize = mpi_get_nbits(sig->rsa.s); + +- tsize = (mpi_get_nbits(sig->rsa.s) + 7) / 8; ++ /* According to RFC 4880 sec 3.2, length of MPI is computed starting ++ * from most significant bit. So the RFC 3447 sec 8.2.2 size check ++ * must be relaxed to conform with shorter signatures - so we fail here ++ * only if signature length is longer than modulus size. ++ */ + pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize); +- if (tsize != k) { ++ if (k < tsize) { + ret = -EBADMSG; + goto error; + } + ++ /* Round up and convert to octets */ ++ k = (k + 7) / 8; ++ + /* (2b) Apply the RSAVP1 verification primitive to the public key */ + ret = RSAVP1(key, sig->rsa.s, &m); + if (ret < 0) +-- +1.7.10.2 + + +From d682ea629a2494aab705468d1479058a03fd7879 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 4 May 2012 16:30:23 +0100 +Subject: [PATCH 10/36] PGPLIB: PGP definitions (RFC 4880) Provide some useful PGP definitions from RFC 4880. These describe details of public key crypto as used by crypto keys for things like signature @@ -1921,7 +2000,7 @@ verification. Signed-off-by: David Howells --- include/linux/pgp.h | 206 +++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 files changed, 206 insertions(+), 0 deletions(-) + 1 file changed, 206 insertions(+) create mode 100644 include/linux/pgp.h diff --git a/include/linux/pgp.h b/include/linux/pgp.h @@ -2137,13 +2216,13 @@ index 0000000..1359f64 + +#endif /* _LINUX_PGP_H */ -- -1.7.9.1 +1.7.10.2 -From 570b106e22577e362c2772bdbfa1049c894b5cfb Mon Sep 17 00:00:00 2001 +From 651d6e549374b13b2d0473db17df90ab66abf855 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Wed, 7 Dec 2011 14:07:12 +0000 -Subject: PGPLIB: Basic packet parser +Date: Fri, 4 May 2012 16:33:28 +0100 +Subject: [PATCH 11/36] PGPLIB: Basic packet parser Provide a simple parser that extracts the packets from a PGP packet blob and passes the desirous ones to the given processor function: @@ -2164,12 +2243,12 @@ This is configured on with CONFIG_PGP_LIBRARY. Signed-off-by: David Howells --- - include/linux/pgp.h | 25 ++++ - security/keys/Kconfig | 6 + - security/keys/Makefile | 1 + - security/keys/pgp_library.c | 254 +++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 286 insertions(+), 0 deletions(-) - create mode 100644 security/keys/pgp_library.c + include/linux/pgp.h | 25 ++++ + security/keys/crypto/Kconfig | 6 + + security/keys/crypto/Makefile | 1 + + security/keys/crypto/pgp_library.c | 254 ++++++++++++++++++++++++++++++++++++ + 4 files changed, 286 insertions(+) + create mode 100644 security/keys/crypto/pgp_library.c diff --git a/include/linux/pgp.h b/include/linux/pgp.h index 1359f64..235270a 100644 @@ -2205,12 +2284,12 @@ index 1359f64..235270a 100644 + struct pgp_parse_pubkey *pk); + #endif /* _LINUX_PGP_H */ -diff --git a/security/keys/Kconfig b/security/keys/Kconfig -index 65d640b..aa3954c 100644 ---- a/security/keys/Kconfig -+++ b/security/keys/Kconfig -@@ -92,3 +92,9 @@ config CRYPTO_KEY_PKEY_ALGO_RSA - depends on CRYPTO_KEY_PUBLIC_KEY_SUBTYPE +diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig +index 4e3777e..88ce0e2 100644 +--- a/security/keys/crypto/Kconfig ++++ b/security/keys/crypto/Kconfig +@@ -22,3 +22,9 @@ config CRYPTO_KEY_PKEY_ALGO_RSA + select MPILIB_EXTRA help This option enables support for the RSA algorithm (PKCS#1, RFC3447). + @@ -2219,22 +2298,20 @@ index 65d640b..aa3954c 100644 + help + This option enables a library that provides a number of simple + utility functions for parsing PGP (RFC 4880) packet-based messages. -diff --git a/security/keys/Makefile b/security/keys/Makefile -index 59e7180..2dbbe6c 100644 ---- a/security/keys/Makefile -+++ b/security/keys/Makefile -@@ -27,5 +27,6 @@ obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/ - obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o +diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile +index b6b1a5a..5fbe54e 100644 +--- a/security/keys/crypto/Makefile ++++ b/security/keys/crypto/Makefile +@@ -7,3 +7,4 @@ crypto_keys-y := crypto_type.o crypto_verify.o + obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o +obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o - - crypto_keys-y := crypto_type.o crypto_verify.o -diff --git a/security/keys/pgp_library.c b/security/keys/pgp_library.c +diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c new file mode 100644 index 0000000..685660f --- /dev/null -+++ b/security/keys/pgp_library.c ++++ b/security/keys/crypto/pgp_library.c @@ -0,0 +1,254 @@ +/* PGP packet parser (RFC 4880) + * @@ -2491,13 +2568,13 @@ index 0000000..685660f +} +EXPORT_SYMBOL_GPL(pgp_parse_public_key); -- -1.7.9.1 +1.7.10.2 -From 194b547524cc4abf00e357948d949871d42bed84 Mon Sep 17 00:00:00 2001 +From 1123a360effa696546dbce1273c680b45c5cf946 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Wed, 7 Dec 2011 14:07:13 +0000 -Subject: PGPLIB: Signature parser +Date: Fri, 4 May 2012 16:33:30 +0100 +Subject: [PATCH 12/36] PGPLIB: Signature parser Provide some PGP signature parsing helpers: @@ -2515,9 +2592,9 @@ Provide some PGP signature parsing helpers: Signed-off-by: David Howells --- - include/linux/pgp.h | 24 ++++ - security/keys/pgp_library.c | 277 +++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 301 insertions(+), 0 deletions(-) + include/linux/pgp.h | 24 ++++ + security/keys/crypto/pgp_library.c | 277 ++++++++++++++++++++++++++++++++++++ + 2 files changed, 301 insertions(+) diff --git a/include/linux/pgp.h b/include/linux/pgp.h index 235270a..ab1a8fa 100644 @@ -2552,10 +2629,10 @@ index 235270a..ab1a8fa 100644 + struct pgp_sig_parameters *p); + #endif /* _LINUX_PGP_H */ -diff --git a/security/keys/pgp_library.c b/security/keys/pgp_library.c +diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c index 685660f..f6b831f 100644 ---- a/security/keys/pgp_library.c -+++ b/security/keys/pgp_library.c +--- a/security/keys/crypto/pgp_library.c ++++ b/security/keys/crypto/pgp_library.c @@ -252,3 +252,280 @@ int pgp_parse_public_key(const u8 **_data, size_t *_datalen, return 0; } @@ -2838,13 +2915,13 @@ index 685660f..f6b831f 100644 +} +EXPORT_SYMBOL_GPL(pgp_parse_sig_params); -- -1.7.9.1 +1.7.10.2 -From ee32f2d2d24a635e7bb46cbd37a0622850f4c66e Mon Sep 17 00:00:00 2001 +From 53f01a04d44b822af15cd31bb451ca13695bdf1c Mon Sep 17 00:00:00 2001 From: David Howells -Date: Wed, 7 Dec 2011 14:07:13 +0000 -Subject: KEYS: PGP data parser +Date: Fri, 4 May 2012 16:36:35 +0100 +Subject: [PATCH 13/36] KEYS: PGP data parser Implement a PGP data parser for the crypto key type to use when instantiating a key. @@ -2858,19 +2935,19 @@ appropriate handler routines (DSA or RSA) and attach it to the key. Signed-off-by: David Howells --- - security/keys/Kconfig | 12 ++ - security/keys/Makefile | 4 + - security/keys/pgp_key_parser.c | 343 ++++++++++++++++++++++++++++++++++++++++ - security/keys/pgp_parser.h | 23 +++ - 4 files changed, 382 insertions(+), 0 deletions(-) - create mode 100644 security/keys/pgp_key_parser.c - create mode 100644 security/keys/pgp_parser.h + security/keys/crypto/Kconfig | 12 ++ + security/keys/crypto/Makefile | 4 + + security/keys/crypto/pgp_key_parser.c | 343 +++++++++++++++++++++++++++++++++ + security/keys/crypto/pgp_parser.h | 23 +++ + 4 files changed, 382 insertions(+) + create mode 100644 security/keys/crypto/pgp_key_parser.c + create mode 100644 security/keys/crypto/pgp_parser.h -diff --git a/security/keys/Kconfig b/security/keys/Kconfig -index aa3954c..fd53028 100644 ---- a/security/keys/Kconfig -+++ b/security/keys/Kconfig -@@ -98,3 +98,15 @@ config PGP_LIBRARY +diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig +index 88ce0e2..1c2ae55 100644 +--- a/security/keys/crypto/Kconfig ++++ b/security/keys/crypto/Kconfig +@@ -28,3 +28,15 @@ config PGP_LIBRARY help This option enables a library that provides a number of simple utility functions for parsing PGP (RFC 4880) packet-based messages. @@ -2886,25 +2963,23 @@ index aa3954c..fd53028 100644 + This option provides support for parsing PGP (RFC 4880) format blobs + for key data and provides the ability to instantiate a crypto key + from a public key packet found inside the blob. -diff --git a/security/keys/Makefile b/security/keys/Makefile -index 2dbbe6c..416670c 100644 ---- a/security/keys/Makefile -+++ b/security/keys/Makefile -@@ -28,5 +28,9 @@ obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o +diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile +index 5fbe54e..3bb2e61 100644 +--- a/security/keys/crypto/Makefile ++++ b/security/keys/crypto/Makefile +@@ -8,3 +8,7 @@ crypto_keys-y := crypto_type.o crypto_verify.o obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o -+obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_parser.o - - crypto_keys-y := crypto_type.o crypto_verify.o + ++obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_parser.o +pgp_parser-y := \ + pgp_key_parser.o -diff --git a/security/keys/pgp_key_parser.c b/security/keys/pgp_key_parser.c +diff --git a/security/keys/crypto/pgp_key_parser.c b/security/keys/crypto/pgp_key_parser.c new file mode 100644 index 0000000..4efc4de --- /dev/null -+++ b/security/keys/pgp_key_parser.c ++++ b/security/keys/crypto/pgp_key_parser.c @@ -0,0 +1,343 @@ +/* Parser for PGP format key data [RFC 4880] + * @@ -3249,11 +3324,11 @@ index 0000000..4efc4de + +module_init(pgp_key_init); +module_exit(pgp_key_exit); -diff --git a/security/keys/pgp_parser.h b/security/keys/pgp_parser.h +diff --git a/security/keys/crypto/pgp_parser.h b/security/keys/crypto/pgp_parser.h new file mode 100644 index 0000000..1cda231 --- /dev/null -+++ b/security/keys/pgp_parser.h ++++ b/security/keys/crypto/pgp_parser.h @@ -0,0 +1,23 @@ +/* PGP crypto data parser internal definitions + * @@ -3279,13 +3354,13 @@ index 0000000..1cda231 +extern const +struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST]; -- -1.7.9.1 +1.7.10.2 -From 0e862034535288f2ee5653563178f6a6b99f8c47 Mon Sep 17 00:00:00 2001 +From 3e401cdc0ae1768ecbc301a631a2a34f56834313 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Wed, 7 Dec 2011 14:07:14 +0000 -Subject: KEYS: PGP-based public key signature verification +Date: Fri, 4 May 2012 16:40:17 +0100 +Subject: [PATCH 14/36] KEYS: PGP-based public key signature verification Provide handlers for PGP-based public-key algorithm signature verification. This does most of the work involved in signature verification as most of it is @@ -3297,27 +3372,27 @@ patch provides. Signed-off-by: David Howells --- - security/keys/Makefile | 3 +- - security/keys/pgp_parser.h | 6 + - security/keys/pgp_pubkey_sig.c | 323 ++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 331 insertions(+), 1 deletions(-) - create mode 100644 security/keys/pgp_pubkey_sig.c + security/keys/crypto/Makefile | 3 +- + security/keys/crypto/pgp_parser.h | 6 + + security/keys/crypto/pgp_pubkey_sig.c | 323 +++++++++++++++++++++++++++++++++ + 3 files changed, 331 insertions(+), 1 deletion(-) + create mode 100644 security/keys/crypto/pgp_pubkey_sig.c -diff --git a/security/keys/Makefile b/security/keys/Makefile -index 416670c..24e83a2 100644 ---- a/security/keys/Makefile -+++ b/security/keys/Makefile -@@ -33,4 +33,5 @@ obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_parser.o - crypto_keys-y := crypto_type.o crypto_verify.o +diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile +index 3bb2e61..d4ac8ac 100644 +--- a/security/keys/crypto/Makefile ++++ b/security/keys/crypto/Makefile +@@ -11,4 +11,5 @@ obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o + obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_parser.o pgp_parser-y := \ - pgp_key_parser.o + pgp_key_parser.o \ + pgp_pubkey_sig.o -diff --git a/security/keys/pgp_parser.h b/security/keys/pgp_parser.h +diff --git a/security/keys/crypto/pgp_parser.h b/security/keys/crypto/pgp_parser.h index 1cda231..a6192ce 100644 ---- a/security/keys/pgp_parser.h -+++ b/security/keys/pgp_parser.h +--- a/security/keys/crypto/pgp_parser.h ++++ b/security/keys/crypto/pgp_parser.h @@ -21,3 +21,9 @@ */ extern const @@ -3328,11 +3403,11 @@ index 1cda231..a6192ce 100644 + */ +extern struct crypto_key_verify_context *pgp_pkey_verify_sig_begin( + struct key *crypto_key, const u8 *sigdata, size_t siglen); -diff --git a/security/keys/pgp_pubkey_sig.c b/security/keys/pgp_pubkey_sig.c +diff --git a/security/keys/crypto/pgp_pubkey_sig.c b/security/keys/crypto/pgp_pubkey_sig.c new file mode 100644 index 0000000..b4b7cb0 --- /dev/null -+++ b/security/keys/pgp_pubkey_sig.c ++++ b/security/keys/crypto/pgp_pubkey_sig.c @@ -0,0 +1,323 @@ +/* Handling for PGP public key signature data [RFC 4880] + * @@ -3658,13 +3733,13 @@ index 0000000..b4b7cb0 + kleave(""); +} -- -1.7.9.1 +1.7.10.2 -From b8d572f41734596c3abbd15b1d2e30f5fa603c01 Mon Sep 17 00:00:00 2001 +From 55e67eca050ff43915912e50dda49ecafdc816aa Mon Sep 17 00:00:00 2001 From: David Howells -Date: Wed, 7 Dec 2011 14:07:15 +0000 -Subject: KEYS: PGP format signature parser +Date: Fri, 4 May 2012 16:40:39 +0100 +Subject: [PATCH 15/36] KEYS: PGP format signature parser Implement a signature parser that will attempt to parse a signature blob as a PGP packet format message. If it can, it will find an appropriate crypto key @@ -3672,27 +3747,27 @@ and set the public-key algorithm according to the data in the signature. Signed-off-by: David Howells --- - security/keys/Makefile | 1 + - security/keys/pgp_key_parser.c | 1 + - security/keys/pgp_parser.h | 6 ++ - security/keys/pgp_sig_parser.c | 104 ++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 112 insertions(+), 0 deletions(-) - create mode 100644 security/keys/pgp_sig_parser.c + security/keys/crypto/Makefile | 1 + + security/keys/crypto/pgp_key_parser.c | 1 + + security/keys/crypto/pgp_parser.h | 6 ++ + security/keys/crypto/pgp_sig_parser.c | 104 +++++++++++++++++++++++++++++++++ + 4 files changed, 112 insertions(+) + create mode 100644 security/keys/crypto/pgp_sig_parser.c -diff --git a/security/keys/Makefile b/security/keys/Makefile -index 24e83a2..9aa48fe 100644 ---- a/security/keys/Makefile -+++ b/security/keys/Makefile -@@ -34,4 +34,5 @@ crypto_keys-y := crypto_type.o crypto_verify.o - +diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile +index d4ac8ac..fa7746d 100644 +--- a/security/keys/crypto/Makefile ++++ b/security/keys/crypto/Makefile +@@ -12,4 +12,5 @@ obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o + obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_parser.o pgp_parser-y := \ pgp_key_parser.o \ + pgp_sig_parser.o \ pgp_pubkey_sig.o -diff --git a/security/keys/pgp_key_parser.c b/security/keys/pgp_key_parser.c +diff --git a/security/keys/crypto/pgp_key_parser.c b/security/keys/crypto/pgp_key_parser.c index 4efc4de..1407e2e 100644 ---- a/security/keys/pgp_key_parser.c -+++ b/security/keys/pgp_key_parser.c +--- a/security/keys/crypto/pgp_key_parser.c ++++ b/security/keys/crypto/pgp_key_parser.c @@ -324,6 +324,7 @@ static struct crypto_key_parser pgp_key_parser = { .owner = THIS_MODULE, .name = "pgp", @@ -3701,10 +3776,10 @@ index 4efc4de..1407e2e 100644 }; /* -diff --git a/security/keys/pgp_parser.h b/security/keys/pgp_parser.h +diff --git a/security/keys/crypto/pgp_parser.h b/security/keys/crypto/pgp_parser.h index a6192ce..73c900e 100644 ---- a/security/keys/pgp_parser.h -+++ b/security/keys/pgp_parser.h +--- a/security/keys/crypto/pgp_parser.h ++++ b/security/keys/crypto/pgp_parser.h @@ -23,6 +23,12 @@ extern const struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST]; @@ -3718,11 +3793,11 @@ index a6192ce..73c900e 100644 * pgp_pubkey_sig.c */ extern struct crypto_key_verify_context *pgp_pkey_verify_sig_begin( -diff --git a/security/keys/pgp_sig_parser.c b/security/keys/pgp_sig_parser.c +diff --git a/security/keys/crypto/pgp_sig_parser.c b/security/keys/crypto/pgp_sig_parser.c new file mode 100644 index 0000000..b72c505 --- /dev/null -+++ b/security/keys/pgp_sig_parser.c ++++ b/security/keys/crypto/pgp_sig_parser.c @@ -0,0 +1,104 @@ +/* Handling for PGP public key signature data [RFC 4880] + * @@ -3829,13 +3904,14 @@ index 0000000..b72c505 + return ctx; +} -- -1.7.9.1 +1.7.10.2 -From e25da6c545204746a8011dc27ce179816f715449 Mon Sep 17 00:00:00 2001 +From 0760cf6519e184298944df0d9f6fe5a097fb16ff Mon Sep 17 00:00:00 2001 From: David Howells -Date: Wed, 7 Dec 2011 14:07:16 +0000 -Subject: KEYS: Provide a function to load keys from a PGP keyring blob +Date: Fri, 4 May 2012 16:41:12 +0100 +Subject: [PATCH 16/36] KEYS: Provide a function to load keys from a PGP + keyring blob Provide a function to load keys from a PGP keyring blob for use in initialising the module signing key keyring: @@ -3857,12 +3933,12 @@ Looking as root in /proc/keys after the module signing keyring has been loaded: Signed-off-by: David Howells --- Documentation/security/keys-crypto.txt | 20 +++++++ - include/keys/crypto-type.h | 3 + - security/keys/Kconfig | 9 +++ - security/keys/Makefile | 1 + - security/keys/pgp_preload.c | 90 ++++++++++++++++++++++++++++++++ - 5 files changed, 123 insertions(+), 0 deletions(-) - create mode 100644 security/keys/pgp_preload.c + include/keys/crypto-type.h | 3 ++ + security/keys/crypto/Kconfig | 9 ++++ + security/keys/crypto/Makefile | 1 + + security/keys/crypto/pgp_preload.c | 90 ++++++++++++++++++++++++++++++++ + 5 files changed, 123 insertions(+) + create mode 100644 security/keys/crypto/pgp_preload.c diff --git a/Documentation/security/keys-crypto.txt b/Documentation/security/keys-crypto.txt index a964717..ba2ab55 100644 @@ -3911,11 +3987,11 @@ index 6b93366..710e77f 100644 + struct key *keyring, const char *descprefix); + #endif /* _KEYS_CRYPTO_TYPE_H */ -diff --git a/security/keys/Kconfig b/security/keys/Kconfig -index fd53028..5e77c2a 100644 ---- a/security/keys/Kconfig -+++ b/security/keys/Kconfig -@@ -110,3 +110,12 @@ config CRYPTO_KEY_PGP_PARSER +diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig +index 1c2ae55..8af0155 100644 +--- a/security/keys/crypto/Kconfig ++++ b/security/keys/crypto/Kconfig +@@ -40,3 +40,12 @@ config CRYPTO_KEY_PGP_PARSER This option provides support for parsing PGP (RFC 4880) format blobs for key data and provides the ability to instantiate a crypto key from a public key packet found inside the blob. @@ -3928,23 +4004,23 @@ index fd53028..5e77c2a 100644 + This option provides a facility for the kernel to preload PGP-wrapped + bundles of keys during boot. It is used by module signing to load + the module signing keys for example. -diff --git a/security/keys/Makefile b/security/keys/Makefile -index 9aa48fe..5a43bdb 100644 ---- a/security/keys/Makefile -+++ b/security/keys/Makefile -@@ -28,6 +28,7 @@ obj-$(CONFIG_CRYPTO_KEY_TYPE) += crypto_keys.o +diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile +index fa7746d..4162ecb 100644 +--- a/security/keys/crypto/Makefile ++++ b/security/keys/crypto/Makefile +@@ -8,6 +8,7 @@ crypto_keys-y := crypto_type.o crypto_verify.o obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o +obj-$(CONFIG_PGP_PRELOAD) += pgp_preload.o - obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_parser.o - crypto_keys-y := crypto_type.o crypto_verify.o -diff --git a/security/keys/pgp_preload.c b/security/keys/pgp_preload.c + obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_parser.o + pgp_parser-y := \ +diff --git a/security/keys/crypto/pgp_preload.c b/security/keys/crypto/pgp_preload.c new file mode 100644 index 0000000..25154e3 --- /dev/null -+++ b/security/keys/pgp_preload.c ++++ b/security/keys/crypto/pgp_preload.c @@ -0,0 +1,90 @@ +/* Cryptographic key request handling + * @@ -4037,13 +4113,87 @@ index 0000000..25154e3 + return pgp_parse_packets(pgpdata, pgpdatalen, &ctx.pgp); +} -- -1.7.9.1 +1.7.10.2 -From dad531381fad892fda776ddb354e1eb936b46b62 Mon Sep 17 00:00:00 2001 +From 8f7d6b082b6b7357e44f9345c8c040f53aa60a7f Mon Sep 17 00:00:00 2001 From: David Howells -Date: Wed, 7 Dec 2011 14:07:16 +0000 -Subject: MODSIGN: Add indications of module ELF types +Date: Thu, 10 May 2012 23:46:56 +0100 +Subject: [PATCH 17/36] Provide macros for forming the name of an ELF note and + its section + +Provide macros for stringifying the name of an ELF note and its section +appropriately so that the macro can be used in both C and assembly. + +Signed-off-by: David Howells +--- + include/linux/elfnote.h | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/include/linux/elfnote.h b/include/linux/elfnote.h +index 278e3ef..949d494 100644 +--- a/include/linux/elfnote.h ++++ b/include/linux/elfnote.h +@@ -58,6 +58,7 @@ + ELFNOTE_END + + #else /* !__ASSEMBLER__ */ ++#include + #include + /* + * Use an anonymous structure which matches the shape of +@@ -93,6 +94,9 @@ + + #define ELFNOTE32(name, type, desc) ELFNOTE(32, name, type, desc) + #define ELFNOTE64(name, type, desc) ELFNOTE(64, name, type, desc) ++ ++#define ELFNOTE_NAME(name) __stringify(name) ++#define ELFNOTE_SECTION(name) ".note."ELFNOTE_NAME(name) + #endif /* __ASSEMBLER__ */ + + #endif /* _LINUX_ELFNOTE_H */ +-- +1.7.10.2 + + +From b37a512b3d6593d541e05550316bd407515c1ec2 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 10 May 2012 23:49:44 +0100 +Subject: [PATCH 18/36] Guard check in module loader against integer overflow + +The check: + + if (len < hdr->e_shoff + hdr->e_shnum * sizeof(Elf_Shdr)) + +may not work if there's an overflow in the right-hand side of the condition. + +Signed-off-by: David Howells +--- + kernel/module.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/kernel/module.c b/kernel/module.c +index 78ac6ec..377cb06 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -2429,7 +2429,8 @@ static int copy_and_check(struct load_info *info, + goto free_hdr; + } + +- if (len < hdr->e_shoff + hdr->e_shnum * sizeof(Elf_Shdr)) { ++ if (hdr->e_shoff >= len || ++ hdr->e_shnum * sizeof(Elf_Shdr) > len - hdr->e_shoff) { + err = -ENOEXEC; + goto free_hdr; + } +-- +1.7.10.2 + + +From a7f2ec2a77490ed84bf8020cd5b41d7c7ea3f3cb Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 10 May 2012 23:49:52 +0100 +Subject: [PATCH 19/36] MODSIGN: Add indications of module ELF types Add per-arch indications of module ELF types and relocation table entry types. @@ -4060,8 +4210,9 @@ Signed-Off-By: David Howells arch/parisc/include/asm/module.h | 8 ++++++++ arch/powerpc/include/asm/module.h | 10 ++++++++++ arch/s390/include/asm/module.h | 3 +++ + arch/x86/include/asm/module.h | 6 ++++++ include/asm-generic/module.h | 10 ++++++++++ - 12 files changed, 74 insertions(+), 2 deletions(-) + 13 files changed, 80 insertions(+), 2 deletions(-) diff --git a/arch/alpha/include/asm/module.h b/arch/alpha/include/asm/module.h index 7b63743..3d5a3ea 100644 @@ -4194,7 +4345,7 @@ index edffe66..9e2cd74 100644 #endif /* _ASM_M68K_MODULE_H */ diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h -index bc01a02..73c71a2 100644 +index 7467d1d..4404cca 100644 --- a/arch/mips/include/asm/module.h +++ b/arch/mips/include/asm/module.h @@ -33,11 +33,15 @@ typedef struct { @@ -4314,6 +4465,21 @@ index 1cc1c5a..b64dab0 100644 #define Elf_Rela ElfW(Rela) #define Elf_Shdr ElfW(Shdr) #define Elf_Sym ElfW(Sym) +diff --git a/arch/x86/include/asm/module.h b/arch/x86/include/asm/module.h +index 9eae775..724f173 100644 +--- a/arch/x86/include/asm/module.h ++++ b/arch/x86/include/asm/module.h +@@ -63,4 +63,10 @@ + # define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY + #endif + ++#ifdef CONFIG_X86_32 ++#define MODULE_HAS_ELF_REL_ONLY ++#else ++#define MODULE_HAS_ELF_RELA_ONLY ++#endif ++ + #endif /* _ASM_X86_MODULE_H */ diff --git a/include/asm-generic/module.h b/include/asm-generic/module.h index ed5b44d..e053617b 100644 --- a/include/asm-generic/module.h @@ -4343,784 +4509,29 @@ index ed5b44d..e053617b 100644 #endif /* __ASM_GENERIC_MODULE_H */ -- -1.7.9.1 +1.7.10.2 - -From a66294fc859a6a9374a6d873d8a6ca3ec683538f Mon Sep 17 00:00:00 2001 +From b31d1ea8afb0b63e872a1bed3a3c88d7696bf2e7 Mon Sep 17 00:00:00 2001 From: David Howells -Date: Wed, 7 Dec 2011 14:07:17 +0000 -Subject: MODSIGN: Module ELF verifier +Date: Thu, 10 May 2012 23:49:53 +0100 +Subject: [PATCH 20/36] MODSIGN: Provide gitignore and make clean rules for + extra files -Do preliminary verification of the ELF structure of a module. This is used to -make sure that the ELF structure can then be used to check the module signature -and access the module data without breaking the module loader. +Provide gitignore and make clean rules for extra files to hide and clean up the +extra files produced by module signing stuff once it is added. Also add a +clean up rule for the module content extractor program used to extract the data +to be signed. -If the module's ELF metadata is determined to be bad, then ELIBBAD will be -returned and a message will be logged to the kernel log. - -Signed-Off-By: David Howells - -Rebased-to-3.3-rc6: Josh Boyer +Signed-off-by: David Howells --- - init/Kconfig | 11 ++ - kernel/Makefile | 2 + - kernel/module-verify-elf.c | 344 ++++++++++++++++++++++++++++++++++++++++++++ - kernel/module-verify.c | 41 ++++++ - kernel/module-verify.h | 53 +++++++ - kernel/module.c | 6 + - 6 files changed, 457 insertions(+), 0 deletions(-) - create mode 100644 kernel/module-verify-elf.c - create mode 100644 kernel/module-verify.c - create mode 100644 kernel/module-verify.h - -diff --git a/init/Kconfig b/init/Kconfig -index 3f42cd6..61b5f03 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -1418,6 +1418,17 @@ config MODULE_SRCVERSION_ALL - the version). With this option, such a "srcversion" field - will be created for all modules. If unsure, say N. - -+config MODULE_VERIFY_ELF -+ bool "Module ELF structure verification" -+ depends on MODULES -+ help -+ Check ELF structure of modules upon load -+ -+config MODULE_VERIFY -+ bool -+ depends on MODULES -+ default y if MODULE_VERIFY_ELF -+ - endif # MODULES - - config INIT_ALL_POSSIBLE -diff --git a/kernel/Makefile b/kernel/Makefile -index 2d9de86..77b7a39 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -52,6 +52,8 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o - obj-$(CONFIG_PROVE_LOCKING) += spinlock.o - obj-$(CONFIG_UID16) += uid16.o - obj-$(CONFIG_MODULES) += module.o -+obj-$(CONFIG_MODULE_VERIFY) += module-verify.o -+obj-$(CONFIG_MODULE_VERIFY_ELF) += module-verify-elf.o - obj-$(CONFIG_KALLSYMS) += kallsyms.o - obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o - obj-$(CONFIG_KEXEC) += kexec.o -diff --git a/kernel/module-verify-elf.c b/kernel/module-verify-elf.c -new file mode 100644 -index 0000000..4dea8d0 ---- /dev/null -+++ b/kernel/module-verify-elf.c -@@ -0,0 +1,344 @@ -+/* module-verify-elf.c: module ELF verifier -+ * -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "module-verify.h" -+ -+#if 0 -+#define _debug(FMT, ...) printk(FMT, ##__VA_ARGS__) -+#else -+#define _debug(FMT, ...) do {} while (0) -+#endif -+ -+/* -+ * verify the ELF structure of a module -+ */ -+int module_verify_elf(struct module_verify_data *mvdata) -+{ -+ const struct elf_note *note; -+ const Elf_Ehdr *hdr = mvdata->hdr; -+ const Elf_Shdr *section, *section2, *secstop; -+ const Elf_Rela *relas, *rela, *relastop; -+ const Elf_Rel *rels, *rel, *relstop; -+ const Elf_Sym *symbol, *symstop; -+ const void *start, *p, *stop; -+ const char *q, *qs; -+ size_t size, sssize, *secsize, tmp, tmp2; -+ long last; -+ int line; -+ -+ size = mvdata->size; -+ mvdata->nsects = hdr->e_shnum; -+ -+#define elfcheck(X) \ -+do { if (unlikely(!(X))) { line = __LINE__; goto elfcheck_error; } } while(0) -+ -+#define seccheck(X) \ -+do { if (unlikely(!(X))) { line = __LINE__; goto seccheck_error; } } while(0) -+ -+#define symcheck(X) \ -+do { if (unlikely(!(X))) { line = __LINE__; goto symcheck_error; } } while(0) -+ -+#define relcheck(X) \ -+do { if (unlikely(!(X))) { line = __LINE__; goto relcheck_error; } } while(0) -+ -+#define relacheck(X) \ -+do { if (unlikely(!(X))) { line = __LINE__; goto relacheck_error; } } while(0) -+ -+#define notecheck(X) \ -+do { if (unlikely(!(X))) { line = __LINE__; goto notecheck_error; } } while(0) -+ -+ /* validate the ELF header */ -+ elfcheck(hdr->e_ehsize < size); -+ /*elfcheck(hdr->e_entry == 0);*/ -+ elfcheck(hdr->e_phoff == 0); -+ elfcheck(hdr->e_phnum == 0); -+ -+ elfcheck(hdr->e_shnum < SHN_LORESERVE); -+ elfcheck(hdr->e_shoff < size); -+ elfcheck(hdr->e_shoff >= hdr->e_ehsize); -+ elfcheck((hdr->e_shoff & (sizeof(long) - 1)) == 0); -+ elfcheck(hdr->e_shstrndx > 0); -+ elfcheck(hdr->e_shstrndx < hdr->e_shnum); -+ elfcheck(hdr->e_shentsize == sizeof(Elf_Shdr)); -+ -+ tmp = (size_t) hdr->e_shentsize * (size_t) hdr->e_shnum; -+ elfcheck(tmp <= size - hdr->e_shoff); -+ -+ /* allocate a table to hold in-file section sizes */ -+ mvdata->secsizes = kcalloc(hdr->e_shnum, sizeof(size_t), GFP_KERNEL); -+ if (!mvdata->secsizes) -+ return -ENOMEM; -+ -+ /* validate the ELF section headers */ -+ mvdata->sections = mvdata->buffer + hdr->e_shoff; -+ secstop = mvdata->sections + mvdata->nsects; -+ -+ sssize = mvdata->sections[hdr->e_shstrndx].sh_size; -+ elfcheck(sssize > 0); -+ -+ section = mvdata->sections; -+ seccheck(section->sh_type == SHT_NULL); -+ seccheck(section->sh_size == 0); -+ seccheck(section->sh_offset == 0); -+ -+ secsize = mvdata->secsizes + 1; -+ for (section++; section < secstop; secsize++, section++) { -+ seccheck(section->sh_name < sssize); -+ seccheck(section->sh_link < hdr->e_shnum); -+ -+ if (section->sh_entsize > 0) -+ seccheck(section->sh_size % section->sh_entsize == 0); -+ -+ seccheck(section->sh_offset >= hdr->e_ehsize); -+ seccheck(section->sh_offset < size); -+ -+ /* determine the section's in-file size */ -+ tmp = size - section->sh_offset; -+ if (section->sh_offset < hdr->e_shoff) -+ tmp = hdr->e_shoff - section->sh_offset; -+ -+ for (section2 = mvdata->sections + 1; -+ section2 < secstop; -+ section2++) { -+ if (section->sh_offset < section2->sh_offset) { -+ tmp2 = section2->sh_offset - -+ section->sh_offset; -+ if (tmp2 < tmp) -+ tmp = tmp2; -+ } -+ } -+ *secsize = tmp; -+ -+ _debug("Section %ld: %zx bytes at %lx\n", -+ section - mvdata->sections, -+ *secsize, -+ (unsigned long) section->sh_offset); -+ -+ /* perform section type specific checks */ -+ switch (section->sh_type) { -+ case SHT_NOBITS: -+ break; -+ -+ case SHT_REL: -+ seccheck(section->sh_entsize == sizeof(Elf_Rel)); -+ goto more_rel_checks; -+ -+ case SHT_RELA: -+ seccheck(section->sh_entsize == sizeof(Elf_Rela)); -+ more_rel_checks: -+ seccheck(section->sh_info > 0); -+ seccheck(section->sh_info < hdr->e_shnum); -+ goto more_sec_checks; -+ -+ case SHT_SYMTAB: -+ seccheck(section->sh_entsize == sizeof(Elf_Sym)); -+ goto more_sec_checks; -+ -+ default: -+ more_sec_checks: -+ /* most types of section must be contained entirely -+ * within the file */ -+ seccheck(section->sh_size <= *secsize); -+ break; -+ } -+ } -+ -+ /* validate the ELF section names */ -+ section = &mvdata->sections[hdr->e_shstrndx]; -+ -+ seccheck(section->sh_offset != hdr->e_shoff); -+ -+ mvdata->secstrings = mvdata->buffer + section->sh_offset; -+ -+ last = -1; -+ for (section = mvdata->sections + 1; section < secstop; section++) { -+ const char *secname; -+ tmp = sssize - section->sh_name; -+ secname = mvdata->secstrings + section->sh_name; -+ seccheck(secname[0] != 0); -+ if (section->sh_name > last) -+ last = section->sh_name; -+ } -+ -+ if (last > -1) { -+ tmp = sssize - last; -+ elfcheck(memchr(mvdata->secstrings + last, 0, tmp) != NULL); -+ } -+ -+ /* look for various sections in the module */ -+ for (section = mvdata->sections + 1; section < secstop; section++) { -+ switch (section->sh_type) { -+ case SHT_SYMTAB: -+ if (strcmp(mvdata->secstrings + section->sh_name, -+ ".symtab") == 0 -+ ) { -+ seccheck(mvdata->symbols == NULL); -+ mvdata->symbols = -+ mvdata->buffer + section->sh_offset; -+ mvdata->nsyms = -+ section->sh_size / sizeof(Elf_Sym); -+ seccheck(section->sh_size > 0); -+ } -+ break; -+ -+ case SHT_STRTAB: -+ if (strcmp(mvdata->secstrings + section->sh_name, -+ ".strtab") == 0 -+ ) { -+ seccheck(mvdata->strings == NULL); -+ mvdata->strings = -+ mvdata->buffer + section->sh_offset; -+ sssize = mvdata->nstrings = section->sh_size; -+ seccheck(section->sh_size > 0); -+ } -+ break; -+ } -+ } -+ -+ if (!mvdata->symbols) { -+ printk("Couldn't locate module symbol table\n"); -+ goto format_error; -+ } -+ -+ if (!mvdata->strings) { -+ printk("Couldn't locate module strings table\n"); -+ goto format_error; -+ } -+ -+ /* validate the symbol table */ -+ symstop = mvdata->symbols + mvdata->nsyms; -+ -+ symbol = mvdata->symbols; -+ symcheck(ELF_ST_TYPE(symbol[0].st_info) == STT_NOTYPE); -+ symcheck(symbol[0].st_shndx == SHN_UNDEF); -+ symcheck(symbol[0].st_value == 0); -+ symcheck(symbol[0].st_size == 0); -+ -+ last = -1; -+ for (symbol++; symbol < symstop; symbol++) { -+ symcheck(symbol->st_name < sssize); -+ if (symbol->st_name > last) -+ last = symbol->st_name; -+ symcheck(symbol->st_shndx < mvdata->nsects || -+ symbol->st_shndx >= SHN_LORESERVE); -+ } -+ -+ if (last > -1) { -+ tmp = sssize - last; -+ elfcheck(memchr(mvdata->strings + last, 0, tmp) != NULL); -+ } -+ -+ /* validate each relocation table and note list as best we can */ -+ for (section = mvdata->sections + 1; section < secstop; section++) { -+ section2 = mvdata->sections + section->sh_info; -+ start = mvdata->buffer + section->sh_offset; -+ stop = start + section->sh_size; -+ -+ switch (section->sh_type) { -+ case SHT_REL: -+ rels = start; -+ relstop = stop; -+ -+ for (rel = rels; rel < relstop; rel++) { -+ relcheck(rel->r_offset < section2->sh_size); -+ relcheck(ELF_R_SYM(rel->r_info) < -+ mvdata->nsyms); -+ } -+ -+ break; -+ -+ case SHT_RELA: -+ relas = start; -+ relastop = stop; -+ -+ for (rela = relas; rela < relastop; rela++) { -+ relacheck(rela->r_offset < section2->sh_size); -+ relacheck(ELF_R_SYM(rela->r_info) < -+ mvdata->nsyms); -+ } -+ -+ break; -+ -+ case SHT_NOTE: -+ p = start; -+ while (p < stop) { -+ note = p; -+ notecheck(stop - p >= sizeof(*note)); -+ p += sizeof(*note); -+ tmp = note->n_namesz; -+ if (tmp > 0) { -+ notecheck(stop - p >= tmp); -+ qs = p + tmp - 1; -+ notecheck(*qs == '\0'); -+ for (q = p; q < qs; q++) -+ notecheck(*q != '\0'); -+ tmp = roundup(tmp, 4); -+ notecheck(stop - p >= tmp); -+ p += tmp; -+ } -+ tmp = note->n_descsz; -+ if (tmp > 0) { -+ notecheck(stop - p >= tmp); -+ tmp = roundup(tmp, 4); -+ notecheck(stop - p >= tmp); -+ p += tmp; -+ } -+ } -+ seccheck(p == stop); -+ break; -+ -+ default: -+ break; -+ } -+ } -+ -+ _debug("ELF okay\n"); -+ return 0; -+ -+elfcheck_error: -+ printk("Verify ELF error (assertion %d)\n", line); -+ goto format_error; -+ -+seccheck_error: -+ printk("Verify ELF error [sec %ld] (assertion %d)\n", -+ (long)(section - mvdata->sections), line); -+ goto format_error; -+ -+symcheck_error: -+ printk("Verify ELF error [sym %ld] (assertion %d)\n", -+ (long)(symbol - mvdata->symbols), line); -+ goto format_error; -+ -+relcheck_error: -+ printk("Verify ELF error [sec %ld rel %ld] (assertion %d)\n", -+ (long)(section - mvdata->sections), -+ (long)(rel - rels), line); -+ goto format_error; -+ -+relacheck_error: -+ printk("Verify ELF error [sec %ld rela %ld] (assertion %d)\n", -+ (long)(section - mvdata->sections), -+ (long)(rela - relas), line); -+ goto format_error; -+ -+notecheck_error: -+ printk("Verify ELF error [sec %ld note %ld] (assertion %d)\n", -+ (long)(section - mvdata->sections), -+ (long)(p - start), line); -+ goto format_error; -+ -+format_error: -+ return -ELIBBAD; -+} -diff --git a/kernel/module-verify.c b/kernel/module-verify.c -new file mode 100644 -index 0000000..875279f ---- /dev/null -+++ b/kernel/module-verify.c -@@ -0,0 +1,41 @@ -+/* module-verify.c: module verifier -+ * -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include "module-verify.h" -+ -+/* -+ * verify a module's integrity -+ * - check the ELF is viable -+ */ -+int module_verify(const Elf_Ehdr *hdr, size_t size) -+{ -+ struct module_verify_data mvdata; -+ int ret; -+ -+ memset(&mvdata, 0, sizeof(mvdata)); -+ mvdata.buffer = hdr; -+ mvdata.hdr = hdr; -+ mvdata.size = size; -+ -+ ret = module_verify_elf(&mvdata); -+ if (ret < 0) { -+ if (ret == -ELIBBAD) -+ printk("Module failed ELF checks\n"); -+ goto error; -+ } -+ -+error: -+ kfree(mvdata.secsizes); -+ kfree(mvdata.canonlist); -+ return ret; -+} -diff --git a/kernel/module-verify.h b/kernel/module-verify.h -new file mode 100644 -index 0000000..20884fc ---- /dev/null -+++ b/kernel/module-verify.h -@@ -0,0 +1,53 @@ -+/* module-verify.h: module verification definitions -+ * -+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ */ -+ -+#include -+#include -+ -+#ifdef CONFIG_MODULE_VERIFY -+struct module_verify_data { -+ const void *buffer; /* module buffer */ -+ const Elf_Ehdr *hdr; /* ELF header */ -+ const Elf_Shdr *sections; /* ELF section table */ -+ const Elf_Sym *symbols; /* ELF symbol table */ -+ const char *secstrings; /* ELF section string table */ -+ const char *strings; /* ELF string table */ -+ size_t *secsizes; /* section size list */ -+ size_t size; /* module object size */ -+ size_t nsects; /* number of sections */ -+ size_t nsyms; /* number of symbols */ -+ size_t nstrings; /* size of strings section */ -+ size_t signed_size; /* count of bytes contributed to digest */ -+ int *canonlist; /* list of canonicalised sections */ -+ int *canonmap; /* section canonicalisation map */ -+ int ncanon; /* number of canonicalised sections */ -+ int sig_index; /* module signature section index */ -+ uint8_t xcsum; /* checksum of bytes contributed to digest */ -+ uint8_t csum; /* checksum of bytes representing a section */ -+}; -+ -+/* -+ * module-verify.c -+ */ -+extern int module_verify(const Elf_Ehdr *hdr, size_t size); -+ -+/* -+ * module-verify-elf.c -+ */ -+#ifdef CONFIG_MODULE_VERIFY_ELF -+extern int module_verify_elf(struct module_verify_data *mvdata); -+#else -+#define module_verify_elf(m) (0) -+#endif -+ -+#else -+#define module_verify(h, s) (0) -+#endif -diff --git a/kernel/module.c b/kernel/module.c -index 2c93276..54d6910 100644 ---- a/kernel/module.c -+++ b/kernel/module.c -@@ -58,6 +58,7 @@ - #include - #include - #include -+#include "module-verify.h" - - #define CREATE_TRACE_POINTS - #include -@@ -2404,6 +2405,11 @@ static int copy_and_check(struct load_info *info, - goto free_hdr; - } - -+ /* Verify the module's contents */ -+ err = module_verify(hdr, len); -+ if (err < 0) -+ goto free_hdr; -+ - info->hdr = hdr; - info->len = len; - return 0; --- -1.7.9.1 - - -From 1ecd333ad910d539e75f8f85d1fb1e3d87547c4e Mon Sep 17 00:00:00 2001 -From: David Howells -Date: Wed, 7 Dec 2011 14:07:18 +0000 -Subject: MODSIGN: Apply signature checking to modules on module load - -Apply signature checking to modules on module load, checking the signature -against the ring of public keys compiled into the kernel (if enabled by -CONFIG_MODULE_SIG). Turning on signature checking will also force the module's -ELF metadata to be verified first. - -These patches have been in use by RHEL and Fedora kernels for years, and so -have been thoroughly tested. The signed modules survive both the debuginfo -separation performed by rpmbuild and the strip performed when modules are being -reduced as much as possible before being included in an initial ramdisk -composition. Signed modules have been tested to work with LE and BE, 32- and -64-bit arch kernels, including i386, x86_64, ppc64, ia64, s390 and s390x. - -There are several reasons why these patches are useful, amongst which are: - - (1) to protect against accidentally-corrupted modules causing damage; - - (2) to protect against maliciously modified modules causing damage; - - (3) to allow a sysadmin (or more likely an IT department) to enforce a policy - that only known and approved modules shall be loaded onto machines which - they're expected to support; - - (4) to allow other support providers to do likewise, or at least to _detect_ - the fact that unsupported modules are loaded; - - (5) to allow the detection of modules replaced by a second-order distro or a - preloaded Linux purveyor. - -These patches have two main appeals: (a) preventing malicious modules from -being loaded, and (b) reducing support workload by pointing out modules on a -crashing box that aren't what they're expected to be. - -Now, this is not a complete solution by any means: the core kernel is not -protected, and nor are /dev/mem or /dev/kmem, but it denies (or at least -controls) one relatively simple attack vector. - -This facility is optional: the builder of a kernel is by no means under any -requirement to actually enable it, let alone force the set of loadable modules -to be restricted to just those that the builder provides (there are degrees of -restriction available). - -Use of the module signing facility is documentated in: - - Documentation/module-signing.txt - -which I've included here for reference: - - ============================== - KERNEL MODULE SIGNING FACILITY - ============================== - -The module signing facilitiy applies cryptographic signature checking to -modules on module load, checking the signature against a ring of public keys -compiled into the kernel. GPG is used to do the cryptographic work and -determines the format of the signature and key data. The facility uses GPG's -MPI library to handle the huge numbers involved. - -This facility is enabled through CONFIG_MODULE_SIG. Turning on signature -checking will also force the module's ELF metadata to be verified before the -signature is checked. - -===================== -SUPPLYING PUBLIC KEYS -===================== - -A set of public keys must be supplied at main kernel compile time. This is -done by taking a GPG public key file, running it through the kernel's bin2c -program and writing the result over crypto/signature/key.h. To automate this -process, something like this could be done: - - cat >genkey < - - This indicates the whereabouts of the GPG keyring that is the source of - the secret key to be used. The default is "./kernel.sec". - - (*) MODPUBKEY= - - This indicates the whereabouts of the GPG keyring that is the source of - the public key to be used. The default is "./kernel.pub". - - (*) MODKEYNAME= - - The name of the key pair to be used from the aforementioned keyrings. - This defaults to being unset, thus leaving the choice of default key to - gpg. - - (*) KEYFLAGS="gpg-options" - - Override the complete gpg command line, including the preceding three - options. The default options supplied to gpg are: - - --no-default-keyring - --secret-keyring $(MODSECKEY) - --keyring $(MODPUBKEY) - --no-default-keyring - --homedir . - --no-options - --no-auto-check-trustdb - --no-permission-warning - - with: - - --default-key $(MODKEYNAME) - - being added if requested. - -The resulting module.ko file will be the signed module. - -======================== -STRIPPING SIGNED MODULES -======================== - -Signed modules may be safely stripped as the signature only covers those parts -of the module the kernel actually uses and any ELF metadata required to deal -with them. Any necessary ELF metadata that is affected by stripping is -canonicalised by the sig generator and the sig checker to hide strip effects. - -This permits the debuginfo to be detached from the module and placed in another -spot so that gdb can find it when referring to that module without the need for -multiple signed versions of the module. Such is done by rpmbuild when -producing RPMs. - -It also permits the module to be stripped as far as possible for when modules -are being reduced prior to being included in an initial ramdisk composition. - -====================== -LOADING SIGNED MODULES -====================== - -Modules are loaded with insmod, exactly as for unsigned modules. The signature -is inserted into the module object file as an ELF section called ".module_sig". -The signature checker will spot it and apply signature checking. - -========================================= -NON-VALID SIGNATURES AND UNSIGNED MODULES -========================================= - -If CONFIG_MODULE_SIG_FORCE is enabled or "enforcemodulesig=1" is supplied on -the kernel command line, the kernel will _only_ load validly signed modules -for which it has a public key. Otherwise, it will also load modules that are -unsigned. Any module for which the kernel has a key, but which proves to have -a signature mismatch will not be permitted to load (returning EKEYREJECTED). - -This table indicates the behaviours of the various situations: - - MODULE STATE PERMISSIVE MODE ENFORCING MODE - =============================== =============== =============== - Unsigned Ok EKEYREJECTED - Signed, no public key ENOKEY ENOKEY - Validly signed, public key Ok Ok - Invalidly signed, public key EKEYREJECTED EKEYREJECTED - Validly signed, expired key EKEYEXPIRED EKEYEXPIRED - Corrupt signature ELIBBAD ELIBBAD - Corrupt ELF ELIBBAD ELIBBAD - -Signed-Off-By: David Howells - -Rebased-to-3.3-rc6-by: Josh Boyer ---- - .gitignore | 15 + - Documentation/module-signing.txt | 186 ++++++++ - Makefile | 1 + - include/linux/elfnote.h | 4 + - include/linux/modsign.h | 27 ++ - include/linux/module.h | 3 + - init/Kconfig | 56 +++- - kernel/Makefile | 2 + - kernel/modsign-pubkey.c | 44 ++ - kernel/module-verify-sig.c | 526 ++++++++++++++++++++++ - kernel/module-verify.c | 5 +- - kernel/module-verify.h | 19 +- - kernel/module.c | 21 +- - scripts/Makefile.modpost | 85 ++++- - scripts/mod/.gitignore | 1 + - scripts/mod/Makefile | 2 +- - scripts/mod/mod-extract.c | 913 ++++++++++++++++++++++++++++++++++++++ - scripts/mod/modsign-note.sh | 16 + - 18 files changed, 1914 insertions(+), 12 deletions(-) - create mode 100644 Documentation/module-signing.txt - create mode 100644 include/linux/modsign.h - create mode 100644 kernel/modsign-pubkey.c - create mode 100644 kernel/module-verify-sig.c - create mode 100644 scripts/mod/mod-extract.c - create mode 100644 scripts/mod/modsign-note.sh + .gitignore | 12 ++++++++++++ + Makefile | 1 + + scripts/mod/.gitignore | 1 + + 3 files changed, 14 insertions(+) diff --git a/.gitignore b/.gitignore -index 57af07c..841a17ee 100644 +index 57af07c..7948eeb 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,9 @@ @@ -5133,7 +4544,7 @@ index 57af07c..841a17ee 100644 *.ko *.so *.so.dbg -@@ -84,3 +87,15 @@ GTAGS +@@ -84,3 +87,12 @@ GTAGS *.orig *~ \#*# @@ -5141,20 +4552,86 @@ index 57af07c..841a17ee 100644 +# +# GPG leavings from module signing +# -+trustdb.gpg ++genkey ++modsign.pub ++modsign.sec +random_seed -+kernel.pub -+kernel.sec -+extract.pub -+secring.gpg -+pubring.gpg -+crypto/signature/key.h ++trustdb.gpg +diff --git a/Makefile b/Makefile +index a06ee9f..1df8b14 100644 +--- a/Makefile ++++ b/Makefile +@@ -1407,6 +1407,7 @@ clean: $(clean-dirs) + $(call cmd,rmfiles) + @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ + \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ ++ -o -name '*.ko.*' \ + -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ + -o -name '*.symtypes' -o -name 'modules.order' \ + -o -name modules.builtin -o -name '.tmp_*.o.*' \ +diff --git a/scripts/mod/.gitignore b/scripts/mod/.gitignore +index e9b7abe..223dfd6 100644 +--- a/scripts/mod/.gitignore ++++ b/scripts/mod/.gitignore +@@ -1,4 +1,5 @@ + elfconfig.h + mk_elfconfig + modpost ++mod-extract + +-- +1.7.10.2 + + +From dce3a6eca8dda09a28cb2f45b87e70e1c2d52139 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 10 May 2012 23:49:53 +0100 +Subject: [PATCH 21/36] MODSIGN: Provide Documentation and Kconfig options + +Provide documentation and kernel configuration options for module signing. + +The documentation can be found in: + + Documentation/module-signing.txt + +The following configuration options are added: + + (1) CONFIG_MODULE_SIG + + Enable module signing. This will both cause the build process to sign + modules and the kernel to check modules when they're loaded. + + (2) CONFIG_MODULE_SIG_SHA1 + CONFIG_MODULE_SIG_SHA224 + CONFIG_MODULE_SIG_SHA256 + CONFIG_MODULE_SIG_SHA384 + CONFIG_MODULE_SIG_SHA512 + + Select the cryptographic hash used to digest the data prior to signing. + Additionally, the crypto module selected will be built into the kernel as + it won't be possible to load it as a module without incurring a circular + dependency when the kernel tries to check its signature. + + (3) CONFIG_MODULE_SIG_FORCE + + Require that any module loaded must be signed with a key compiled into + the kernel. All other modules are rejected with EKEYREJECTED. + +Signed-off-by: David Howells +--- + Documentation/module-signing.txt | 194 ++++++++++++++++++++++++++++++++++++++ + include/linux/modsign.h | 27 ++++++ + init/Kconfig | 53 +++++++++++ + 3 files changed, 274 insertions(+) + create mode 100644 Documentation/module-signing.txt + create mode 100644 include/linux/modsign.h + diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt new file mode 100644 -index 0000000..300b91a +index 0000000..d75d473 --- /dev/null +++ b/Documentation/module-signing.txt -@@ -0,0 +1,186 @@ +@@ -0,0 +1,194 @@ + ============================== + KERNEL MODULE SIGNING FACILITY + ============================== @@ -5185,16 +4662,16 @@ index 0000000..300b91a + +A set of public keys must be supplied at kernel image build time. This is done +by taking a GPG public key file and placing it in the base of the kernel -+directory in a file called kernel.pub. ++directory in a file called modsign.pub. + +For example, a throwaway key could be generated automatically by something like +the following: + + cat >genkey < + + This indicates the whereabouts of the GPG keyring that is the source of -+ the secret key to be used. The default is "./kernel.sec". ++ the secret key to be used. The default is "./modsign.sec". + + (*) MODPUBKEY= + + This indicates the whereabouts of the GPG keyring that is the source of -+ the public key to be used. The default is "./kernel.pub". ++ the public key to be used. The default is "./modsign.pub". + + (*) MODKEYNAME= + @@ -5296,10 +4770,16 @@ index 0000000..300b91a +STRIPPING SIGNED MODULES +======================== + -+Signed modules may be safely stripped as the signature only covers those parts -+of the module the kernel actually uses and any ELF metadata required to deal -+with them. Any necessary ELF metadata that is affected by stripping is -+canonicalised by the sig generator and the sig checker to hide strip effects. ++Signed modules may be safely stripped with any of the following: ++ ++ strip -x ++ strip -g ++ eu-strip ++ ++as the signature only covers those parts of the module the kernel actually uses ++and any ELF metadata required to deal with them. Any necessary ELF metadata ++that is affected by stripping is canonicalised by the sig generator and the sig ++checker to hide strip effects. + +This permits the debuginfo to be detached from the module and placed in another +spot so that gdb can find it when referring to that module without the need for @@ -5309,14 +4789,19 @@ index 0000000..300b91a +It also permits the module to be stripped as far as possible for when modules +are being reduced prior to being included in an initial ramdisk composition. + ++Note that "strip" and "strip -s" may not be used on a module, signed or ++otherwise, as they remove the symbol table and render the relocation tables ++unusable. ++ + +====================== +LOADING SIGNED MODULES +====================== + +Modules are loaded with insmod, exactly as for unsigned modules. The signature -+is inserted into the module object file as an ELF section called ".module_sig". -+The signature checker will detect it and apply signature checking. ++is inserted into the module object file during the build process as an ELF note ++called "module.sig" in an ELF section called ".note.module.sig". The signature ++checker will detect it and apply signature checking. + + +========================================= @@ -5341,40 +4826,6 @@ index 0000000..300b91a + Signed, hash algorithm unavailable ENOPKG ENOPKG + Corrupt signature EBADMSG EBADMSG + Corrupt ELF ELIBBAD ELIBBAD -diff --git a/Makefile b/Makefile -index 66d13c9..8ba824f 100644 ---- a/Makefile -+++ b/Makefile -@@ -1407,6 +1407,7 @@ clean: $(clean-dirs) - $(call cmd,rmfiles) - @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ - \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ -+ -o -name '*.ko.*' \ - -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ - -o -name '*.symtypes' -o -name 'modules.order' \ - -o -name modules.builtin -o -name '.tmp_*.o.*' \ -diff --git a/include/linux/elfnote.h b/include/linux/elfnote.h -index 278e3ef..949d494 100644 ---- a/include/linux/elfnote.h -+++ b/include/linux/elfnote.h -@@ -58,6 +58,7 @@ - ELFNOTE_END - - #else /* !__ASSEMBLER__ */ -+#include - #include - /* - * Use an anonymous structure which matches the shape of -@@ -93,6 +94,9 @@ - - #define ELFNOTE32(name, type, desc) ELFNOTE(32, name, type, desc) - #define ELFNOTE64(name, type, desc) ELFNOTE(64, name, type, desc) -+ -+#define ELFNOTE_NAME(name) __stringify(name) -+#define ELFNOTE_SECTION(name) ".note."ELFNOTE_NAME(name) - #endif /* __ASSEMBLER__ */ - - #endif /* _LINUX_ELFNOTE_H */ diff --git a/include/linux/modsign.h b/include/linux/modsign.h new file mode 100644 index 0000000..c5ac87a @@ -5408,37 +4859,22 @@ index 0000000..c5ac87a +#endif + +#endif /* _LINUX_MODSIGN_H */ -diff --git a/include/linux/module.h b/include/linux/module.h -index 4598bf0..2bd03f1 100644 ---- a/include/linux/module.h -+++ b/include/linux/module.h -@@ -294,6 +294,9 @@ struct module - - unsigned int taints; /* same bits as kernel:tainted */ - -+ /* Is this module GPG signed */ -+ int gpgsig_ok; -+ - #ifdef CONFIG_GENERIC_BUG - /* Support for BUG */ - unsigned num_bugs; diff --git a/init/Kconfig b/init/Kconfig -index 61b5f03..b21dcae 100644 +index 6cfd71d..7cda3e6 100644 --- a/init/Kconfig +++ b/init/Kconfig -@@ -1424,10 +1424,64 @@ config MODULE_VERIFY_ELF - help - Check ELF structure of modules upon load +@@ -1409,6 +1409,59 @@ config MODULE_SRCVERSION_ALL + the version). With this option, such a "srcversion" field + will be created for all modules. If unsure, say N. +config MODULE_SIG -+ bool "Module signature verification (EXPERIMENTAL)" -+ depends on MODULES && EXPERIMENTAL ++ bool "Module signature verification" ++ depends on MODULES + select CRYPTO_KEY_TYPE + select CRYPTO_KEY_PKEY_ALGO_DSA + select CRYPTO_KEY_PKEY_ALGO_RSA + select PGP_PARSER + select PGP_PRELOAD -+ select MODULE_VERIFY_ELF + help + Check modules for valid signatures upon load. For more information + see: @@ -5484,759 +4920,65 @@ index 61b5f03..b21dcae 100644 + Reject unsigned modules or signed modules for which we don't have a + key. + - config MODULE_VERIFY - bool - depends on MODULES -- default y if MODULE_VERIFY_ELF -+ default y if MODULE_VERIFY_ELF || MODULE_SIG - endif # MODULES -diff --git a/kernel/Makefile b/kernel/Makefile -index 77b7a39..9732e11 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -54,6 +54,8 @@ obj-$(CONFIG_UID16) += uid16.o - obj-$(CONFIG_MODULES) += module.o - obj-$(CONFIG_MODULE_VERIFY) += module-verify.o - obj-$(CONFIG_MODULE_VERIFY_ELF) += module-verify-elf.o -+obj-$(CONFIG_MODULE_SIG) += module-verify-sig.o modsign-pubkey.o -+kernel/modsign-pubkey.o: kernel.pub - obj-$(CONFIG_KALLSYMS) += kallsyms.o - obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o - obj-$(CONFIG_KEXEC) += kexec.o -diff --git a/kernel/modsign-pubkey.c b/kernel/modsign-pubkey.c -new file mode 100644 -index 0000000..df55565 ---- /dev/null -+++ b/kernel/modsign-pubkey.c -@@ -0,0 +1,44 @@ -+/* Public keys for module signature verification -+ * -+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public Licence -+ * as published by the Free Software Foundation; either version -+ * 2 of the Licence, or (at your option) any later version. -+ */ -+ -+#include -+#include -+#include "module-verify.h" -+ -+extern __initdata const u8 modsign_public_keys[]; -+extern __initdata const u8 modsign_public_keys_end[]; -+asm(".section .init.data,\"aw\"\n" -+ "modsign_public_keys:\n" -+ ".incbin \"kernel.pub\"\n" -+ "modsign_public_keys_end:" -+ ); -+ -+/* -+ * We need to make sure ccache doesn't cache the .o file as it doesn't notice -+ * if kernel.pub changes. -+ */ -+static __initdata const char annoy_ccache[] = __TIME__ "foo"; -+ -+/* -+ * Load the compiled-in keys -+ */ -+static __init int modsign_pubkey_init(void) -+{ -+ pr_notice("Load module verification keys\n"); -+ -+ if (preload_pgp_keys(modsign_public_keys, -+ modsign_public_keys_end - modsign_public_keys, -+ modsign_keyring, "modsign.") < 0) -+ panic("Can't load module signing keys\n"); -+ -+ return 0; -+} -+late_initcall(modsign_pubkey_init); -diff --git a/kernel/module-verify-sig.c b/kernel/module-verify-sig.c -new file mode 100644 -index 0000000..ced5681 ---- /dev/null -+++ b/kernel/module-verify-sig.c -@@ -0,0 +1,526 @@ -+/* Module signature checker -+ * -+ * Copyright (C) 2004,2011 Red Hat, Inc. All Rights Reserved. -+ * Written by David Howells (dhowells@redhat.com) -+ * - Derived from GregKH's RSA module signer -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "module-verify.h" -+ -+#undef MODSIGN_DEBUG -+ -+struct key *modsign_keyring; -+ -+int modsign_debug; -+core_param(modsign_debug, modsign_debug, bool, 0644); -+ -+#define _debug(FMT, ...) \ -+ do { \ -+ if (unlikely(modsign_debug)) \ -+ pr_debug(FMT, ##__VA_ARGS__); \ -+ } while(0) -+ -+#ifdef MODSIGN_DEBUG -+#define count_and_csum(C, __p, __n) \ -+do { \ -+ int __loop; \ -+ for (__loop = 0; __loop < __n; __loop++) { \ -+ (C)->csum += __p[__loop]; \ -+ (C)->xcsum += __p[__loop]; \ -+ } \ -+ (C)->signed_size += __n; \ -+} while (0) -+#else -+#define count_and_csum(C, __p, __n) \ -+do { \ -+ (C)->signed_size += __n; \ -+} while (0) -+#endif -+ -+#define crypto_digest_update_data(C, PTR, N) \ -+do { \ -+ uint8_t *__p = (uint8_t *)(PTR); \ -+ size_t __n = (N); \ -+ count_and_csum((C), __p, __n); \ -+ verify_sig_add_data((C)->mod_sig, __p, __n); \ -+} while (0) -+ -+#define crypto_digest_update_val(C, VAL) \ -+do { \ -+ uint8_t *__p = (uint8_t *)&(VAL); \ -+ size_t __n = sizeof(VAL); \ -+ count_and_csum((C), __p, __n); \ -+ verify_sig_add_data((C)->mod_sig, __p, __n); \ -+} while (0) -+ -+static int module_verify_canonicalise(struct module_verify_data *mvdata); -+ -+static int extract_elf_rela(struct module_verify_data *mvdata, -+ int secix, -+ const Elf_Rela *relatab, size_t nrels, -+ const char *sh_name); -+ -+static int extract_elf_rel(struct module_verify_data *mvdata, -+ int secix, -+ const Elf_Rel *reltab, size_t nrels, -+ const char *sh_name); -+ -+#ifdef CONFIG_MODULE_SIG_FORCE -+static int signedonly = 1; -+#else -+static int signedonly; -+#endif -+ -+static int __init sign_setup(char *str) -+{ -+ signedonly = 1; -+ return 0; -+} -+__setup("enforcemodulesig", sign_setup); -+ -+static const char modsign_note_name[] = ELFNOTE_NAME(MODSIGN_NOTE_NAME); -+static const char modsign_note_section[] = ELFNOTE_SECTION(MODSIGN_NOTE_NAME); -+ -+/* -+ * verify a module's signature -+ */ -+int module_verify_signature(struct module_verify_data *mvdata, -+ int *_gpgsig_ok) -+{ -+ struct crypto_key_verify_context *mod_sig; -+ const struct elf_note *note; -+ const Elf_Shdr *sechdrs = mvdata->sections; -+ const char *secstrings = mvdata->secstrings; -+ const char *sig; -+ unsigned note_size, sig_size, note_namesz; -+ int loop, ret; -+ -+ _debug("looking for sig section '%s'\n", modsign_note_section); -+ -+ for (loop = 1; loop < mvdata->nsects; loop++) { -+ switch (sechdrs[loop].sh_type) { -+ case SHT_NOTE: -+ if (strcmp(mvdata->secstrings + sechdrs[loop].sh_name, -+ modsign_note_section) == 0) -+ mvdata->sig_index = loop; -+ break; -+ } -+ } -+ -+ if (mvdata->sig_index <= 0) -+ goto no_signature; -+ -+ note = mvdata->buffer + sechdrs[mvdata->sig_index].sh_offset; -+ note_size = sechdrs[mvdata->sig_index].sh_size; -+ -+ /* there should be one note of the appropriate type */ -+ if (note_size < sizeof(*note) + 2 * 4) -+ goto format_error_no_free; -+ note_namesz = note->n_namesz; -+ sig_size = note->n_descsz; -+ if (note_namesz != sizeof(modsign_note_name)) -+ goto format_error_no_free; -+ if (note->n_type != MODSIGN_NOTE_TYPE) -+ goto format_error_no_free; -+ if (memcmp(note + 1, modsign_note_name, note_namesz) != 0) -+ goto format_error_no_free; -+ sig = (void *)(note + 1) + roundup(note_namesz, 4); -+ -+ _debug("sig in section %d (size %d)\n", -+ mvdata->sig_index, sig_size); -+ _debug("%02x%02x%02x%02x%02x%02x%02x%02x\n", -+ sig[0], sig[1], sig[2], sig[3], -+ sig[4], sig[5], sig[6], sig[7]); -+ -+ /* produce a canonicalisation map for the sections */ -+ ret = module_verify_canonicalise(mvdata); -+ if (ret < 0) -+ return ret; -+ -+ /* Find the crypto key for the module signature -+ * - !!! if this tries to load the required hash algorithm module, -+ * we will deadlock!!! -+ */ -+ mod_sig = verify_sig_begin(modsign_keyring, sig, sig_size); -+ if (IS_ERR(mod_sig)) { -+ pr_err("Couldn't initiate module signature verification: %ld\n", -+ PTR_ERR(mod_sig)); -+ return PTR_ERR(mod_sig); -+ } -+ -+ mvdata->mod_sig = mod_sig; -+ -+#ifdef MODSIGN_DEBUG -+ mvdata->xcsum = 0; -+#endif -+ -+ /* load data from each relevant section into the digest */ -+ for (loop = 0; loop < mvdata->ncanon; loop++) { -+ int sect = mvdata->canonlist[loop]; -+ unsigned long sh_type = sechdrs[sect].sh_type; -+ unsigned long sh_info = sechdrs[sect].sh_info; -+ unsigned long sh_size = sechdrs[sect].sh_size; -+ unsigned long sh_flags = sechdrs[sect].sh_flags; -+ const char *sh_name = secstrings + sechdrs[sect].sh_name; -+ const void *data = mvdata->buffer + sechdrs[sect].sh_offset; -+ -+#ifdef MODSIGN_DEBUG -+ mvdata->csum = 0; -+#endif -+ -+ /* it would be nice to include relocation sections, but the act -+ * of adding a signature to the module seems changes their -+ * contents, because the symtab gets changed when sections are -+ * added or removed */ -+ if (sh_type == SHT_REL || sh_type == SHT_RELA) { -+ uint32_t xsh_info = mvdata->canonmap[sh_info]; -+ -+ crypto_digest_update_data(mvdata, sh_name, strlen(sh_name)); -+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_type); -+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_flags); -+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_size); -+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_addralign); -+ crypto_digest_update_val(mvdata, xsh_info); -+ -+ if (sh_type == SHT_RELA) -+ ret = extract_elf_rela( -+ mvdata, sect, -+ data, -+ sh_size / sizeof(Elf_Rela), -+ sh_name); -+ else -+ ret = extract_elf_rel( -+ mvdata, sect, -+ data, -+ sh_size / sizeof(Elf_Rel), -+ sh_name); -+ -+ if (ret < 0) -+ goto format_error; -+ continue; -+ } -+ -+ /* include the headers of BSS sections */ -+ if (sh_type == SHT_NOBITS && sh_flags & SHF_ALLOC) { -+ crypto_digest_update_data(mvdata, sh_name, strlen(sh_name)); -+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_type); -+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_flags); -+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_size); -+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_addralign); -+ goto digested; -+ } -+ -+ /* include allocatable loadable sections */ -+ if (sh_type != SHT_NOBITS && sh_flags & SHF_ALLOC) -+ goto include_section; -+ -+ continue; -+ -+ include_section: -+ crypto_digest_update_data(mvdata, sh_name, strlen(sh_name)); -+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_type); -+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_flags); -+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_size); -+ crypto_digest_update_val(mvdata, sechdrs[sect].sh_addralign); -+ -+ crypto_digest_update_data(mvdata, data, sh_size); -+ -+ digested: -+ _debug("%08zx %02x digested the %s section, size %ld\n", -+ mvdata->signed_size, mvdata->csum, sh_name, sh_size); -+ } -+ -+ _debug("Contributed %zu bytes to the digest (csum 0x%02x)\n", -+ mvdata->signed_size, mvdata->xcsum); -+ -+ /* do the actual signature verification */ -+ ret = verify_sig_end(mvdata->mod_sig, sig, sig_size); -+ mvdata->mod_sig = NULL; -+ -+ _debug("verify-sig : %d\n", ret); -+ -+ switch (ret) { -+ case 0: /* good signature */ -+ *_gpgsig_ok = 1; -+ break; -+ case -EKEYREJECTED: /* signature mismatch or number format error */ -+ pr_err("Module signature verification failed\n"); -+ break; -+ case -ENOKEY: /* signed, but we don't have the public key */ -+ pr_err("Module signed with unknown public key\n"); -+ break; -+ default: /* other error (probably ENOMEM) */ -+ break; -+ } -+ -+ return ret; -+ -+format_error: -+ verify_sig_cancel(mvdata->mod_sig); -+ mvdata->mod_sig = NULL; -+format_error_no_free: -+ pr_err("Module format error encountered\n"); -+ return -ELIBBAD; -+ -+ /* deal with the case of an unsigned module */ -+no_signature: -+ _debug("no signature found\n"); -+ if (!signedonly) -+ return 0; -+ pr_err("An attempt to load unsigned module was rejected\n"); -+ return -EKEYREJECTED; -+} -+ -+/* -+ * canonicalise the section table index numbers -+ */ -+static int module_verify_canonicalise(struct module_verify_data *mvdata) -+{ -+ int canon, loop, changed, tmp; -+ -+ /* produce a list of index numbers of sections that contribute -+ * to the kernel's module image -+ */ -+ mvdata->canonlist = -+ kmalloc(sizeof(int) * mvdata->nsects * 2, GFP_KERNEL); -+ if (!mvdata->canonlist) -+ return -ENOMEM; -+ -+ mvdata->canonmap = mvdata->canonlist + mvdata->nsects; -+ canon = 0; -+ -+ for (loop = 1; loop < mvdata->nsects; loop++) { -+ const Elf_Shdr *section = mvdata->sections + loop; -+ -+ if (loop == mvdata->sig_index) -+ continue; -+ -+ /* we only need to canonicalise allocatable sections */ -+ if (section->sh_flags & SHF_ALLOC) -+ mvdata->canonlist[canon++] = loop; -+ else if ((section->sh_type == SHT_REL || -+ section->sh_type == SHT_RELA) && -+ mvdata->sections[section->sh_info].sh_flags & SHF_ALLOC) -+ mvdata->canonlist[canon++] = loop; -+ } -+ -+ /* canonicalise the index numbers of the contributing section */ -+ do { -+ changed = 0; -+ -+ for (loop = 0; loop < canon - 1; loop++) { -+ const char *x, *y; -+ -+ x = mvdata->secstrings + -+ mvdata->sections[mvdata->canonlist[loop + 0]].sh_name; -+ y = mvdata->secstrings + -+ mvdata->sections[mvdata->canonlist[loop + 1]].sh_name; -+ -+ if (strcmp(x, y) > 0) { -+ tmp = mvdata->canonlist[loop + 0]; -+ mvdata->canonlist[loop + 0] = -+ mvdata->canonlist[loop + 1]; -+ mvdata->canonlist[loop + 1] = tmp; -+ changed = 1; -+ } -+ } -+ -+ } while (changed); -+ -+ for (loop = 0; loop < canon; loop++) -+ mvdata->canonmap[mvdata->canonlist[loop]] = loop + 1; -+ mvdata->ncanon = canon; -+ return 0; -+} -+ -+/* -+ * extract an ELF RELA table -+ * - need to canonicalise the entries in case section addition/removal has -+ * rearranged the symbol table and the section table -+ */ -+static int extract_elf_rela(struct module_verify_data *mvdata, -+ int secix, -+ const Elf_Rela *relatab, size_t nrels, -+ const char *sh_name) -+{ -+ struct { -+#if defined(MODULES_ARE_ELF32) -+ uint32_t r_offset; -+ uint32_t r_addend; -+ uint32_t st_value; -+ uint32_t st_size; -+ uint16_t st_shndx; -+ uint8_t r_type; -+ uint8_t st_info; -+ uint8_t st_other; -+#elif defined(MODULES_ARE_ELF64) -+ uint64_t r_offset; -+ uint64_t r_addend; -+ uint64_t st_value; -+ uint64_t st_size; -+ uint32_t r_type; -+ uint16_t st_shndx; -+ uint8_t st_info; -+ uint8_t st_other; -+#else -+#error unsupported module type -+#endif -+ } __attribute__((packed)) relocation; -+ -+ const Elf_Rela *reloc; -+ const Elf_Sym *symbol; -+ size_t loop; -+ -+ /* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */ -+ for (loop = 0; loop < nrels; loop++) { -+ int st_shndx; -+ -+ reloc = &relatab[loop]; -+ -+ /* decode the relocation */ -+ relocation.r_offset = reloc->r_offset; -+ relocation.r_addend = reloc->r_addend; -+ relocation.r_type = ELF_R_TYPE(reloc->r_info); -+ -+ /* decode the symbol referenced by the relocation */ -+ symbol = &mvdata->symbols[ELF_R_SYM(reloc->r_info)]; -+ relocation.st_info = symbol->st_info; -+ relocation.st_other = symbol->st_other; -+ relocation.st_value = symbol->st_value; -+ relocation.st_size = symbol->st_size; -+ relocation.st_shndx = symbol->st_shndx; -+ st_shndx = symbol->st_shndx; -+ -+ /* canonicalise the section used by the symbol */ -+ if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects) -+ relocation.st_shndx = mvdata->canonmap[st_shndx]; -+ -+ crypto_digest_update_val(mvdata, relocation); -+ -+ /* undefined symbols must be named if referenced */ -+ if (st_shndx == SHN_UNDEF) { -+ const char *name = mvdata->strings + symbol->st_name; -+ crypto_digest_update_data(mvdata, -+ name, strlen(name) + 1); -+ } -+ } -+ -+ _debug("%08zx %02x digested the %s section, nrels %zu\n", -+ mvdata->signed_size, mvdata->csum, sh_name, nrels); -+ -+ return 0; -+} -+ -+/* -+ * extract an ELF REL table -+ * - need to canonicalise the entries in case section addition/removal has -+ * rearranged the symbol table and the section table -+ */ -+static int extract_elf_rel(struct module_verify_data *mvdata, -+ int secix, -+ const Elf_Rel *reltab, size_t nrels, -+ const char *sh_name) -+{ -+ struct { -+#if defined(MODULES_ARE_ELF32) -+ uint32_t r_offset; -+ uint32_t st_value; -+ uint32_t st_size; -+ uint16_t st_shndx; -+ uint8_t r_type; -+ uint8_t st_info; -+ uint8_t st_other; -+#elif defined(MODULES_ARE_ELF64) -+ uint64_t r_offset; -+ uint64_t st_value; -+ uint64_t st_size; -+ uint32_t r_type; -+ uint16_t st_shndx; -+ uint8_t st_info; -+ uint8_t st_other; -+#else -+#error unsupported module type -+#endif -+ } __attribute__((packed)) relocation; -+ -+ const Elf_Rel *reloc; -+ const Elf_Sym *symbol; -+ size_t loop; -+ -+ /* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */ -+ for (loop = 0; loop < nrels; loop++) { -+ int st_shndx; -+ -+ reloc = &reltab[loop]; -+ -+ /* decode the relocation */ -+ relocation.r_offset = reloc->r_offset; -+ relocation.r_type = ELF_R_TYPE(reloc->r_info); -+ -+ /* decode the symbol referenced by the relocation */ -+ symbol = &mvdata->symbols[ELF_R_SYM(reloc->r_info)]; -+ relocation.st_info = symbol->st_info; -+ relocation.st_other = symbol->st_other; -+ relocation.st_value = symbol->st_value; -+ relocation.st_size = symbol->st_size; -+ relocation.st_shndx = symbol->st_shndx; -+ st_shndx = symbol->st_shndx; -+ -+ /* canonicalise the section used by the symbol */ -+ if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects) -+ relocation.st_shndx = mvdata->canonmap[st_shndx]; -+ -+ crypto_digest_update_val(mvdata, relocation); -+ -+ /* undefined symbols must be named if referenced */ -+ if (st_shndx == SHN_UNDEF) { -+ const char *name = mvdata->strings + symbol->st_name; -+ crypto_digest_update_data(mvdata, -+ name, strlen(name) + 1); -+ } -+ } -+ -+ _debug("%08zx %02x digested the %s section, nrels %zu\n", -+ mvdata->signed_size, mvdata->csum, sh_name, nrels); -+ -+ return 0; -+} -+ -+/* -+ * Load the compiled-in keys -+ */ -+static __init int module_verify_init(void) -+{ -+ pr_notice("Initialise module verification\n"); -+ -+ modsign_keyring = key_alloc(&key_type_keyring, ".module_sign", -+ 0, 0, current_cred(), -+ (KEY_POS_ALL & ~KEY_POS_SETATTR) | -+ KEY_USR_VIEW | KEY_USR_READ, -+ KEY_ALLOC_NOT_IN_QUOTA); -+ if (IS_ERR(modsign_keyring)) -+ panic("Can't allocate module signing keyring\n"); -+ -+ if (key_instantiate_and_link(modsign_keyring, NULL, 0, NULL, NULL) < 0) -+ panic("Can't instantiate module signing keyring\n"); -+ -+ return 0; -+} -+ -+/* -+ * Must be initialised before we try and load the keys into the keyring. -+ */ -+device_initcall(module_verify_init); -diff --git a/kernel/module-verify.c b/kernel/module-verify.c -index 875279f..64c5813 100644 ---- a/kernel/module-verify.c -+++ b/kernel/module-verify.c -@@ -16,8 +16,9 @@ - /* - * verify a module's integrity - * - check the ELF is viable -+ * - check the module's signature - */ --int module_verify(const Elf_Ehdr *hdr, size_t size) -+int module_verify(const Elf_Ehdr *hdr, size_t size, int *_gpgsig_ok) - { - struct module_verify_data mvdata; - int ret; -@@ -34,6 +35,8 @@ int module_verify(const Elf_Ehdr *hdr, size_t size) - goto error; - } - -+ ret = module_verify_signature(&mvdata, _gpgsig_ok); -+ - error: - kfree(mvdata.secsizes); - kfree(mvdata.canonlist); -diff --git a/kernel/module-verify.h b/kernel/module-verify.h -index 20884fc..0ccdb71 100644 ---- a/kernel/module-verify.h -+++ b/kernel/module-verify.h -@@ -10,10 +10,13 @@ - */ - - #include -+#include -+#include - #include - - #ifdef CONFIG_MODULE_VERIFY - struct module_verify_data { -+ struct crypto_key_verify_context *mod_sig; /* Module signing context */ - const void *buffer; /* module buffer */ - const Elf_Ehdr *hdr; /* ELF header */ - const Elf_Shdr *sections; /* ELF section table */ -@@ -37,7 +40,7 @@ struct module_verify_data { - /* - * module-verify.c - */ --extern int module_verify(const Elf_Ehdr *hdr, size_t size); -+extern int module_verify(const Elf_Ehdr *hdr, size_t size, int *_gpgsig_ok); - - /* - * module-verify-elf.c -@@ -48,6 +51,18 @@ extern int module_verify_elf(struct module_verify_data *mvdata); - #define module_verify_elf(m) (0) - #endif - -+/* -+ * module-verify-sig.c -+ */ -+#ifdef CONFIG_MODULE_SIG -+extern struct key *modsign_keyring; -+ -+extern int module_verify_signature(struct module_verify_data *mvdata, -+ int *_gpgsig_ok); -+#else -+#define module_verify_signature(m, g) (0) -+#endif -+ - #else --#define module_verify(h, s) (0) -+#define module_verify(h, s, g) (0) - #endif -diff --git a/kernel/module.c b/kernel/module.c -index 54d6910..bb38584 100644 ---- a/kernel/module.c -+++ b/kernel/module.c -@@ -2372,7 +2372,8 @@ static inline void kmemleak_load_module(const struct module *mod, - /* Sets info->hdr and info->len. */ - static int copy_and_check(struct load_info *info, - const void __user *umod, unsigned long len, -- const char __user *uargs) -+ const char __user *uargs, -+ int *_gpgsig_ok) - { - int err; - Elf_Ehdr *hdr; -@@ -2406,7 +2407,7 @@ static int copy_and_check(struct load_info *info, - } - - /* Verify the module's contents */ -- err = module_verify(hdr, len); -+ err = module_verify(hdr, len, _gpgsig_ok); - if (err < 0) - goto free_hdr; - -@@ -2752,7 +2753,8 @@ int __weak module_frob_arch_sections(Elf_Ehdr *hdr, - return 0; - } - --static struct module *layout_and_allocate(struct load_info *info) -+static struct module *layout_and_allocate(struct load_info *info, -+ int gpgsig_ok) - { - /* Module within temporary copy. */ - struct module *mod; -@@ -2762,6 +2764,7 @@ static struct module *layout_and_allocate(struct load_info *info) - mod = setup_load_info(info); - if (IS_ERR(mod)) - return mod; -+ mod->gpgsig_ok = gpgsig_ok; - - err = check_modinfo(mod, info); - if (err) -@@ -2845,17 +2848,18 @@ static struct module *load_module(void __user *umod, - struct load_info info = { NULL, }; - struct module *mod; - long err; -+ int gpgsig_ok; - - pr_debug("load_module: umod=%p, len=%lu, uargs=%p\n", - umod, len, uargs); - - /* Copy in the blobs from userspace, check they are vaguely sane. */ -- err = copy_and_check(&info, umod, len, uargs); -+ err = copy_and_check(&info, umod, len, uargs, &gpgsig_ok); - if (err) - return ERR_PTR(err); - - /* Figure out module layout, and allocate all the memory. */ -- mod = layout_and_allocate(&info); -+ mod = layout_and_allocate(&info, gpgsig_ok); - if (IS_ERR(mod)) { - err = PTR_ERR(mod); - goto free_copy; -@@ -3491,8 +3495,13 @@ void print_modules(void) - printk(KERN_DEFAULT "Modules linked in:"); - /* Most callers should already have preempt disabled, but make sure */ - preempt_disable(); -- list_for_each_entry_rcu(mod, &modules, list) -+ list_for_each_entry_rcu(mod, &modules, list) { - printk(" %s%s", mod->name, module_flags(mod, buf)); -+#ifdef CONFIG_MODULE_SIG -+ if (!mod->gpgsig_ok) -+ printk("(U)"); -+#endif -+ } - preempt_enable(); - if (last_unloaded_module[0]) - printk(" [last unloaded: %s]", last_unloaded_module); + config INIT_ALL_POSSIBLE +-- +1.7.10.2 + + +From f9980a27c5d2d02af2feb578957145a206088fff Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 10 May 2012 23:49:54 +0100 +Subject: [PATCH 22/36] MODSIGN: Sign modules during the build process + +If CONFIG_MODULE_SIG is set, then this patch will cause the module to get a +signature installed. The following steps will occur: + + (1) The module will be linked to foo.ko.unsigned instead of foo.ko + + (2) The module's signable content will be extracted to foo.ko.digest by the + mod-extract program. + + (3) The signature will be generated on foo.ko.digest by gpg and placed in + foo.ko.digest.sig + + (4) The signature will be encapsulated into an ELF note and placed into a file + called foo.ko.note.o using the output from modsign-note.sh piped into the + assembler. + + (5) The unsigned module from (1) and the signature ELF note from (4) will be + linked together to produce foo.ko + +Step (3) requires private and public keys to be available. By default these +are expected to be found in PGP keyring files called modsign.sec (the secret +key) and modsign.pub (the public key) in the build root. + +If the secret key is not found then signing will be skipped and the unsigned +module from (1) will just be copied to foo.ko. + +If signing occurs, lines like the following will be seen: + + LD [M] fs/foo/foo.ko.unsigned + SIGN [M] fs/foo/foo.ko + +will appear in the build log. If it is skipped, the following will be seen: + + LD [M] fs/foo/foo.ko.unsigned + NO SIGN [M] fs/foo/foo.ko + +Signed-off-by: David Howells +--- + scripts/Makefile.modpost | 87 ++++- + scripts/mod/Makefile | 2 +- + scripts/mod/mod-extract.c | 913 +++++++++++++++++++++++++++++++++++++++++++ + scripts/mod/modsign-note.sh | 16 + + 4 files changed, 1016 insertions(+), 2 deletions(-) + create mode 100644 scripts/mod/mod-extract.c + create mode 100644 scripts/mod/modsign-note.sh + diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost -index 08dce14..b436b04 100644 +index 08dce14..17465d8 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -14,7 +14,8 @@ @@ -6266,7 +5008,7 @@ index 08dce14..b436b04 100644 quiet_cmd_ld_ko_o = LD [M] $@ cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \ $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ -@@ -125,7 +129,86 @@ $(modules): %.ko :%.o %.mod.o FORCE +@@ -125,7 +129,88 @@ $(modules): %.ko :%.o %.mod.o FORCE $(call if_changed,ld_ko_o) targets += $(modules) @@ -6284,8 +5026,8 @@ index 08dce14..b436b04 100644 +targets += $(modules:.ko=.ko.unsigned) + +# Step 7), sign the modules -+MODSECKEY = ./kernel.sec -+MODPUBKEY = ./kernel.pub ++MODSECKEY = ./modsign.sec ++MODPUBKEY = ./modsign.pub +KEYFLAGS = --no-default-keyring --secret-keyring $(MODSECKEY) --keyring $(MODPUBKEY) --no-default-keyring --homedir . --no-options --no-auto-check-trustdb --no-permission-warning + +ifdef CONFIG_MODULE_SIG_SHA1 @@ -6331,6 +5073,7 @@ index 08dce14..b436b04 100644 +endif + +ifeq ($(SIGN_MODULES),1) ++KEYRING_DEP := modsign.sec modsign.pub +quiet_cmd_sign_ko_ko_unsigned = SIGN [M] $@ + cmd_sign_ko_ko_unsigned = \ + scripts/mod/mod-extract $< $@.digest && \ @@ -6340,12 +5083,13 @@ index 08dce14..b436b04 100644 + $(CC) -x assembler-with-cpp $(c_flags) $(CFLAGS_MODULE) -c -o $@.note.o - && \ + $(LD) -r $(LDFLAGS) -o $@ $< $@.note.o +else ++KEYRING_DEP := +quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@ + cmd_sign_ko_ko_unsigned = \ + cp $< $@ +endif + -+$(modules): %.ko :%.ko.unsigned FORCE ++$(modules): %.ko :%.ko.unsigned $(KEYRING_DEP) FORCE + $(call if_changed,sign_ko_ko_unsigned) + +targets += $(modules) @@ -6353,16 +5097,6 @@ index 08dce14..b436b04 100644 # Add FORCE to the prequisites of a target to force it to be always rebuilt. # --------------------------------------------------------------------------- -diff --git a/scripts/mod/.gitignore b/scripts/mod/.gitignore -index e9b7abe..223dfd6 100644 ---- a/scripts/mod/.gitignore -+++ b/scripts/mod/.gitignore -@@ -1,4 +1,5 @@ - elfconfig.h - mk_elfconfig - modpost -+mod-extract - diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile index ff954f8..4654e3b 100644 --- a/scripts/mod/Makefile @@ -7315,78 +6049,2048 @@ index 0000000..bca67c0 + +exit 0 -- -1.7.9.1 +1.7.10.2 -From 31e77b71e584a702c8e44b83f6af03bb8511cf8d Mon Sep 17 00:00:00 2001 -From: Josh Boyer -Date: Tue, 6 Mar 2012 12:56:49 -0500 -Subject: [PATCH] Make sure MPILIB is selected for stuff that uses it... -security/built-in.o: In function `public_key_destroy': -/home/jwboyer/kernel/kernel-3.2.fc17/linux-3.3.0-0.rc6.git0.3.fc17.x86_64/security/keys/public_key.c:41: undefined reference to `mpi_free' -security/built-in.o: In function `RSA_verify_signature': -/home/jwboyer/kernel/kernel-3.2.fc17/linux-3.3.0-0.rc6.git0.3.fc17.x86_64/security/keys/crypto_rsa.c:222: undefined reference to `mpi_get_nbits' -/home/jwboyer/kernel/kernel-3.2.fc17/linux-3.3.0-0.rc6.git0.3.fc17.x86_64/security/keys/crypto_rsa.c:224: undefined reference to `mpi_get_nbits' +From 38ddca03060502e8134320b732758fd6b6a98247 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 10 May 2012 23:49:55 +0100 +Subject: [PATCH 23/36] MODSIGN: Module signature verification stub -security/built-in.o: In function `RSAVP1': -/home/jwboyer/kernel/kernel-3.2.fc17/linux-3.3.0-0.rc6.git0.3.fc17.x86_64/security/keys/crypto_rsa.c:93: undefined reference to `mpi_cmp_ui' -/home/jwboyer/kernel/kernel-3.2.fc17/linux-3.3.0-0.rc6.git0.3.fc17.x86_64/security/keys/crypto_rsa.c:97: undefined reference to `mpi_cmp' +Create a stub for the module signature verifier and link it into module.c so +that it gets called. A field is added to struct module to record whether or +not a valid module signature was detected. -Signed-off-by: Josh Boyer +The stub also implements the policy for handling unsigned modules and the +printing of error messages to indicate various problems with the module. + +If CONFIG_MODULE_SIG_FORCE is enabled or "enforcemodulesig=1" is supplied on +the kernel command line, the kernel will _only_ load validly signed modules +for which it has a public key. Otherwise, it will also load modules that are +unsigned. Any module for which the kernel has a key, but which proves to have +a signature mismatch will not be permitted to load. + +This table indicates the behaviours in the various situations: + + MODULE STATE PERMISSIVE MODE ENFORCING MODE + ======================================= =============== =============== + Unsigned Ok EKEYREJECTED + Signed, no public key ENOKEY ENOKEY + Validly signed, public key Ok Ok + Invalidly signed, public key EKEYREJECTED EKEYREJECTED + Validly signed, expired key EKEYEXPIRED EKEYEXPIRED + Signed, hash algorithm unavailable ENOPKG ENOPKG + Corrupt signature EBADMSG EBADMSG + Corrupt ELF ELIBBAD ELIBBAD + +Signed-off-by: David Howells --- - security/keys/Kconfig | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) + include/linux/module.h | 3 ++ + kernel/Makefile | 1 + + kernel/module-verify-defs.h | 77 ++++++++++++++++++++++++++++++ + kernel/module-verify.c | 109 +++++++++++++++++++++++++++++++++++++++++++ + kernel/module-verify.h | 19 ++++++++ + kernel/module.c | 26 +++++++++-- + 6 files changed, 230 insertions(+), 5 deletions(-) + create mode 100644 kernel/module-verify-defs.h + create mode 100644 kernel/module-verify.c + create mode 100644 kernel/module-verify.h -diff --git a/security/keys/Kconfig b/security/keys/Kconfig -index 5e77c2a..e40f9b68 100644 ---- a/security/keys/Kconfig -+++ b/security/keys/Kconfig -@@ -89,12 +89,14 @@ config CRYPTO_KEY_PUBLIC_KEY_SUBTYPE +diff --git a/include/linux/module.h b/include/linux/module.h +index fbcafe2..7391833 100644 +--- a/include/linux/module.h ++++ b/include/linux/module.h +@@ -227,6 +227,9 @@ struct module + /* Unique handle for this module */ + char name[MODULE_NAME_LEN]; - config CRYPTO_KEY_PKEY_ALGO_RSA - tristate "RSA public-key algorithm" -+ select MPILIB_EXTRA - depends on CRYPTO_KEY_PUBLIC_KEY_SUBTYPE - help - This option enables support for the RSA algorithm (PKCS#1, RFC3447). ++ /* Is this module GPG signed */ ++ bool gpgsig_ok; ++ + /* Sysfs stuff. */ + struct module_kobject mkobj; + struct module_attribute *modinfo_attrs; +diff --git a/kernel/Makefile b/kernel/Makefile +index cb41b95..7608053 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -51,6 +51,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o + obj-$(CONFIG_PROVE_LOCKING) += spinlock.o + obj-$(CONFIG_UID16) += uid16.o + obj-$(CONFIG_MODULES) += module.o ++obj-$(CONFIG_MODULE_SIG) += module-verify.o + obj-$(CONFIG_KALLSYMS) += kallsyms.o + obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o + obj-$(CONFIG_KEXEC) += kexec.o +diff --git a/kernel/module-verify-defs.h b/kernel/module-verify-defs.h +new file mode 100644 +index 0000000..292d2ba +--- /dev/null ++++ b/kernel/module-verify-defs.h +@@ -0,0 +1,77 @@ ++/* Module verification internal definitions ++ * ++ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#ifdef CONFIG_MODULE_SIG ++ ++/* ++ * Internal state ++ */ ++struct module_verify_data { ++ struct crypto_key_verify_context *mod_sig; /* Module signing context */ ++ union { ++ const void *buffer; /* module buffer */ ++ const Elf_Ehdr *hdr; /* ELF header */ ++ }; ++ const Elf_Shdr *sections; /* ELF section table */ ++ const char *secstrings; /* ELF section string table */ ++ const void *sig; /* Signature note content */ ++ size_t size; /* module object size */ ++ size_t nsects; /* number of sections */ ++ size_t sig_size; /* Size of signature */ ++ size_t signed_size; /* count of bytes contributed to digest */ ++ unsigned *canonlist; /* list of canonicalised sections */ ++ unsigned *canonmap; /* section canonicalisation map */ ++ unsigned ncanon; /* number of canonicalised sections */ ++ unsigned sig_index; /* module signature section index */ ++ uint8_t xcsum; /* checksum of bytes contributed to digest */ ++ uint8_t csum; /* checksum of bytes representing a section */ ++}; ++ ++/* ++ * Whether or not we support various types of ELF relocation record ++ */ ++#if defined(MODULE_HAS_ELF_REL_ONLY) ++#define is_elf_rel(sh_type) ((sh_type) == SHT_REL) ++#define is_elf_rela(sh_type) (0) ++#elif defined(MODULE_HAS_ELF_RELA_ONLY) ++#define is_elf_rel(sh_type) (0) ++#define is_elf_rela(sh_type) ((sh_type) == SHT_RELA) ++#else ++#define is_elf_rel(sh_type) ((sh_type) == SHT_REL) ++#define is_elf_rela(sh_type) ((sh_type) == SHT_RELA) ++#endif ++ ++/* ++ * Debugging. Define DEBUG to enable. ++ */ ++#define _debug(FMT, ...) \ ++ do { \ ++ if (unlikely(modsign_debug)) \ ++ pr_debug(FMT, ##__VA_ARGS__); \ ++ } while(0) ++ ++#ifdef DEBUG ++#define count_and_csum(C, __p, __n) \ ++do { \ ++ int __loop; \ ++ for (__loop = 0; __loop < __n; __loop++) { \ ++ (C)->csum += __p[__loop]; \ ++ (C)->xcsum += __p[__loop]; \ ++ } \ ++ (C)->signed_size += __n; \ ++} while (0) ++#else ++#define count_and_csum(C, __p, __n) \ ++do { \ ++} while (0) ++#endif ++ ++#endif /* CONFIG_MODULE_SIG */ +diff --git a/kernel/module-verify.c b/kernel/module-verify.c +new file mode 100644 +index 0000000..0a3eb4b +--- /dev/null ++++ b/kernel/module-verify.c +@@ -0,0 +1,109 @@ ++/* Module signature verification ++ * ++ * The code in this file examines a signed kernel module and attempts to ++ * determine if the PGP signature inside the module matches a digest of the ++ * allocatable sections and the canonicalised relocation tables for those ++ * allocatable sections. ++ * ++ * The module signature is included in an ELF note within the ELF structure of ++ * the module blob. This, combined with the minimal canonicalisation performed ++ * here, permits the module to pass through "strip -x", "strip -g" and ++ * "eu-strip" without becoming corrupt. "strip" and "strip -s" will render a ++ * module unusable by removing the symbol table. ++ * ++ * Copyright (C) 2004, 2011, 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * - Derived from GregKH's RSA module signer ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ */ ++ ++#undef DEBUG ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "module-verify.h" ++#include "module-verify-defs.h" ++ ++#ifdef DEBUG ++static int modsign_debug; ++core_param(modsign_debug, modsign_debug, int, 0644); ++#else ++#define modsign_debug false ++#endif ++ ++#ifdef CONFIG_MODULE_SIG_FORCE ++#define modsign_signedonly true ++#else ++static bool modsign_signedonly; ++#endif ++ ++static const char modsign_note_name[] = ELFNOTE_NAME(MODSIGN_NOTE_NAME); ++static const char modsign_note_section[] = ELFNOTE_SECTION(MODSIGN_NOTE_NAME); ++ ++/* ++ * Verify a module's integrity ++ */ ++int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok) ++{ ++ struct module_verify_data mvdata; ++ int ret; ++ ++ memset(&mvdata, 0, sizeof(mvdata)); ++ mvdata.buffer = hdr; ++ mvdata.size = size; ++ ++ if (mvdata.sig_index <= 0) { ++ /* Deal with an unsigned module */ ++ if (modsign_signedonly) { ++ pr_err("An attempt to load unsigned module was rejected\n"); ++ return -EKEYREJECTED; ++ } else { ++ return 0; ++ } ++ goto out; ++ } ++ ++ ret = 0; ++ ++out: ++ switch (ret) { ++ case 0: /* Good signature */ ++ *_gpgsig_ok = true; ++ break; ++ case -ELIBBAD: ++ pr_err("Module format error encountered\n"); ++ break; ++ case -EBADMSG: ++ pr_err("Module signature error encountered\n"); ++ break; ++ case -EKEYREJECTED: /* Signature mismatch or number format error */ ++ pr_err("Module signature verification failed\n"); ++ break; ++ case -ENOKEY: /* Signed, but we don't have the public key */ ++ pr_err("Module signed with unknown public key\n"); ++ break; ++ default: /* Other error (probably ENOMEM) */ ++ break; ++ } ++ return ret; ++} ++ ++static int __init sign_setup(char *str) ++{ ++#ifndef CONFIG_MODULE_SIG_FORCE ++ modsign_signedonly = true; ++#endif ++ return 0; ++} ++__setup("enforcemodulesig", sign_setup); +diff --git a/kernel/module-verify.h b/kernel/module-verify.h +new file mode 100644 +index 0000000..6bb6b56 +--- /dev/null ++++ b/kernel/module-verify.h +@@ -0,0 +1,19 @@ ++/* Module verification definitions ++ * ++ * Copyright (C) 2004, 2012 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ */ ++ ++#ifdef CONFIG_MODULE_SIG ++extern int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok); ++#else ++static inline int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok) ++{ ++ return 0; ++} ++#endif +diff --git a/kernel/module.c b/kernel/module.c +index 377cb06..c3797f7 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -58,6 +58,7 @@ + #include + #include + #include ++#include "module-verify.h" - config PGP_LIBRARY - tristate "PGP parsing library" -+ select MPILIB - help - This option enables a library that provides a number of simple - utility functions for parsing PGP (RFC 4880) packet-based messages. --- -1.7.9.1 - -diff --git a/security/keys/crypto_rsa.c b/security/keys/crypto_rsa.c ---- a/security/keys/crypto_rsa.c ---- b/security/keys/crypto_rsa.c -@@ -219,15 +219,24 @@ - kenter(""); - - /* (1) Check the signature size against the public key modulus size */ -- k = (mpi_get_nbits(key->rsa.n) + 7) / 8; -+ k = mpi_get_nbits(key->rsa.n); -+ tsize = mpi_get_nbits(sig->rsa.s); - -- tsize = (mpi_get_nbits(sig->rsa.s) + 7) / 8; -+ /* According to RFC 4880 sec 3.2, length of MPI is computed starting -+ * from most significant bit. -+ * So the RFC 3447 sec 8.2.2 size check must be relaxed to conform -+ * with shorter signatures. -+ * Fail here only if signature length is longer than modulus size. -+ */ - pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize); -- if (tsize != k) { -+ if (k < tsize) { - ret = -EBADMSG; - goto error; + #define CREATE_TRACE_POINTS + #include +@@ -2402,7 +2403,8 @@ static inline void kmemleak_load_module(const struct module *mod, + /* Sets info->hdr and info->len. */ + static int copy_and_check(struct load_info *info, + const void __user *umod, unsigned long len, +- const char __user *uargs) ++ const char __user *uargs, ++ bool *_gpgsig_ok) + { + int err; + Elf_Ehdr *hdr; +@@ -2435,6 +2437,12 @@ static int copy_and_check(struct load_info *info, + goto free_hdr; } -+ /* Round up to octets */ -+ k = (k + 7) / 8; ++ /* Verify the module's contents */ ++ *_gpgsig_ok = false; ++ err = module_verify(hdr, len, _gpgsig_ok); ++ if (err < 0) ++ goto free_hdr; + - /* (2b) Apply the RSAVP1 verification primitive to the public key */ - ret = RSAVP1(key, sig->rsa.s, &m); + info->hdr = hdr; + info->len = len; + return 0; +@@ -2777,7 +2785,8 @@ int __weak module_frob_arch_sections(Elf_Ehdr *hdr, + return 0; + } + +-static struct module *layout_and_allocate(struct load_info *info) ++static struct module *layout_and_allocate(struct load_info *info, ++ bool gpgsig_ok) + { + /* Module within temporary copy. */ + struct module *mod; +@@ -2787,6 +2796,7 @@ static struct module *layout_and_allocate(struct load_info *info) + mod = setup_load_info(info); + if (IS_ERR(mod)) + return mod; ++ mod->gpgsig_ok = gpgsig_ok; + + err = check_modinfo(mod, info); + if (err) +@@ -2870,17 +2880,18 @@ static struct module *load_module(void __user *umod, + struct load_info info = { NULL, }; + struct module *mod; + long err; ++ bool gpgsig_ok; + + pr_debug("load_module: umod=%p, len=%lu, uargs=%p\n", + umod, len, uargs); + + /* Copy in the blobs from userspace, check they are vaguely sane. */ +- err = copy_and_check(&info, umod, len, uargs); ++ err = copy_and_check(&info, umod, len, uargs, &gpgsig_ok); + if (err) + return ERR_PTR(err); + + /* Figure out module layout, and allocate all the memory. */ +- mod = layout_and_allocate(&info); ++ mod = layout_and_allocate(&info, gpgsig_ok); + if (IS_ERR(mod)) { + err = PTR_ERR(mod); + goto free_copy; +@@ -3517,8 +3528,13 @@ void print_modules(void) + printk(KERN_DEFAULT "Modules linked in:"); + /* Most callers should already have preempt disabled, but make sure */ + preempt_disable(); +- list_for_each_entry_rcu(mod, &modules, list) ++ list_for_each_entry_rcu(mod, &modules, list) { + printk(" %s%s", mod->name, module_flags(mod, buf)); ++#ifdef CONFIG_MODULE_SIG ++ if (!mod->gpgsig_ok) ++ printk("(U)"); ++#endif ++ } + preempt_enable(); + if (last_unloaded_module[0]) + printk(" [last unloaded: %s]", last_unloaded_module); +-- +1.7.10.2 + + +From 6f5323e52cdc37969939ef82036783da67afe69f Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 10 May 2012 23:49:55 +0100 +Subject: [PATCH 24/36] MODSIGN: Provide module signing public keys to the + kernel + +Include a PGP keyring containing the public keys required to perform module +verification in the kernel image during build and create a special keyring +during boot which is then populated with keys of crypto type holding the public +keys found in the PGP keyring. + +These can be seen by root: + +[root@andromeda ~]# cat /proc/keys +07ad4ee0 I----- 1 perm 3f010000 0 0 crypto modsign.0: RSA 87b9b3bd [] +15c7f8c3 I----- 1 perm 1f030000 0 0 keyring .module_sign: 1/4 +... + +It is probably worth permitting root to invalidate these keys, resulting in +their removal and preventing further modules from being loaded with that key. + +Signed-off-by: David Howells +--- + kernel/Makefile | 3 +- + kernel/modsign-pubkey.c | 74 +++++++++++++++++++++++++++++++++++++++++++ + kernel/module-verify-defs.h | 4 +++ + kernel/module-verify.c | 2 -- + 4 files changed, 80 insertions(+), 3 deletions(-) + create mode 100644 kernel/modsign-pubkey.c + +diff --git a/kernel/Makefile b/kernel/Makefile +index 7608053..986ed7f 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -51,7 +51,8 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o + obj-$(CONFIG_PROVE_LOCKING) += spinlock.o + obj-$(CONFIG_UID16) += uid16.o + obj-$(CONFIG_MODULES) += module.o +-obj-$(CONFIG_MODULE_SIG) += module-verify.o ++obj-$(CONFIG_MODULE_SIG) += module-verify.o modsign-pubkey.o ++kernel/modsign-pubkey.o: modsign.pub + obj-$(CONFIG_KALLSYMS) += kallsyms.o + obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o + obj-$(CONFIG_KEXEC) += kexec.o +diff --git a/kernel/modsign-pubkey.c b/kernel/modsign-pubkey.c +new file mode 100644 +index 0000000..2ada460 +--- /dev/null ++++ b/kernel/modsign-pubkey.c +@@ -0,0 +1,74 @@ ++/* Public keys for module signature verification ++ * ++ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. ++ * Written by David Howells (dhowells@redhat.com) ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public Licence ++ * as published by the Free Software Foundation; either version ++ * 2 of the Licence, or (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include "module-verify-defs.h" ++ ++struct key *modsign_keyring; ++ ++extern __initdata const u8 modsign_public_keys[]; ++extern __initdata const u8 modsign_public_keys_end[]; ++asm(".section .init.data,\"aw\"\n" ++ "modsign_public_keys:\n" ++ ".incbin \"modsign.pub\"\n" ++ "modsign_public_keys_end:" ++ ); ++ ++/* ++ * We need to make sure ccache doesn't cache the .o file as it doesn't notice ++ * if modsign.pub changes. ++ */ ++static __initdata const char annoy_ccache[] = __TIME__ "foo"; ++ ++/* ++ * Load the compiled-in keys ++ */ ++static __init int module_verify_init(void) ++{ ++ pr_notice("Initialise module verification\n"); ++ ++ modsign_keyring = key_alloc(&key_type_keyring, ".module_sign", ++ 0, 0, current_cred(), ++ (KEY_POS_ALL & ~KEY_POS_SETATTR) | ++ KEY_USR_VIEW | KEY_USR_READ, ++ KEY_ALLOC_NOT_IN_QUOTA); ++ if (IS_ERR(modsign_keyring)) ++ panic("Can't allocate module signing keyring\n"); ++ ++ if (key_instantiate_and_link(modsign_keyring, NULL, 0, NULL, NULL) < 0) ++ panic("Can't instantiate module signing keyring\n"); ++ ++ return 0; ++} ++ ++/* ++ * Must be initialised before we try and load the keys into the keyring. ++ */ ++device_initcall(module_verify_init); ++ ++/* ++ * Load the compiled-in keys ++ */ ++static __init int modsign_pubkey_init(void) ++{ ++ pr_notice("Load module verification keys\n"); ++ ++ if (preload_pgp_keys(modsign_public_keys, ++ modsign_public_keys_end - modsign_public_keys, ++ modsign_keyring, "modsign.") < 0) ++ panic("Can't load module signing keys\n"); ++ ++ return 0; ++} ++late_initcall(modsign_pubkey_init); +diff --git a/kernel/module-verify-defs.h b/kernel/module-verify-defs.h +index 292d2ba..45bea45 100644 +--- a/kernel/module-verify-defs.h ++++ b/kernel/module-verify-defs.h +@@ -11,6 +11,10 @@ + + #ifdef CONFIG_MODULE_SIG + ++#include ++ ++extern struct key *modsign_keyring; ++ + /* + * Internal state + */ +diff --git a/kernel/module-verify.c b/kernel/module-verify.c +index 0a3eb4b..b1c1d4c 100644 +--- a/kernel/module-verify.c ++++ b/kernel/module-verify.c +@@ -27,8 +27,6 @@ + #include + #include + #include +-#include +-#include + #include + #include + #include +-- +1.7.10.2 + + +From 5727333d123ef9d7fa2666069306bf3ec2d7f110 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 10 May 2012 23:49:56 +0100 +Subject: [PATCH 25/36] MODSIGN: Check the ELF container + +Check the ELF container of the kernel module to prevent the kernel from +crashing or getting corrupted whilst trying to use it and locate the module +signature note if present. + +We try to check as little as possible. We check the metadata that the +signature checker actually has to use, and leave anything that it doesn't +actually need to the signature to catch. + +The stuff we need to check is: + + (1) The locations and offsets in the ELF header of important parts like the + section table. + + (2) The section table. Note that we only check sh_info for section types that + we're actually interested in (string, symbol and relocation tables). We + also check that alignments are what we expect for those tables. + + (3) That non-empty string tables have the required NUL at the end so that we + can be sure that all strings therein are NUL-terminated. We don't bother + checking for the required NUL at the beginning as it shouldn't cause a + problem to us. + + (4) The name offset and section index in each symbol. We could defer this to + when we deal with the relocation tables so that we only check symbols that + are used by relocations - but we would then end up checking some symbols + multiple times. + + (5) The module signature note section and the first note in it if present. + + (6) That relocations applied to an allocatable section only refer to + symbols in allocatable sections and absolute symbols (done in the module + signing code rather than here). + +Note that these checks survive "strip -x", "strip -g" and "eu-strip" being +applied to a module and detect if the module was given to "strip" or "strip -s" +and report an error. + +We can skip some direct checks that turn out unnecessary or redundant: + + (1) That sh_link has a greater than 0 value for symbol tables and relocation + tables. These require the index of a string table and a symbol table + respectively - and since we have already checked section 0 is of SHT_NULL + type, checking the symbol type renders the sh_link > 0 check redundant. + + (2) That a non-empty string table begins with a NUL. Since we check the + string table ends with a NUL, any string in there will be NUL-terminated + and shouldn't cause us to transgress beyond the bounds of the string table + when using strlen(). + + (3) That strings in a string table actually make sense. We don't care, so + long as it is NUL terminated. Any string that refers to an undefined + symbol is added to the crypto digest and will be checked that way. + Strings that we directly look for (such as ".modinfo") will be validated + by that. + + (4) That sections don't overlap. We don't actually care if sections overlap + in the file, provided we don't see bad metadata. If the sections holding + the allocatable content overlap, then the signature check is likely to + fail. + + (5) That symbol values and relocation offsets and addends make sense. We just + add this data to the digest if it pertains to an allocatable section. + + (6) That allocatable note sections, other than the signature note, make sense. + The contents of these get added to the digest in their entirety, so we + don't need to check them manually. + +If bad ELF is detected, ELIBBAD is indicated. + +Note! The "noinline" attribute on the module_verify_elf() function results in +somewhat smaller code. Similarly, having separate loops to check basic section +parameters and to check type-specific features of sections results in smaller +code, presumably because some local variables can be discarded. + +Signed-off-by: David Howells +--- + kernel/module-verify.c | 226 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 226 insertions(+) + +diff --git a/kernel/module-verify.c b/kernel/module-verify.c +index b1c1d4c..5711aeb 100644 +--- a/kernel/module-verify.c ++++ b/kernel/module-verify.c +@@ -50,6 +50,224 @@ static const char modsign_note_name[] = ELFNOTE_NAME(MODSIGN_NOTE_NAME); + static const char modsign_note_section[] = ELFNOTE_SECTION(MODSIGN_NOTE_NAME); + + /* ++ * Verify the minimum amount of ELF structure of a module needed to check the ++ * module's signature without bad ELF crashing the kernel. ++ */ ++static noinline int module_verify_elf(struct module_verify_data *mvdata) ++{ ++ const struct elf_note *note; ++ const Elf_Ehdr *hdr = mvdata->hdr; ++ const Elf_Shdr *section, *secstop; ++ const Elf_Sym *symbols, *symbol, *symstop; ++ const char *strtab; ++ size_t size, secsize, secstrsize, strsize, notesize, notemetasize; ++ unsigned line; ++ ++ size = mvdata->size; ++ ++#define elfcheck(X) \ ++do { if (unlikely(!(X))) { line = __LINE__; goto elfcheck_error; } } while(0) ++ ++#define seccheck(X) \ ++do { if (unlikely(!(X))) { line = __LINE__; goto seccheck_error; } } while(0) ++ ++#define symcheck(X) \ ++do { if (unlikely(!(X))) { line = __LINE__; goto symcheck_error; } } while(0) ++ ++ /* Validate the ELF header */ ++ elfcheck(size > sizeof(Elf_Ehdr)); ++ elfcheck(hdr->e_ehsize < size); ++ ++ elfcheck(hdr->e_shnum < SHN_LORESERVE); ++ elfcheck(hdr->e_shstrndx < hdr->e_shnum); ++ elfcheck(hdr->e_shentsize == sizeof(Elf_Shdr)); ++ elfcheck(hdr->e_shoff < size); ++ elfcheck(hdr->e_shoff >= hdr->e_ehsize); ++ elfcheck(hdr->e_shoff % sizeof(long) == 0); ++ elfcheck(hdr->e_shnum * sizeof(Elf_Shdr) <= size - hdr->e_shoff); ++ ++ /* Validate the section table contents */ ++ mvdata->nsects = hdr->e_shnum; ++ mvdata->sections = mvdata->buffer + hdr->e_shoff; ++ secstop = mvdata->sections + mvdata->nsects; ++ ++ /* Section 0 is special, usually indicating an undefined symbol */ ++ seccheck(mvdata->sections[SHN_UNDEF].sh_type == SHT_NULL); ++ ++ /* We also want access to the section name table */ ++ seccheck(mvdata->sections[hdr->e_shstrndx].sh_type == SHT_STRTAB); ++ secstrsize = mvdata->sections[hdr->e_shstrndx].sh_size; ++ ++ for (section = mvdata->sections + 1; section < secstop; section++) { ++ seccheck(section->sh_name < secstrsize); ++ seccheck(section->sh_link < hdr->e_shnum); ++ ++ /* Section file offsets must reside within the file, though ++ * they don't have to actually consume file space (.bss for ++ * example). ++ */ ++ seccheck(section->sh_offset >= hdr->e_ehsize); ++ seccheck((section->sh_offset & (section->sh_addralign - 1)) == 0); ++ seccheck(section->sh_offset <= size); ++ if (section->sh_type != SHT_NOBITS) ++ seccheck(section->sh_size <= size - section->sh_offset); ++ ++ /* Some types of section should contain arrays of fixed-length ++ * records of a predetermined size and mustn't contain partial ++ * records. Also, records we're going to access directly must ++ * have appropriate alignment that we don't get a misalignment ++ * exception. ++ */ ++ if (section->sh_entsize > 1) ++ seccheck(section->sh_size % section->sh_entsize == 0); ++ ++ switch (section->sh_type) { ++ case SHT_SYMTAB: ++ seccheck(section->sh_entsize == sizeof(Elf_Sym)); ++ seccheck(section->sh_addralign % sizeof(long) == 0); ++ break; ++ case SHT_REL: ++#ifndef MODULE_HAS_ELF_RELA_ONLY ++ seccheck(section->sh_entsize == sizeof(Elf_Rel)); ++ seccheck(section->sh_addralign % sizeof(long) == 0); ++ break; ++#else ++ seccheck(false); ++ break; ++#endif ++ case SHT_RELA: ++#ifndef MODULE_HAS_ELF_REL_ONLY ++ seccheck(section->sh_entsize == sizeof(Elf_Rela)); ++ seccheck(section->sh_addralign % sizeof(long) == 0); ++ break; ++#else ++ seccheck(false); ++ break; ++#endif ++ case SHT_NOTE: ++ seccheck(section->sh_addralign % 4 == 0); ++ break; ++ case SHT_STRTAB: ++ /* We require all string tables to be non-empty. If ++ * not empty, a string table must end in a NUL (it ++ * should also begin with a NUL, but it's not a problem ++ * for us if it doesn't). ++ */ ++ seccheck(section->sh_size >= 2); ++ strtab = mvdata->buffer + section->sh_offset; ++ seccheck(strtab[section->sh_size - 1] == '\0'); ++ break; ++ } ++ } ++ ++ /* Check features specific to the type of each section. ++ * ++ * Note that having a separate loop here allows the compiler to discard ++ * some local variables used in the above loop thus making the code ++ * smaller. ++ */ ++ for (section = mvdata->sections + 1; section < secstop; section++) { ++ switch (section->sh_type) { ++ case SHT_SYMTAB: ++ /* Symbol tables nominate a string table. */ ++ seccheck(mvdata->sections[section->sh_link].sh_type == ++ SHT_STRTAB); ++ ++ /* Validate the symbols in the table. The first symbol ++ * (STN_UNDEF) is special. ++ */ ++ symbol = symbols = mvdata->buffer + section->sh_offset; ++ symstop = mvdata->buffer + ++ (section->sh_offset + section->sh_size); ++ ++ symcheck(ELF_ST_TYPE(symbols[0].st_info) == STT_NOTYPE); ++ symcheck(symbol[0].st_shndx == SHN_UNDEF); ++ ++ strsize = mvdata->sections[section->sh_link].sh_size; ++ for (symbol++; symbol < symstop; symbol++) { ++ symcheck(symbol->st_name < strsize); ++ symcheck(symbol->st_shndx < hdr->e_shnum || ++ symbol->st_shndx >= SHN_LORESERVE); ++ } ++ break; ++ ++#ifndef MODULE_HAS_ELF_RELA_ONLY ++ case SHT_REL: ++#endif ++#ifndef MODULE_HAS_ELF_REL_ONLY ++ case SHT_RELA: ++#endif ++ /* Relocation tables nominate a symbol table and a ++ * target section to which the relocations will be ++ * applied. ++ */ ++ seccheck(mvdata->sections[section->sh_link].sh_type == ++ SHT_SYMTAB); ++ seccheck(section->sh_info > 0); ++ seccheck(section->sh_info < hdr->e_shnum); ++ break; ++ } ++ } ++ ++ /* We can now use section name string table section as we checked its ++ * bounds in the loop above. ++ * ++ * Each name is NUL-terminated, and the table as a whole should have a ++ * NUL at either end as there to be at least one named section for the ++ * module information. ++ */ ++ section = &mvdata->sections[hdr->e_shstrndx]; ++ mvdata->secstrings = mvdata->buffer + section->sh_offset; ++ ++ for (section = mvdata->sections + 1; section < secstop; section++) { ++ const char *name = mvdata->secstrings + section->sh_name; ++ ++ switch (section->sh_type) { ++ case SHT_NOTE: ++ if (strcmp(name, modsign_note_section) != 0) ++ continue; ++ ++ /* We've found a note purporting to contain a signature ++ * so we should check the structure of that. ++ */ ++ notemetasize = sizeof(struct elf_note) + ++ roundup(sizeof(modsign_note_name), 4); ++ ++ seccheck(mvdata->sig_index == 0); ++ seccheck(section->sh_size > notemetasize); ++ note = mvdata->buffer + section->sh_offset; ++ seccheck(note->n_type == MODSIGN_NOTE_TYPE); ++ seccheck(note->n_namesz == sizeof(modsign_note_name)); ++ ++ notesize = section->sh_size - notemetasize; ++ seccheck(note->n_descsz <= notesize); ++ ++ seccheck(memcmp(note + 1, modsign_note_name, ++ note->n_namesz) == 0); ++ ++ mvdata->sig_size = note->n_descsz; ++ mvdata->sig = (void *)note + notemetasize; ++ mvdata->sig_index = section - mvdata->sections; ++ break; ++ } ++ } ++ ++ return 0; ++ ++elfcheck_error: ++ _debug("Verify ELF error (check %u)\n", line); ++ return -ELIBBAD; ++seccheck_error: ++ _debug("Verify ELF error [sec %ld] (check %u)\n", ++ (long)(section - mvdata->sections), line); ++ return -ELIBBAD; ++symcheck_error: ++ _debug("Verify ELF error [sym %ld] (check %u)\n", ++ (long)(symbol - symbols), line); ++ return -ELIBBAD; ++} ++ ++/* + * Verify a module's integrity + */ + int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok) +@@ -61,6 +279,14 @@ int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok) + mvdata.buffer = hdr; + mvdata.size = size; + ++ /* Minimally check the ELF to make sure building the signature digest ++ * won't crash the kernel. ++ */ ++ ret = module_verify_elf(&mvdata); ++ if (ret < 0) ++ goto out; ++ ++ /* The ELF checker found the sig for us if it exists */ + if (mvdata.sig_index <= 0) { + /* Deal with an unsigned module */ + if (modsign_signedonly) { +-- +1.7.10.2 + + +From 21a28e681f53685960f2780b7884e8b391122259 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 10 May 2012 23:49:56 +0100 +Subject: [PATCH 26/36] MODSIGN: Produce a filtered and canonicalised section + list + +Build a list of the sections in which we're interested and canonicalise the +section indices to avoid the problems of the section table being altered by ld +when the signature is linked into the binary and by strip. + +The only sections in which we're actually interested are those that are marked +allocatable (which will be kept in memory) and relocation tables that are +applicable to those sections. + +Canonicalisation is done by sorting the filtered list in order of section name. + +Signed-off-by: David Howells +--- + kernel/module-verify.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 80 insertions(+) + +diff --git a/kernel/module-verify.c b/kernel/module-verify.c +index 5711aeb..13c60c2 100644 +--- a/kernel/module-verify.c ++++ b/kernel/module-verify.c +@@ -268,6 +268,80 @@ symcheck_error: + } + + /* ++ * Canonicalise the section table index numbers. ++ * ++ * We build a list of the sections we want to add to the digest and sort it by ++ * name. We're only interested in adding two types of section: ++ * ++ * (1) Allocatable sections. These should have no references to other ++ * sections. ++ * ++ * (2) Relocation tables for allocatable sections. The section table entry ++ * has a reference to the target section to which the relocations will be ++ * applied. The relocation entries have references to symbols in ++ * non-allocatable sections. Symbols can be replaced by their contents, ++ * but do include a further reference to a section - which must be ++ * canonicalised. ++ * ++ * We also build a map of raw section index to canonical section index. ++ */ ++static int module_verify_canonicalise(struct module_verify_data *mvdata) ++{ ++ const Elf_Shdr *sechdrs = mvdata->sections; ++ unsigned *canonlist, canon, loop, tmp; ++ bool changed; ++ ++ canonlist = kmalloc(sizeof(unsigned) * mvdata->nsects * 2, GFP_KERNEL); ++ if (!canonlist) ++ return -ENOMEM; ++ ++ mvdata->canonlist = canonlist; ++ mvdata->canonmap = canonlist + mvdata->nsects; ++ canon = 0; ++ ++ for (loop = 1; loop < mvdata->nsects; loop++) { ++ const Elf_Shdr *section = mvdata->sections + loop; ++ ++ if (loop == mvdata->sig_index) ++ continue; ++ ++ /* We only want allocatable sections and relocation tables */ ++ if (section->sh_flags & SHF_ALLOC) ++ canonlist[canon++] = loop; ++ else if ((is_elf_rel(section->sh_type) || ++ is_elf_rela(section->sh_type)) && ++ mvdata->sections[section->sh_info].sh_flags & SHF_ALLOC) ++ canonlist[canon++] = loop; ++ } ++ ++ /* Sort the canonicalisation list */ ++ do { ++ changed = false; ++ ++ for (loop = 0; loop < canon - 1; loop++) { ++ const char *x, *y; ++ ++ x = mvdata->secstrings + sechdrs[canonlist[loop + 0]].sh_name; ++ y = mvdata->secstrings + sechdrs[canonlist[loop + 1]].sh_name; ++ ++ if (strcmp(x, y) > 0) { ++ tmp = canonlist[loop + 0]; ++ canonlist[loop + 0] = canonlist[loop + 1]; ++ canonlist[loop + 1] = tmp; ++ changed = true; ++ } ++ } ++ } while (changed); ++ ++ /* What we really want is a raw-to-canon lookup table */ ++ memset(mvdata->canonmap, 0xff, mvdata->nsects * sizeof(unsigned)); ++ for (loop = 0; loop < canon; loop++) ++ mvdata->canonmap[mvdata->canonlist[loop]] = loop + 1; ++ mvdata->ncanon = canon; ++ return 0; ++} ++ ++/* + * Verify a module's integrity + */ + int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok) +@@ -298,7 +372,13 @@ int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok) + goto out; + } + ++ /* Produce a canonicalisation map for the sections */ ++ ret = module_verify_canonicalise(&mvdata); ++ if (ret < 0) ++ goto out; ++ + ret = 0; ++ kfree(mvdata.canonlist); + + out: + switch (ret) { +-- +1.7.10.2 + + +From 92fb97859c50a0dd63886baf057477a7a336b2a1 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 10 May 2012 23:49:56 +0100 +Subject: [PATCH 27/36] MODSIGN: Create digest of module content and check + signature + +Apply signature checking to modules on module load, checking the signature +against the ring of public keys compiled into the kernel (if enabled by +CONFIG_MODULE_SIG). Turning on signature checking will also force the module's +ELF metadata to be verified first. + +There are several reasons why these patches are useful, amongst which are: + + (1) to prevent accidentally corrupted modules from causing damage; + + (2) to prevent maliciously modified modules from causing damage; + + (3) to allow a sysadmin (or more likely an IT department) to enforce a policy + that only known and approved modules shall be loaded onto machines which + they're expected to support; + + (4) to allow other support providers to do likewise, or at least to _detect_ + the fact that unsupported modules are loaded; + + (5) to allow the detection of modules replaced by a second-order distro or a + preloaded Linux purveyor. + +These patches have two main appeals: (a) preventing malicious modules from +being loaded, and (b) reducing support workload by pointing out modules on a +crashing box that aren't what they're expected to be. + +Note that this is not a complete solution by any means: the core kernel is not +protected, and nor are /dev/mem or /dev/kmem, but it denies (or at least +controls) one relatively simple attack vector. To protect the kernel image +would be the responsibility of the boot loader or the system BIOS. + +This facility is optional: the builder of a kernel is by no means under any +requirement to actually enable it, let alone force the set of loadable modules +to be restricted to just those that the builder provides (there are degrees of +restriction available). + +Note! The "noinline" attribute on module_verify_signature() results in +somewhat smaller code. + +Signed-off-by: David Howells +--- + kernel/module-verify.c | 321 +++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 320 insertions(+), 1 deletion(-) + +diff --git a/kernel/module-verify.c b/kernel/module-verify.c +index 13c60c2..a31b39c 100644 +--- a/kernel/module-verify.c ++++ b/kernel/module-verify.c +@@ -49,6 +49,22 @@ static bool modsign_signedonly; + static const char modsign_note_name[] = ELFNOTE_NAME(MODSIGN_NOTE_NAME); + static const char modsign_note_section[] = ELFNOTE_SECTION(MODSIGN_NOTE_NAME); + ++#define crypto_digest_update_data(C, PTR, N) \ ++do { \ ++ uint8_t *__p = (uint8_t *)(PTR); \ ++ size_t __n = (N); \ ++ count_and_csum((C), __p, __n); \ ++ verify_sig_add_data((C)->mod_sig, __p, __n); \ ++} while (0) ++ ++#define crypto_digest_update_val(C, VAL) \ ++do { \ ++ uint8_t *__p = (uint8_t *)&(VAL); \ ++ size_t __n = sizeof(VAL); \ ++ count_and_csum((C), __p, __n); \ ++ verify_sig_add_data((C)->mod_sig, __p, __n); \ ++} while (0) ++ + /* + * Verify the minimum amount of ELF structure of a module needed to check the + * module's signature without bad ELF crashing the kernel. +@@ -342,6 +358,309 @@ static int module_verify_canonicalise(struct module_verify_data *mvdata) + } + + /* ++ * Extract an ELF REL table ++ * ++ * We need to canonicalise the entries in case section/symbol addition/removal ++ * has rearranged the symbol table and the section table. ++ */ ++static int extract_elf_rel(struct module_verify_data *mvdata, ++ unsigned secix, ++ const Elf_Rel *reltab, size_t nrels, ++ const char *sh_name) ++{ ++ struct { ++#if defined(MODULES_ARE_ELF32) ++ uint32_t r_offset; ++ uint32_t st_value; ++ uint32_t st_size; ++ uint16_t st_shndx; ++ uint8_t r_type; ++ uint8_t st_info; ++ uint8_t st_other; ++#elif defined(MODULES_ARE_ELF64) ++ uint64_t r_offset; ++ uint64_t st_value; ++ uint64_t st_size; ++ uint32_t r_type; ++ uint16_t st_shndx; ++ uint8_t st_info; ++ uint8_t st_other; ++#else ++#error unsupported module type ++#endif ++ } __attribute__((packed)) relocation; ++ ++ const Elf_Rel *reloc; ++ const Elf_Sym *symbols, *symbol; ++ const char *strings; ++ unsigned long r_sym; ++ size_t nsyms, loop; ++ ++ nsyms = mvdata->sections[secix].sh_size / sizeof(Elf_Sym); ++ symbols = mvdata->buffer + mvdata->sections[secix].sh_offset; ++ strings = mvdata->buffer + ++ mvdata->sections[mvdata->sections[secix].sh_link].sh_offset; ++ ++ /* Contribute the relevant bits from a join of { REL, SYMBOL, SECTION } */ ++ for (loop = 0; loop < nrels; loop++) { ++ unsigned st_shndx; ++ ++ reloc = &reltab[loop]; ++ ++ /* Decode the relocation */ ++ relocation.r_offset = reloc->r_offset; ++ relocation.r_type = ELF_R_TYPE(reloc->r_info); ++ ++ /* Decode the symbol referenced by the relocation */ ++ r_sym = ELF_R_SYM(reloc->r_info); ++ if (r_sym >= nsyms) ++ return -ELIBBAD; ++ symbol = &symbols[r_sym]; ++ relocation.st_info = symbol->st_info; ++ relocation.st_other = symbol->st_other; ++ relocation.st_value = symbol->st_value; ++ relocation.st_size = symbol->st_size; ++ relocation.st_shndx = symbol->st_shndx; ++ st_shndx = symbol->st_shndx; ++ ++ /* Canonicalise the section used by the symbol */ ++ if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects) { ++ if (!(mvdata->sections[st_shndx].sh_flags & SHF_ALLOC)) ++ return -ELIBBAD; ++ relocation.st_shndx = mvdata->canonmap[st_shndx]; ++ } ++ ++ crypto_digest_update_val(mvdata, relocation); ++ ++ /* Undefined symbols must be named if referenced */ ++ if (st_shndx == SHN_UNDEF) { ++ const char *name = strings + symbol->st_name; ++ crypto_digest_update_data(mvdata, ++ name, strlen(name) + 1); ++ } ++ } ++ ++ _debug("%08zx %02x digested the %s section, nrels %zu\n", ++ mvdata->signed_size, mvdata->csum, sh_name, nrels); ++ ++ return 0; ++} ++ ++/* ++ * Extract an ELF RELA table ++ * ++ * We need to canonicalise the entries in case section/symbol addition/removal ++ * has rearranged the symbol table and the section table. ++ */ ++static int extract_elf_rela(struct module_verify_data *mvdata, ++ unsigned secix, ++ const Elf_Rela *relatab, size_t nrels, ++ const char *sh_name) ++{ ++ struct { ++#if defined(MODULES_ARE_ELF32) ++ uint32_t r_offset; ++ uint32_t r_addend; ++ uint32_t st_value; ++ uint32_t st_size; ++ uint16_t st_shndx; ++ uint8_t r_type; ++ uint8_t st_info; ++ uint8_t st_other; ++#elif defined(MODULES_ARE_ELF64) ++ uint64_t r_offset; ++ uint64_t r_addend; ++ uint64_t st_value; ++ uint64_t st_size; ++ uint32_t r_type; ++ uint16_t st_shndx; ++ uint8_t st_info; ++ uint8_t st_other; ++#else ++#error unsupported module type ++#endif ++ } __attribute__((packed)) relocation; ++ ++ const Elf_Shdr *relsec, *symsec, *strsec; ++ const Elf_Rela *reloc; ++ const Elf_Sym *symbols, *symbol; ++ unsigned long r_sym; ++ const char *strings; ++ size_t nsyms, loop; ++ ++ relsec = &mvdata->sections[secix]; ++ symsec = &mvdata->sections[relsec->sh_link]; ++ strsec = &mvdata->sections[symsec->sh_link]; ++ nsyms = symsec->sh_size / sizeof(Elf_Sym); ++ symbols = mvdata->buffer + symsec->sh_offset; ++ strings = mvdata->buffer + strsec->sh_offset; ++ ++ /* Contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */ ++ for (loop = 0; loop < nrels; loop++) { ++ unsigned st_shndx; ++ ++ reloc = &relatab[loop]; ++ ++ /* Decode the relocation */ ++ relocation.r_offset = reloc->r_offset; ++ relocation.r_addend = reloc->r_addend; ++ relocation.r_type = ELF_R_TYPE(reloc->r_info); ++ ++ /* Decode the symbol referenced by the relocation */ ++ r_sym = ELF_R_SYM(reloc->r_info); ++ if (r_sym >= nsyms) ++ return -ELIBBAD; ++ symbol = &symbols[r_sym]; ++ relocation.st_info = symbol->st_info; ++ relocation.st_other = symbol->st_other; ++ relocation.st_value = symbol->st_value; ++ relocation.st_size = symbol->st_size; ++ relocation.st_shndx = 0; ++ st_shndx = symbol->st_shndx; ++ ++ /* Canonicalise the section used by the symbol */ ++ if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects) { ++ if (!(mvdata->sections[st_shndx].sh_flags & SHF_ALLOC)) ++ return -ELIBBAD; ++ relocation.st_shndx = mvdata->canonmap[st_shndx]; ++ } ++ ++ crypto_digest_update_val(mvdata, relocation); ++ ++ /* Undefined symbols must be named if referenced */ ++ if (st_shndx == SHN_UNDEF) { ++ const char *name = strings + symbol->st_name; ++ crypto_digest_update_data(mvdata, ++ name, strlen(name) + 1); ++ } ++ } ++ ++ _debug("%08zx %02x digested the %s section, nrels %zu\n", ++ mvdata->signed_size, mvdata->csum, sh_name, nrels); ++ ++ return 0; ++} ++ ++/* ++ * Verify a module's signature ++ */ ++static noinline int module_verify_signature(struct module_verify_data *mvdata) ++{ ++ struct crypto_key_verify_context *mod_sig; ++ const Elf_Shdr *sechdrs = mvdata->sections; ++ const char *secstrings = mvdata->secstrings; ++ const u8 *sig = mvdata->sig; ++ size_t sig_size = mvdata->sig_size; ++ int loop, ret; ++ ++ _debug("sig in section %u (size %zu)\n", ++ mvdata->sig_index, mvdata->sig_size); ++ _debug("%02x%02x%02x%02x%02x%02x%02x%02x\n", ++ sig[0], sig[1], sig[2], sig[3], ++ sig[4], sig[5], sig[6], sig[7]); ++ ++ /* Find the crypto key for the module signature ++ * - !!! if this tries to load the required hash algorithm module, ++ * we will deadlock!!! ++ */ ++ mod_sig = verify_sig_begin(modsign_keyring, sig, sig_size); ++ if (IS_ERR(mod_sig)) { ++ pr_err("Couldn't initiate module signature verification: %ld\n", ++ PTR_ERR(mod_sig)); ++ return PTR_ERR(mod_sig); ++ } ++ ++ mvdata->mod_sig = mod_sig; ++#ifdef DEBUG ++ mvdata->xcsum = 0; ++#endif ++ ++ /* Load data from each relevant section into the digest. Note that ++ * canonlist[] is a filtered list and only contains the sections we ++ * actually want. ++ */ ++ for (loop = 0; loop < mvdata->ncanon; loop++) { ++ int sect = mvdata->canonlist[loop]; ++ unsigned long sh_type = sechdrs[sect].sh_type; ++ unsigned long sh_info = sechdrs[sect].sh_info; ++ unsigned long sh_size = sechdrs[sect].sh_size; ++ const char *sh_name = secstrings + sechdrs[sect].sh_name; ++ const void *data = mvdata->buffer + sechdrs[sect].sh_offset; ++ ++#ifdef DEBUG ++ mvdata->csum = 0; ++#endif ++ ++ /* Digest the headers of any section we include. */ ++ crypto_digest_update_data(mvdata, sh_name, strlen(sh_name)); ++ crypto_digest_update_val(mvdata, sechdrs[sect].sh_type); ++ crypto_digest_update_val(mvdata, sechdrs[sect].sh_flags); ++ crypto_digest_update_val(mvdata, sechdrs[sect].sh_size); ++ crypto_digest_update_val(mvdata, sechdrs[sect].sh_addralign); ++ ++ /* Relocation record sections refer to the section to be ++ * relocated, but this needs to be canonicalised to survive ++ * stripping. ++ */ ++ if (is_elf_rel(sh_type) || is_elf_rela(sh_type)) ++ crypto_digest_update_val(mvdata, ++ mvdata->canonmap[sh_info]); ++ ++ /* Since relocation records give details of how we have to ++ * alter the allocatable sections, we need to digest these too. ++ * ++ * These, however, refer to metadata (symbols and sections) ++ * that may have been altered by the process of adding the ++ * signature section or the process of being stripped. ++ * ++ * To deal with this, we substitute the referenced metadata for ++ * the references to that metadata. So, for instance, the ++ * symbol ref from the relocation record is replaced with the ++ * contents of the symbol to which it refers, and the symbol's ++ * section ref is replaced with a canonicalised section number. ++ */ ++ if (is_elf_rel(sh_type)) { ++ ret = extract_elf_rel(mvdata, sect, ++ data, ++ sh_size / sizeof(Elf_Rel), ++ sh_name); ++ if (ret < 0) ++ goto format_error; ++ continue; ++ } ++ ++ if (is_elf_rela(sh_type)) { ++ ret = extract_elf_rela(mvdata, sect, ++ data, ++ sh_size / sizeof(Elf_Rela), ++ sh_name); ++ if (ret < 0) ++ goto format_error; ++ continue; ++ } ++ ++ /* Include allocatable loadable sections */ ++ if (sh_type != SHT_NOBITS) ++ crypto_digest_update_data(mvdata, data, sh_size); ++ ++ _debug("%08zx %02x digested the %s section, size %ld\n", ++ mvdata->signed_size, mvdata->csum, sh_name, sh_size); ++ } ++ ++ _debug("Contributed %zu bytes to the digest (csum 0x%02x)\n", ++ mvdata->signed_size, mvdata->xcsum); ++ ++ /* Do the actual signature verification */ ++ ret = verify_sig_end(mvdata->mod_sig, sig, sig_size); ++ _debug("verify-sig : %d\n", ret); ++ return ret; ++ ++format_error: ++ verify_sig_cancel(mvdata->mod_sig); ++ return -ELIBBAD; ++} ++ ++/* + * Verify a module's integrity + */ + int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok) +@@ -377,7 +696,7 @@ int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok) if (ret < 0) + goto out; + +- ret = 0; ++ ret = module_verify_signature(&mvdata); + kfree(mvdata.canonlist); + + out: +-- +1.7.10.2 + + +From 2e9f557c1235027c0c7223a8a072333758905066 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 10 May 2012 23:49:57 +0100 +Subject: [PATCH 28/36] MODSIGN: Automatically generate module signing keys if + missing + +Automatically generate keys for module signing if they're absent so that +allyesconfig doesn't break. The builder should consider generating their own +keyrings, however, so that the keys are appropriately named and any extra keys +required get imported. + +Also change the names of the keyring files to modsign.pub and modsign.sec so +that they are then a more obvious what they're about and add a dependency for +the signing rules on the keyring files so that the signatures get regenerated +if the keyrings change. + +Signed-off-by: David Howells +--- + kernel/Makefile | 42 +++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 41 insertions(+), 1 deletion(-) + +diff --git a/kernel/Makefile b/kernel/Makefile +index 986ed7f..d8139bb 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -52,7 +52,6 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o + obj-$(CONFIG_UID16) += uid16.o + obj-$(CONFIG_MODULES) += module.o + obj-$(CONFIG_MODULE_SIG) += module-verify.o modsign-pubkey.o +-kernel/modsign-pubkey.o: modsign.pub + obj-$(CONFIG_KALLSYMS) += kallsyms.o + obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o + obj-$(CONFIG_KEXEC) += kexec.o +@@ -129,3 +128,44 @@ quiet_cmd_timeconst = TIMEC $@ + targets += timeconst.h + $(obj)/timeconst.h: $(src)/timeconst.pl FORCE + $(call if_changed,timeconst) ++ ++############################################################################### ++# ++# If module signing is requested, say by allyesconfig, but a key has not been ++# supplied, then one will need to be generated to make sure the build does not ++# fail and that the kernel may be used afterwards. ++# ++############################################################################### ++ifeq ($(CONFIG_MODULE_SIG),y) ++kernel/modsign-pubkey.o: modsign.pub ++ ++modsign.pub modsign.sec: genkey ++ @echo "###" ++ @echo "### Now generating a PGP key pair to be used for signing modules." ++ @echo "###" ++ @echo "### If this takes a long time, you might wish to run rngd in the" ++ @echo "### background to keep the supply of entropy topped up. It" ++ @echo "### needs to be run as root, and should use a hardware random" ++ @echo "### number generator if one is available, eg:" ++ @echo "###" ++ @echo "### rngd -r /dev/hwrandom" ++ @echo "###" ++ gpg --homedir . --batch --gen-key genkey ++ @echo "###" ++ @echo "### Key pair generated." ++ @echo "###" ++ rm -f pubring.gpg secring.gpg trustdb.gpg ++ ++genkey: ++ echo "%pubring modsign.pub" >genkey ++ echo "%secring modsign.sec" >>genkey ++ echo "%no-protection: yes" >> genkey ++ echo "%transient-key: yes" >>genkey ++ echo "Key-Type: RSA" >>genkey ++ echo "Key-Length: 4096" >>genkey ++ echo "Name-Real: Sample kernel key" >>genkey ++ echo "Name-Comment: Sample kernel module signing key" >>genkey ++ echo "%commit" >>genkey ++ ++endif ++CLEAN_FILES += modsign.pub modsign.sec genkey random_seed +-- +1.7.10.2 + + +From 958049a9def253735019a5acf19b4c2aeec9f01c Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 10 May 2012 23:55:35 +0100 +Subject: [PATCH 29/36] MODSIGN: Suppress some redundant ELF checks + +Suppress some redundant ELF checks in module_verify_elf() that are also done +by copy_and_check() in the core module loader code prior to calling +module_verify(). + +Signed-off-by: David Howells +--- + kernel/module-verify.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/kernel/module-verify.c b/kernel/module-verify.c +index a31b39c..e1bfd28 100644 +--- a/kernel/module-verify.c ++++ b/kernel/module-verify.c +@@ -76,7 +76,7 @@ static noinline int module_verify_elf(struct module_verify_data *mvdata) + const Elf_Shdr *section, *secstop; + const Elf_Sym *symbols, *symbol, *symstop; + const char *strtab; +- size_t size, secsize, secstrsize, strsize, notesize, notemetasize; ++ size_t size, secstrsize, strsize, notesize, notemetasize; + unsigned line; + + size = mvdata->size; +@@ -96,11 +96,11 @@ do { if (unlikely(!(X))) { line = __LINE__; goto symcheck_error; } } while(0) + + elfcheck(hdr->e_shnum < SHN_LORESERVE); + elfcheck(hdr->e_shstrndx < hdr->e_shnum); +- elfcheck(hdr->e_shentsize == sizeof(Elf_Shdr)); +- elfcheck(hdr->e_shoff < size); ++ /* elfcheck(hdr->e_shentsize == sizeof(Elf_Shdr)); */ ++ /* elfcheck(hdr->e_shoff < size); */ + elfcheck(hdr->e_shoff >= hdr->e_ehsize); + elfcheck(hdr->e_shoff % sizeof(long) == 0); +- elfcheck(hdr->e_shnum * sizeof(Elf_Shdr) <= size - hdr->e_shoff); ++ /* elfcheck(hdr->e_shnum * sizeof(Elf_Shdr) <= size - hdr->e_shoff); */ + + /* Validate the section table contents */ + mvdata->nsects = hdr->e_shnum; +-- +1.7.10.2 + + +From b5df4e7900852395a1ccb70190827cccc0c0de2d Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 11 May 2012 16:56:05 +0100 +Subject: [PATCH 30/36] MODSIGN: Fix some checkpatch noise + +Fix some warnings and errors produced by checkpatch. + +Reported-by: Tetsuo Handa +Signed-off-by: David Howells +--- + kernel/module-verify-defs.h | 24 ++++++++++++------------ + kernel/module-verify.c | 18 +++++++++++------- + kernel/module-verify.h | 3 ++- + security/keys/crypto/pgp_key_parser.c | 2 +- + 4 files changed, 26 insertions(+), 21 deletions(-) + +diff --git a/kernel/module-verify-defs.h b/kernel/module-verify-defs.h +index 45bea45..2fe31e1 100644 +--- a/kernel/module-verify-defs.h ++++ b/kernel/module-verify-defs.h +@@ -60,22 +60,22 @@ struct module_verify_data { + do { \ + if (unlikely(modsign_debug)) \ + pr_debug(FMT, ##__VA_ARGS__); \ +- } while(0) ++ } while (0) + + #ifdef DEBUG +-#define count_and_csum(C, __p, __n) \ +-do { \ +- int __loop; \ +- for (__loop = 0; __loop < __n; __loop++) { \ +- (C)->csum += __p[__loop]; \ +- (C)->xcsum += __p[__loop]; \ +- } \ +- (C)->signed_size += __n; \ +-} while (0) ++#define count_and_csum(C, __p, __n) \ ++ do { \ ++ int __loop; \ ++ for (__loop = 0; __loop < __n; __loop++) { \ ++ (C)->csum += __p[__loop]; \ ++ (C)->xcsum += __p[__loop]; \ ++ } \ ++ (C)->signed_size += __n; \ ++ } while (0) + #else + #define count_and_csum(C, __p, __n) \ +-do { \ +-} while (0) ++ do { \ ++ } while (0) + #endif + + #endif /* CONFIG_MODULE_SIG */ +diff --git a/kernel/module-verify.c b/kernel/module-verify.c +index e1bfd28..161cf3e 100644 +--- a/kernel/module-verify.c ++++ b/kernel/module-verify.c +@@ -82,13 +82,13 @@ static noinline int module_verify_elf(struct module_verify_data *mvdata) + size = mvdata->size; + + #define elfcheck(X) \ +-do { if (unlikely(!(X))) { line = __LINE__; goto elfcheck_error; } } while(0) ++do { if (unlikely(!(X))) { line = __LINE__; goto elfcheck_error; } } while (0) + + #define seccheck(X) \ +-do { if (unlikely(!(X))) { line = __LINE__; goto seccheck_error; } } while(0) ++do { if (unlikely(!(X))) { line = __LINE__; goto seccheck_error; } } while (0) + + #define symcheck(X) \ +-do { if (unlikely(!(X))) { line = __LINE__; goto symcheck_error; } } while(0) ++do { if (unlikely(!(X))) { line = __LINE__; goto symcheck_error; } } while (0) + + /* Validate the ELF header */ + elfcheck(size > sizeof(Elf_Ehdr)); +@@ -388,7 +388,7 @@ static int extract_elf_rel(struct module_verify_data *mvdata, + #else + #error unsupported module type + #endif +- } __attribute__((packed)) relocation; ++ } __packed relocation; + + const Elf_Rel *reloc; + const Elf_Sym *symbols, *symbol; +@@ -401,7 +401,9 @@ static int extract_elf_rel(struct module_verify_data *mvdata, + strings = mvdata->buffer + + mvdata->sections[mvdata->sections[secix].sh_link].sh_offset; + +- /* Contribute the relevant bits from a join of { REL, SYMBOL, SECTION } */ ++ /* Contribute the relevant bits from a join of ++ * { REL, SYMBOL, SECTION } ++ */ + for (loop = 0; loop < nrels; loop++) { + unsigned st_shndx; + +@@ -479,7 +481,7 @@ static int extract_elf_rela(struct module_verify_data *mvdata, + #else + #error unsupported module type + #endif +- } __attribute__((packed)) relocation; ++ } __packed relocation; + + const Elf_Shdr *relsec, *symsec, *strsec; + const Elf_Rela *reloc; +@@ -495,7 +497,9 @@ static int extract_elf_rela(struct module_verify_data *mvdata, + symbols = mvdata->buffer + symsec->sh_offset; + strings = mvdata->buffer + strsec->sh_offset; + +- /* Contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */ ++ /* Contribute the relevant bits from a join of ++ * { RELA, SYMBOL, SECTION } ++ */ + for (loop = 0; loop < nrels; loop++) { + unsigned st_shndx; + +diff --git a/kernel/module-verify.h b/kernel/module-verify.h +index 6bb6b56..c640634 100644 +--- a/kernel/module-verify.h ++++ b/kernel/module-verify.h +@@ -12,7 +12,8 @@ + #ifdef CONFIG_MODULE_SIG + extern int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok); + #else +-static inline int module_verify(const Elf_Ehdr *hdr, size_t size, bool *_gpgsig_ok) ++static inline int module_verify(const Elf_Ehdr *hdr, size_t size, ++ bool *_gpgsig_ok) + { + return 0; + } +diff --git a/security/keys/crypto/pgp_key_parser.c b/security/keys/crypto/pgp_key_parser.c +index 1407e2e..d913538 100644 +--- a/security/keys/crypto/pgp_key_parser.c ++++ b/security/keys/crypto/pgp_key_parser.c +@@ -94,7 +94,7 @@ static int pgp_calc_pkey_keyid(struct shash_desc *digest, + if (pgp->version < PGP_KEY_VERSION_4) { + u16 a16; + +- if( pgp->expires_at) ++ if (pgp->expires_at) + a16 = (pgp->expires_at - pgp->creation_time) / 86400UL; + else + a16 = 0; +-- +1.7.10.2 + + +From 27ecab7d7ee104299133c9ffd51d00ea378ed56b Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 16 May 2012 15:13:41 +0100 +Subject: [PATCH 31/36] PGPLIB: Preclear array on stack + +Preclear an array on the stack so that the error handling that frees what the +array might point to won't crash. + +Reported-by: Tetsuo Handa +Signed-off-by: David Howells +--- + security/keys/crypto/pgp_key_parser.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/security/keys/crypto/pgp_key_parser.c b/security/keys/crypto/pgp_key_parser.c +index d913538..84ce457 100644 +--- a/security/keys/crypto/pgp_key_parser.c ++++ b/security/keys/crypto/pgp_key_parser.c +@@ -71,6 +71,9 @@ static int pgp_calc_pkey_keyid(struct shash_desc *digest, + + kenter(""); + ++ for (i = 0; i < ARRAY_SIZE(pp); i++) ++ pp[i] = NULL; ++ + n = (pgp->version < PGP_KEY_VERSION_4) ? 8 : 6; + for (i = 0; i < npkey; i++) { + nb[i] = mpi_get_nbits(key->mpi[i]); +-- +1.7.10.2 + + +From a382a46fe70ee35cfb6fe97faa8abffd82368cbe Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Wed, 16 May 2012 15:19:24 +0100 +Subject: [PATCH 32/36] PGPLIB: Check the length in a packet or subpacket + +Check the length in a packet or subpacket to make sure there isn't an overflow +should the length not fit into the lower 31 bits of an integer. + +It is possible that both pgp_parse_packet_header() and +pgp_parse_sig_subpkt_header() could see packets that purport to be >2G in size. +Normally this will not be a problem because EBADMSG is indicated if the size +indicated is greater than the remnant size of the data - but just in case we do +end up parsing a >2G blob, a couple of simple checks can prevent an overflow +from occurring. + +Reported-by: Stephan Mueller +Signed-off-by: David Howells +--- + security/keys/crypto/pgp_library.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c +index f6b831f..a9462f5 100644 +--- a/security/keys/crypto/pgp_library.c ++++ b/security/keys/crypto/pgp_library.c +@@ -137,6 +137,8 @@ ssize_t pgp_parse_packet_header(const u8 **_data, size_t *_datalen, + pr_devel("datalen=%zu size=%zu", datalen, size); + if (datalen < size) + goto short_packet; ++ if ((int)size < 0) ++ goto too_big; + + *_data = data; + *_datalen = datalen; +@@ -147,6 +149,9 @@ ssize_t pgp_parse_packet_header(const u8 **_data, size_t *_datalen, + short_packet: + pr_debug("Attempt to parse short packet\n"); + return -EBADMSG; ++too_big: ++ pr_debug("Signature subpacket size >2G\n"); ++ return -EMSGSIZE; + } + + /** +@@ -312,6 +317,8 @@ ssize_t pgp_parse_sig_subpkt_header(const u8 **_data, size_t *_datalen, + pr_debug("Signature subpacket size can't be zero\n"); + return -EBADMSG; + } ++ if ((int)size < 0) ++ goto too_big; + + type = *data++ & ~PGP_SIG_SUBPKT_TYPE_CRITICAL_MASK; + datalen--; +@@ -330,6 +337,9 @@ ssize_t pgp_parse_sig_subpkt_header(const u8 **_data, size_t *_datalen, + short_subpacket: + pr_debug("Attempt to parse short signature subpacket\n"); + return -EBADMSG; ++too_big: ++ pr_debug("Signature subpacket size >2G\n"); ++ return -EMSGSIZE; + } + + /** +-- +1.7.10.2 + + +From a577fc904c197d97b028863989d9a891c3e1ea17 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 17 May 2012 17:41:36 +0100 +Subject: [PATCH 33/36] PGPLIB: Remnant length should be decreased in + pgp_parse_sig_params() + +The remnant length of the signature packet should be decreased rather than +being increased as we parse in pgp_parse_sig_params(). + +Signed-off-by: David Howells +--- + security/keys/crypto/pgp_library.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c +index a9462f5..1ff3628 100644 +--- a/security/keys/crypto/pgp_library.c ++++ b/security/keys/crypto/pgp_library.c +@@ -503,7 +503,7 @@ int pgp_parse_sig_params(const u8 **_data, size_t *_datalen, + if (ret < 0) + return ret; + data += subdatalen; +- datalen += subdatalen; ++ datalen -= subdatalen; + } + + subdatalen = *data++ << 8; +@@ -521,7 +521,7 @@ int pgp_parse_sig_params(const u8 **_data, size_t *_datalen, + if (ret < 0) + return ret; + data += subdatalen; +- datalen += subdatalen; ++ datalen -= subdatalen; + } + + if (!ctx.got_the_issuer) { +-- +1.7.10.2 + + +From ab7204f60a1cedecb24bb2888db5d03bdcf20488 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 17 May 2012 17:41:36 +0100 +Subject: [PATCH 34/36] PGPLIB: Parse 5-octet length new-format packet headers + +Parse 5-octet length new-format packet headers to extract the 32-bit length +encoded therein [RFC4880 4.2.2.3]. + +Signed-off-by: David Howells +--- + security/keys/crypto/pgp_library.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c +index 1ff3628..310ee2f 100644 +--- a/security/keys/crypto/pgp_library.c ++++ b/security/keys/crypto/pgp_library.c +@@ -86,8 +86,17 @@ ssize_t pgp_parse_packet_header(const u8 **_data, size_t *_datalen, + *_headerlen = 3; + break; + case 0xff: +- pr_debug("Five-byte packet length not supported\n"); +- return -EBADMSG; ++ /* Five-byte length */ ++ if (datalen < 5) ++ goto short_packet; ++ size = data[1] << 24; ++ size |= data[2] << 16; ++ size |= data[3] << 8; ++ size |= data[4]; ++ data += 5; ++ datalen -= 5; ++ *_headerlen = 6; ++ break; + default: + pr_debug("Error parsing packet length\n"); + return -EBADMSG; +-- +1.7.10.2 + + +From df233b65b833e085f39d80dc6f77c383b32786ce Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Thu, 17 May 2012 17:41:36 +0100 +Subject: [PATCH 35/36] PGPLIB: Change the debug message for Partial Body + Length specifier + +Change the debug message displayed if we encounter a Partial Body Length +specifier whilst parsing a PGP stream [RFC4880 4.2.2.4]. + +Signed-off-by: David Howells +--- + security/keys/crypto/pgp_library.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c +index 310ee2f..111cbd7 100644 +--- a/security/keys/crypto/pgp_library.c ++++ b/security/keys/crypto/pgp_library.c +@@ -98,7 +98,7 @@ ssize_t pgp_parse_packet_header(const u8 **_data, size_t *_datalen, + *_headerlen = 6; + break; + default: +- pr_debug("Error parsing packet length\n"); ++ pr_debug("Partial body length packet not supported\n"); + return -EBADMSG; + } + } else { +-- +1.7.10.2 + + +From 3ac676c62cceabdbf814bbc3495f36abd1848a97 Mon Sep 17 00:00:00 2001 +From: David Howells +Date: Fri, 18 May 2012 16:44:14 +0100 +Subject: [PATCH 36/36] PGPLIB: Adjust error handling + +Adjust the error handling in the following ways: + + (1) When parsing signature subpacket header, do the size checks before + accessing the subpacket type (which is in the subpacket payload governed + by the size). + + (2) Indicate ENOPKG when we are asked to use a public key algorithm we don't + support rather than returning ENOKEY. + + (3) Indicate EKEYREJECTED if the key that matches the signature demands a + different key algorithm to the signature. + + (4) Indicate ENOMSG if the signature blob does not contain a signature + packet. Possibly this should be EBADMSG - though that causes the next + packet parser to be tried if available. + + (5) Give a better debug message in the case of an unsupported hash. + + (6) Don't return keyring-related errors when searching for a key containing + the public key (EACCES, ENOTDIR, EAGAIN), but rather map them to ENOKEY. + Possibly EACCES should be passed through as you also get that if there + *is* a matching key, but it cannot be accessed. + +Signed-off-by: David Howells +--- + Documentation/module-signing.txt | 2 ++ + security/keys/crypto/pgp_library.c | 16 ++++++++-------- + security/keys/crypto/pgp_pubkey_sig.c | 9 +++++---- + security/keys/crypto/pgp_sig_parser.c | 15 ++++++++++++--- + 4 files changed, 27 insertions(+), 15 deletions(-) + +diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt +index d75d473..d3beb1e 100644 +--- a/Documentation/module-signing.txt ++++ b/Documentation/module-signing.txt +@@ -185,10 +185,12 @@ This table indicates the behaviours of the various situations: + MODULE STATE PERMISSIVE MODE ENFORCING MODE + ======================================= =============== =============== + Unsigned Ok EKEYREJECTED ++ No signature packet in the signature ENOMSG ENOMSG + Signed, no public key ENOKEY ENOKEY + Validly signed, public key Ok Ok + Invalidly signed, public key EKEYREJECTED EKEYREJECTED + Validly signed, expired key EKEYEXPIRED EKEYEXPIRED ++ Signed, pubkey algorithm unavailable ENOPKG ENOPKG + Signed, hash algorithm unavailable ENOPKG ENOPKG + Corrupt signature EBADMSG EBADMSG + Corrupt ELF ELIBBAD ELIBBAD +diff --git a/security/keys/crypto/pgp_library.c b/security/keys/crypto/pgp_library.c +index 111cbd7..ee08b86 100644 +--- a/security/keys/crypto/pgp_library.c ++++ b/security/keys/crypto/pgp_library.c +@@ -322,10 +322,11 @@ ssize_t pgp_parse_sig_subpkt_header(const u8 **_data, size_t *_datalen, + } + + /* The type octet is included in the size */ +- if (size == 0) { +- pr_debug("Signature subpacket size can't be zero\n"); +- return -EBADMSG; +- } ++ pr_devel("datalen=%zu size=%zu", datalen, size); ++ if (datalen < size) ++ goto short_subpacket; ++ if (size == 0) ++ goto very_short_subpacket; + if ((int)size < 0) + goto too_big; + +@@ -333,16 +334,15 @@ ssize_t pgp_parse_sig_subpkt_header(const u8 **_data, size_t *_datalen, + datalen--; + size--; + +- pr_devel("datalen=%zu size=%zu", datalen, size); +- if (datalen < size) +- goto short_subpacket; +- + *_data = data; + *_datalen = datalen; + *_type = type; + pr_devel("Found subpkt type=%u size=%zd\n", type, size); + return size; + ++very_short_subpacket: ++ pr_debug("Signature subpacket size can't be zero\n"); ++ return -EBADMSG; + short_subpacket: + pr_debug("Attempt to parse short signature subpacket\n"); + return -EBADMSG; +diff --git a/security/keys/crypto/pgp_pubkey_sig.c b/security/keys/crypto/pgp_pubkey_sig.c +index b4b7cb0..bc02dfa 100644 +--- a/security/keys/crypto/pgp_pubkey_sig.c ++++ b/security/keys/crypto/pgp_pubkey_sig.c +@@ -86,12 +86,12 @@ struct crypto_key_verify_context *pgp_pkey_verify_sig_begin( + !pgp_public_key_algorithms[p.params.pubkey_algo]) { + pr_debug("Unsupported public key algorithm %u\n", + p.params.pubkey_algo); +- return ERR_PTR(-ENOKEY); ++ return ERR_PTR(-ENOPKG); + } + + if (pgp_public_key_algorithms[p.params.pubkey_algo] != key->algo) { +- kleave(" = -ENOKEY [wrong pk algo]"); +- return ERR_PTR(-ENOKEY); ++ kleave(" = -EKEYREJECTED [wrong pk algo]"); ++ return ERR_PTR(-EKEYREJECTED); + } + + if (!(key->capabilities & PKEY_CAN_VERIFY)) { +@@ -101,7 +101,8 @@ struct crypto_key_verify_context *pgp_pkey_verify_sig_begin( + + if (p.params.hash_algo >= PGP_HASH__LAST || + !pgp_hash_algorithms[p.params.hash_algo]) { +- kleave(" = -ENOPKG [hash]"); ++ pr_debug("Unsupported hash algorithm %u\n", ++ p.params.hash_algo); + return ERR_PTR(-ENOPKG); + } + +diff --git a/security/keys/crypto/pgp_sig_parser.c b/security/keys/crypto/pgp_sig_parser.c +index b72c505..3dd223f 100644 +--- a/security/keys/crypto/pgp_sig_parser.c ++++ b/security/keys/crypto/pgp_sig_parser.c +@@ -66,7 +66,7 @@ static struct key *find_key_for_pgp_sig(struct key *keyring, + return ERR_PTR(ret); + + if (!p.found_sig) +- return ERR_PTR(-EINVAL); ++ return ERR_PTR(-ENOMSG); + + sprintf(criterion, "id:%08x%08x", + be32_to_cpu(p.params.issuer32[0]), +@@ -76,8 +76,17 @@ static struct key *find_key_for_pgp_sig(struct key *keyring, + + key = keyring_search(make_key_ref(keyring, 1), + &key_type_crypto, criterion); +- if (IS_ERR(key)) +- return ERR_CAST(key); ++ if (IS_ERR(key)) { ++ switch (PTR_ERR(key)) { ++ /* Hide some search errors */ ++ case -EACCES: ++ case -ENOTDIR: ++ case -EAGAIN: ++ return ERR_PTR(-ENOKEY); ++ default: ++ return ERR_CAST(key); ++ } ++ } + + pr_debug("Found key %x\n", key_serial(key_ref_to_ptr(key))); + return key_ref_to_ptr(key); +-- +1.7.10.2 +