diff --git a/qubespolicy/__init__.py b/qubespolicy/__init__.py index 7aaabc22..74c54302 100755 --- a/qubespolicy/__init__.py +++ b/qubespolicy/__init__.py @@ -607,6 +607,15 @@ class Policy(object): 'policy define \'allow\' action at {}:{} but no target is ' 'specified by caller or policy'.format( rule.filename, rule.lineno)) + if actual_target == '$dispvm': + if system_info['domains'][source]['default_dispvm'] is None: + raise AccessDenied( + 'policy define \'allow\' action to $dispvm at {}:{} ' + 'but no DispVM base is set for this VM'.format( + rule.filename, rule.lineno)) + actual_target = '$dispvm:' + \ + system_info['domains'][source]['default_dispvm'] + return PolicyAction(self.service, source, actual_target, rule, target) else: diff --git a/qubespolicy/tests/__init__.py b/qubespolicy/tests/__init__.py index 6c3ee4a7..536d1b22 100644 --- a/qubespolicy/tests/__init__.py +++ b/qubespolicy/tests/__init__.py @@ -725,6 +725,19 @@ class TC_20_Policy(qubes.tests.QubesTestCase): 'default-dvm', '$dispvm:default-dvm', 'test-invalid-dvm', 'test-no-dvm', 'test-template', 'test-standalone']) + def test_034_eval_resolve_dispvm(self): + with open(os.path.join(tmp_policy_dir, 'test.service'), 'w') as f: + f.write('test-vm3 $dispvm allow\n') + + policy = qubespolicy.Policy('test.service', tmp_policy_dir) + action = policy.evaluate(system_info, 'test-vm3', '$dispvm') + self.assertEqual(action.rule, policy.policy_rules[0]) + self.assertEqual(action.action, qubespolicy.Action.allow) + self.assertEqual(action.target, '$dispvm:default-dvm') + self.assertEqual(action.original_target, '$dispvm') + self.assertEqual(action.service, 'test.service') + self.assertIsNone(action.targets_for_ask) + class TC_30_Misc(qubes.tests.QubesTestCase): @unittest.mock.patch('socket.socket')