|
| 1 | +efivarfs: force RO when remounting if SetVariable is not supported |
| 2 | + |
| 3 | +jira LE-1907 |
| 4 | +cve CVE-2023-52463 |
| 5 | +Rebuild_History Non-Buildable kernel-4.18.0-553.16.1.el8_10 |
| 6 | +commit-author Ilias Apalodimas < [email protected]> |
| 7 | +commit 0e8d2444168dd519fea501599d150e62718ed2fe |
| 8 | +Empty-Commit: Cherry-Pick Conflicts during history rebuild. |
| 9 | +Will be included in final tarball splat. Ref for failed cherry-pick at: |
| 10 | +ciq/ciq_backports/kernel-4.18.0-553.16.1.el8_10/0e8d2444.failed |
| 11 | + |
| 12 | +If SetVariable at runtime is not supported by the firmware we never assign |
| 13 | +a callback for that function. At the same time mount the efivarfs as |
| 14 | +RO so no one can call that. However, we never check the permission flags |
| 15 | +when someone remounts the filesystem as RW. As a result this leads to a |
| 16 | +crash looking like this: |
| 17 | + |
| 18 | +$ mount -o remount,rw /sys/firmware/efi/efivars |
| 19 | +$ efi-updatevar -f PK.auth PK |
| 20 | + |
| 21 | +[ 303.279166] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 |
| 22 | +[ 303.280482] Mem abort info: |
| 23 | +[ 303.280854] ESR = 0x0000000086000004 |
| 24 | +[ 303.281338] EC = 0x21: IABT (current EL), IL = 32 bits |
| 25 | +[ 303.282016] SET = 0, FnV = 0 |
| 26 | +[ 303.282414] EA = 0, S1PTW = 0 |
| 27 | +[ 303.282821] FSC = 0x04: level 0 translation fault |
| 28 | +[ 303.283771] user pgtable: 4k pages, 48-bit VAs, pgdp=000000004258c000 |
| 29 | +[ 303.284913] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000 |
| 30 | +[ 303.286076] Internal error: Oops: 0000000086000004 [#1] PREEMPT SMP |
| 31 | +[ 303.286936] Modules linked in: qrtr tpm_tis tpm_tis_core crct10dif_ce arm_smccc_trng rng_core drm fuse ip_tables x_tables ipv6 |
| 32 | +[ 303.288586] CPU: 1 PID: 755 Comm: efi-updatevar Not tainted 6.3.0-rc1-00108-gc7d0c4695c68 #1 |
| 33 | +[ 303.289748] Hardware name: Unknown Unknown Product/Unknown Product, BIOS 2023.04-00627-g88336918701d 04/01/2023 |
| 34 | +[ 303.291150] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) |
| 35 | +[ 303.292123] pc : 0x0 |
| 36 | +[ 303.292443] lr : efivar_set_variable_locked+0x74/0xec |
| 37 | +[ 303.293156] sp : ffff800008673c10 |
| 38 | +[ 303.293619] x29: ffff800008673c10 x28: ffff0000037e8000 x27: 0000000000000000 |
| 39 | +[ 303.294592] x26: 0000000000000800 x25: ffff000002467400 x24: 0000000000000027 |
| 40 | +[ 303.295572] x23: ffffd49ea9832000 x22: ffff0000020c9800 x21: ffff000002467000 |
| 41 | +[ 303.296566] x20: 0000000000000001 x19: 00000000000007fc x18: 0000000000000000 |
| 42 | +[ 303.297531] x17: 0000000000000000 x16: 0000000000000000 x15: 0000aaaac807ab54 |
| 43 | +[ 303.298495] x14: ed37489f673633c0 x13: 71c45c606de13f80 x12: 47464259e219acf4 |
| 44 | +[ 303.299453] x11: ffff000002af7b01 x10: 0000000000000003 x9 : 0000000000000002 |
| 45 | +[ 303.300431] x8 : 0000000000000010 x7 : ffffd49ea8973230 x6 : 0000000000a85201 |
| 46 | +[ 303.301412] x5 : 0000000000000000 x4 : ffff0000020c9800 x3 : 00000000000007fc |
| 47 | +[ 303.302370] x2 : 0000000000000027 x1 : ffff000002467400 x0 : ffff000002467000 |
| 48 | +[ 303.303341] Call trace: |
| 49 | +[ 303.303679] 0x0 |
| 50 | +[ 303.303938] efivar_entry_set_get_size+0x98/0x16c |
| 51 | +[ 303.304585] efivarfs_file_write+0xd0/0x1a4 |
| 52 | +[ 303.305148] vfs_write+0xc4/0x2e4 |
| 53 | +[ 303.305601] ksys_write+0x70/0x104 |
| 54 | +[ 303.306073] __arm64_sys_write+0x1c/0x28 |
| 55 | +[ 303.306622] invoke_syscall+0x48/0x114 |
| 56 | +[ 303.307156] el0_svc_common.constprop.0+0x44/0xec |
| 57 | +[ 303.307803] do_el0_svc+0x38/0x98 |
| 58 | +[ 303.308268] el0_svc+0x2c/0x84 |
| 59 | +[ 303.308702] el0t_64_sync_handler+0xf4/0x120 |
| 60 | +[ 303.309293] el0t_64_sync+0x190/0x194 |
| 61 | +[ 303.309794] Code: ???????? ???????? ???????? ???????? (????????) |
| 62 | +[ 303.310612] ---[ end trace 0000000000000000 ]--- |
| 63 | + |
| 64 | +Fix this by adding a .reconfigure() function to the fs operations which |
| 65 | +we can use to check the requested flags and deny anything that's not RO |
| 66 | +if the firmware doesn't implement SetVariable at runtime. |
| 67 | + |
| 68 | +Fixes: f88814cc2578 ("efi/efivars: Expose RT service availability via efivars abstraction") |
| 69 | + Signed-off-by: Ilias Apalodimas < [email protected]> |
| 70 | + Signed-off-by: Ard Biesheuvel < [email protected]> |
| 71 | +(cherry picked from commit 0e8d2444168dd519fea501599d150e62718ed2fe) |
| 72 | + Signed-off-by: Jonathan Maple < [email protected]> |
| 73 | + |
| 74 | +# Conflicts: |
| 75 | +# fs/efivarfs/super.c |
| 76 | +diff --cc fs/efivarfs/super.c |
| 77 | +index 25b2a651810b,869537f1a550..000000000000 |
| 78 | +--- a/fs/efivarfs/super.c |
| 79 | ++++ b/fs/efivarfs/super.c |
| 80 | +@@@ -16,6 -14,8 +16,11 @@@ |
| 81 | + #include <linux/ucs2_string.h> |
| 82 | + #include <linux/slab.h> |
| 83 | + #include <linux/magic.h> |
| 84 | +++<<<<<<< HEAD |
| 85 | +++======= |
| 86 | ++ #include <linux/statfs.h> |
| 87 | ++ #include <linux/printk.h> |
| 88 | +++>>>>>>> 0e8d2444168d (efivarfs: force RO when remounting if SetVariable is not supported) |
| 89 | + |
| 90 | + #include "internal.h" |
| 91 | + |
| 92 | +@@@ -231,8 -334,20 +236,23 @@@ static int efivarfs_get_tree(struct fs_ |
| 93 | + return get_tree_single(fc, efivarfs_fill_super); |
| 94 | + } |
| 95 | + |
| 96 | ++ static int efivarfs_reconfigure(struct fs_context *fc) |
| 97 | ++ { |
| 98 | ++ if (!efivar_supports_writes() && !(fc->sb_flags & SB_RDONLY)) { |
| 99 | ++ pr_err("Firmware does not support SetVariableRT. Can not remount with rw\n"); |
| 100 | ++ return -EINVAL; |
| 101 | ++ } |
| 102 | ++ |
| 103 | ++ return 0; |
| 104 | ++ } |
| 105 | ++ |
| 106 | + static const struct fs_context_operations efivarfs_context_ops = { |
| 107 | + .get_tree = efivarfs_get_tree, |
| 108 | +++<<<<<<< HEAD |
| 109 | +++======= |
| 110 | ++ .parse_param = efivarfs_parse_param, |
| 111 | ++ .reconfigure = efivarfs_reconfigure, |
| 112 | +++>>>>>>> 0e8d2444168d (efivarfs: force RO when remounting if SetVariable is not supported) |
| 113 | + }; |
| 114 | + |
| 115 | + static int efivarfs_init_fs_context(struct fs_context *fc) |
| 116 | +* Unmerged path fs/efivarfs/super.c |
0 commit comments