[libvirt PATCH 3/9] util: generate a persistent system token

Michal Prívozník mprivozn at redhat.com
Thu May 6 10:13:01 UTC 2021


On 5/4/21 7:43 PM, Daniel P. Berrangé wrote:
> When creating the system identity set the system token. The system
> token is currently stored in a local path
> 
>    /var/run/libvirt/common/system.token
> 
> Obviously with only traditional UNIX DAC in effect, this is largely
> security through obscurity, if the client is running at the same
> privilege level as the daemon. It does, however, reliably distinguish
> an unprivilegd client from the system daemons.
> 
> With a MAC system like SELinux though, or possible use of containers,
> access can be further restricted.
> 
> A possible future improvement for Linux would be to populate the
> kernel keyring with a secret for libvirt daemons to share.
> 
> Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
> ---
>  src/util/viridentity.c | 107 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 107 insertions(+)
> 
> diff --git a/src/util/viridentity.c b/src/util/viridentity.c
> index 7da4ea12f5..065db06e49 100644
> --- a/src/util/viridentity.c
> +++ b/src/util/viridentity.c
> @@ -22,6 +22,7 @@
>  #include <config.h>
>  
>  #include <unistd.h>
> +#include <fcntl.h>
>  #if WITH_SELINUX
>  # include <selinux/selinux.h>
>  #endif
> @@ -32,11 +33,14 @@
>  #include "viridentity.h"
>  #include "virlog.h"
>  #include "virobject.h"
> +#include "virrandom.h"
>  #include "virthread.h"
>  #include "virutil.h"
>  #include "virstring.h"
>  #include "virprocess.h"
>  #include "virtypedparam.h"
> +#include "virfile.h"
> +#include "configmake.h"
>  
>  #define VIR_FROM_THIS VIR_FROM_IDENTITY
>  
> @@ -54,7 +58,10 @@ struct _virIdentity {
>  
>  G_DEFINE_TYPE(virIdentity, vir_identity, G_TYPE_OBJECT)
>  
> +static char *virIdentityEnsureSystemToken(void);
> +
>  static virThreadLocal virIdentityCurrent;
> +static char *systemToken;
>  
>  static void virIdentityFinalize(GObject *obj);
>  
> @@ -73,6 +80,9 @@ static int virIdentityOnceInit(void)
>          return -1;
>      }
>  
> +    if (!(systemToken = virIdentityEnsureSystemToken()))
> +        return -1;
> +
>      return 0;
>  }
>  
> @@ -144,6 +154,103 @@ int virIdentitySetCurrent(virIdentity *ident)
>  }
>  
>  
> +#define TOKEN_BYTES 16
> +#define TOKEN_STRLEN (TOKEN_BYTES * 2)
> +
> +static char *
> +virIdentityConstructSystemTokenPath(void)
> +{
> +    g_autofree char *commondir = NULL;
> +    if (geteuid() == 0) {
> +        commondir = g_strdup(RUNSTATEDIR "/libvirt/common");
> +    } else {
> +        g_autofree char *rundir = virGetUserRuntimeDirectory();
> +        commondir = g_strdup_printf("%s/common", rundir);
> +    }
> +
> +    if (g_mkdir_with_parents(commondir, 0700) < 0) {
> +        virReportSystemError(errno,
> +                             _("Cannot create daemon common directory '%s'"),
> +                             commondir);
> +        return NULL;
> +    }
> +
> +    return g_strdup_printf("%s/system.token", commondir);
> +}
> +
> +
> +static char *
> +virIdentityEnsureSystemToken(void)
> +{
> +    g_autofree char *tokenfile = virIdentityConstructSystemTokenPath();
> +    g_autofree char *token = NULL;
> +    int fd = -1;

Or VIR_AUTOCLOSE fd = -1 and drop those explicit close calls at the end.

> +    struct stat st;
> +
> +    fd = open(tokenfile, O_RDWR|O_APPEND|O_CREAT, 0600);
> +    if (fd < 0) {
> +        virReportSystemError(errno,
> +                             _("Unable to open system token %s"),
> +                             tokenfile);
> +        goto error;
> +    }
> +
> +    if (virSetCloseExec(fd) < 0) {

I know we have this pattern in many areas, but it's inherently racy.
What's stopping us from passing O_CLOEXEC to open()? IIUC, O_CLOEXEC
will exist on mingw where it's just an alias to O_NOINHERIT.

> +        virReportSystemError(errno,
> +                             _("Failed to set close-on-exec flag '%s'"),
> +                             tokenfile);
> +        goto error;
> +    }

Michal




More information about the libvir-list mailing list