[Libguestfs] ANNOUNCE: CVE-2013-4419: insecure temporary directory handling for guestfish's network socket

Richard W.M. Jones rjones at redhat.com
Thu Oct 17 12:00:38 UTC 2013


This issue has been assigned CVE-2013-4419.

https://bugzilla.redhat.com/show_bug.cgi?id=1016960
(Note this bug is private, but will be made public shortly)

----------------------------------------------------------------------

When using the guestfish --remote or guestfish --listen options,
guestfish would create a socket in a known location
(/tmp/.guestfish-$UID/socket-$PID).

The location has to be a known one in order for both ends to
communicate.  However no checking was done that the containing
directory (/tmp/.guestfish-$UID) is owned by the user.  Thus another
user could create this directory and potentially modify sockets owned
by another user's guestfish client or server.

Thanks: Michael Scherer for discovering this issue.

----------------------------------------------------------------------

You can remediate this issue in one of three ways:

(1) Apply the attached patch to libguestfs and rebuild from source.

(2) Run the following command on your system before using the
guestfish --listen option.  Pay attention to any errors from mkdir,
which might indicate that the directory has been hijacked.

    rm -rf /tmp/.guestfish-`id -u`
    mkdir -m 0700 /tmp/.guestfish-`id -u`

(3) Wait for new packages to become available shortly.  This afternoon
I will build packages for Fedora, which will be available through
updates-testing.  Packages will be available for RHEL 6 shortly
through RHEL channels.  Debian and SuSE maintainers were made aware of
this issue and will provide packages.

----------------------------------------------------------------------

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
libguestfs lets you edit virtual machines.  Supports shell scripting,
bindings from many languages.  http://libguestfs.org
-------------- next part --------------
>From b112e771df8c568d6dc4d518926c58555baa1c56 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones at redhat.com>
Date: Wed, 9 Oct 2013 12:08:10 +0100
Subject: [PATCH] fish: CVE-2013-4419: Fix insecure temporary directory
 handling for remote guestfish (RHBZ#1016960).

When using the guestfish --remote or guestfish --listen options,
guestfish would create a socket in a known location
(/tmp/.guestfish-$UID/socket-$PID).

The location has to be a known one in order for both ends to
communicate.  However no checking was done that the containing
directory (/tmp/.guestfish-$UID) is owned by the user.  Thus another
user could create this directory and potentially modify sockets owned
by another user's guestfish client or server.

This commit fixes the issue by creating the directory unconditionally,
and then checking that the directory has the correct owner and
permissions, thus preventing another user from creating the directory
first.

If guestfish sees a suspicious socket directory it will print an error
like this and exit with an error status:

  guestfish: '/tmp/.guestfish-1000' is not a directory or has insecure owner or permissions

Thanks: Michael Scherer for discovering this issue.

Version 2:
 - Add assigned CVE number.
 - Update documentation.

Signed-off-by: Richard W.M. Jones <rjones at redhat.com>
---
 fish/guestfish.pod |  3 +++
 fish/rc.c          | 43 +++++++++++++++++++++++++++++++++++++++----
 src/guestfs.pod    | 17 +++++++++++++++++
 3 files changed, 59 insertions(+), 4 deletions(-)

diff --git a/fish/guestfish.pod b/fish/guestfish.pod
index 7d40c18..e727b06 100644
--- a/fish/guestfish.pod
+++ b/fish/guestfish.pod
@@ -1006,6 +1006,9 @@ user ID of the process, and C<$PID> is the process ID of the server.
 
 Guestfish client and server versions must match exactly.
 
+Older versions of guestfish were vulnerable to CVE-2013-4419 (see
+L<guestfs(3)/CVE-2013-4419>).  This is fixed in the current version.
+
 =head2 USING REMOTE CONTROL ROBUSTLY FROM SHELL SCRIPTS
 
 From Bash, you can use the following code which creates a guestfish
diff --git a/fish/rc.c b/fish/rc.c
index aa4b849..c736042 100644
--- a/fish/rc.c
+++ b/fish/rc.c
@@ -29,6 +29,7 @@
 #include <sys/un.h>
 #include <signal.h>
 #include <sys/socket.h>
+#include <errno.h>
 
 #include <rpc/types.h>
 #include <rpc/xdr.h>
@@ -38,17 +39,49 @@
 #include "fish.h"
 #include "rc_protocol.h"
 
+/* Because this is a Unix domain socket, the total path length must be
+ * under 108 bytes.
+ */
+#define SOCKET_DIR "/tmp/.guestfish-%d" /* euid */
+#define SOCKET_PATH "/tmp/.guestfish-%d/socket-%d" /* euid, pid */
+
+static void
+create_sockdir (void)
+{
+  uid_t euid = geteuid ();
+  char dir[128];
+  int r;
+  struct stat statbuf;
+
+  /* Create the directory, and ensure it is owned by the user. */
+  snprintf (dir, sizeof dir, SOCKET_DIR, euid);
+  r = mkdir (dir, 0700);
+  if (r == -1 && errno != EEXIST) {
+  error:
+    perror (dir);
+    exit (EXIT_FAILURE);
+  }
+  if (lstat (dir, &statbuf) == -1)
+    goto error;
+  if (!S_ISDIR (statbuf.st_mode) ||
+      (statbuf.st_mode & 0777) != 0700 ||
+      statbuf.st_uid != euid) {
+    fprintf (stderr,
+             _("guestfish: '%s' is not a directory or has insecure owner or permissions\n"),
+             dir);
+    exit (EXIT_FAILURE);
+  }
+}
+
 static void
 create_sockpath (pid_t pid, char *sockpath, size_t len,
                  struct sockaddr_un *addr)
 {
-  char dir[128];
   uid_t euid = geteuid ();
 
-  snprintf (dir, sizeof dir, "/tmp/.guestfish-%d", euid);
-  ignore_value (mkdir (dir, 0700));
+  create_sockdir ();
 
-  snprintf (sockpath, len, "/tmp/.guestfish-%d/socket-%d", euid, pid);
+  snprintf (sockpath, len, SOCKET_PATH, euid, pid);
 
   addr->sun_family = AF_UNIX;
   strcpy (addr->sun_path, sockpath);
@@ -196,6 +229,8 @@ rc_listen (void)
   memset (&hello, 0, sizeof hello);
   memset (&call, 0, sizeof call);
 
+  create_sockdir ();
+
   pid = fork ();
   if (pid == -1) {
     perror ("fork");
diff --git a/src/guestfs.pod b/src/guestfs.pod
index 908ce96..9895f5e 100644
--- a/src/guestfs.pod
+++ b/src/guestfs.pod
@@ -2099,6 +2099,23 @@ double-free in the C library (denial of service).
 It is sufficient to update libguestfs to a version that is not
 vulnerable: libguestfs E<ge> 1.20.8, E<ge> 1.22.2 or E<ge> 1.23.2.
 
+=head2 CVE-2013-4419
+
+L<https://bugzilla.redhat.com/1016960>
+
+When using the L<guestfish(1)> I<--remote> or guestfish I<--listen>
+options, guestfish would create a socket in a known location
+(C</tmp/.guestfish-$UID/socket-$PID>).
+
+The location has to be a known one in order for both ends to
+communicate.  However no checking was done that the containing
+directory (C</tmp/.guestfish-$UID>) is owned by the user.  Thus
+another user could create this directory and potentially hijack
+sockets owned by another user's guestfish client or server.
+
+It is sufficient to update libguestfs to a version that is not
+vulnerable: libguestfs E<ge> 1.20.12, E<ge> 1.22.7 or E<ge> 1.24.
+
 =head1 CONNECTION MANAGEMENT
 
 =head2 guestfs_h *
-- 
1.8.3.1



More information about the Libguestfs mailing list