Hello,
I cannot use IMA digital signatures with CONFIG_VMAP_STACK if some
kernel debugging options are selected (namely CONFIG_DEBUG_SG and/or CONFIG_DEBUG_VIRTUAL).
When taking a look at public_key_verify_signature() definition in
crypto/asymmetric_keys/public_key.c, we can see the following code:
struct scatterlist src_sg[2];
[...]
sg_init_table(src_sg, 2);
sg_set_buf(&src_sg[0], sig->s, sig->s_size);
sg_set_buf(&src_sg[1], sig->digest, sig->digest_size);
akcipher_request_set_crypt(req, src_sg, NULL, sig->s_size,
sig->digest_size);
While this code runs perfectly fine with kernels packaged by distributors, they do
not enable CONFIG_DEBUG_VIRTUAL nor CONFIG_DEBUG_SG. When enabling either of these
options with CONFIG_VMAP_STACK, it triggers a kernel BUG() when trying to measure
a signed file. BUG() result below:
[ 7583.382625] kernel BUG at include/linux/scatterlist.h:137!
[ 7583.382684] invalid opcode: 0000 [#1] SMP NOPTI
[ 7583.382732] CPU: 3 PID: 2219 Comm: bash Not tainted 5.13.0-vanilla.viveris.x86_64 #1
[ 7583.382804] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
[ 7583.382878] RIP: 0010:public_key_verify_signature+0x3be/0x3d0
[ 7583.382944] Code: e9 6f ff ff ff 0f 0b 4c 89 ef e8 3d 37 cb ff 4c 89 e6 4c 89 e7 e8 f2 79 fd ff b8 f4 ff ff ff e9 50 ff ff ff 0f 0b 0f 0b 0f 0b <0f> 0b 0f 0b e8 a9 21 64 00 66 0f 1f 84 00 00 00 00 00 0f 1f 44 00
[ 7583.383099] RSP: 0018:ffffa773c08f7930 EFLAGS: 00010246
[ 7583.383143] RAX: 0000000000000000 RBX: 0000000000000020 RCX: 0000000000000028
[ 7583.383198] RDX: 0000171ec08f7b38 RSI: 0000000000000017 RDI: ffffa774408f7b38
[ 7583.383260] RBP: ffffa773c08f7a70 R08: 0000000000000000 R09: ffffa773c08f7960
[ 7583.383314] R10: 000000000000000a R11: 0000000000000004 R12: ffff905602ba9e80
[ 7583.383356] R13: ffff905601131600 R14: ffff90560153aa00 R15: ffffa773c08f7b38
[ 7583.383397] FS: 00007ff25b9de740(0000) GS:ffff90567b980000(0000) knlGS:0000000000000000
[ 7583.383455] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 7583.383489] CR2: 0000561db1b06b88 CR3: 0000000103702002 CR4: 0000000000770ee0
[ 7583.383554] PKRU: 55555554
[ 7583.383573] Call Trace:
[ 7583.383607] ? kfree+0xd6/0x420
[ 7583.383632] ? keyring_search+0xc2/0xf0
[ 7583.383661] ? asymmetric_key_match_preparse+0x90/0x90
[ 7583.383696] ? key_default_cmp+0x20/0x20
[ 7583.383727] asymmetric_verify+0x13f/0x310
[ 7583.383757] evm_verify_hmac+0x23b/0x2e0
[ 7583.383785] ima_appraise_measurement+0x799/0x7f0
[ 7583.383817] process_measurement+0x728/0x920
[ 7583.383846] ? avc_has_perm+0xc4/0x1d0
[ 7583.383874] ? __kernel_read+0x19b/0x2c0
[ 7583.383902] ? __kernel_read+0x19b/0x2c0
[ 7583.383929] ima_bprm_check+0x55/0xb0
[ 7583.383954] bprm_execve+0x29b/0x5b0
[ 7583.383979] do_execveat_common.isra.39+0x199/0x1c0
[ 7583.384012] __x64_sys_execve+0x32/0x40
[ 7583.384038] do_syscall_64+0x5a/0x70
[ 7583.384066] ? do_user_addr_fault+0x1ce/0x640
[ 7583.384095] ? do_syscall_64+0x69/0x70
[ 7583.384121] ? exc_page_fault+0x7f/0x170
[ 7583.384149] entry_SYSCALL_64_after_hwframe+0x44/0xae
[ 7583.384182] RIP: 0033:0x7ff25b09005b
[ 7583.385275] Code: 41 89 01 eb da 66 2e 0f 1f 84 00 00 00 00 00 f7 d8 64 41 89 01 eb d6 0f 1f 84 00 00 00 00 00 f3 0f 1e fa b8 3b 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d fd 5d 2f 00 f7 d8 64 89 01 48
[ 7583.387623] RSP: 002b:00007fffa3461d78 EFLAGS: 00000246 ORIG_RAX: 000000000000003b
[ 7583.388801] RAX: ffffffffffffffda RBX: 0000561db1b20020 RCX: 00007ff25b09005b
[ 7583.389976] RDX: 0000561db1a51b40 RSI: 0000561db1b06b80 RDI: 0000561db1b20020
[ 7583.391193] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000001
[ 7583.392288] R10: 0000000000000008 R11: 0000000000000246 R12: 0000561db1b20020
[ 7583.393209] R13: 0000561db1b06b80 R14: 0000561db1a51b40 R15: 0000561db194d880
[ 7583.394121] Modules linked in: nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 rfkill ip_set nf_tables nfnetlink vfat fat intel_rapl_msr intel_rapl_common kvm_intel kvm ppdev irqbypass iTCO_wdt intel_pmc_bxt iTCO_vendor_support parport_pc parport joydev pcspkr i2c_i801 lpc_ich i2c_smbus dm_crypt xfs bochs_drm drm_vram_helper drm_kms_helper crct10dif_pclmul cec drm_ttm_helper crc32_pclmul ttm crc32c_intel drm ghash_clmulni_intel serio_raw virtio_net net_failover virtio_blk failover qemu_fw_cfg fuse
[ 7583.398129] ---[ end trace 42ba5ecbb402c663 ]---
[ 7583.398798] RIP: 0010:public_key_verify_signature+0x3be/0x3d0
[ 7583.399256] Code: e9 6f ff ff ff 0f 0b 4c 89 ef e8 3d 37 cb ff 4c 89 e6 4c 89 e7 e8 f2 79 fd ff b8 f4 ff ff ff e9 50 ff ff ff 0f 0b 0f 0b 0f 0b <0f> 0b 0f 0b e8 a9 21 64 00 66 0f 1f 84 00 00 00 00 00 0f 1f 44 00
[ 7583.400187] RSP: 0018:ffffa773c08f7930 EFLAGS: 00010246
[ 7583.400734] RAX: 0000000000000000 RBX: 0000000000000020 RCX: 0000000000000028
[ 7583.401200] RDX: 0000171ec08f7b38 RSI: 0000000000000017 RDI: ffffa774408f7b38
[ 7583.401695] RBP: ffffa773c08f7a70 R08: 0000000000000000 R09: ffffa773c08f7960
[ 7583.402044] R10: 000000000000000a R11: 0000000000000004 R12: ffff905602ba9e80
[ 7583.402425] R13: ffff905601131600 R14: ffff90560153aa00 R15: ffffa773c08f7b38
[ 7583.402775] FS: 00007ff25b9de740(0000) GS:ffff90567b980000(0000) knlGS:0000000000000000
[ 7583.403121] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 7583.403511] CR2: 0000561db1b06b88 CR3: 0000000103702002 CR4: 0000000000770ee0
[ 7583.403868] PKRU: 55555554
[ 7583.591257] BUG: Bad rss-counter state mm:00000000085d4bcd type:MM_ANONPAGES val:1
This BUG() was collected on a vanilla 5.13.0 kernel, and I can confirm I also ran
into this with 5.14.0-rc1. I'm afraid I don't have a simple reproducer here,
as it currently involves building the kernel with CONFIG DEBUG_SG, enabling
IMA digital signatures and running any signed file. That said, there are probably
other users of skcipher with on-stack addresses and they should experience
the same problem.
Variants of this bug are already known as it was identified and explained
back in 2016: http://lkml.iu.edu/hypermail/linux/kernel/1612.1/01472.html
It was explained again in another mail by Andy Lutomirski 6 months later:
https://seclists.org/oss-sec/2017/q2/600
Other commits also referenced the limitations of using scatterlist on the
stack, like 5a3235e50c0e3219d8659cbec996dae960acfee8 (net: phy: mscc:
avoid skcipher API for single block AES encryption) that say:
"Note that the scatterlist API does not permit references to buffers
that are located on the stack, so the existing code is incorrect in
any case, but avoiding the skcipher and scatterlist APIs entirely is
the most straight-forward approach to fixing this."
As a quick TL:DR; from what I could gather of the above exchanges,
scatter-gather operations are theoretically not usable on the stack as
they expect the memory addresses they manipulate to be convertible to
physical addresses and back (by adding/subtracting PAGE_OFFSET).
That doesn't work very well when CONFIG_VMAP_STACK is in use: the
physical address obtained through this process is invalid. However,
because the two operations (virt_to_page/page_address) are inverse
of each other, and the (invalid) physical address is not used directly
anywhere, it works in pratice! At least, it works as long as you do
not enable CONFIG_DEBUG_SG and/or CONFIG_DEBUG_VIRTUAL, as they will
BUG() on invalid physical addresses, even if those addresses are
never dereferenced. As a consequence, it appears one cannot use IMA
with digital signatures if both VMAP_STACK and (DEBUG_SC ||
DEBUG_VIRTUAL) are enabled.
I was wondering if this behavior was considered correct and if there was
some official guidance on enabling DEBUG_SG/DEBUG_VIRTUAL for "hardened"
Linux systems? Do you believe I should just disable DEBUG_SG and
DEBUG_VIRTUAL ?
Note: I CC'ed Andy Lutomirski as he was the main developer of CONFIG_VMAP_STACK
and he identified this problem in the past.
I did not CC linux-integrity because while it occurs when using IMA, the code
triggering the bug appears to be part of the crypto subsystem.
Thanks,
Simon