summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--genkey6
-rw-r--r--kernel.spec29
-rw-r--r--modsign-20120510.patch (renamed from modsign-20111207.patch)4606
3 files changed, 2665 insertions, 1976 deletions
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 <<EOF
-###
-### Now generating a PGP key pair to be used for signing modules.
-###
-### If this takes a long time, you might wish to run rngd in the background to
-### keep the supply of entropy topped up. It needs to be run as root, and
-### should use a hardware random number generator if one is available, eg:
-###
-### rngd -r /dev/hwrandom
-###
-### If one isn't available, the pseudo-random number generator can be used:
-###
-### rngd -r /dev/urandom
-###
-EOF
-gpg --homedir . --batch --gen-key %{SOURCE11}
-cat <<EOF
-###
-### Key pair generated.
-###
-EOF
+cp %{SOURCE11} .
%endif
cd ..
@@ -2317,6 +2297,9 @@ fi
# ||----w |
# || ||
%changelog
+* Mon May 21 2012 Josh Boyer <jwboyer@redhat.com>
+- Update the modsign patchset to the most recent version
+
* Mon May 21 2012 Josh Boyer <jwboyer@redhat.com> - 3.5.0-0.rc0.git1.2
- Linux v3.4-1622-g31a6710
diff --git a/modsign-20111207.patch b/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 <dhowells@redhat.com>
-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 <dhowells@redhat.com>
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 <dhowells@redhat.com>
-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 <dhowells@redhat.com>
---
- 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 <dhowells@redhat.com>
-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 <dhowells@redhat.com>
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 <dhowells@redhat.com>
-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 <dhowells@redhat.com>
---
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 <dhowells@redhat.com>
-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 <dhowells@redhat.com>
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 <dhowells@redhat.com>
-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 <dhowells@redhat.com>
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 <dhowells@redhat.com>
-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 <dhowells@redhat.com>
---
- 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
-
-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
+ 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/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 <dhowells@redhat.com>
-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 <dhowells@redhat.com>
---
- 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
-
-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
+ 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/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 a1ac402f327ab537a629c4d365b3f5461eaecb82 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+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 <mbroz@redhat.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ 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 82b8d487e66a5218ca9f91ca406db97b2113da60 Mon Sep 17 00:00:00 2001
+From d682ea629a2494aab705468d1479058a03fd7879 Mon Sep 17 00:00:00 2001
From: David Howells <dhowells@redhat.com>
-Date: Wed, 7 Dec 2011 14:07:11 +0000
-Subject: PGPLIB: PGP definitions (RFC 4880)
+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 <dhowells@redhat.com>
---
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 <dhowells@redhat.com>
-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 <dhowells@redhat.com>
---
- 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 <dhowells@redhat.com>
-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 <dhowells@redhat.com>
---
- 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 <dhowells@redhat.com>
-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 <dhowells@redhat.com>
---
- 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
-
-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
+ 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/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 <dhowells@redhat.com>
-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 <dhowells@redhat.com>
---
- 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
-
-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
+ 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/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 <dhowells@redhat.com>
-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 <dhowells@redhat.com>
---
- 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
-
-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
-
+ 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/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 <dhowells@redhat.com>
-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 <dhowells@redhat.com>
---
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 8f7d6b082b6b7357e44f9345c8c040f53aa60a7f Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+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 <dhowells@redhat.com>
+---
+ 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 <linux/stringify.h>
+ #include <linux/elf.h>
+ /*
+ * 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 dad531381fad892fda776ddb354e1eb936b46b62 Mon Sep 17 00:00:00 2001
+From b37a512b3d6593d541e05550316bd407515c1ec2 Mon Sep 17 00:00:00 2001
From: David Howells <dhowells@redhat.com>
-Date: Wed, 7 Dec 2011 14:07:16 +0000
-Subject: MODSIGN: Add indications of module ELF types
+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 <dhowells@redhat.com>
+---
+ 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 <dhowells@redhat.com>
+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 <dhowells@redhat.com>
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,818 +4509,129 @@ 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 <dhowells@redhat.com>
-Date: Wed, 7 Dec 2011 14:07:17 +0000
-Subject: MODSIGN: Module ELF verifier
-
-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.
+Date: Thu, 10 May 2012 23:49:53 +0100
+Subject: [PATCH 20/36] MODSIGN: Provide gitignore and make clean rules for
+ extra files
-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.
+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.
-Signed-Off-By: David Howells <dhowells@redhat.com>
-
-Rebased-to-3.3-rc6: Josh Boyer <jwboyer@redhat.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
---
- 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
+ .gitignore | 12 ++++++++++++
+ Makefile | 1 +
+ scripts/mod/.gitignore | 1 +
+ 3 files changed, 14 insertions(+)
-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 <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/elf.h>
-+#include <linux/ctype.h>
-+#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 <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#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 <linux/types.h>
-+#include <asm/module.h>
-+
-+#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
+diff --git a/.gitignore b/.gitignore
+index 57af07c..7948eeb 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -14,6 +14,9 @@
+ *.o.*
+ *.a
+ *.s
++*.ko.unsigned
++*.ko.digest
++*.ko.digest.sig
+ *.ko
+ *.so
+ *.so.dbg
+@@ -84,3 +87,12 @@ GTAGS
+ *.orig
+ *~
+ \#*#
+
-+#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 <linux/jump_label.h>
- #include <linux/pfn.h>
- #include <linux/bsearch.h>
-+#include "module-verify.h"
-
- #define CREATE_TRACE_POINTS
- #include <trace/events/module.h>
-@@ -2404,6 +2405,11 @@ static int copy_and_check(struct load_info *info,
- goto free_hdr;
- }
++#
++# GPG leavings from module signing
++#
++genkey
++modsign.pub
++modsign.sec
++random_seed
++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
-+ /* 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
+1.7.10.2
-From 1ecd333ad910d539e75f8f85d1fb1e3d87547c4e Mon Sep 17 00:00:00 2001
+From dce3a6eca8dda09a28cb2f45b87e70e1c2d52139 Mon Sep 17 00:00:00 2001
From: David Howells <dhowells@redhat.com>
-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.
+Date: Thu, 10 May 2012 23:49:53 +0100
+Subject: [PATCH 21/36] MODSIGN: Provide Documentation and Kconfig options
-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;
+Provide documentation and kernel configuration options for module signing.
- (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:
+The documentation can be found 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.
+The following configuration options are added:
-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.
+ (1) CONFIG_MODULE_SIG
-=====================
-SUPPLYING PUBLIC KEYS
-=====================
+ Enable module signing. This will both cause the build process to sign
+ modules and the kernel to check modules when they're loaded.
-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 <<EOF
- %pubring kernel.pub
- %secring kernel.sec
- Key-Type: DSA
- Key-Length: 512
- Name-Real: A. N. Other
- Name-Comment: Kernel Module GPG key
- %commit
- EOF
- make scripts/bin2c
- gpg --homedir . --batch --gen-key genkey
-
-The above generates fresh keys using /dev/random. If there's insufficient data
-in /dev/random, more can be provided more by running:
-
- rngd -r /dev/urandom
-
-in the background.
-
-Note:
-
- (1) That "keyname" is the name of the key in the keyring. This differentiates
- it from any other keys that may be added to the keyring.
-
- (2) That no GPG password is used in the above scriptlet.
-
- (3) It may be desirable to shred and delete the private key file after signing
- the modules.
-
-==============
-MODULE SIGNING
-==============
-
-Modules will then be signed automatically. The kernel make command line can
-include the following options:
-
- (*) MODSECKEY=<secret-key-ring-path>
-
- 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=<public-key-ring-path>
-
- 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=<key-name>
-
- 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).
+ (2) CONFIG_MODULE_SIG_SHA1
+ CONFIG_MODULE_SIG_SHA224
+ CONFIG_MODULE_SIG_SHA256
+ CONFIG_MODULE_SIG_SHA384
+ CONFIG_MODULE_SIG_SHA512
-This table indicates the behaviours of the various situations:
+ 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.
- 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
+ (3) CONFIG_MODULE_SIG_FORCE
-Signed-Off-By: David Howells <dhowells@redhat.com>
+ Require that any module loaded must be signed with a key compiled into
+ the kernel. All other modules are rejected with EKEYREJECTED.
-Rebased-to-3.3-rc6-by: Josh Boyer <jwboyer@redhat.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
---
- .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(-)
+ 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
- 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
-diff --git a/.gitignore b/.gitignore
-index 57af07c..841a17ee 100644
---- a/.gitignore
-+++ b/.gitignore
-@@ -14,6 +14,9 @@
- *.o.*
- *.a
- *.s
-+*.ko.unsigned
-+*.ko.digest
-+*.ko.digest.sig
- *.ko
- *.so
- *.so.dbg
-@@ -84,3 +87,15 @@ GTAGS
- *.orig
- *~
- \#*#
-+
-+#
-+# GPG leavings from module signing
-+#
-+trustdb.gpg
-+random_seed
-+kernel.pub
-+kernel.sec
-+extract.pub
-+secring.gpg
-+pubring.gpg
-+crypto/signature/key.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 <<EOF
-+ %pubring kernel.pub
-+ %secring kernel.sec
-+ Key-Type: DSA
-+ Key-Length: 512
++ %pubring modsign.pub
++ %secring modsign.sec
++ Key-Type: RSA
++ Key-Length: 4096
+ Name-Real: A. N. Other
+ Name-Comment: Kernel Module GPG key
+ %commit
@@ -5202,15 +4679,12 @@ index 0000000..300b91a
+ gpg --homedir . --batch --gen-key genkey
+
+The above generates fresh keys using /dev/random. If there's insufficient data
-+in /dev/random, more can be provided more by running:
-+
-+ rngd -r /dev/urandom
-+
-+in the background.
++in /dev/random, more can be provided using the rngd program if there's a
++hardware random number generator available.
+
+Note that no GPG password is used in the above scriptlet.
+
-+The kernel.pub file is compiled into the kernel directly by the assembler by
++The modsign.pub file is compiled into the kernel directly by the assembler by
+means of an ".incbin" directive in kernel/modsign-pubkey.c.
+
+Once the kernel is running, the keys are visible to root as kernel crypto keys
@@ -5255,12 +4729,12 @@ index 0000000..300b91a
+ (*) MODSECKEY=<secret-key-ring-path>
+
+ 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=<public-key-ring-path>
+
+ 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=<key-name>
+
@@ -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 <linux/stringify.h>
- #include <linux/elf.h>
- /*
- * 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 <linux/kernel.h>
-+#include <keys/crypto-type.h>
-+#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 <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/elf.h>
-+#include <linux/sched.h>
-+#include <linux/cred.h>
-+#include <linux/modsign.h>
-+#include <keys/keyring-type.h>
-+#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 <linux/types.h>
-+#include <linux/elf.h>
-+#include <keys/crypto-type.h>
- #include <asm/module.h>
-
- #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 <dhowells@redhat.com>
+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 <dhowells@redhat.com>
+---
+ 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 38ddca03060502e8134320b732758fd6b6a98247 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 10 May 2012 23:49:55 +0100
+Subject: [PATCH 23/36] MODSIGN: Module signature verification stub
+
+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.
+
+The stub also implements the policy for handling unsigned modules and the
+printing of error messages to indicate various problems with the module.
-From 31e77b71e584a702c8e44b83f6af03bb8511cf8d Mon Sep 17 00:00:00 2001
-From: Josh Boyer <jwboyer@redhat.com>
-Date: Tue, 6 Mar 2012 12:56:49 -0500
-Subject: [PATCH] Make sure MPILIB is selected for stuff that uses it...
+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.
-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'
+This table indicates the behaviours in the various situations:
-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'
+ 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: Josh Boyer <jwboyer@redhat.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
---
- 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 <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/elf.h>
++#include <linux/elfnote.h>
++#include <linux/sched.h>
++#include <linux/cred.h>
++#include <linux/modsign.h>
++#include <linux/moduleparam.h>
++#include <keys/crypto-type.h>
++#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 <linux/jump_label.h>
+ #include <linux/pfn.h>
+ #include <linux/bsearch.h>
++#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.
+ #define CREATE_TRACE_POINTS
+ #include <trace/events/module.h>
+@@ -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;
+ }
+
++ /* Verify the module's contents */
++ *_gpgsig_ok = false;
++ err = module_verify(hdr, len, _gpgsig_ok);
++ if (err < 0)
++ goto free_hdr;
++
+ 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.9.1
+1.7.10.2
-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("");
+
+From 6f5323e52cdc37969939ef82036783da67afe69f Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+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 <dhowells@redhat.com>
+---
+ 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 <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/cred.h>
++#include <keys/crypto-type.h>
++#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 @@
- /* (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);
+ #ifdef CONFIG_MODULE_SIG
-- 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.
++#include <linux/module.h>
++
++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 <linux/slab.h>
+ #include <linux/elf.h>
+ #include <linux/elfnote.h>
+-#include <linux/sched.h>
+-#include <linux/cred.h>
+ #include <linux/modsign.h>
+ #include <linux/moduleparam.h>
+ #include <keys/crypto-type.h>
+--
+1.7.10.2
+
+
+From 5727333d123ef9d7fa2666069306bf3ec2d7f110 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+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 <dhowells@redhat.com>
+---
+ 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.
+ */
- pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize);
-- if (tsize != k) {
-+ if (k < tsize) {
- ret = -EBADMSG;
- goto error;
++ 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 <dhowells@redhat.com>
+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 <dhowells@redhat.com>
+---
+ 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;
}
-+ /* Round up to octets */
-+ k = (k + 7) / 8;
++ /* Produce a canonicalisation map for the sections */
++ ret = module_verify_canonicalise(&mvdata);
++ if (ret < 0)
++ goto out;
+
- /* (2b) Apply the RSAVP1 verification primitive to the public key */
- ret = RSAVP1(key, sig->rsa.s, &m);
+ ret = 0;
++ kfree(mvdata.canonlist);
+
+ out:
+ switch (ret) {
+--
+1.7.10.2
+
+
+From 92fb97859c50a0dd63886baf057477a7a336b2a1 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+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 <dhowells@redhat.com>
+---
+ 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 <dhowells@redhat.com>
+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 <dhowells@redhat.com>
+---
+ 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 <dhowells@redhat.com>
+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 <dhowells@redhat.com>
+---
+ 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 <dhowells@redhat.com>
+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 <penguin-kernel@I-love.SAKURA.ne.jp>
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ 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 <dhowells@redhat.com>
+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 <penguin-kernel@I-love.SAKURA.ne.jp>
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ 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 <dhowells@redhat.com>
+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 <stephan.mueller@atsec.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+---
+ 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 <dhowells@redhat.com>
+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 <dhowells@redhat.com>
+---
+ 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 <dhowells@redhat.com>
+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 <dhowells@redhat.com>
+---
+ 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 <dhowells@redhat.com>
+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 <dhowells@redhat.com>
+---
+ 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 <dhowells@redhat.com>
+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 <dhowells@redhat.com>
+---
+ 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
+