]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
update modsign
authorMaxim Uvarov <maxim.uvarov@oracle.com>
Mon, 30 Jan 2012 20:17:43 +0000 (12:17 -0800)
committerMaxim Uvarov <maxim.uvarov@oracle.com>
Thu, 2 Feb 2012 01:17:56 +0000 (17:17 -0800)
Orabug: 13615815
This patch updates modsign and makes force option work.

Signed-off-by: Maxim Uvarov <maxim.uvarov@oracle.com>
17 files changed:
.gitignore
crypto/signature/dsa.c
crypto/signature/ksign-parse.c
crypto/signature/ksign.c
crypto/signature/local.h
include/asm-generic/module.h
include/linux/crypto/ksign.h
include/linux/elfnote.h
kernel/module-verify-elf.c
kernel/module-verify-sig.c
kernel/module-verify.c
kernel/module-verify.h [moved from include/linux/module-verify.h with 93% similarity]
kernel/module.c
scripts/Makefile.modpost
scripts/mod/mod-extract.c
uek-rpm/ol5/kernel-uek.spec
uek-rpm/ol6/kernel-uek.spec

index 9dacde0a4b2dcec4ce33013354b6c46738daaef7..7889b6212fb73832767c08169d3d2bf90b4aeaff 100644 (file)
@@ -19,6 +19,9 @@
 *.so.dbg
 *.mod.c
 *.i
+*.ko.unsigned
+*.ko.digest.sig
+*.ko.digest
 *.lst
 *.symtypes
 *.order
index 469539c496065afe4f7223f9dbd83965d1cdf65d..12cd0b1d4f05fde7f94f936c450a7a051dcb3405 100644 (file)
@@ -94,3 +94,4 @@ cleanup:
        mpi_free(v);
        return rc;
 }
+EXPORT_SYMBOL_GPL(DSA_verify);
index f7026fa44e97495cdf2bdd81e1efb72d3f80757b..e8e220fd60203ee564bc4e58bd3d317166972874 100644 (file)
@@ -83,7 +83,7 @@ void ksign_free_user_id(struct ksign_user_id *uid)
 /*
  *
  */
-static void ksign_calc_pk_keyid(struct hash_desc *sha1,
+static void ksign_calc_pk_keyid(struct shash_desc *digest,
                                struct ksign_public_key *pk)
 {
        unsigned n;
@@ -94,8 +94,6 @@ static void ksign_calc_pk_keyid(struct hash_desc *sha1,
        int i;
        int npkey = DSA_NPKEY;
 
-       crypto_hash_init(sha1);
-
        n = pk->version < 4 ? 8 : 6;
        for (i = 0; i < npkey; i++) {
                nb[i] = mpi_get_nbits(pk->pkey[i]);
@@ -103,20 +101,20 @@ static void ksign_calc_pk_keyid(struct hash_desc *sha1,
                n += 2 + nn[i];
        }
 
-       SHA1_putc(sha1, 0x99);     /* ctb */
-       SHA1_putc(sha1, n >> 8);   /* 2 uint8_t length header */
-       SHA1_putc(sha1, n);
+       SHA1_putc(digest, 0x99);     /* ctb */
+       SHA1_putc(digest, n >> 8);   /* 2 uint8_t length header */
+       SHA1_putc(digest, n);
 
        if (pk->version < 4)
-               SHA1_putc(sha1, 3);
+               SHA1_putc(digest, 3);
        else
-               SHA1_putc(sha1, 4);
+               SHA1_putc(digest, 4);
 
        a32 = pk->timestamp;
-       SHA1_putc(sha1, a32 >> 24 );
-       SHA1_putc(sha1, a32 >> 16 );
-       SHA1_putc(sha1, a32 >>  8 );
-       SHA1_putc(sha1, a32 >>  0 );
+       SHA1_putc(digest, a32 >> 24 );
+       SHA1_putc(digest, a32 >> 16 );
+       SHA1_putc(digest, a32 >>  8 );
+       SHA1_putc(digest, a32 >>  0 );
 
        if (pk->version < 4) {
                uint16_t a16;
@@ -126,16 +124,16 @@ static void ksign_calc_pk_keyid(struct hash_desc *sha1,
                                ((pk->expiredate - pk->timestamp) / 86400L);
                else
                        a16 = 0;
-               SHA1_putc(sha1, a16 >> 8);
-               SHA1_putc(sha1, a16 >> 0);
+               SHA1_putc(digest, a16 >> 8);
+               SHA1_putc(digest, a16 >> 0);
        }
 
-       SHA1_putc(sha1, PUBKEY_ALGO_DSA);
+       SHA1_putc(digest, PUBKEY_ALGO_DSA);
 
        for (i = 0; i < npkey; i++) {
-               SHA1_putc(sha1, nb[i] >> 8);
-               SHA1_putc(sha1, nb[i]);
-               SHA1_write(sha1, pp[i], nn[i]);
+               SHA1_putc(digest, nb[i] >> 8);
+               SHA1_putc(digest, nb[i]);
+               SHA1_write(digest, pp[i], nn[i]);
                kfree(pp[i]);
        }
 }
@@ -180,9 +178,10 @@ static int ksign_parse_key(const uint8_t *datap, const uint8_t *endp,
                           ksign_public_key_actor_t pkfnx, void *fnxdata)
 {
        struct ksign_public_key *pk;
-       struct hash_desc sha1;
+       struct crypto_shash *tfm;
+       struct shash_desc *digest;
        unsigned long timestamp, expiredate;
-       uint8_t hash[SHA1_DIGEST_SIZE];
+       uint8_t sha1[SHA1_DIGEST_SIZE];
        int i, version;
        int is_v4 = 0;
        int rc = 0;
@@ -242,23 +241,39 @@ static int ksign_parse_key(const uint8_t *datap, const uint8_t *endp,
 
        rc = -ENOMEM;
 
-       sha1.tfm = crypto_alloc_hash("sha1", 0, 0);
-       if (!sha1.tfm)
-               goto cleanup;
-       sha1.flags = 0;
+       tfm = crypto_alloc_shash("sha1", 0, 0);
+       if (!tfm)
+               goto cleanup_pubkey;
+
+       digest = kmalloc(sizeof(*digest) + crypto_shash_descsize(tfm),
+                        GFP_KERNEL);
+       if (!digest)
+               goto cleanup_tfm;
+
+       digest->tfm = tfm;
+       digest->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+       rc = crypto_shash_init(digest);
+       if (rc < 0)
+               goto cleanup_sha1;
+
+       ksign_calc_pk_keyid(digest, pk);
 
-       ksign_calc_pk_keyid(&sha1, pk);
-       crypto_hash_final(&sha1, hash);
-       crypto_free_hash(sha1.tfm);
+       rc = crypto_shash_final(digest, sha1);
+       if (rc < 0)
+               goto cleanup_sha1;
 
-       pk->keyid[0] = hash[12] << 24 | hash[13] << 16 | hash[14] << 8 | hash[15];
-       pk->keyid[1] = hash[16] << 24 | hash[17] << 16 | hash[18] << 8 | hash[19];
+       pk->keyid[0] = sha1[12] << 24 | sha1[13] << 16 | sha1[14] << 8 | sha1[15];
+       pk->keyid[1] = sha1[16] << 24 | sha1[17] << 16 | sha1[18] << 8 | sha1[19];
 
        rc = 0;
        if (pkfnx)
                rc = pkfnx(pk, fnxdata);
 
-cleanup:
+cleanup_sha1:
+       kfree(digest);
+cleanup_tfm:
+       crypto_free_shash(tfm);
+cleanup_pubkey:
        ksign_put_public_key(pk);
        return rc;
 }
index 8dcccd489d4946b2fc3bdaf7c27344b533897eb2..8b318a3ef134318bade7265cc6973e8933d010be 100644 (file)
 #include <asm/errno.h>
 #include "local.h"
 
-#if 0
-#define _debug(FMT, ...) printk(KERN_DEBUG FMT, ##__VA_ARGS__)
-#else
-#define _debug(FMT, ...) do { ; } while (0)
-#endif
+int ksign_debug;
+core_param(ksign_debug, ksign_debug, bool, 0644);
+
+#define _debug(FMT, ...)                                       \
+       do {                                                    \
+               if (unlikely(ksign_debug))                      \
+                       printk(KERN_DEBUG FMT, ##__VA_ARGS__);  \
+       } while(0)
 
 /*
  * check the signature which is contained in SIG.
  */
 static int ksign_signature_check(const struct ksign_signature *sig,
-                                struct crypto_hash *sha1_tfm)
+                                struct shash_desc *digest)
 {
        struct ksign_public_key *pk;
-       struct hash_desc sha1_d;
        uint8_t sha1[SHA1_DIGEST_SIZE];
        MPI result = NULL;
        int rc = 0;
@@ -46,29 +48,26 @@ static int ksign_signature_check(const struct ksign_signature *sig,
                       pk->timestamp - sig->timestamp,
                       pk->timestamp, sig->timestamp);
 
-       sha1_d.tfm = sha1_tfm;
-       sha1_d.flags = 0;
-
        /* complete the digest */
        if (sig->version >= 4)
-               SHA1_putc(&sha1_d, sig->version);
-       SHA1_putc(&sha1_d, sig->sig_class);
+               SHA1_putc(digest, sig->version);
+       SHA1_putc(digest, sig->sig_class);
 
        if (sig->version < 4) {
                u32 a = sig->timestamp;
-               SHA1_putc(&sha1_d, (a >> 24) & 0xff);
-               SHA1_putc(&sha1_d, (a >> 16) & 0xff);
-               SHA1_putc(&sha1_d, (a >>  8) & 0xff);
-               SHA1_putc(&sha1_d, (a >>  0) & 0xff);
+               SHA1_putc(digest, (a >> 24) & 0xff);
+               SHA1_putc(digest, (a >> 16) & 0xff);
+               SHA1_putc(digest, (a >>  8) & 0xff);
+               SHA1_putc(digest, (a >>  0) & 0xff);
        }
        else {
                uint8_t buf[6];
                size_t n;
-               SHA1_putc(&sha1_d, PUBKEY_ALGO_DSA);
-               SHA1_putc(&sha1_d, DIGEST_ALGO_SHA1);
+               SHA1_putc(digest, PUBKEY_ALGO_DSA);
+               SHA1_putc(digest, DIGEST_ALGO_SHA1);
                if (sig->hashed_data) {
                        n = (sig->hashed_data[0] << 8) | sig->hashed_data[1];
-                       SHA1_write(&sha1_d, sig->hashed_data, n + 2);
+                       SHA1_write(digest, sig->hashed_data, n + 2);
                        n += 6;
                }
                else {
@@ -82,12 +81,9 @@ static int ksign_signature_check(const struct ksign_signature *sig,
                buf[3] = n >> 16;
                buf[4] = n >>  8;
                buf[5] = n;
-               SHA1_write(&sha1_d, buf, 6);
+               SHA1_write(digest, buf, 6);
        }
-
-       crypto_hash_final(&sha1_d, sha1);
-       crypto_free_hash(sha1_tfm);
-
+       crypto_shash_final(digest, sha1);
        rc = -ENOMEM;
        result = mpi_alloc((SHA1_DIGEST_SIZE + BYTES_PER_MPI_LIMB - 1) /
                           BYTES_PER_MPI_LIMB);
@@ -132,15 +128,59 @@ static int ksign_grab_signature(struct ksign_signature *sig, void *fnxdata)
 
 /*
  * verify the signature of some data with one of the kernel's known public keys
- * - the SHA1 context should be currently open with the signed data digested
- *   into it so that more data can be appended
- * - the SHA1 context is finalised and freed before returning
+ * - the SHA1 digest supplied should have the data to be checked already loaded
+ *   in to it
  */
 int ksign_verify_signature(const char *sigdata, unsigned sig_size,
-                          struct crypto_hash *sha1)
+                          struct shash_desc *partial_digest)
 {
        struct ksign_signature *sig = NULL;
-       int retval;
+       struct shash_desc *digest = NULL;
+       uint8_t sha1[SHA1_DIGEST_SIZE];
+       void *export_buf = NULL;
+       int retval, loop;
+
+       /* copy the current state of the digest, something that we have to do
+        * by exporting the old state and importing into the new state
+        */
+       export_buf = kmalloc(crypto_shash_statesize(partial_digest->tfm),
+                            GFP_KERNEL);
+       if (!export_buf)
+               return -ENOMEM;
+
+       retval = crypto_shash_export(partial_digest, export_buf);
+       if (retval < 0)
+               goto cleanup;
+
+       retval = -ENOMEM;
+       digest = kmalloc(sizeof(*partial_digest) +
+                        crypto_shash_descsize(partial_digest->tfm),
+                        GFP_KERNEL);
+       if (!digest)
+               goto cleanup;
+
+       digest->tfm = partial_digest->tfm;
+       digest->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+       if (ksign_debug) {
+               /* print the partial digest for debugging purposes */
+               retval = crypto_shash_import(digest, export_buf);
+               if (retval < 0)
+                       goto cleanup;
+
+               crypto_shash_final(digest, sha1);
+               printk(KERN_WARNING "Modsign digest: ");
+               for (loop = 0; loop < sizeof(sha1); loop++)
+                       printk("%02x", sha1[loop]);
+               printk("\n");
+       }
+
+       retval = crypto_shash_import(digest, export_buf);
+       if (retval < 0)
+               goto cleanup;
+
+       kfree(export_buf);
+       export_buf = NULL;
 
        /* parse the signature data to get the actual signature */
        retval = ksign_parse_packets(sigdata, sig_size,
@@ -152,14 +192,15 @@ int ksign_verify_signature(const char *sigdata, unsigned sig_size,
        if (!sig) {
                printk(KERN_NOTICE
                       "Couldn't find valid DSA signature in module\n");
-               return -ENOENT;
+               retval = -ENOENT;
+               goto cleanup;
        }
 
        _debug("signature keyid: %08x%08x ver=%u\n",
               sig->keyid[0], sig->keyid[1], sig->version);
 
        /* check the data SHA1 transformation against the public key */
-       retval = ksign_signature_check(sig, sha1);
+       retval = ksign_signature_check(sig, digest);
        switch (retval) {
        case 0:
                _debug("ksign: Signature check succeeded\n");
@@ -168,15 +209,16 @@ int ksign_verify_signature(const char *sigdata, unsigned sig_size,
                _debug("ksign: Signature check ENOMEM\n");
                break;
        default:
-               _debug("ksign: Signature check failed\n");
+               _debug("ksign: Signature check failed: %d\n", retval);
                if (retval != -ENOKEY)
                        retval = -EKEYREJECTED;
                break;
        }
 
- cleanup:
+cleanup:
        if (sig)
                ksign_free_signature(sig);
-
+       kfree(export_buf);
+       kfree(digest);
        return retval;
 }
index c7ad2adbd154ce9269e753e765e60453f597b04b..3f910b1d76ffa0aec7f1322d1e1ef1e58a5ed84c 100644 (file)
@@ -153,18 +153,12 @@ extern int DSA_verify(const MPI datahash, const MPI sig[], const MPI pkey[]);
  * - we _know_ the data is locked into kernel memory, so we don't want to have
  *   to kmap() it
  */
-static inline void SHA1_putc(struct hash_desc *sha1, uint8_t ch)
+static inline void SHA1_putc(struct shash_desc *digest, uint8_t ch)
 {
-       struct scatterlist sg;
-
-       sg_init_one(&sg, &ch, 1);
-       crypto_hash_update(sha1, &sg, 1);
+       crypto_shash_update(digest, &ch, 1);
 }
 
-static inline void SHA1_write(struct hash_desc *sha1, const void *s, size_t n)
+static inline void SHA1_write(struct shash_desc *digest, const void *s, size_t n)
 {
-       struct scatterlist sg;
-
-       sg_init_one(&sg, s, n);
-       crypto_hash_update(sha1, &sg, n);
+       crypto_shash_update(digest, s, n);
 }
index ed5b44de4c915b27b61a2ef77dc58d0c69ecc569..8f05cae9b0a7465e29287e91df3372f1f30cdfcf 100644 (file)
@@ -10,13 +10,23 @@ struct mod_arch_specific
 };
 
 #ifdef CONFIG_64BIT
+#define MODULES_ARE_ELF64
 #define Elf_Shdr Elf64_Shdr
 #define Elf_Sym Elf64_Sym
 #define Elf_Ehdr Elf64_Ehdr
+#define Elf_Rel         Elf64_Rel
+#define Elf_Rela        Elf64_Rela
+#define ELF_R_TYPE(X)   ELF64_R_TYPE(X)
+#define ELF_R_SYM(X)    ELF64_R_SYM(X)
 #else
+#define MODULES_ARE_ELF32
 #define Elf_Shdr Elf32_Shdr
 #define Elf_Sym Elf32_Sym
 #define Elf_Ehdr Elf32_Ehdr
+#define Elf_Rel         Elf32_Rel
+#define Elf_Rela        Elf32_Rela
+#define ELF_R_TYPE(X)   ELF32_R_TYPE(X)
+#define ELF_R_SYM(X)    ELF32_R_SYM(X)
 #endif
 
 #endif /* __ASM_GENERIC_MODULE_H */
index 27c9e4acdfc9f01bded567837af5b6a63f148dc3..0fc084d054ec9d3bbc09ba6c0ad8eaf9eccd39f9 100644 (file)
 #ifndef _LINUX_CRYPTO_KSIGN_H
 #define _LINUX_CRYPTO_KSIGN_H
 
-#include <linux/types.h>
-
 #ifdef CONFIG_CRYPTO_SIGNATURE
+
+#include <crypto/hash.h>
+
 extern int ksign_verify_signature(const char *sig, unsigned sig_size,
-                                 struct crypto_hash *sha1);
+                                 struct shash_desc *digest);
 #endif
 
 #endif /* _LINUX_CRYPTO_KSIGN_H */
index 4d5c5d56093f7bde8ee1547e69fd3089150dfbda..3bab35e599d2b4e555e9bb9b14e272f356de84b8 100644 (file)
@@ -94,8 +94,8 @@
 #define ELFNOTE32(name, type, desc) ELFNOTE(32, name, type, desc)
 #define ELFNOTE64(name, type, desc) ELFNOTE(64, name, type, desc)
 
-#define ELFNOTE_NAME(name)     #name
-#define ELFNOTE_SECTION(name)  ".note."#name
+#define ELFNOTE_NAME(name)     __stringify(name)
+#define ELFNOTE_SECTION(name)  ".note."ELFNOTE_NAME(name)
 #endif /* __ASSEMBLER__ */
 
 #endif /* _LINUX_ELFNOTE_H */
index f18015b421d47a25399391df28ca2e5e534c6ae9..4dea8d08fdffa071794bccb0946326c0c6d96cf7 100644 (file)
@@ -13,9 +13,7 @@
 #include <linux/slab.h>
 #include <linux/elf.h>
 #include <linux/ctype.h>
-#include <linux/module-verify.h>
-#include <linux/elf.h>
-#include <linux/module-verify-elf.h>
+#include "module-verify.h"
 
 #if 0
 #define _debug(FMT, ...) printk(FMT, ##__VA_ARGS__)
index 9810ee32b3680c895e4ce746dfd61dcd8d8b2a7e..b009d8e59764ec82bcdbf8ac34645568c27d6c1b 100644 (file)
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/elf.h>
-#include <linux/scatterlist.h>
-#include <linux/crypto.h>
 #include <linux/crypto/ksign.h>
 #include <linux/modsign.h>
-#include <linux/module-verify.h>
-#include <linux/module-verify-elf.h>
+#include "module-verify.h"
 
-#undef MODSIGN_DEBUG
+int modsign_debug;
+core_param(modsign_debug, modsign_debug, bool, 0644);
 
-#ifdef MODSIGN_DEBUG
-#define _debug(FMT, ...) printk(FMT, ##__VA_ARGS__)
-#else
-#define _debug(FMT, ...) do {} while (0)
-#endif
+#define _debug(FMT, ...)                           \
+       do {                                        \
+               if (unlikely(modsign_debug))        \
+                       printk(FMT, ##__VA_ARGS__); \
+       } while(0)
 
 #ifdef MODSIGN_DEBUG
 #define count_and_csum(C, __p, __n)                    \
@@ -48,22 +46,18 @@ do {                                                \
 
 #define crypto_digest_update_data(C, PTR, N)                   \
 do {                                                           \
-       struct scatterlist sg;                                  \
        uint8_t *__p = (uint8_t *)(PTR);                        \
        size_t __n = (N);                                       \
        count_and_csum((C), __p, __n);                          \
-       sg_init_one(&sg, __p, __n);                             \
-       crypto_hash_update(&(C)->hash, &sg, __n);               \
+       crypto_shash_update((C)->hash, __p, __n);               \
 } while (0)
 
-#define crypto_digest_update_val(C, VAL)                               \
+#define crypto_digest_update_val(C, VAL)                       \
 do {                                                           \
-       struct scatterlist sg;                                  \
        uint8_t *__p = (uint8_t *)&(VAL);                       \
        size_t __n = sizeof(VAL);                               \
        count_and_csum((C), __p, __n);                          \
-       sg_init_one(&sg, __p, __n);                             \
-       crypto_hash_update(&(C)->hash, &sg, __n);               \
+       crypto_shash_update((C)->hash, __p, __n);               \
 } while (0)
 
 static int module_verify_canonicalise(struct module_verify_data *mvdata);
@@ -101,18 +95,21 @@ int module_verify_signature(struct module_verify_data *mvdata,
                            int *_gpgsig_ok)
 {
        const struct elf_note *note;
+       struct crypto_shash *tfm;
        const Elf_Shdr *sechdrs = mvdata->sections;
        const char *secstrings = mvdata->secstrings;
        const char *sig;
        unsigned note_size, sig_size, note_namesz;
-       int i, ret;
+       int loop, ret;
 
-       for (i = 1; i < mvdata->nsects; i++) {
-               switch (sechdrs[i].sh_type) {
+       _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[i].sh_name,
+                       if (strcmp(mvdata->secstrings + sechdrs[loop].sh_name,
                                   modsign_note_section) == 0)
-                               mvdata->sig_index = i;
+                               mvdata->sig_index = loop;
                        break;
                }
        }
@@ -150,29 +147,43 @@ int module_verify_signature(struct module_verify_data *mvdata,
        /* grab an SHA1 transformation context
         * - !!! if this tries to load the sha1.ko module, we will deadlock!!!
         */
-       mvdata->hash.tfm = crypto_alloc_hash("sha1", 0, 0);
-       if (!mvdata->hash.tfm) {
-               printk("Couldn't load module - SHA1 transform unavailable\n");
+       tfm = crypto_alloc_shash("sha1", 0, 0);
+       if (!tfm) {
+               printk(KERN_ERR
+                      "Couldn't load module - SHA1 transform unavailable\n");
                return -EPERM;
        }
 
-       crypto_hash_init(&mvdata->hash);
+       mvdata->hash = kmalloc(sizeof(*mvdata->hash) +
+                              crypto_shash_descsize(tfm),
+                              GFP_KERNEL);
+       if (!mvdata->hash) {
+               crypto_free_shash(tfm);
+               return -ENOMEM;
+       }
+
+       mvdata->hash->tfm = tfm;
+       mvdata->hash->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+       ret = crypto_shash_init(mvdata->hash);
+       if (ret < 0) {
+               crypto_free_shash(mvdata->hash->tfm);
+               kfree(mvdata->hash);
+               return -ENOMEM;
+       }
 
 #ifdef MODSIGN_DEBUG
        mvdata->xcsum = 0;
 #endif
 
        /* load data from each relevant section into the digest */
-       for (i = 1; i < mvdata->nsects; i++) {
-               unsigned long sh_type = sechdrs[i].sh_type;
-               unsigned long sh_info = sechdrs[i].sh_info;
-               unsigned long sh_size = sechdrs[i].sh_size;
-               unsigned long sh_flags = sechdrs[i].sh_flags;
-               const char *sh_name = secstrings + sechdrs[i].sh_name;
-               const void *data = mvdata->buffer + sechdrs[i].sh_offset;
-
-               if (i == mvdata->sig_index)
-                       continue;
+       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;
@@ -183,36 +194,43 @@ int module_verify_signature(struct module_verify_data *mvdata,
                 * contents, because the symtab gets changed when sections are
                 * added or removed */
                if (sh_type == SHT_REL || sh_type == SHT_RELA) {
-                       if (mvdata->canonlist[sh_info]) {
-                               uint32_t xsh_info = mvdata->canonmap[sh_info];
-
-                               crypto_digest_update_data(mvdata, sh_name, strlen(sh_name));
-                               crypto_digest_update_val(mvdata, sechdrs[i].sh_type);
-                               crypto_digest_update_val(mvdata, sechdrs[i].sh_flags);
-                               crypto_digest_update_val(mvdata, sechdrs[i].sh_size);
-                               crypto_digest_update_val(mvdata, sechdrs[i].sh_addralign);
-                               crypto_digest_update_val(mvdata, xsh_info);
-
-                               if (sh_type == SHT_RELA)
-                                       ret = extract_elf_rela(
-                                               mvdata, i,
-                                               data,
-                                               sh_size / sizeof(Elf_Rela),
-                                               sh_name);
-                               else
-                                       ret = extract_elf_rel(
-                                               mvdata, i,
-                                               data,
-                                               sh_size / sizeof(Elf_Rel),
-                                               sh_name);
-
-                               if (ret < 0)
-                                       goto format_error;
-                       }
-
+                       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;
+               }
+
                /* ignore gcc's build ID section as it seems to get modified by
                 * the build process */
                if (strcmp(sh_name, ".note.gnu.build-id") == 0)
@@ -226,23 +244,26 @@ int module_verify_signature(struct module_verify_data *mvdata,
 
        include_section:
                crypto_digest_update_data(mvdata, sh_name, strlen(sh_name));
-               crypto_digest_update_val(mvdata, sechdrs[i].sh_type);
-               crypto_digest_update_val(mvdata, sechdrs[i].sh_flags);
-               crypto_digest_update_val(mvdata, sechdrs[i].sh_size);
-               crypto_digest_update_val(mvdata, sechdrs[i].sh_addralign);
+               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);
-
-               mvdata->canonlist[i] = 1;
        }
 
        _debug("Contributed %zu bytes to the digest (csum 0x%02x)\n",
               mvdata->signed_size, mvdata->xcsum);
 
        /* do the actual signature verification */
-       ret = ksign_verify_signature(sig, sig_size, mvdata->hash.tfm);
+       ret = ksign_verify_signature(sig, sig_size, mvdata->hash);
+
+       crypto_free_shash(mvdata->hash->tfm);
+       kfree(mvdata->hash);
 
        _debug("verify-sig : %d\n", ret);
 
@@ -263,13 +284,15 @@ int module_verify_signature(struct module_verify_data *mvdata,
        return ret;
 
 format_error:
-       crypto_free_hash(mvdata->hash.tfm);
+       crypto_free_shash(mvdata->hash->tfm);
+       kfree(mvdata->hash);
 format_error_no_free:
        printk(KERN_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;
        printk(KERN_ERR "An attempt to load unsigned module was rejected\n");
@@ -297,11 +320,16 @@ static int module_verify_canonicalise(struct module_verify_data *mvdata)
        for (loop = 1; loop < mvdata->nsects; loop++) {
                const Elf_Shdr *section = mvdata->sections + loop;
 
-               if (loop != mvdata->sig_index) {
-                       /* we only need to canonicalise allocatable sections */
-                       if (section->sh_flags & SHF_ALLOC)
-                               mvdata->canonlist[canon++] = 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 */
@@ -329,7 +357,7 @@ static int module_verify_canonicalise(struct module_verify_data *mvdata)
 
        for (loop = 0; loop < canon; loop++)
                mvdata->canonmap[mvdata->canonlist[loop]] = loop + 1;
-
+       mvdata->ncanon = canon;
        return 0;
 }
 
index 80ff866bc0ca7bc7b6eee38caeca4ca21a8d8713..18632438637591250c6e7c3e39726837efeec55b 100644 (file)
@@ -11,7 +11,8 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/module-verify.h>
+#include <linux/fips.h>
+#include "module-verify.h"
 
 /*
  * verify a module's integrity
@@ -36,6 +37,11 @@ int module_verify(const Elf_Ehdr *hdr, size_t size, int *_gpgsig_ok)
        }
 
        ret = module_verify_signature(&mvdata, _gpgsig_ok);
+#ifdef CONFIG_CRYPTO_FIPS
+       if (ret < 0 && fips_enabled)
+               panic("Module verification failed with error %d in FIPS mode\n",
+                     ret);
+#endif
 
 error:
        kfree(mvdata.secsizes);
similarity index 93%
rename from include/linux/module-verify.h
rename to kernel/module-verify.h
index 95995b291973ccd7d12d8f6c0fc29c9d2ab5433e..4e7b8e4d3829062fbc89990eff7b3deb53612bd6 100644 (file)
  */
 
 #include <linux/types.h>
-#include <linux/crypto.h>
+#include <crypto/hash.h>
 #include <asm/module.h>
 
 #ifdef CONFIG_MODULE_VERIFY
 struct module_verify_data {
-       struct hash_desc        hash;           /* module signature digest */
+       struct shash_desc       *hash;          /* module signature digest (SHA1) */
        const void              *buffer;        /* module buffer */
        const Elf_Ehdr          *hdr;           /* ELF header */
        const Elf_Shdr          *sections;      /* ELF section table */
@@ -30,6 +30,7 @@ struct module_verify_data {
        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 */
index 06cfec84ec366500928857e1b3ad0a2091e6d385..c4f5b89ed03ec73503a6ddc70c61ae710dacdc36 100644 (file)
@@ -58,7 +58,7 @@
 #include <linux/jump_label.h>
 #include <linux/pfn.h>
 #include <linux/bsearch.h>
-#include <linux/module-verify.h>
+#include "module-verify.h"
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/module.h>
index f4de5c14085046815b66ade476d4b7a3a56ad45f..809c5b8deed092ad4795fef0ff156a284456691c 100644 (file)
@@ -139,7 +139,7 @@ quiet_cmd_ld_ko_unsigned_o = LD [M]  $@
 $(modules:.ko=.ko.unsigned): %.ko.unsigned :%.o %.mod.o FORCE
        $(call if_changed,ld_ko_unsigned_o)
 
-targets += $(modules)
+targets += $(modules:.ko=.ko.unsigned)
 
 # Step 7), sign the modules
 MODSECKEY = ./kernel.sec
@@ -150,14 +150,31 @@ KEYFLAGS += --default-key $(MODKEYNAME)
 endif
 
 ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY))
+ifeq ($(KBUILD_SRC),)
+       # no O= is being used
+       SCRIPTS_DIR := scripts
+else
+       SCRIPTS_DIR := $(KBUILD_SRC)/scripts
+endif
+SIGN_MODULES := 1
+else
+SIGN_MODULES := 0
+endif
+
+# only sign if it's an in-tree module
+ifneq ($(KBUILD_EXTMOD),)
+SIGN_MODULES := 0
+endif
+
+ifeq ($(SIGN_MODULES),1)
 quiet_cmd_sign_ko_ko_unsigned = SIGN [M] $@
       cmd_sign_ko_ko_unsigned = \
                scripts/mod/mod-extract $< $@.digest && \
                rm -f $@.digest.sig && \
                gpg --batch --no-greeting $(KEYFLAGS) -b $@.digest && \
-               sh scripts/mod/modsign-note.sh $@.digest.sig | \
+               sh $(SCRIPTS_DIR)/mod/modsign-note.sh $@.digest.sig | \
                  $(CC) -x assembler-with-cpp $(c_flags) $(CFLAGS_MODULE) -c -o $@.note.o - && \
-               $(LD) -r -o $@ $< $@.note.o
+               $(LD) -r $(LDFLAGS) -o $@ $< $@.note.o
 else
 quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@
       cmd_sign_ko_ko_unsigned = \
index 0922e3a9bb8f2cb681560a6c014c2cf101307d12..14e155713b54b9d273aff15d26b788e8cc9718ac 100644 (file)
@@ -33,39 +33,39 @@ struct byteorder {
        void (*set64)(uint64_t *, uint64_t);
 };
 
-uint16_t get16_le(const uint16_t *p) { return __le16_to_cpu(*p); }
-uint32_t get32_le(const uint32_t *p) { return __le32_to_cpu(*p); }
-uint64_t get64_le(const uint64_t *p) { return __le64_to_cpu(*p); }
-uint16_t get16_be(const uint16_t *p) { return __be16_to_cpu(*p); }
-uint32_t get32_be(const uint32_t *p) { return __be32_to_cpu(*p); }
-uint64_t get64_be(const uint64_t *p) { return __be64_to_cpu(*p); }
-
-void set16_le(uint16_t *p, uint16_t n) { *p = __cpu_to_le16(n); }
-void set32_le(uint32_t *p, uint32_t n) { *p = __cpu_to_le32(n); }
-void set64_le(uint64_t *p, uint64_t n) { *p = __cpu_to_le64(n); }
-void set16_be(uint16_t *p, uint16_t n) { *p = __cpu_to_be16(n); }
-void set32_be(uint32_t *p, uint32_t n) { *p = __cpu_to_be32(n); }
-void set64_be(uint64_t *p, uint64_t n) { *p = __cpu_to_be64(n); }
-
-const struct byteorder byteorder_le = {
+static uint16_t get16_le(const uint16_t *p) { return __le16_to_cpu(*p); }
+static uint32_t get32_le(const uint32_t *p) { return __le32_to_cpu(*p); }
+static uint64_t get64_le(const uint64_t *p) { return __le64_to_cpu(*p); }
+static uint16_t get16_be(const uint16_t *p) { return __be16_to_cpu(*p); }
+static uint32_t get32_be(const uint32_t *p) { return __be32_to_cpu(*p); }
+static uint64_t get64_be(const uint64_t *p) { return __be64_to_cpu(*p); }
+
+static void set16_le(uint16_t *p, uint16_t n) { *p = __cpu_to_le16(n); }
+static void set32_le(uint32_t *p, uint32_t n) { *p = __cpu_to_le32(n); }
+static void set64_le(uint64_t *p, uint64_t n) { *p = __cpu_to_le64(n); }
+static void set16_be(uint16_t *p, uint16_t n) { *p = __cpu_to_be16(n); }
+static void set32_be(uint32_t *p, uint32_t n) { *p = __cpu_to_be32(n); }
+static void set64_be(uint64_t *p, uint64_t n) { *p = __cpu_to_be64(n); }
+
+static const struct byteorder byteorder_le = {
        get16_le, get32_le, get64_le,
        set16_le, set32_le, set64_le
 };
-const struct byteorder byteorder_be = {
+static const struct byteorder byteorder_be = {
        get16_be, get32_be, get64_be,
        set16_be, set32_be, set64_be
 };
-const struct byteorder *order;
+static const struct byteorder *order;
 
-uint16_t get16(const uint16_t *p) { return order->get16(p); }
-uint32_t get32(const uint32_t *p) { return order->get32(p); }
-uint64_t get64(const uint64_t *p) { return order->get64(p); }
-void set16(uint16_t *p, uint16_t n) { order->set16(p, n); }
-void set32(uint32_t *p, uint32_t n) { order->set32(p, n); }
-void set64(uint64_t *p, uint64_t n) { order->set64(p, n); }
+static inline uint16_t get16(const uint16_t *p) { return order->get16(p); }
+static inline uint32_t get32(const uint32_t *p) { return order->get32(p); }
+static inline uint64_t get64(const uint64_t *p) { return order->get64(p); }
+static inline void set16(uint16_t *p, uint16_t n) { order->set16(p, n); }
+static inline void set32(uint32_t *p, uint32_t n) { order->set32(p, n); }
+static inline void set64(uint64_t *p, uint64_t n) { order->set64(p, n); }
 
-FILE *outfd;
-uint8_t csum, xcsum;
+static FILE *outfd;
+static uint8_t csum, xcsum;
 
 static void write_out(const void *data, size_t size)
 {
@@ -235,8 +235,8 @@ static void extract_elf64_rela(const void *buffer, int secix, int targetix,
                set32(&relocation.r_type, ELF64_R_TYPE(r_info));
 
                if (ELF64_R_SYM(r_info) >= nsyms) {
-                       fprintf(stderr, "Invalid symbol ID %lx in relocation %zu\n",
-                               ELF64_R_SYM(r_info), loop);
+                       fprintf(stderr, "Invalid symbol ID %zx in relocation %zu\n",
+                               (size_t)ELF64_R_SYM(r_info), loop);
                        exit(1);
                }
 
@@ -302,8 +302,8 @@ static void extract_elf64_rel(const void *buffer, int secix, int targetix,
                set32(&relocation.r_type, ELF64_R_TYPE(r_info));
 
                if (ELF64_R_SYM(r_info) >= nsyms) {
-                       fprintf(stderr, "Invalid symbol ID %lx in relocation %zi\n",
-                               ELF64_R_SYM(r_info), loop);
+                       fprintf(stderr, "Invalid symbol ID %zx in relocation %zu\n",
+                               (size_t)ELF64_R_SYM(r_info), loop);
                        exit(1);
                }
 
@@ -369,6 +369,7 @@ static void extract_elf64(void *buffer, size_t len, Elf64_Ehdr *hdr)
                Elf64_Word  sh_type     = get32(&sections[loop].sh_type);
                Elf64_Xword sh_size     = get64(&sections[loop].sh_size);
                Elf64_Xword sh_flags    = get64(&sections[loop].sh_flags);
+               Elf64_Word  sh_info     = get32(&sections[loop].sh_info);
                Elf64_Off   sh_offset   = get64(&sections[loop].sh_offset);
                void *data = buffer + sh_offset;
 
@@ -381,6 +382,9 @@ static void extract_elf64(void *buffer, size_t len, Elf64_Ehdr *hdr)
                /* we only need to canonicalise allocatable sections */
                if (sh_flags & SHF_ALLOC)
                        canonlist[canon++] = loop;
+               else if ((sh_type == SHT_REL || sh_type == SHT_RELA) &&
+                        get64(&sections[sh_info].sh_flags) & SHF_ALLOC)
+                       canonlist[canon++] = loop;
 
                /* keep track of certain special sections */
                switch (sh_type) {
@@ -447,27 +451,28 @@ static void extract_elf64(void *buffer, size_t len, Elf64_Ehdr *hdr)
                }
        }
 
-       memset(canonlist, 0, sizeof(int) * shnum);
-
        /* iterate through the section table looking for sections we want to
         * contribute to the signature */
        verbose("\n");
-       verbose("FILE POS CS SECT NAME\n");
-       verbose("======== == ==== ==============================\n");
-
-       for (loop = 1; loop < shnum; loop++) {
-               const char *sh_name = secstrings + get32(&sections[loop].sh_name);
-               Elf64_Word  sh_type     = get32(&sections[loop].sh_type);
-               Elf64_Xword sh_size     = get64(&sections[loop].sh_size);
-               Elf64_Xword sh_flags    = get64(&sections[loop].sh_flags);
-               Elf64_Word  sh_info     = get32(&sections[loop].sh_info);
-               Elf64_Off   sh_offset   = get64(&sections[loop].sh_offset);
+       verbose("CAN FILE POS CS SECT NAME\n");
+       verbose("=== ======== == ==== ==============================\n");
+
+       for (loop = 0; loop < canon; loop++) {
+               int sect = canonlist[loop];
+               const char *sh_name = secstrings + get32(&sections[sect].sh_name);
+               Elf64_Word  sh_type     = get32(&sections[sect].sh_type);
+               Elf64_Xword sh_size     = get64(&sections[sect].sh_size);
+               Elf64_Xword sh_flags    = get64(&sections[sect].sh_flags);
+               Elf64_Word  sh_info     = get32(&sections[sect].sh_info);
+               Elf64_Off   sh_offset   = get64(&sections[sect].sh_offset);
                void *data = buffer + sh_offset;
 
                csum = 0;
 
                /* include canonicalised relocation sections */
                if (sh_type == SHT_REL || sh_type == SHT_RELA) {
+                       Elf32_Word canon_sh_info;
+
                        if (sh_info <= 0 && sh_info >= hdr->e_shnum) {
                                fprintf(stderr,
                                        "Invalid ELF - REL/RELA sh_info does"
@@ -475,41 +480,49 @@ static void extract_elf64(void *buffer, size_t len, Elf64_Ehdr *hdr)
                                exit(3);
                        }
 
-                       if (canonlist[sh_info]) {
-                               Elf32_Word xsh_info;
-
-                               verbose("%08lx ", ftell(outfd));
-
-                               set32(&xsh_info, canonmap[sh_info]);
-
-                               /* write out selected portions of the section
-                                * header */
-                               write_out(sh_name, strlen(sh_name));
-                               write_out_val(sections[loop].sh_type);
-                               write_out_val(sections[loop].sh_flags);
-                               write_out_val(sections[loop].sh_size);
-                               write_out_val(sections[loop].sh_addralign);
-                               write_out_val(xsh_info);
-
-                               if (sh_type == SHT_RELA)
-                                       extract_elf64_rela(buffer, loop, sh_info,
-                                                          data, sh_size / sizeof(Elf64_Rela),
-                                                          symbols, nsyms,
-                                                          sections, shnum, canonmap,
-                                                          strings, nstrings,
-                                                          sh_name);
-                               else
-                                       extract_elf64_rel(buffer, loop, sh_info,
-                                                         data, sh_size / sizeof(Elf64_Rel),
-                                                         symbols, nsyms,
-                                                         sections, shnum, canonmap,
-                                                         strings, nstrings,
-                                                         sh_name);
-                       }
-
+                       verbose("%3u %08lx ", loop, ftell(outfd));
+
+                       set32(&canon_sh_info, canonmap[sh_info]);
+
+                       /* write out selected portions of the section header */
+                       write_out(sh_name, strlen(sh_name));
+                       write_out_val(sections[sect].sh_type);
+                       write_out_val(sections[sect].sh_flags);
+                       write_out_val(sections[sect].sh_size);
+                       write_out_val(sections[sect].sh_addralign);
+                       write_out_val(canon_sh_info);
+
+                       if (sh_type == SHT_RELA)
+                               extract_elf64_rela(buffer, sect, sh_info,
+                                                  data, sh_size / sizeof(Elf64_Rela),
+                                                  symbols, nsyms,
+                                                  sections, shnum, canonmap,
+                                                  strings, nstrings,
+                                                  sh_name);
+                       else
+                               extract_elf64_rel(buffer, sect, sh_info,
+                                                 data, sh_size / sizeof(Elf64_Rel),
+                                                 symbols, nsyms,
+                                                 sections, shnum, canonmap,
+                                                 strings, nstrings,
+                                                 sh_name);
                        continue;
                }
 
+               /* include the headers of BSS sections */
+               if (sh_type == SHT_NOBITS && sh_flags & SHF_ALLOC) {
+                       verbose("%3u %08lx ", loop, ftell(outfd));
+
+                       /* write out selected portions of the section header */
+                       write_out(sh_name, strlen(sh_name));
+                       write_out_val(sections[sect].sh_type);
+                       write_out_val(sections[sect].sh_flags);
+                       write_out_val(sections[sect].sh_size);
+                       write_out_val(sections[sect].sh_addralign);
+
+                       verbose("%02x %4d %s\n", csum, sect, sh_name);
+               }
+
                /* ignore gcc's build ID section as it seems to get modified by
                 * the build process */
                if (strcmp(sh_name, ".note.gnu.build-id") == 0)
@@ -523,22 +536,19 @@ static void extract_elf64(void *buffer, size_t len, Elf64_Ehdr *hdr)
                continue;
 
        include_section:
-               verbose("%08lx ", ftell(outfd));
+               verbose("%3u %08lx ", loop, ftell(outfd));
 
                /* write out selected portions of the section header */
                write_out(sh_name, strlen(sh_name));
-               write_out_val(sections[loop].sh_type);
-               write_out_val(sections[loop].sh_flags);
-               write_out_val(sections[loop].sh_size);
-               write_out_val(sections[loop].sh_addralign);
+               write_out_val(sections[sect].sh_type);
+               write_out_val(sections[sect].sh_flags);
+               write_out_val(sections[sect].sh_size);
+               write_out_val(sections[sect].sh_addralign);
 
                /* write out the section data */
                write_out(data, sh_size);
 
-               verbose("%02x %4d %s\n", csum, loop, sh_name);
-
-               /* note the section has been written */
-               canonlist[loop] = 1;
+               verbose("%02x %4d %s\n", csum, sect, sh_name);
        }
 
        verbose("%08lx         (%lu bytes csum 0x%02x)\n",
@@ -720,6 +730,7 @@ static void extract_elf32(void *buffer, size_t len, Elf32_Ehdr *hdr)
                Elf32_Word  sh_type     = get32(&sections[loop].sh_type);
                Elf32_Xword sh_size     = get32(&sections[loop].sh_size);
                Elf32_Xword sh_flags    = get32(&sections[loop].sh_flags);
+               Elf64_Word  sh_info     = get32(&sections[loop].sh_info);
                Elf32_Off   sh_offset   = get32(&sections[loop].sh_offset);
                void *data = buffer + sh_offset;
 
@@ -732,6 +743,9 @@ static void extract_elf32(void *buffer, size_t len, Elf32_Ehdr *hdr)
                /* we only need to canonicalise allocatable sections */
                if (sh_flags & SHF_ALLOC)
                        canonlist[canon++] = loop;
+               else if ((sh_type == SHT_REL || sh_type == SHT_RELA) &&
+                        get32(&sections[sh_info].sh_flags) & SHF_ALLOC)
+                       canonlist[canon++] = loop;
 
                /* keep track of certain special sections */
                switch (sh_type) {
@@ -798,21 +812,20 @@ static void extract_elf32(void *buffer, size_t len, Elf32_Ehdr *hdr)
                }
        }
 
-       memset(canonlist, 0, sizeof(int) * shnum);
-
        /* iterate through the section table looking for sections we want to
         * contribute to the signature */
        verbose("\n");
-       verbose("FILE POS CS SECT NAME\n");
-       verbose("======== == ==== ==============================\n");
-
-       for (loop = 1; loop < shnum; loop++) {
-               const char *sh_name = secstrings + get32(&sections[loop].sh_name);
-               Elf32_Word  sh_type     = get32(&sections[loop].sh_type);
-               Elf32_Xword sh_size     = get32(&sections[loop].sh_size);
-               Elf32_Xword sh_flags    = get32(&sections[loop].sh_flags);
-               Elf32_Word  sh_info     = get32(&sections[loop].sh_info);
-               Elf32_Off   sh_offset   = get32(&sections[loop].sh_offset);
+       verbose("CAN FILE POS CS SECT NAME\n");
+       verbose("=== ======== == ==== ==============================\n");
+
+       for (loop = 0; loop < canon; loop++) {
+               int sect = canonlist[loop];
+               const char *sh_name = secstrings + get32(&sections[sect].sh_name);
+               Elf32_Word  sh_type     = get32(&sections[sect].sh_type);
+               Elf32_Xword sh_size     = get32(&sections[sect].sh_size);
+               Elf32_Xword sh_flags    = get32(&sections[sect].sh_flags);
+               Elf32_Word  sh_info     = get32(&sections[sect].sh_info);
+               Elf32_Off   sh_offset   = get32(&sections[sect].sh_offset);
                void *data = buffer + sh_offset;
 
                csum = 0;
@@ -825,6 +838,8 @@ static void extract_elf32(void *buffer, size_t len, Elf32_Ehdr *hdr)
 
                /* include canonicalised relocation sections */
                if (sh_type == SHT_REL || sh_type == SHT_RELA) {
+                       Elf32_Word canon_sh_info;
+
                        if (sh_info <= 0 && sh_info >= hdr->e_shnum) {
                                fprintf(stderr,
                                        "Invalid ELF - REL/RELA sh_info does"
@@ -832,40 +847,49 @@ static void extract_elf32(void *buffer, size_t len, Elf32_Ehdr *hdr)
                                exit(3);
                        }
 
-                       if (canonlist[sh_info]) {
-                               Elf32_Word xsh_info;
-
-                               verbose("%08lx ", ftell(outfd));
-
-                               set32(&xsh_info, canonmap[sh_info]);
-
-                               /* write out selected portions of the section header */
-                               write_out(sh_name, strlen(sh_name));
-                               write_out_val(sections[loop].sh_type);
-                               write_out_val(sections[loop].sh_flags);
-                               write_out_val(sections[loop].sh_size);
-                               write_out_val(sections[loop].sh_addralign);
-                               write_out_val(xsh_info);
-
-                               if (sh_type == SHT_RELA)
-                                       extract_elf32_rela(buffer, loop, sh_info,
-                                                          data, sh_size / sizeof(Elf32_Rela),
-                                                          symbols, nsyms,
-                                                          sections, shnum, canonmap,
-                                                          strings, nstrings,
-                                                          sh_name);
-                               else
-                                       extract_elf32_rel(buffer, loop, sh_info,
-                                                         data, sh_size / sizeof(Elf32_Rel),
-                                                         symbols, nsyms,
-                                                         sections, shnum, canonmap,
-                                                         strings, nstrings,
-                                                         sh_name);
-                       }
-
+                       verbose("%3u %08lx ", loop, ftell(outfd));
+
+                       set32(&canon_sh_info, canonmap[sh_info]);
+
+                       /* write out selected portions of the section header */
+                       write_out(sh_name, strlen(sh_name));
+                       write_out_val(sections[sect].sh_type);
+                       write_out_val(sections[sect].sh_flags);
+                       write_out_val(sections[sect].sh_size);
+                       write_out_val(sections[sect].sh_addralign);
+                       write_out_val(canon_sh_info);
+
+                       if (sh_type == SHT_RELA)
+                               extract_elf32_rela(buffer, sect, sh_info,
+                                                  data, sh_size / sizeof(Elf32_Rela),
+                                                  symbols, nsyms,
+                                                  sections, shnum, canonmap,
+                                                  strings, nstrings,
+                                                  sh_name);
+                       else
+                               extract_elf32_rel(buffer, sect, sh_info,
+                                                 data, sh_size / sizeof(Elf32_Rel),
+                                                 symbols, nsyms,
+                                                 sections, shnum, canonmap,
+                                                 strings, nstrings,
+                                                 sh_name);
                        continue;
                }
 
+               /* include the headers of BSS sections */
+               if (sh_type == SHT_NOBITS && sh_flags & SHF_ALLOC) {
+                       verbose("%3u %08lx ", loop, ftell(outfd));
+
+                       /* write out selected portions of the section header */
+                       write_out(sh_name, strlen(sh_name));
+                       write_out_val(sections[sect].sh_type);
+                       write_out_val(sections[sect].sh_flags);
+                       write_out_val(sections[sect].sh_size);
+                       write_out_val(sections[sect].sh_addralign);
+
+                       verbose("%02x %4d %s\n", csum, sect, sh_name);
+               }
+
                /* ignore gcc's build ID section as it seems to get modified by
                 * the build process */
                if (strcmp(sh_name, ".note.gnu.build-id") == 0)
@@ -879,22 +903,19 @@ static void extract_elf32(void *buffer, size_t len, Elf32_Ehdr *hdr)
                continue;
 
        include_section:
-               verbose("%08lx ", ftell(outfd));
+               verbose("%3u %08lx ", loop, ftell(outfd));
 
                /* write out selected portions of the section header */
                write_out(sh_name, strlen(sh_name));
-               write_out_val(sections[loop].sh_type);
-               write_out_val(sections[loop].sh_flags);
-               write_out_val(sections[loop].sh_size);
-               write_out_val(sections[loop].sh_addralign);
+               write_out_val(sections[sect].sh_type);
+               write_out_val(sections[sect].sh_flags);
+               write_out_val(sections[sect].sh_size);
+               write_out_val(sections[sect].sh_addralign);
 
                /* write out the section data */
                write_out(data, sh_size);
 
-               verbose("%02x %4d %s\n", csum, loop, sh_name);
-
-               /* note the section has been written */
-               canonlist[loop] = 1;
+               verbose("%02x %4d %s\n", csum, sect, sh_name);
        }
 
        verbose("%08lx         (%lu bytes csum 0x%02x)\n",
index b7b060ce4ead720695bbb63a0c02f168789f06d3..53c38f539fc8c8e1236e6fceef3317adfa84e0b5 100644 (file)
@@ -998,20 +998,36 @@ done
 # get rid of unwanted files resulting from patch fuzz
 find . \( -name "*.orig" -o -name "*~" \) -exec rm -f {} \; >/dev/null
 %if %{signmodules}
-  cp %{SOURCE19} .
-  pwd
-  gpg --homedir . --batch --gen-key %{SOURCE11}
-# if there're external keys to be included
-  if [ -s %{SOURCE19} ]; then
-      gpg --homedir . --no-default-keyring --keyring kernel.pub --import %{SOURCE19}
-  fi
-  gpg --homedir . --export --keyring kernel.pub Oracle > extract.pub
-  gcc -o scripts/bin2c scripts/bin2c.c
-  scripts/bin2c ksign_def_public_key __initdata < extract.pub >crypto/signature/key.h
-%endif
-                
+cp %{SOURCE19} .
+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
 
-cd ..
+if [ -s %{SOURCE19} ]; then
+        gpg --homedir . --no-default-keyring --keyring kernel.pub --import %{SOURCE19}
+fi
+gpg --homedir . --export --keyring ./kernel.pub Oracle > extract.pub
+gcc -o scripts/bin2c scripts/bin2c.c
+scripts/bin2c ksign_def_public_key __initdata <extract.pub >crypto/signature/key.h
+%endif
 
 ###
 ### build
index a998e1fdd22886c901b97a2195ad8223b82586a2..27babb3ea8a8d655fbb085d8c4f9cae6aec5fe9e 100644 (file)
@@ -1009,20 +1009,36 @@ done
 # get rid of unwanted files resulting from patch fuzz
 find . \( -name "*.orig" -o -name "*~" \) -exec rm -f {} \; >/dev/null
 %if %{signmodules}
-  cp %{SOURCE19} .
-  pwd
-  gpg --homedir . --batch --gen-key %{SOURCE11}
+cp %{SOURCE19} .
+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
 # if there're external keys to be included
-  if [ -s %{SOURCE19} ]; then
-      gpg --homedir . --no-default-keyring --keyring kernel.pub --import %{SOURCE19}
-  fi
-  gpg --homedir . --export --keyring kernel.pub Oracle > extract.pub
-  gcc -o scripts/bin2c scripts/bin2c.c
-  scripts/bin2c ksign_def_public_key __initdata < extract.pub >crypto/signature/key.h
+if [ -s %{SOURCE19} ]; then
+        gpg --homedir . --no-default-keyring --keyring kernel.pub --import %{SOURCE19}
+fi
+gpg --homedir . --export --keyring ./kernel.pub Oracle > extract.pub
+gcc -o scripts/bin2c scripts/bin2c.c
+scripts/bin2c ksign_def_public_key __initdata <extract.pub >crypto/signature/key.h
 %endif
-                
-
-cd ..
 
 ###
 ### build