Skip to content

shim: change automatically enable MOK_POLICY_REQUIRE_NX#761

Merged
vathpela merged 1 commit intorhboot:mainfrom
vathpela:enable-dynamic-nx-policy
Jul 25, 2025
Merged

shim: change automatically enable MOK_POLICY_REQUIRE_NX#761
vathpela merged 1 commit intorhboot:mainfrom
vathpela:enable-dynamic-nx-policy

Conversation

@vathpela
Copy link
Copy Markdown
Member

Currently whether shim enforces NX on its downstream consumers is set at build time. It would be better for this to be automatically detected and enforced.

This patch changes the policy to be dynamically detected. In the case where shim has the NX bit set and the system has an appropriate protocol installed and appears to be enforcing NX, we enable the MOK policy bit to require NX.

@vathpela vathpela force-pushed the enable-dynamic-nx-policy branch from ecd665e to 296537c Compare July 17, 2025 16:50
@vathpela vathpela requested a review from jsetje July 17, 2025 16:51
@vathpela vathpela force-pushed the enable-dynamic-nx-policy branch from 296537c to e886747 Compare July 17, 2025 18:44
@kukrimate
Copy link
Copy Markdown
Collaborator

kukrimate commented Jul 21, 2025

This patch is great, I haven't tested it but assuming it works correctly.

It solves a miserable problems around NX deployment by letting non-NX chainloaded objects to continue working on non-NX machines even if the shim is set to NX compat.

@joeyli
Copy link
Copy Markdown
Contributor

joeyli commented Jul 23, 2025

Hi vathpela,

I have tested your patch on OVMF edk2-stable202505 and Mu release/202202. It works to me to auto detect firmware's NX/RO support and auto enable MOK_POLICY_REQUIRE_NX:

OVMF edk2-stable202505:

MdeModulePkg/MdeModulePkg.dec
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x0007BD5|UINT64|0x00001048

shim.c:2035:efi_main() SBAT self-check succeeded
memattrs.c:455:get_hsi_mem_info() Setting HSI from NX to HASMAP|NX
memattrs.c:52:get_dxe_services_table() Looking for configuration table 05AD34BA-6F02-4214-2E95-4DA0398E2BB9
memattrs.c:56:get_dxe_services_table() Testing configuration table EE4E5898-3914-4259-6E9D-DC7BD79403CF
memattrs.c:56:get_dxe_services_table() Testing configuration table 05AD34BA-6F02-4214-2E95-4DA0398E2BB9
memattrs.c:61:get_dxe_services_table() Looking for DXE Services Signature 0x565245535F455844, found signature 0x565245535F455844
memattrs.c:74:get_dxe_services_table() Setting dxe_services_table to 0x7FEE9DA0
memattrs.c:463:get_hsi_mem_info() Setting HSI from HASMAP|NX to HASMAP|HASDST|NX
memattrs.c:468:get_hsi_mem_info() Setting HSI from HASMAP|HASDST|NX to HASMAP|HASDST|HASDSTGMSD|NX
memattrs.c:474:get_hsi_mem_info() Setting HSI from HASMAP|HASDST|HASDSTGMSD|NX to HASMAP|HASDST|HASDSTGMSD|HASDSTSMSA|NX
memattrs.c:496:get_hsi_mem_info() get_hsi_mem_info() is on a writable page: HASMAP|HASDST|HASDSTGMSD|HASDSTSMSA|NX->ROW|HASMAP|HASDST|HASDSTGMSD|HASDSTSMSA|NX

Vigor136:~ # cat /sys/firmware/efi/mok-variables/HSIStatus
heap-is-executable: 0
stack-is-executable: 0
ro-sections-are-writable: 1 <-- OVMF does not handle RO
has-memory-attribute-protocol: 1
has-dxe-services-table: 1
has-get-memory-space-descriptor: 1
has-set-memory-space-attributes: 1
shim-has-nx-compat-set: 1

Mu release/202202:

shim.c:2013:efi_main() SkuSiPolicyVersion variable initialization done �
memattrs.c:455:get_hsi_mem_info() Setting HSI from NX to HASMAP|NX �
memattrs.c:52:get_dxe_services_table() Looking for configuration table 05AD34BA-6F02-4214-2E95-4DA0398E2BB9
memattrs.c:56:get_dxe_services_table() Testing configuration table EE4E5898-3914-4259-6E9D-DC7BD79403CF ����������������������������
memattrs.c:56:get_dxe_services_table() Testing configuration table 05AD34BA-6F02-4214-2E95-4DA0398E2BB9
memattrs.c:61:get_dxe_services_table() Looking for DXE Services Signature 0x565245535F455844, found signature 0x565245535F455844
memattrs.c:74:get_dxe_services_table() Setting dxe_services_table to 0x7BF58780
memattrs.c:463:get_hsi_mem_info() Setting HSI from HASMAP|NX to HASMAP|HASDST|NX
memattrs.c:468:get_hsi_mem_info() Setting HSI from HASMAP|HASDST|NX to HASMAP|HASDST|HASDSTGMSD|NX
memattrs.c:474:get_hsi_mem_info() Setting HSI from HASMAP|HASDST|HASDSTGMSD|NX to HASMAP|HASDST|HASDSTGMSD|HASDSTSMSA|NX
pe-relocate.c:687:set_shim_nx_policy() Enforcing NX policy for all images <-- set Forcing NX policy
mok.c:1260:import_mok_state() importing minimal mok state variables

Vigor136:~ # cat /sys/firmware/efi/mok-variables/HSIStatus
heap-is-executable: 0
stack-is-executable: 0
ro-sections-are-writable: 0 <-- Mu handles RO
has-memory-attribute-protocol: 1
has-dxe-services-table: 1
has-get-memory-space-descriptor: 1
has-set-memory-space-attributes: 1
shim-has-nx-compat-set: 1

@joeyli
Copy link
Copy Markdown
Contributor

joeyli commented Jul 23, 2025

I tested this patch using edk2-ovmf-202505, which is enforcing NX, and edk2-ovmf-202502, where enforcement can be turned on or off. When NX is being enforced, and shim has NX-compat bit set, it refuses to load a non-NX kernel, and refuses to load a non-NX grub2. If shim is not NX-compat, everything loads. Without the patch, it is as Mate wrote: NX-compat shim will continue to load non-NX compat grub2, kernels.

@marta-lewandowska

Hi Marta,
I tested edk2-stable202505 but my result is that the ro-sections-are-writable checking is NOT pass:

Vigor136:~ # cat /sys/firmware/efi/mok-variables/HSIStatus
heap-is-executable: 0
stack-is-executable: 0
ro-sections-are-writable: 1 <-- OVMF does not handle RO
has-memory-attribute-protocol: 1
has-dxe-services-table: 1
has-get-memory-space-descriptor: 1
has-set-memory-space-attributes: 1
shim-has-nx-compat-set: 1

Could you please teach me how to enable the RO section on OVMF?

Thanks a lot!

@vathpela
Copy link
Copy Markdown
Member Author

Could you please teach me how to enable the RO section on OVMF?

I think kraxon has done some work in https://copr.fedorainfracloud.org/coprs/kraxel/edk2.testbuilds/builds/ for this?

@marta-lewandowska
Copy link
Copy Markdown

Hi Joey, after posting that comment, I later deleted it because I wasn't quite happy with my testing. Sorry about that! I need to do a few more tests, I think.

@marta-lewandowska
Copy link
Copy Markdown

@joeyli I think you need edk2-ovmf-20250523-12, which is available in fedora rawhide:
[root@localhost ~]# cat /sys/firmware/efi/mok-variables/HSIStatus
heap-is-executable: 0
stack-is-executable: 0
ro-sections-are-writable: 0
has-memory-attribute-protocol: 1
has-dxe-services-table: 1
has-get-memory-space-descriptor: 1
has-set-memory-space-attributes: 1
shim-has-nx-compat-set: 1

@marta-lewandowska
Copy link
Copy Markdown

Tested the patch with edk2-ovmf-20250523-12, and it does what the commit message promises: since this fw enforces NX, a shim with NX compat bit set only loads GRUB and kernels which are also NX compat.
memattrs.c:455:get_hsi_mem_info() Setting HSI from NX to HASMAP|NX
memattrs.c:52:get_dxe_services_table() Looking for configuration table 05AD34BA-6F02-4214-2E95-4DA0398E2BB9
memattrs.c:56:get_dxe_services_table() Testing configuration table EE4E5898-3914-4259-6E9D-DC7BD79403CF
memattrs.c:56:get_dxe_services_table() Testing configuration table 05AD34BA-6F02-4214-2E95-4DA0398E2BB9
memattrs.c:61:get_dxe_services_table() Looking for DXE Services Signature 0x565245535F455844, found signature 0x565245535F455844
memattrs.c:74:get_dxe_services_table() Setting dxe_services_table to 0x7EF88C40
memattrs.c:463:get_hsi_mem_info() Setting HSI from HASMAP|NX to HASMAP|HASDST|NX
memattrs.c:468:get_hsi_mem_info() Setting HSI from HASMAP|HASDST|NX to HASMAP|HASDST|HASDSTGMSD|NX
memattrs.c:474:get_hsi_mem_info() Setting HSI from HASMAP|HASDST|HASDSTGMSD|NX to HASMAP|HASDST|HASDSTGMSD|HASDSTSMSA|NX
pe-relocate.c:687:set_shim_nx_policy() Enforcing NX policy for all images

[root@localhost ~]# cat /sys/firmware/efi/mok-variables/HSIStatus
heap-is-executable: 0
stack-is-executable: 0
ro-sections-are-writable: 0
has-memory-attribute-protocol: 1
has-dxe-services-table: 1
has-get-memory-space-descriptor: 1
has-set-memory-space-attributes: 1
shim-has-nx-compat-set: 0

If the shim is non NX-compat, it will load non NX compat GRUB and kernels even if fw is enforcing.

@joeyli
Copy link
Copy Markdown
Contributor

joeyli commented Jul 24, 2025

Could you please teach me how to enable the RO section on OVMF?

I think kraxon has done some work in https://copr.fedorainfracloud.org/coprs/kraxel/edk2.testbuilds/builds/ for this?

Thanks for vathpela and marta's information. The opt/org.tianocore/UninstallMemAttrProtocol=no does no work to me on my ovmf for ro-exctions. But I will dig vathpela's URL for finding out more detail.

Thanks a lot!

@joeyli
Copy link
Copy Markdown
Contributor

joeyli commented Jul 24, 2025

Could you please teach me how to enable the RO section on OVMF?

I think kraxon has done some work in https://copr.fedorainfracloud.org/coprs/kraxel/edk2.testbuilds/builds/ for this?

Thanks for vathpela and marta's information. The opt/org.tianocore/UninstallMemAttrProtocol=no does no work to me on my ovmf for ro-exctions. But I will dig vathpela's URL for finding out more detail.

Thanks a lot!

After enabling 'Set image protection policy' feature for 'Image from unknown device', the ro-sections works on ovmf edk2-stable202505 now. I put the change of ovmf here for reference:

--- edk2-edk2-stable202505.orig/MdeModulePkg/MdeModulePkg.dec
+++ edk2-edk2-stable202505/MdeModulePkg/MdeModulePkg.dec

  • gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy|0x00000002|UINT32|0x00001047^M
  • gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy|0x00000003|UINT32|0x00001047^M
  • gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x0000000|UINT64|0x00001048^M
  • gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x0007FD5|UINT64|0x00001048^M

And the following is testing result from Peter's patch with patches ovmf edk2-stable202505:

memattrs.c:463:get_hsi_mem_info() Setting HSI from HASMAP|NX to HASMAP|HASDST|NX
memattrs.c:468:get_hsi_mem_info() Setting HSI from HASMAP|HASDST|NX to HASMAP|HASDST|HASDSTGMSD|NX
memattrs.c:474:get_hsi_mem_info() Setting HSI from HASMAP|HASDST|HASDSTGMSD|NX to HASMAP|HASDST|HASDSTGMSD|HASDSTSMSA|NX
pe-relocate.c:687:set_shim_nx_policy() Enforcing NX policy for all images <-- force NX success on ovmf

Vigor136:~ # cat /sys/firmware/efi/mok-variables/HSIStatus
heap-is-executable: 0
stack-is-executable: 0
ro-sections-are-writable: 0 <-- ro-sections success on ovmf
has-memory-attribute-protocol: 1
has-dxe-services-table: 1
has-get-memory-space-descriptor: 1
has-set-memory-space-attributes: 1
shim-has-nx-compat-set: 1

@vathpela vathpela force-pushed the enable-dynamic-nx-policy branch from e886747 to 340d776 Compare July 24, 2025 18:20
Currently whether shim enforces NX on its downstream consumers is set at
build time.  It would be better for this to be automatically detected
and enforced.

This patch changes the policy to be dynamically detected.  In the case
where shim has the NX bit set and the system has an appropriate protocol
installed *and* appears to be enforcing NX, we enable the MOK policy bit
to require NX.

Signed-off-by: Peter Jones <pjones@redhat.com>
@vathpela vathpela force-pushed the enable-dynamic-nx-policy branch from 340d776 to 88cd97c Compare July 24, 2025 18:23
@vathpela vathpela marked this pull request as ready for review July 24, 2025 18:55
@vathpela vathpela merged commit 72a4c41 into rhboot:main Jul 25, 2025
20 checks passed
@vathpela vathpela deleted the enable-dynamic-nx-policy branch July 25, 2025 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants