From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
stable@vger.kernel.org,
Frank van der Linden <fllinden@amazon.com>,
Jessica Yu <jeyu@kernel.org>, Sasha Levin <sashal@kernel.org>
Subject: [PATCH 5.4 05/74] module: harden ELF info handling
Date: Mon, 5 Apr 2021 10:53:29 +0200 [thread overview]
Message-ID: <20210405085024.881993743@linuxfoundation.org> (raw)
In-Reply-To: <20210405085024.703004126@linuxfoundation.org>
From: Frank van der Linden <fllinden@amazon.com>
[ Upstream commit ec2a29593c83ed71a7f16e3243941ebfcf75fdf6 ]
5fdc7db644 ("module: setup load info before module_sig_check()")
moved the ELF setup, so that it was done before the signature
check. This made the module name available to signature error
messages.
However, the checks for ELF correctness in setup_load_info
are not sufficient to prevent bad memory references due to
corrupted offset fields, indices, etc.
So, there's a regression in behavior here: a corrupt and unsigned
(or badly signed) module, which might previously have been rejected
immediately, can now cause an oops/crash.
Harden ELF handling for module loading by doing the following:
- Move the signature check back up so that it comes before ELF
initialization. It's best to do the signature check to see
if we can trust the module, before using the ELF structures
inside it. This also makes checks against info->len
more accurate again, as this field will be reduced by the
length of the signature in mod_check_sig().
The module name is now once again not available for error
messages during the signature check, but that seems like
a fair tradeoff.
- Check if sections have offset / size fields that at least don't
exceed the length of the module.
- Check if sections have section name offsets that don't fall
outside the section name table.
- Add a few other sanity checks against invalid section indices,
etc.
This is not an exhaustive consistency check, but the idea is to
at least get through the signature and blacklist checks without
crashing because of corrupted ELF info, and to error out gracefully
for most issues that would have caused problems later on.
Fixes: 5fdc7db6448a ("module: setup load info before module_sig_check()")
Signed-off-by: Frank van der Linden <fllinden@amazon.com>
Signed-off-by: Jessica Yu <jeyu@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/module.c | 143 +++++++++++++++++++++++++++++++++-----
kernel/module_signature.c | 2 +-
kernel/module_signing.c | 2 +-
3 files changed, 127 insertions(+), 20 deletions(-)
diff --git a/kernel/module.c b/kernel/module.c
index 8d1def62a415..c60559b5bf10 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2926,7 +2926,7 @@ static int module_sig_check(struct load_info *info, int flags)
}
if (is_module_sig_enforced()) {
- pr_notice("%s: loading of %s is rejected\n", info->name, reason);
+ pr_notice("Loading of %s is rejected\n", reason);
return -EKEYREJECTED;
}
@@ -2939,9 +2939,33 @@ static int module_sig_check(struct load_info *info, int flags)
}
#endif /* !CONFIG_MODULE_SIG */
-/* Sanity checks against invalid binaries, wrong arch, weird elf version. */
-static int elf_header_check(struct load_info *info)
+static int validate_section_offset(struct load_info *info, Elf_Shdr *shdr)
{
+ unsigned long secend;
+
+ /*
+ * Check for both overflow and offset/size being
+ * too large.
+ */
+ secend = shdr->sh_offset + shdr->sh_size;
+ if (secend < shdr->sh_offset || secend > info->len)
+ return -ENOEXEC;
+
+ return 0;
+}
+
+/*
+ * Sanity checks against invalid binaries, wrong arch, weird elf version.
+ *
+ * Also do basic validity checks against section offsets and sizes, the
+ * section name string table, and the indices used for it (sh_name).
+ */
+static int elf_validity_check(struct load_info *info)
+{
+ unsigned int i;
+ Elf_Shdr *shdr, *strhdr;
+ int err;
+
if (info->len < sizeof(*(info->hdr)))
return -ENOEXEC;
@@ -2951,11 +2975,78 @@ static int elf_header_check(struct load_info *info)
|| info->hdr->e_shentsize != sizeof(Elf_Shdr))
return -ENOEXEC;
+ /*
+ * e_shnum is 16 bits, and sizeof(Elf_Shdr) is
+ * known and small. So e_shnum * sizeof(Elf_Shdr)
+ * will not overflow unsigned long on any platform.
+ */
if (info->hdr->e_shoff >= info->len
|| (info->hdr->e_shnum * sizeof(Elf_Shdr) >
info->len - info->hdr->e_shoff))
return -ENOEXEC;
+ info->sechdrs = (void *)info->hdr + info->hdr->e_shoff;
+
+ /*
+ * Verify if the section name table index is valid.
+ */
+ if (info->hdr->e_shstrndx == SHN_UNDEF
+ || info->hdr->e_shstrndx >= info->hdr->e_shnum)
+ return -ENOEXEC;
+
+ strhdr = &info->sechdrs[info->hdr->e_shstrndx];
+ err = validate_section_offset(info, strhdr);
+ if (err < 0)
+ return err;
+
+ /*
+ * The section name table must be NUL-terminated, as required
+ * by the spec. This makes strcmp and pr_* calls that access
+ * strings in the section safe.
+ */
+ info->secstrings = (void *)info->hdr + strhdr->sh_offset;
+ if (info->secstrings[strhdr->sh_size - 1] != '\0')
+ return -ENOEXEC;
+
+ /*
+ * The code assumes that section 0 has a length of zero and
+ * an addr of zero, so check for it.
+ */
+ if (info->sechdrs[0].sh_type != SHT_NULL
+ || info->sechdrs[0].sh_size != 0
+ || info->sechdrs[0].sh_addr != 0)
+ return -ENOEXEC;
+
+ for (i = 1; i < info->hdr->e_shnum; i++) {
+ shdr = &info->sechdrs[i];
+ switch (shdr->sh_type) {
+ case SHT_NULL:
+ case SHT_NOBITS:
+ continue;
+ case SHT_SYMTAB:
+ if (shdr->sh_link == SHN_UNDEF
+ || shdr->sh_link >= info->hdr->e_shnum)
+ return -ENOEXEC;
+ fallthrough;
+ default:
+ err = validate_section_offset(info, shdr);
+ if (err < 0) {
+ pr_err("Invalid ELF section in module (section %u type %u)\n",
+ i, shdr->sh_type);
+ return err;
+ }
+
+ if (shdr->sh_flags & SHF_ALLOC) {
+ if (shdr->sh_name >= strhdr->sh_size) {
+ pr_err("Invalid ELF section name in module (section %u type %u)\n",
+ i, shdr->sh_type);
+ return -ENOEXEC;
+ }
+ }
+ break;
+ }
+ }
+
return 0;
}
@@ -3052,11 +3143,6 @@ static int rewrite_section_headers(struct load_info *info, int flags)
for (i = 1; i < info->hdr->e_shnum; i++) {
Elf_Shdr *shdr = &info->sechdrs[i];
- if (shdr->sh_type != SHT_NOBITS
- && info->len < shdr->sh_offset + shdr->sh_size) {
- pr_err("Module len %lu truncated\n", info->len);
- return -ENOEXEC;
- }
/* Mark all sections sh_addr with their address in the
temporary image. */
@@ -3088,11 +3174,6 @@ static int setup_load_info(struct load_info *info, int flags)
{
unsigned int i;
- /* Set up the convenience variables */
- info->sechdrs = (void *)info->hdr + info->hdr->e_shoff;
- info->secstrings = (void *)info->hdr
- + info->sechdrs[info->hdr->e_shstrndx].sh_offset;
-
/* Try to find a name early so we can log errors with a module name */
info->index.info = find_sec(info, ".modinfo");
if (info->index.info)
@@ -3820,23 +3901,49 @@ static int load_module(struct load_info *info, const char __user *uargs,
long err = 0;
char *after_dashes;
- err = elf_header_check(info);
+ /*
+ * Do the signature check (if any) first. All that
+ * the signature check needs is info->len, it does
+ * not need any of the section info. That can be
+ * set up later. This will minimize the chances
+ * of a corrupt module causing problems before
+ * we even get to the signature check.
+ *
+ * The check will also adjust info->len by stripping
+ * off the sig length at the end of the module, making
+ * checks against info->len more correct.
+ */
+ err = module_sig_check(info, flags);
if (err)
goto free_copy;
+ /*
+ * Do basic sanity checks against the ELF header and
+ * sections.
+ */
+ err = elf_validity_check(info);
+ if (err) {
+ pr_err("Module has invalid ELF structures\n");
+ goto free_copy;
+ }
+
+ /*
+ * Everything checks out, so set up the section info
+ * in the info structure.
+ */
err = setup_load_info(info, flags);
if (err)
goto free_copy;
+ /*
+ * Now that we know we have the correct module name, check
+ * if it's blacklisted.
+ */
if (blacklisted(info->name)) {
err = -EPERM;
goto free_copy;
}
- err = module_sig_check(info, flags);
- if (err)
- goto free_copy;
-
err = rewrite_section_headers(info, flags);
if (err)
goto free_copy;
diff --git a/kernel/module_signature.c b/kernel/module_signature.c
index 4224a1086b7d..00132d12487c 100644
--- a/kernel/module_signature.c
+++ b/kernel/module_signature.c
@@ -25,7 +25,7 @@ int mod_check_sig(const struct module_signature *ms, size_t file_len,
return -EBADMSG;
if (ms->id_type != PKEY_ID_PKCS7) {
- pr_err("%s: Module is not signed with expected PKCS#7 message\n",
+ pr_err("%s: not signed with expected PKCS#7 message\n",
name);
return -ENOPKG;
}
diff --git a/kernel/module_signing.c b/kernel/module_signing.c
index 9d9fc678c91d..8723ae70ea1f 100644
--- a/kernel/module_signing.c
+++ b/kernel/module_signing.c
@@ -30,7 +30,7 @@ int mod_verify_sig(const void *mod, struct load_info *info)
memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
- ret = mod_check_sig(&ms, modlen, info->name);
+ ret = mod_check_sig(&ms, modlen, "module");
if (ret)
return ret;
--
2.30.1
next prev parent reply other threads:[~2021-04-05 9:05 UTC|newest]
Thread overview: 84+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-05 8:53 [PATCH 5.4 00/74] 5.4.110-rc1 review Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 01/74] selinux: vsock: Set SID for socket returned by accept() Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 02/74] ipv6: weaken the v4mapped source check Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 03/74] module: merge repetitive strings in module_sig_check() Greg Kroah-Hartman
2021-04-05 13:35 ` Sergey Shtylyov
2021-04-05 13:40 ` Greg Kroah-Hartman
2021-04-05 14:11 ` Sergey Shtylyov
2021-04-05 16:14 ` Sasha Levin
2021-04-05 8:53 ` [PATCH 5.4 04/74] module: avoid *goto*s " Greg Kroah-Hartman
2021-04-05 8:53 ` Greg Kroah-Hartman [this message]
2021-04-05 8:53 ` [PATCH 5.4 06/74] ext4: shrink race window in ext4_should_retry_alloc() Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 07/74] ext4: fix bh ref count on error paths Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 08/74] fs: nfsd: fix kconfig dependency warning for NFSD_V4 Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 09/74] rpc: fix NULL dereference on kmalloc failure Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 10/74] iomap: Fix negative assignment to unsigned sis->pages in iomap_swapfile_activate Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 11/74] ASoC: rt5640: Fix dac- and adc- vol-tlv values being off by a factor of 10 Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 12/74] ASoC: rt5651: " Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 13/74] ASoC: sgtl5000: set DAP_AVC_CTRL register to correct default value on probe Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 14/74] ASoC: es8316: Simplify adc_pga_gain_tlv table Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 15/74] ASoC: cs42l42: Fix Bitclock polarity inversion Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 16/74] ASoC: cs42l42: Fix channel width support Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 17/74] ASoC: cs42l42: Fix mixer volume control Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 18/74] ASoC: cs42l42: Always wait at least 3ms after reset Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 19/74] NFSD: fix error handling in NFSv4.0 callbacks Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 20/74] powerpc: Force inlining of cpu_has_feature() to avoid build failure Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 21/74] vhost: Fix vhost_vq_reset() Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 22/74] scsi: st: Fix a use after free in st_open() Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 23/74] scsi: qla2xxx: Fix broken #endif placement Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 24/74] staging: comedi: cb_pcidas: fix request_irq() warn Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 25/74] staging: comedi: cb_pcidas64: " Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 26/74] ASoC: rt5659: Update MCLK rate in set_sysclk() Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 27/74] thermal/core: Add NULL pointer check before using cooling device stats Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 28/74] locking/ww_mutex: Simplify use_ww_ctx & ww_ctx handling Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 29/74] ext4: do not iput inode under running transaction in ext4_rename() Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 30/74] net: mvpp2: fix interrupt mask/unmask skip condition Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 31/74] flow_dissector: fix TTL and TOS dissection on IPv4 fragments Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 32/74] can: dev: move driver related infrastructure into separate subdir Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 33/74] net: introduce CAN specific pointer in the struct net_device Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 34/74] can: tcan4x5x: fix max register value Greg Kroah-Hartman
2021-04-05 8:53 ` [PATCH 5.4 35/74] brcmfmac: clear EAP/association status bits on linkdown events Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 36/74] ath10k: hold RCU lock when calling ieee80211_find_sta_by_ifaddr() Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 37/74] net: ethernet: aquantia: Handle error cleanup of start on open Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 38/74] appletalk: Fix skb allocation size in loopback case Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 39/74] net: wan/lmc: unregister device when no matching device is found Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 40/74] bpf: Remove MTU check in __bpf_skb_max_len Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 41/74] ALSA: usb-audio: Apply sample rate quirk to Logitech Connect Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 42/74] ALSA: hda: Re-add dropped snd_poewr_change_state() calls Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 43/74] ALSA: hda: Add missing sanity checks in PM prepare/complete callbacks Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 44/74] ALSA: hda/realtek: fix a determine_headset_type issue for a Dell AIO Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 45/74] ALSA: hda/realtek: call alc_update_headset_mode() in hp_automute_hook Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 46/74] xtensa: move coprocessor_flush to the .text section Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 47/74] PM: runtime: Fix race getting/putting suppliers at probe Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 48/74] PM: runtime: Fix ordering in pm_runtime_get_suppliers() Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 49/74] tracing: Fix stack trace event size Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 50/74] mm: fix race by making init_zero_pfn() early_initcall Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 51/74] drm/amdgpu: fix offset calculation in amdgpu_vm_bo_clear_mappings() Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 52/74] drm/amdgpu: check alignment on CPU page for bo map Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 53/74] reiserfs: update reiserfs_xattrs_initialized() condition Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 54/74] drm/tegra: sor: Grab runtime PM reference across reset Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 55/74] vfio/nvlink: Add missing SPAPR_TCE_IOMMU depends Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 56/74] pinctrl: rockchip: fix restore error in resume Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 57/74] extcon: Add stubs for extcon_register_notifier_all() functions Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 58/74] extcon: Fix error handling in extcon_dev_register Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 59/74] firewire: nosy: Fix a use-after-free bug in nosy_ioctl() Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 60/74] usbip: vhci_hcd fix shift out-of-bounds in vhci_hub_control() Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 61/74] USB: quirks: ignore remote wake-up on Fibocom L850-GL LTE modem Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 62/74] usb: musb: Fix suspend with devices connected for a64 Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 63/74] usb: xhci-mtk: fix broken streams issue on 0.96 xHCI Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 64/74] cdc-acm: fix BREAK rx code path adding necessary calls Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 65/74] USB: cdc-acm: untangle a circular dependency between callback and softint Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 66/74] USB: cdc-acm: downgrade message to debug Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 67/74] USB: cdc-acm: fix double free on probe failure Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 68/74] USB: cdc-acm: fix use-after-free after " Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 69/74] usb: gadget: udc: amd5536udc_pci fix null-ptr-dereference Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 70/74] usb: dwc2: Fix HPRT0.PrtSusp bit setting for HiKey 960 board Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 71/74] usb: dwc2: Prevent core suspend when port connection flag is 0 Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 72/74] staging: rtl8192e: Fix incorrect source in memcpy() Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 73/74] staging: rtl8192e: Change state information from u16 to u8 Greg Kroah-Hartman
2021-04-05 8:54 ` [PATCH 5.4 74/74] drivers: video: fbcon: fix NULL dereference in fbcon_cursor() Greg Kroah-Hartman
2021-04-05 16:51 ` [PATCH 5.4 00/74] 5.4.110-rc1 review Florian Fainelli
2021-04-05 17:58 ` Guenter Roeck
2021-04-06 0:29 ` Shuah Khan
2021-04-06 3:42 ` Naresh Kamboju
2021-04-06 7:12 ` Samuel Zou
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210405085024.881993743@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=fllinden@amazon.com \
--cc=jeyu@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=sashal@kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox