[PATCH 0/2] qemu: Handle passt logfile a bit better

*** BLURB HERE *** Michal Prívozník (2): qemu_passt: Precreate passt logfile docs: Move passt log file in our example XML docs/formatdomain.rst | 2 +- src/qemu/qemu_passt.c | 40 +++++++++++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 6 deletions(-) -- 2.39.3

There are a few situations where passt itself is unable to create a file because it runs under QEMU user (e.g. just like our example from formatdomain.rst suggests: /var/log/passt.log). If libvirtd runs with sufficient permissions (e.g. as root) it can create the file and set seclabels on it so that passt can then open it. Ideally, we would just pass pre-opened FD, but this wasn't viewed as secure enough [1]. So lets just create the file and set seclabels. For the case when both libvirtd and passt have the same permissions, well then we fail before even needing to fork() and exec(). 1: https://archives.passt.top/passt-dev/20230606225836.63aecebe@elisabeth/ Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2209191 Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- src/qemu/qemu_passt.c | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_passt.c b/src/qemu/qemu_passt.c index 99636a3a49..25b22d8ad9 100644 --- a/src/qemu/qemu_passt.c +++ b/src/qemu/qemu_passt.c @@ -20,6 +20,8 @@ #include <config.h> +#include <fcntl.h> + #include "qemu_dbus.h" #include "qemu_extdevice.h" #include "qemu_security.h" @@ -136,9 +138,13 @@ void qemuPasstStop(virDomainObj *vm, virDomainNetDef *net) { + qemuDomainObjPrivate *priv = vm->privateData; + virQEMUDriver *driver = priv->driver; g_autofree char *pidfile = qemuPasstCreatePidFilename(vm, net); g_autofree char *passtSocketName = qemuPasstCreateSocketPath(vm, net); + qemuSecurityDomainRestorePathLabel(driver, vm, net->backend.logFile); + qemuPasstKill(pidfile, passtSocketName); } @@ -166,10 +172,12 @@ qemuPasstStart(virDomainObj *vm, { qemuDomainObjPrivate *priv = vm->privateData; virQEMUDriver *driver = priv->driver; + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); g_autofree char *passtSocketName = qemuPasstCreateSocketPath(vm, net); g_autoptr(virCommand) cmd = NULL; g_autofree char *pidfile = qemuPasstCreatePidFilename(vm, net); char macaddr[VIR_MAC_STRING_BUFLEN]; + bool needUnlink = false; size_t i; cmd = virCommandNew(PASST); @@ -191,8 +199,25 @@ qemuPasstStart(virDomainObj *vm, if (net->sourceDev) virCommandAddArgList(cmd, "--interface", net->sourceDev, NULL); - if (net->backend.logFile) + if (net->backend.logFile) { + VIR_AUTOCLOSE logfd = -1; + /* The logFile location is not restricted to a per-domain directory. It + * can be anywhere. Pre-create it as passt may not have enough perms to + * do so. */ + if (qemuDomainOpenFile(cfg, vm->def, net->backend.logFile, + O_CREAT | O_TRUNC | O_APPEND | O_RDWR, + &needUnlink) < 0) { + return -1; + } + + if (qemuSecurityDomainSetPathLabel(driver, vm, + net->backend.logFile, false) < 0) { + goto error; + } + + /* Worse, passt deliberately doesn't support FD passing. */ virCommandAddArgList(cmd, "--log-file", net->backend.logFile, NULL); + } /* Add IP address info */ for (i = 0; i < net->guestIP.nips; i++) { @@ -203,7 +228,7 @@ qemuPasstStart(virDomainObj *vm, * a single IPv4 and single IPv6 address */ if (!(addr = virSocketAddrFormat(&ip->address))) - return -1; + goto error; virCommandAddArgList(cmd, "--address", addr, NULL); @@ -231,14 +256,14 @@ qemuPasstStart(virDomainObj *vm, /* validation guarantees this will never happen */ virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid portForward proto value %1$u"), pf->proto); - return -1; + goto error; } if (VIR_SOCKET_ADDR_VALID(&pf->address)) { g_autofree char *addr = NULL; if (!(addr = virSocketAddrFormat(&pf->address))) - return -1; + goto error; virBufferAddStr(&buf, addr); emitsep = true; @@ -284,7 +309,7 @@ qemuPasstStart(virDomainObj *vm, if (qemuExtDeviceLogCommand(driver, vm, cmd, "passt") < 0) - return -1; + goto error; if (qemuSecurityCommandRun(driver, vm, cmd, -1, -1, true, NULL) < 0) goto error; @@ -292,6 +317,11 @@ qemuPasstStart(virDomainObj *vm, return 0; error: + if (needUnlink && unlink(net->backend.logFile) < 0) { + VIR_WARN("Unable to unlink '%s': %s", + net->backend.logFile, g_strerror(errno)); + } + qemuPasstKill(pidfile, passtSocketName); return -1; } -- 2.39.3

In our passt example XML we use /var/log/passt.log as path to the log file. This is not optimal, because in case of unprivileged daemon, neither libvirt nor passt has enough permissions to create the file. Let's move the file under /tmp. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- docs/formatdomain.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index c3526439bf..ec154605fc 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -4896,7 +4896,7 @@ ports **with the exception of some subset**. <devices> ... <interface type='user'> - <backend type='passt' logFile='/var/log/passt.log'/> + <backend type='passt' logFile='/tmp/passt.log'/> <mac address="00:11:22:33:44:55"/> <source dev='eth0'/> <ip family='ipv4' address='172.17.2.4' prefix='24'/> -- 2.39.3

On 6/12/23 10:15, Michal Privoznik wrote:
*** BLURB HERE ***
Michal Prívozník (2): qemu_passt: Precreate passt logfile docs: Move passt log file in our example XML
docs/formatdomain.rst | 2 +- src/qemu/qemu_passt.c | 40 +++++++++++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 6 deletions(-)
Polite ping. Michal

On a Monday in 2023, Michal Prívozník wrote:
On 6/12/23 10:15, Michal Privoznik wrote:
*** BLURB HERE ***
Michal Prívozník (2): qemu_passt: Precreate passt logfile docs: Move passt log file in our example XML
docs/formatdomain.rst | 2 +- src/qemu/qemu_passt.c | 40 +++++++++++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 6 deletions(-)
Polite ping.
Politely Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
Michal
participants (3)
-
Ján Tomko
-
Michal Privoznik
-
Michal Prívozník