secrets: acquire a pidfile in the driver root directory

When we allow multiple instances of the driver for the same user
account, using a separate root directory, we need to ensure mutual
exclusion. Use a pidfile to guarantee this.

In privileged libvirtd this ends up locking

   /var/run/libvirt/secrets/driver.pid

In unprivileged libvirtd this ends up locking

  /run/user/$UID/libvirt/secrets/run/driver.pid

NB, the latter can vary depending on $XDG_RUNTIME_DIR

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2019-05-23 11:34:08 +01:00
parent 1af03e2714
commit 8292b9e364

View File

@ -37,6 +37,7 @@
#include "viruuid.h" #include "viruuid.h"
#include "virerror.h" #include "virerror.h"
#include "virfile.h" #include "virfile.h"
#include "virpidfile.h"
#include "configmake.h" #include "configmake.h"
#include "virstring.h" #include "virstring.h"
#include "viraccessapicheck.h" #include "viraccessapicheck.h"
@ -56,8 +57,12 @@ struct _virSecretDriverState {
virMutex lock; virMutex lock;
bool privileged; /* readonly */ bool privileged; /* readonly */
virSecretObjListPtr secrets; virSecretObjListPtr secrets;
char *stateDir;
char *configDir; char *configDir;
/* pid file FD, ensures two copies of the driver can't use the same root */
int lockFD;
/* Immutable pointer, self-locking APIs */ /* Immutable pointer, self-locking APIs */
virObjectEventStatePtr secretEventState; virObjectEventStatePtr secretEventState;
}; };
@ -434,6 +439,10 @@ secretStateCleanup(void)
virObjectUnref(driver->secretEventState); virObjectUnref(driver->secretEventState);
if (driver->lockFD != -1)
virPidFileRelease(driver->stateDir, "driver", driver->lockFD);
VIR_FREE(driver->stateDir);
secretDriverUnlock(); secretDriverUnlock();
virMutexDestroy(&driver->lock); virMutexDestroy(&driver->lock);
VIR_FREE(driver); VIR_FREE(driver);
@ -447,11 +456,10 @@ secretStateInitialize(bool privileged,
virStateInhibitCallback callback ATTRIBUTE_UNUSED, virStateInhibitCallback callback ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED) void *opaque ATTRIBUTE_UNUSED)
{ {
char *base = NULL;
if (VIR_ALLOC(driver) < 0) if (VIR_ALLOC(driver) < 0)
return -1; return -1;
driver->lockFD = -1;
if (virMutexInit(&driver->lock) < 0) { if (virMutexInit(&driver->lock) < 0) {
VIR_FREE(driver); VIR_FREE(driver);
return -1; return -1;
@ -462,15 +470,26 @@ secretStateInitialize(bool privileged,
driver->privileged = privileged; driver->privileged = privileged;
if (privileged) { if (privileged) {
if (VIR_STRDUP(base, SYSCONFDIR "/libvirt") < 0) if (virAsprintf(&driver->configDir,
"%s/libvirt/secrets", SYSCONFDIR) < 0)
goto error;
if (virAsprintf(&driver->stateDir,
"%s/run/libvirt/secrets", LOCALSTATEDIR) < 0)
goto error; goto error;
} else { } else {
if (!(base = virGetUserConfigDirectory())) VIR_AUTOFREE(char *) rundir = NULL;
VIR_AUTOFREE(char *) cfgdir = NULL;
if (!(cfgdir = virGetUserConfigDirectory()))
goto error;
if (virAsprintf(&driver->configDir, "%s/secrets/", cfgdir) < 0)
goto error;
if (!(rundir = virGetUserRuntimeDirectory()))
goto error;
if (virAsprintf(&driver->stateDir, "%s/secrets/run", rundir) < 0)
goto error; goto error;
} }
if (virAsprintf(&driver->configDir, "%s/secrets", base) < 0)
goto error;
VIR_FREE(base);
if (virFileMakePathWithMode(driver->configDir, S_IRWXU) < 0) { if (virFileMakePathWithMode(driver->configDir, S_IRWXU) < 0) {
virReportSystemError(errno, _("cannot create config directory '%s'"), virReportSystemError(errno, _("cannot create config directory '%s'"),
@ -478,6 +497,16 @@ secretStateInitialize(bool privileged,
goto error; goto error;
} }
if (virFileMakePathWithMode(driver->stateDir, S_IRWXU) < 0) {
virReportSystemError(errno, _("cannot create state directory '%s'"),
driver->stateDir);
goto error;
}
if ((driver->lockFD =
virPidFileAcquire(driver->stateDir, "driver", true, getpid())) < 0)
goto error;
if (!(driver->secrets = virSecretObjListNew())) if (!(driver->secrets = virSecretObjListNew()))
goto error; goto error;
@ -488,7 +517,6 @@ secretStateInitialize(bool privileged,
return 0; return 0;
error: error:
VIR_FREE(base);
secretDriverUnlock(); secretDriverUnlock();
secretStateCleanup(); secretStateCleanup();
return -1; return -1;