From 6137b62856a556603728f471626c6f7bc362afe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Mon, 8 Dec 2025 01:32:42 +0100 Subject: [PATCH] Deserialize device from qrexec arg properly Avoid ':', '*' and '?' in the argument, as those are not allowed over qrexec. Fixes QubesOS/qubes-issues#10040 --- qubes/device_protocol.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/qubes/device_protocol.py b/qubes/device_protocol.py index e89a673fe..00b4387e4 100644 --- a/qubes/device_protocol.py +++ b/qubes/device_protocol.py @@ -536,6 +536,15 @@ def __lt__(self, other): def __repr__(self): return f"{self.port!r}:{self.device_id}" + @property + def repr_for_qarg(self): + """Object representation for qrexec argument""" + res = repr(self).replace(":", "+") + # replace '?' in category + unknown_dev = repr(DeviceInterface.unknown()) + res = res.replace(unknown_dev, "_" * len(unknown_dev)) + return res.replace("*", "_") + def __str__(self): return f"{self.port}:{self.device_id}" @@ -595,12 +604,20 @@ def _parse( """ if backend is None: backend_name, identity = representation.split(sep, 1) + if backend_name == "_": + backend_name = "*" if backend_name != "*": backend = get_domain(backend_name) else: identity = representation - port_id, _, devid = identity.partition(":") + port_id, _, devid = identity.replace(sep, ":").partition(":") + if port_id == "_": + port_id = "*" + if devid == "_": + devid = "*" + unknown_dev = repr(DeviceInterface.unknown()) + devid = devid.replace("_" * len(unknown_dev), unknown_dev) return cls( Port(backend_domain=backend, port_id=port_id, devclass=devclass), device_id=devid or None, @@ -1276,6 +1293,11 @@ def clone(self, **kwargs): def __repr__(self): return f"{self.virtual_device!r}" + @property + def repr_for_qarg(self): + """Object representation for qrexec argument""" + return self.virtual_device.repr_for_qarg + def __str__(self): return f"{self.virtual_device}"