1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* Module signature checker 3 * 4 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.com) 6 */ 7 8 #include <linux/kernel.h> 9 #include <linux/errno.h> 10 #include <linux/module.h> 11 #include <linux/module_signature.h> 12 #include <linux/string.h> 13 #include <linux/verification.h> 14 #include <linux/security.h> 15 #include <crypto/public_key.h> 16 #include <uapi/linux/module.h> 17 #include "internal.h" 18 19 #undef MODULE_PARAM_PREFIX 20 #define MODULE_PARAM_PREFIX "module." 21 22 static bool sig_enforce = IS_ENABLED(CONFIG_MODULE_SIG_FORCE); 23 module_param(sig_enforce, bool_enable_only, 0644); 24 25 /* 26 * Export sig_enforce kernel cmdline parameter to allow other subsystems rely 27 * on that instead of directly to CONFIG_MODULE_SIG_FORCE config. 28 */ 29 bool is_module_sig_enforced(void) 30 { 31 return sig_enforce; 32 } 33 EXPORT_SYMBOL(is_module_sig_enforced); 34 35 void set_module_sig_enforced(void) 36 { 37 sig_enforce = true; 38 } 39 40 /* 41 * Verify the signature on a module. 42 */ 43 int mod_verify_sig(const void *mod, struct load_info *info) 44 { 45 struct module_signature ms; 46 size_t sig_len, modlen = info->len; 47 int ret; 48 49 pr_devel("==>%s(,%zu)\n", __func__, modlen); 50 51 if (modlen <= sizeof(ms)) 52 return -EBADMSG; 53 54 memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms)); 55 56 ret = mod_check_sig(&ms, modlen, "module"); 57 if (ret) 58 return ret; 59 60 sig_len = be32_to_cpu(ms.sig_len); 61 modlen -= sig_len + sizeof(ms); 62 info->len = modlen; 63 64 return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len, 65 VERIFY_USE_SECONDARY_KEYRING, 66 VERIFYING_MODULE_SIGNATURE, 67 NULL, NULL); 68 } 69 70 int module_sig_check(struct load_info *info, int flags) 71 { 72 int err = -ENODATA; 73 const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; 74 const char *reason; 75 const void *mod = info->hdr; 76 bool mangled_module = flags & (MODULE_INIT_IGNORE_MODVERSIONS | 77 MODULE_INIT_IGNORE_VERMAGIC); 78 /* 79 * Do not allow mangled modules as a module with version information 80 * removed is no longer the module that was signed. 81 */ 82 if (!mangled_module && 83 info->len > markerlen && 84 memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) { 85 /* We truncate the module to discard the signature */ 86 info->len -= markerlen; 87 err = mod_verify_sig(mod, info); 88 if (!err) { 89 info->sig_ok = true; 90 return 0; 91 } 92 } 93 94 /* 95 * We don't permit modules to be loaded into the trusted kernels 96 * without a valid signature on them, but if we're not enforcing, 97 * certain errors are non-fatal. 98 */ 99 switch (err) { 100 case -ENODATA: 101 reason = "unsigned module"; 102 break; 103 case -ENOPKG: 104 reason = "module with unsupported crypto"; 105 break; 106 case -ENOKEY: 107 reason = "module with unavailable key"; 108 break; 109 110 default: 111 /* 112 * All other errors are fatal, including lack of memory, 113 * unparseable signatures, and signature check failures -- 114 * even if signatures aren't required. 115 */ 116 return err; 117 } 118 119 if (is_module_sig_enforced()) { 120 pr_notice("Loading of %s is rejected\n", reason); 121 return -EKEYREJECTED; 122 } 123 124 return security_locked_down(LOCKDOWN_MODULE_SIGNATURE); 125 } 126
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.