From 39ea3b389a45f6c433b6102b61191583ac381425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sun, 2 Oct 2022 00:31:22 +0200 Subject: [PATCH 1/2] net: avoid assigning .0 and .255 IPs for higher VM ID Those occasionally cause issues if OS within a VM (especially without qubes tools installed) assumes /24 netmask. It wasn't an issue before, because max QID was 254. --- qubes/tests/vm/mix/net.py | 22 ++++++++++++++++++++++ qubes/vm/mix/net.py | 21 +++++++++++++++------ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/qubes/tests/vm/mix/net.py b/qubes/tests/vm/mix/net.py index a8b1e1f58..f7d99032f 100644 --- a/qubes/tests/vm/mix/net.py +++ b/qubes/tests/vm/mix/net.py @@ -27,6 +27,8 @@ import qubes.tests import qubes.tests.vm.qubesvm +from qubes.vm.mix.net import vmid_to_ipv4 + class TC_00_NetVMMixin( qubes.tests.vm.qubesvm.QubesVMTestsMixin, qubes.tests.QubesTestCase): @@ -154,3 +156,23 @@ def test_170_provides_network_netvm(self): self.assertPropertyValue(vm2, 'netvm', None, None, '') self.assertPropertyValue(vm2, 'netvm', '', None, '') self.assertPropertyValue(vm, 'provides_network', False, False, 'False') + + def test_200_vmid_to_ipv4(self): + testcases = ( + (1, '0.1'), + (2, '0.2'), + (254, '0.254'), + (255, '1.1'), + (256, '1.2'), + (257, '1.3'), + (508, '1.254'), + (509, '2.1'), + (510, '2.2'), + (511, '2.3'), + (512, '2.4'), + (513, '2.5'), + ) + for vmid, ip in testcases: + with self.subTest(str(vmid)): + self.assertEqual(ipaddress.IPv4Address('1.1.' + ip), + vmid_to_ipv4('1.1', vmid)) diff --git a/qubes/vm/mix/net.py b/qubes/vm/mix/net.py index 258e685a1..afe63941e 100644 --- a/qubes/vm/mix/net.py +++ b/qubes/vm/mix/net.py @@ -101,6 +101,19 @@ def __str__(self): return ' '.join(self) +def vmid_to_ipv4(prefix, vmid): + # avoid .0 and .255 addresses, it may trip some heuristics + # if OS assumes /24 netmask + # preserve unchanged IPs for low vmid + if vmid < 255: + return ipaddress.IPv4Address('{}.{}.{}'.format( + prefix, (vmid >> 8) & 0xff, vmid & 0xff)) + # don't reserve first .1 for vmid 0, as it is invalid + vmid -= 1 + return ipaddress.IPv4Address('{}.{}.{}'.format( + prefix, vmid // 254, (vmid % 254) + 1)) + + class NetVMMixin(qubes.events.Emitter): ''' Mixin containing network functionality ''' mac = qubes.property('mac', type=str, @@ -180,13 +193,9 @@ def get_ip_for_vm(vm): ''' import qubes.vm.dispvm # pylint: disable=redefined-outer-name if isinstance(vm, qubes.vm.dispvm.DispVM): - return ipaddress.IPv4Address('10.138.{}.{}'.format( - (vm.dispid >> 8) & 0xff, vm.dispid & 0xff)) + return vmid_to_ipv4('10.138', vm.dispid) - # VM technically can get address which ends in '.0'. This currently - # does not happen, because qid < 253, but may happen in the future. - return ipaddress.IPv4Address('10.137.{}.{}'.format( - (vm.qid >> 8) & 0xff, vm.qid & 0xff)) + return vmid_to_ipv4('10.137', vm.qid) @staticmethod def get_ip6_for_vm(vm): From f65ab1f5fd9977cae657441ea0b78677e8593ab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sun, 2 Oct 2022 00:33:56 +0200 Subject: [PATCH 2/2] Raise VM limit from 254 to 10000 Make max QID equal to max DispID. Technically QID could be up to 64770 (because of how IP addresses are assigned), but set the limit lower to allow future adjustments to the IP calculation without being forced into weird corner cases. Fixes QubesOS/qubes-issues#2519 --- qubes/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qubes/config.py b/qubes/config.py index a8f6c9de7..bf82e19c2 100644 --- a/qubes/config.py +++ b/qubes/config.py @@ -75,7 +75,7 @@ }, } -max_qid = 254 +max_qid = 10000 max_dispid = 10000 #: built-in standard labels, if creating new one, allocate them above this