Skip to content

Commit

Permalink
Validate default_kernel global property on set
Browse files Browse the repository at this point in the history
  • Loading branch information
alimirjamali committed Aug 19, 2024
1 parent a1a023b commit 9991c35
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 21 deletions.
29 changes: 29 additions & 0 deletions qubes/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,28 @@ def _setter_default_netvm(app, prop, value):
return value


def validate_kernel(obj, property_name: str, kernel: str) -> None:
"""Helper function to validate existence of specific kernel"""
if not kernel:
return
dirname = os.path.join(
qubes.config.qubes_base_dir,
qubes.config.system_path['qubes_kernels_base_dir'],
kernel)
if not os.path.exists(dirname):
raise qubes.exc.QubesPropertyValueError(
obj, property_name, kernel,
'Kernel {!r} not installed'.format(
kernel))
for filename in ('vmlinuz',):
if not os.path.exists(os.path.join(dirname, filename)):
raise qubes.exc.QubesPropertyValueError(
obj, property_name, kernel,
'Kernel {!r} not properly installed: '
'missing {!r} file'.format(
kernel, filename))


class Qubes(qubes.PropertyHolder):
"""Main Qubes application
Expand Down Expand Up @@ -1593,3 +1615,10 @@ def on_property_set_default_dispvm(self, event, name, newvalue,
# resetting dispvm to its default value
vm.fire_event('property-reset:default_dispvm',
name='default_dispvm', oldvalue=oldvalue)

@qubes.events.handler('property-pre-set:default_kernel')
# pylint: disable-next=invalid-name
def on_property_pre_set_default_kernel(self, event, name, newvalue,
oldvalue=None):
# pylint: disable=unused-argument
validate_kernel(self, 'default_kernel', newvalue)
8 changes: 8 additions & 0 deletions qubes/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,14 @@ def setUp(self):
self.loop = asyncio.get_event_loop()
self.addCleanup(self.cleanup_loop)

self.kernel_validator_original = qubes.app.validate_kernel
def kernel_validator_patched(obj, key, value):
if value.startswith('unittest'):
self.kernel_validator_original(obj, key, value)
self.skip_kernel_validation_patch = unittest.mock.patch(
'qubes.app.validate_kernel', kernel_validator_patched)
self.skip_kernel_validation_patch.start()

def cleanup_gc(self):
gc.collect()
leaked = [obj for obj in gc.get_objects() + gc.garbage
Expand Down
3 changes: 3 additions & 0 deletions qubes/tests/api_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,12 @@ def setUp(self):
self.base_dir_patch3 = unittest.mock.patch.dict(
qubes.config.defaults['pool_configs']['varlibqubes'],
{'dir_path': self.test_base_dir})
self.skip_kernel_validation_patch = unittest.mock.patch(
'qubes.app.validate_kernel', lambda obj, key, value: None)
self.base_dir_patch.start()
self.base_dir_patch2.start()
self.base_dir_patch3.start()
self.skip_kernel_validation_patch.start()
app = qubes.Qubes('/tmp/qubes-test.xml', load=False)
app.vmm = unittest.mock.Mock(spec=qubes.app.VMMConnection)
app.load_initial_values()
Expand Down
10 changes: 10 additions & 0 deletions qubes/tests/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,16 @@ def test_206_remove_attached(self):
with self.assertRaises(qubes.exc.QubesVMInUseError):
del self.app.domains[vm]

def test_207_default_kernel(self):
with self.assertRaises(qubes.exc.QubesPropertyValueError):
# invalid path check
self.app.default_kernel = 'unittest_Evil_Maid_Kernel'
with self.assertRaises(qubes.exc.QubesPropertyValueError):
# vmlinuz check
with mock.patch('os.path.exists') as existence:
existence.side_effect = [True, False]
self.app.default_kernel = 'unittest_GNU_Hurd_1.0.0'

@qubes.tests.skipUnlessGit
def test_900_example_xml_in_doc(self):
self.assertXMLIsValid(
Expand Down
8 changes: 5 additions & 3 deletions qubes/tests/vm/qubesvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,12 @@ def test_002_setter_qid_gt_max(self):
qubes.vm._setter_qid(self.vm,
self.prop, qubes.config.max_qid + 5)

@unittest.skip('test not implemented')
def test_020_setter_kernel(self):
pass

self.assertEqual(
qubes.vm.qubesvm._setter_kernel(self.vm, self.prop, None), '')
with self.assertRaises(ValueError):
qubes.vm.qubesvm._setter_kernel(self.vm,
self.prop, 'path/in/kernel/property')

def test_030_setter_label_object(self):
label = TestApp.labels[1]
Expand Down
19 changes: 1 addition & 18 deletions qubes/vm/qubesvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -1040,24 +1040,7 @@ def on_property_set_tmpl_for_dvms(self, event, name,
@qubes.events.handler('property-pre-set:kernel')
def on_property_pre_set_kernel(self, event, name, newvalue, oldvalue=None):
# pylint: disable=unused-argument
if not newvalue:
return
dirname = os.path.join(
qubes.config.qubes_base_dir,
qubes.config.system_path['qubes_kernels_base_dir'],
newvalue)
if not os.path.exists(dirname):
raise qubes.exc.QubesPropertyValueError(
self, self.property_get_def(name), newvalue,
'Kernel {!r} not installed'.format(
newvalue))
for filename in ('vmlinuz',):
if not os.path.exists(os.path.join(dirname, filename)):
raise qubes.exc.QubesPropertyValueError(
self, self.property_get_def(name), newvalue,
'Kernel {!r} not properly installed: '
'missing {!r} file'.format(
newvalue, filename))
qubes.app.validate_kernel(self, name, newvalue)

@qubes.events.handler('property-pre-set:autostart')
def on_property_pre_set_autostart(self, event, name, newvalue,
Expand Down

0 comments on commit 9991c35

Please sign in to comment.