Skip to content

Commit 2322b3c

Browse files
committed
Add a flag to disable installing bootloaders
Disables bootloader installations (calls to grub-install) for security reasons as part of the mitigation for CVE-2026-43003. Depends-On: https://review.opendev.org/c/openstack/ironic/+/990724 Related-Bug: 2148310 Change-Id: I10c88426d5838820ecf6853dca5b3878dc29bdf4 Signed-off-by: Clif Houck <me@clifhouck.com> Signed-off-by: Jay Faulkner <jay@jvf.cc> (cherry picked from commit 6cd463a) (cherry picked from commit 1dc4048) (cherry picked from commit 10d133a522245f7228131bfc82b28e3f3c2ddd60)
1 parent 0474f30 commit 2322b3c

5 files changed

Lines changed: 71 additions & 11 deletions

File tree

‎ironic_python_agent/agent.py‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,9 @@ def process_lookup_data(self, content):
402402

403403
# Update config with values from Ironic
404404
config = content.get('config', {})
405+
if config.get('enable_bios_bootloader_install'):
406+
cfg.CONF.set_override('enable_bios_bootloader_install',
407+
config['enable_bios_bootloader_install'])
405408
if config.get('metrics'):
406409
for opt, val in config.items():
407410
setattr(cfg.CONF.metrics, opt, val)

‎ironic_python_agent/config.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,13 @@
346346
'image validation logic will fail the deployment '
347347
'process. This check is skipped if deep image '
348348
'inspection is disabled.'),
349+
cfg.BoolOpt('enable_bios_bootloader_install',
350+
default=False,
351+
help='Enables support for partition images which require a '
352+
'legacy bootloader -- and a call to ``grub-install``. '
353+
'Generally, this should remain disabled for maximum '
354+
'security, however, this option allows it to be '
355+
're-enabled for compatibility.'),
349356
]
350357

351358
disk_utils_opts = [

‎ironic_python_agent/extensions/image.py‎

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -716,15 +716,24 @@ def install_bootloader(self, root_uuid, efi_system_part_uuid=None,
716716
' Assuming a whole disk image')
717717
return
718718

719-
# In case we can't use efibootmgr for uefi we will continue using grub2
720-
LOG.debug('Using grub2-install to set up boot files')
721-
try:
722-
_install_grub2(device,
723-
root_uuid=root_uuid,
724-
efi_system_part_uuid=efi_system_part_uuid,
725-
prep_boot_part_uuid=prep_boot_part_uuid,
726-
target_boot_mode=target_boot_mode)
727-
except Exception as e:
728-
LOG.error('Error setting up bootloader. Error %s', e)
719+
if CONF.enable_bios_bootloader_install:
720+
# In case we can't use efibootmgr for uefi we will continue
721+
# using grub2
722+
LOG.debug('Using grub2-install to set up boot files')
723+
try:
724+
_install_grub2(device,
725+
root_uuid=root_uuid,
726+
efi_system_part_uuid=efi_system_part_uuid,
727+
prep_boot_part_uuid=prep_boot_part_uuid,
728+
target_boot_mode=target_boot_mode)
729+
except Exception as e:
730+
LOG.error('Error setting up bootloader. Error %s', e)
731+
if not ignore_failure:
732+
raise
733+
else:
734+
msg = ("Install of legacy BIOS bootloaders disabled by "
735+
"CONF.enable_bios_bootloader_install as part of "
736+
"CVE-2026-43003 mitigation.")
737+
LOG.error(msg)
729738
if not ignore_failure:
730-
raise
739+
raise errors.InvalidImage(details=msg)

‎ironic_python_agent/tests/unit/extensions/test_image.py‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def setUp(self):
5252
self.fake_efi_system_part_uuid = '45AB-2312'
5353
self.fake_prep_boot_part_uuid = '76937797-3253-8843-999999999999'
5454
self.fake_dir = '/tmp/fake-dir'
55+
self.config(enable_bios_bootloader_install=True)
5556

5657
@mock.patch.object(image, '_install_grub2', autospec=True)
5758
def test__install_bootloader_bios(self, mock_grub2,
@@ -68,8 +69,39 @@ def test__install_bootloader_bios(self, mock_grub2,
6869
self.fake_dev, root_uuid=self.fake_root_uuid,
6970
efi_system_part_uuid=None, prep_boot_part_uuid=None,
7071
target_boot_mode='bios'
72+
7173
)
7274

75+
@mock.patch.object(image, '_install_grub2', autospec=True)
76+
def test__install_bootloader_bios_disabled(self, mock_grub2,
77+
mock_execute, mock_dispatch):
78+
self.config(enable_bios_bootloader_install=False)
79+
mock_dispatch.side_effect = [
80+
self.fake_dev, hardware.BootInfo(current_boot_mode='bios')
81+
]
82+
self.agent_extension.install_bootloader(
83+
root_uuid=self.fake_root_uuid).join()
84+
mock_dispatch.assert_any_call('get_os_install_device')
85+
mock_dispatch.assert_any_call('get_boot_info')
86+
self.assertEqual(2, mock_dispatch.call_count)
87+
mock_grub2.assert_not_called()
88+
89+
@mock.patch.object(image, '_install_grub2', autospec=True)
90+
def test__install_bootloader_bios_disabled_dont_ignore_failures(
91+
self, mock_grub2, mock_execute, mock_dispatch):
92+
self.config(enable_bios_bootloader_install=False)
93+
self.config(ignore_bootloader_failure=False)
94+
mock_dispatch.side_effect = [
95+
self.fake_dev, hardware.BootInfo(current_boot_mode='bios')
96+
]
97+
result = self.agent_extension.install_bootloader(
98+
root_uuid=self.fake_root_uuid).join()
99+
mock_dispatch.assert_any_call('get_os_install_device')
100+
mock_dispatch.assert_any_call('get_boot_info')
101+
self.assertEqual(2, mock_dispatch.call_count)
102+
self.assertIsNotNone(result.command_error)
103+
mock_grub2.assert_not_called()
104+
73105
@mock.patch.object(efi_utils, 'manage_uefi', autospec=True)
74106
@mock.patch.object(image, '_install_grub2', autospec=True)
75107
def test__install_bootloader_uefi(self, mock_grub2, mock_uefi,
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
security:
3+
- |
4+
Disable installation of bootloaders (via grub-install) by default in order
5+
to improve security posture by adding a new configuration option
6+
`enable_bios_bootloader_install` which defaults to `False`. Operators
7+
who still need this functionality can re-enable installation of
8+
bootloaders by setting `enable_bios_bootloader_install` to `True`.
9+
Addresses CVE-2026-43003.

0 commit comments

Comments
 (0)