]> xenbits.xensource.com Git - libvirt.git/commitdiff
util: helper to temporary elevate privileges of the current identity
authorDaniel P. Berrangé <berrange@redhat.com>
Fri, 30 Apr 2021 15:52:30 +0000 (16:52 +0100)
committerDaniel P. Berrangé <berrange@redhat.com>
Thu, 13 May 2021 10:07:36 +0000 (11:07 +0100)
When talking to the secret driver, the callers inside libvirt daemons
need to be able to run with an elevated privileges that prove the API
calls are made by a libvirt daemon, not an end user application.

The virIdentityElevateCurrent method will take the current identity
and, if not already present, add the system token. The old current
identity is returned to the caller. With the VIR_IDENTITY_AUTORESTORE
annotation, the old current identity will be restored upon leaving
the codeblock scope.

    ... early work with regular privileges ...
    if (something needing elevated privs) {
        VIR_IDENTITY_AUTORESTORE virIdentity *oldident =
    virIdentityElevateCurrent();
if (!oldident)
    return -1;

        ... do something with elevated privileges ...
    }
    ... later work with regular privileges ...

Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
src/libvirt_private.syms
src/util/viridentity.c
src/util/viridentity.h

index 443a78e69819457a6e28c489db0b9d40b3115dd8..2ea950c5cda85606242d7f527b2b542ef2e20e83 100644 (file)
@@ -2396,6 +2396,7 @@ virHostGetBootTime;
 
 
 # util/viridentity.h
+virIdentityElevateCurrent;
 virIdentityEnsureSystemToken;
 virIdentityGetCurrent;
 virIdentityGetGroupName;
@@ -2412,6 +2413,7 @@ virIdentityGetUserName;
 virIdentityGetX509DName;
 virIdentityNew;
 virIdentityNewCopy;
+virIdentityRestoreHelper;
 virIdentitySetCurrent;
 virIdentitySetGroupName;
 virIdentitySetParameters;
index 01edabf2d7ffe0ed2a94798fee26224adabe56ba..2e3fcc5add47a7510002ba7eca82e7d2461a1f50 100644 (file)
@@ -154,6 +154,53 @@ int virIdentitySetCurrent(virIdentity *ident)
 }
 
 
+/**
+ * virIdentityElevateCurrent:
+ *
+ * Set the new identity to be associated with this thread,
+ * to an elevated copy of the current identity. The old
+ * current identity is returned and should be released by
+ * the caller when no longer required.
+ *
+ * Returns the previous identity, or NULL on error
+ */
+virIdentity *virIdentityElevateCurrent(void)
+{
+    g_autoptr(virIdentity) ident = virIdentityGetCurrent();
+    const char *token;
+    int rc;
+
+    if (!ident) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("No current identity to elevate"));
+        return NULL;
+    }
+
+    if ((rc = virIdentityGetSystemToken(ident, &token)) < 0)
+        return NULL;
+
+    if (rc == 0) {
+        g_autoptr(virIdentity) identel = virIdentityNewCopy(ident);
+
+        if (virIdentitySetSystemToken(identel, systemToken) < 0)
+            return NULL;
+
+        if (virIdentitySetCurrent(identel) < 0)
+            return NULL;
+    }
+
+    return g_steal_pointer(&ident);
+}
+
+
+void virIdentityRestoreHelper(virIdentity **identptr)
+{
+    virIdentity *ident = *identptr;
+
+    if (ident != NULL)
+        virIdentitySetCurrent(ident);
+}
+
 #define TOKEN_BYTES 16
 #define TOKEN_STRLEN (TOKEN_BYTES * 2)
 
index 512bca286d8ca63c3e08a27c6903da4102704784..848e5b2056250a5bb29b8ceca41736b50992aec7 100644 (file)
 #define VIR_TYPE_IDENTITY vir_identity_get_type()
 G_DECLARE_FINAL_TYPE(virIdentity, vir_identity, VIR, IDENTITY, GObject);
 
+#define VIR_IDENTITY_AUTORESTORE __attribute__((cleanup(virIdentityRestoreHelper)))
+
 virIdentity *virIdentityGetCurrent(void);
 int virIdentitySetCurrent(virIdentity *ident);
+virIdentity *virIdentityElevateCurrent(void);
+
+void virIdentityRestoreHelper(virIdentity **identptr);
 
 virIdentity *virIdentityGetSystem(void);