Add an API to allow skipping the system-wide hooks directory
(/etc/libvirt/hooks) for non-root users. When enabled, only the
user hooks directory (~/.config/libvirt/hooks) is searched.

This allows daemon config to control whether system hooks should
be used in session mode.

Signed-off-by: Marc-André Lureau <[email protected]>
---
 src/libvirt_private.syms |  1 +
 src/util/virhook.c       | 30 +++++++++++++++++++++++++++---
 src/util/virhook.h       |  1 +
 3 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 798d2d28c893..ce00f961b678 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2618,6 +2618,7 @@ virHashCodeGen;
 virHookCall;
 virHookInitialize;
 virHookPresent;
+virHookSetSkipSystemHooks;
 
 
 # util/virhostcpu.h
diff --git a/src/util/virhook.c b/src/util/virhook.c
index f62ac902bb40..aa68109ff193 100644
--- a/src/util/virhook.c
+++ b/src/util/virhook.c
@@ -41,6 +41,21 @@ VIR_LOG_INIT("util.hook");
 
 #define LIBVIRT_HOOK_DIR SYSCONFDIR "/libvirt/hooks"
 
+static bool virHookSkipSystemHooks;
+
+/**
+ * virHookSetSkipSystemHooks:
+ * @skip: if true, skip system hooks directory for non-root
+ *
+ * Configure whether the system-wide hooks directory (/etc/libvirt/hooks)
+ * should be skipped for non-root users. By default, both the system
+ * directory and the user directory (~/.config/libvirt/hooks) are searched.
+ */
+void
+virHookSetSkipSystemHooks(bool skip)
+{
+    virHookSkipSystemHooks = skip;
+}
 
 /**
  * virHookGetDirs:
@@ -48,7 +63,10 @@ VIR_LOG_INIT("util.hook");
  * Returns a NULL-terminated array of hook directories to search,
  * in priority order. For root, only /etc/libvirt/hooks is returned.
  * For non-root users, both /etc/libvirt/hooks and
- * ~/.config/libvirt/hooks are returned (system first, then user).
+ * ~/.config/libvirt/hooks are returned (system first, then user),
+ * unless virHookSetSkipSystemHooks(true) has been called (via the
+ * skip_system_hooks config option), in which case only the user
+ * directory is returned.
  *
  * The caller must free the result with g_strfreev().
  */
@@ -58,9 +76,12 @@ virHookGetDirs(void)
     g_autofree char *configdir = NULL;
     GPtrArray *dirs = g_ptr_array_new();
 
-    g_ptr_array_add(dirs, g_strdup(LIBVIRT_HOOK_DIR));
+    if (geteuid() == 0) {
+        g_ptr_array_add(dirs, g_strdup(LIBVIRT_HOOK_DIR));
+    } else {
+        if (!virHookSkipSystemHooks)
+            g_ptr_array_add(dirs, g_strdup(LIBVIRT_HOOK_DIR));
 
-    if (geteuid() != 0) {
         configdir = virGetUserConfigDirectory();
         g_ptr_array_add(dirs, g_build_filename(configdir, "hooks", NULL));
     }
@@ -377,6 +398,9 @@ virRunScript(const char *path,
  * output produced by each script is fed as input to the next script and
  * so on, chaining across directories.
  *
+ * For non-root users, the system hooks directory can be skipped by setting
+ * the skip_system_hooks daemon config option.
+ *
  * Returns: 0 if the execution succeeded, 1 if the script was not found or
  *          invalid parameters, and -1 if script returned an error
  */
diff --git a/src/util/virhook.h b/src/util/virhook.h
index d8237c837e94..47d5bf4266e9 100644
--- a/src/util/virhook.h
+++ b/src/util/virhook.h
@@ -109,6 +109,7 @@ typedef enum {
 } virHookBhyveOpType;
 
 int virHookInitialize(void);
+void virHookSetSkipSystemHooks(bool skip);
 
 int virHookPresent(int driver);
 

-- 
2.56.0.rc0.29.g47ce80527c56

Reply via email to