Blob Blame History Raw
From 9aa3d40e0b24bbd3dfa5d51198ffc289fa901c9f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Tue, 6 Dec 2011 14:22:04 +0100
Subject: [PATCH] Fix CVE-2011-4114 ported for 1.010.

From: r1296 | rschupp | 2011-11-14 21:01:18 +0100 (Po, 14 lis 2011) | 11 lines

myldr/mktmpdir.c:
- (par_mktmpdir) CVE-2011-4114:
  - create parent of cache directory (i.e. /tmp/par-USER) with mode 0700
  - if it already exists, check that (and bail out if not)
    - it's not a symlink
    - it's mode 0700
    - it's owned by USER

NOTE: PAR contains a "copy" of par_mktmpdir (in Perl); this
must be fixed as well and we must require the fixed version.

Adjusted error message from r1313 is included.
---
 myldr/mktmpdir.c |   38 +++++++++++++++++++++++++++++++++++---
 1 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/myldr/mktmpdir.c b/myldr/mktmpdir.c
index 6699831..2293268 100644
--- a/myldr/mktmpdir.c
+++ b/myldr/mktmpdir.c
@@ -161,10 +161,42 @@ char *par_mktmpdir ( char **argv ) {
        stmpdir2 is the top $TEMP/par-$USER, needed to build stmpdir.  We
        need 2 buffers because snprintf() can't write to a buffer it's
        reading from. */
-    stmpdir = malloc( stmp_len );
     stmpdir2 = malloc( stmp_len );
     sprintf(stmpdir2, "%s%s%s%s", tmpdir, dir_sep, subdirbuf_prefix, username);
-    my_mkdir(stmpdir2, 0755);
+#ifdef WIN32
+    _mkdir(stmpdir2);         /* FIXME bail if error (other than EEXIST) */
+#else
+    {
+        struct stat st;
+
+        if (mkdir(stmpdir2, 0700) == -1 && errno != EEXIST) {
+            fprintf(stderr, "%s: creation of private subdirectory %s failed (errno=%i)\n", 
+                    argv[0], stmpdir2, errno);
+            return NULL;
+        }
+
+        /* now check that:
+         * - stmpdir2 is a directory (and not a symlink)
+         * - stmpdir2 is owned by the user
+         * - stmpdir2 has mode 0700
+         */
+        if (lstat(stmpdir2, &st) == -1) {
+            fprintf(stderr, "%s: stat of private subdirectory %s failed (errno=%i)\n",
+                    argv[0], stmpdir2, errno);
+            return NULL;
+        }
+
+        if (!S_ISDIR(st.st_mode)
+            || st.st_uid != getuid()
+            || (st.st_mode & 0777) != 0700 ) {
+            fprintf(stderr, "%s: private subdirectory %s is unsafe (please remove it and retry your operation)\n",
+                    argv[0], stmpdir2);
+            return NULL;
+        }
+    }
+#endif
+
+    stmpdir = malloc( stmp_len );
 
     /* Doesn't really work - XXX */
     val = par_getenv( "PATH" );
@@ -250,7 +282,7 @@ char *par_mktmpdir ( char **argv ) {
            a prior invocation crashed leaving garbage in a temp directory that
            might interfere. */
 
-        while (my_mkdir(stmpdir, 0755) == -1 && errno == EEXIST) {
+        while (my_mkdir(stmpdir, 0700) == -1 && errno == EEXIST) {
             sprintf(
                 stmpdir,
                 "%s%stemp-%u-%u%s",
-- 
1.7.7.4