]> xenbits.xensource.com Git - libvirt.git/commitdiff
vsh: Fix 'stdin' closing in 'cmdComplete'
authorPeter Krempa <pkrempa@redhat.com>
Tue, 26 Mar 2024 15:28:33 +0000 (16:28 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Thu, 25 Apr 2024 12:13:19 +0000 (14:13 +0200)
While the 'complete' command is meant to be hidden and used only for
the completion script, there's nothing preventing it being used in all
virsh modes.

This poses a problem as the command tries to close 'stdin' to avoid the
possibility that an auth callback would want to read the password.

In interactive mode this immediately terminates virsh and in
non-interactive mode it attempts to close it multiple times if you use
virsh in batch mode.

Fix the issues by using virOnce() to close it exactly once and do so
only in non-interactive mode.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
tools/vsh.c

index 3fd567c1bf55af702c1cd9c684a535b37fb95011..1e8be2393e978258d5d44f4848dc18c55aefbec3 100644 (file)
@@ -3405,11 +3405,25 @@ const vshCmdInfo info_complete = {
 
 
 #ifdef WITH_READLINE
+
+static virOnceControl vshCmdCompleteCloseStdinOnce = VIR_ONCE_CONTROL_INITIALIZER;
+
+static void
+vshCmdCompleteCloseStdin(void)
+{
+    /* In non-interactive mode which is how the 'complete' command is intended
+     * to be used we need to ensure that any authentication callback will not
+     * attempt to read any input which would break the completion */
+    int stdin_fileno = STDIN_FILENO;
+
+    VIR_FORCE_CLOSE(stdin_fileno);
+}
+
+
 bool
 cmdComplete(vshControl *ctl, const vshCmd *cmd)
 {
     const vshClientHooks *hooks = ctl->hooks;
-    int stdin_fileno = STDIN_FILENO;
     const char *arg = "";
     const vshCmdOpt *opt = NULL;
     g_auto(GStrv) matches = NULL;
@@ -3422,7 +3436,10 @@ cmdComplete(vshControl *ctl, const vshCmd *cmd)
     /* This command is flagged VSH_CMD_FLAG_NOCONNECT because we
      * need to prevent auth hooks reading any input. Therefore, we
      * have to close stdin and then connect ourselves. */
-    VIR_FORCE_CLOSE(stdin_fileno);
+    if (!ctl->imode) {
+        if (virOnce(&vshCmdCompleteCloseStdinOnce, vshCmdCompleteCloseStdin) < 0)
+            return false;
+    }
 
     if (!(hooks && hooks->connHandler && hooks->connHandler(ctl)))
         return false;