Blob Blame History Raw
From 29add823913b66e0637d27d962ad5c5f9c85de70 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Mon, 28 Jan 2019 12:13:54 +0100
Subject: [PATCH] lib: make selinux functions work with selinux disabled

Resolves:
https://github.com/pbrezina/authselect/issues/133
---
 src/lib/util/file.c     | 38 +++++++++++++++++++++++++++++++++
 src/lib/util/file.h     | 13 +++++++++++-
 src/lib/util/selinux.c  | 47 ++++++++++++++++-------------------------
 src/lib/util/selinux.h  |  8 ++++---
 src/lib/util/template.c | 23 ++++++--------------
 5 files changed, 79 insertions(+), 50 deletions(-)

diff --git a/src/lib/util/file.c b/src/lib/util/file.c
index fa231f771a7d0cdd449b69c4bf7b00d93aefc375..2e23ce39ec04e6aaf79f16410f9ac08dc3f9d54c 100644
--- a/src/lib/util/file.c
+++ b/src/lib/util/file.c
@@ -329,3 +329,41 @@ file_make_path(const char *path, mode_t mode)
     return EOK;
 
 }
+
+errno_t
+file_mktmp_for(const char *path, mode_t mode, char **_tmpfile)
+{
+    mode_t oldmask;
+    char *tmpfile;
+    errno_t ret;
+    int fd;
+
+    oldmask = umask(mode);
+
+    tmpfile = format("%s.XXXXXX", path);
+    if (tmpfile == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    fd = mkstemp(tmpfile);
+    if (fd == -1) {
+        ret = errno;
+        goto done;
+    }
+
+    close(fd);
+
+    *_tmpfile = tmpfile;
+
+    ret = EOK;
+
+done:
+    if (ret != EOK) {
+        free(tmpfile);
+    }
+
+    umask(oldmask);
+
+    return ret;
+}
diff --git a/src/lib/util/file.h b/src/lib/util/file.h
index 49ebef37443bf137439bad27fd75283c25c9c3e5..6d5823791bfcc581304200d0c2d37b41c3d7b95d 100644
--- a/src/lib/util/file.h
+++ b/src/lib/util/file.h
@@ -133,7 +133,7 @@ file_get_parent_directory(const char *filepath);
 /**
  * Create all directories in a path. Path must end with a directory not a file.
  *
- * @param filename       Path to the file whose directories should be created.
+ * @param path           Path to the file whose directories should be created.
  * @param mode           Directory mode.
  *
  * @return EOK on success, other errno code on error.
@@ -141,4 +141,15 @@ file_get_parent_directory(const char *filepath);
 errno_t
 file_make_path(const char *path, mode_t mode);
 
+/**
+ * Make temporary file for @path so it can be first written and then safelly
+ * renamed to @path.
+ *
+ * @param path           Path to the file whose directories should be created.
+ * @param mode           Temporary file mode.
+ * @param _tmpfile       Path to created temporary file.
+ */
+errno_t
+file_mktmp_for(const char *path, mode_t mode, char **_tmpfile);
+
 #endif /* _FILE_H_ */
diff --git a/src/lib/util/selinux.c b/src/lib/util/selinux.c
index 9b0e0ff26b768d88f67a42985c5d5bafb8aa58ec..01b68087b265c0ef1c1087f626df8e20de086338 100644
--- a/src/lib/util/selinux.c
+++ b/src/lib/util/selinux.c
@@ -26,6 +26,7 @@
 #include <selinux/label.h>
 
 #include "common/common.h"
+#include "lib/util/file.h"
 
 errno_t
 selinux_get_default_context(const char *path,
@@ -61,15 +62,19 @@ selinux_get_default_context(const char *path,
 }
 
 errno_t
-selinux_mkstemp_of(const char *filepath,
-                   char **_tmpfile)
+selinux_mkstemp_for(const char *filepath,
+                    mode_t mode,
+                    char **_tmpfile)
 {
     char *original_context = NULL;
     char *default_context = NULL;
-    char *tmpfile = NULL;
+    char *tmpfile;
     errno_t ret;
     int seret;
-    int fd;
+
+    if (is_selinux_enabled() != 1) {
+        return file_mktmp_for(filepath, mode, _tmpfile);
+    }
 
     seret = getfscreatecon(&original_context);
     if (seret != 0) {
@@ -77,12 +82,6 @@ selinux_mkstemp_of(const char *filepath,
         return EIO;
     }
 
-    tmpfile = format("%s.XXXXXX", filepath);
-    if (tmpfile == NULL) {
-        ret = ENOMEM;
-        goto done;
-    }
-
     ret = selinux_get_default_context(filepath, &default_context);
     if (ret == ENOENT) {
         default_context = NULL;
@@ -92,6 +91,7 @@ selinux_mkstemp_of(const char *filepath,
         goto done;
     }
 
+    /* Set desired fs create context. */
     seret = setfscreatecon(default_context);
     if (seret != 0) {
         ERROR("Unable to set fscreate selinux context!");
@@ -99,22 +99,9 @@ selinux_mkstemp_of(const char *filepath,
         goto done;
     }
 
-    fd = mkstemp(tmpfile);
-    if (fd == -1) {
-        ret = errno;
-
-        seret = setfscreatecon(original_context);
-        if (seret != 0) {
-            ERROR("Unable to restore fscreate selinux context!");
-            ret = EIO;
-            goto done;
-        }
-
-        goto done;
-    }
-
-    close(fd);
+    ret = file_mktmp_for(filepath, mode, &tmpfile);
 
+    /* Restore original fs create context. */
     seret = setfscreatecon(original_context);
     if (seret != 0) {
         ERROR("Unable to restore fscreate selinux context!");
@@ -122,6 +109,12 @@ selinux_mkstemp_of(const char *filepath,
         goto done;
     }
 
+    /* Check result of file_mktmp_for() */
+    if (ret != EOK) {
+        free(tmpfile);
+        goto done;
+    }
+
     *_tmpfile = tmpfile;
 
     ret = EOK;
@@ -135,9 +128,5 @@ done:
         freecon(default_context);
     }
 
-    if (ret != EOK) {
-        free(tmpfile);
-    }
-
     return ret;
 }
diff --git a/src/lib/util/selinux.h b/src/lib/util/selinux.h
index 26f2374140562dd085145845ed3092a0ddcf924e..8abfb3fb5d244b32570cc9e573b2e12df14177e1 100644
--- a/src/lib/util/selinux.h
+++ b/src/lib/util/selinux.h
@@ -39,12 +39,14 @@ selinux_get_default_context(const char *path);
  * set to default security context of @filepath.
  *
  * @param filepath File for which a temporary file should be created.
- * @param _tmpfile Create temporary file.
+ * @param mode     Temporary file mode.
+ * @param _tmpfile Created temporary file.
  *
  * @return EOK on success, other errno code on failure.
  */
 errno_t
-selinux_mkstemp_of(const char *filepath,
-                   char **_tmpfile);
+selinux_mkstemp_for(const char *filepath,
+                    mode_t mode,
+                    char **_tmpfile);
 
 #endif /* _SELINUX_H_ */
diff --git a/src/lib/util/template.c b/src/lib/util/template.c
index 9773dcbf1ecbde4fe2408f1b816dce129747806f..1f3464912d8fe7afe8a7f0920fe31eb5c2dfaba5 100644
--- a/src/lib/util/template.c
+++ b/src/lib/util/template.c
@@ -592,36 +592,25 @@ template_write_temporary(const char *filepath,
                          mode_t mode,
                          char **_tmpfile)
 {
-    mode_t oldmask;
     char *tmpfile;
     errno_t ret;
 
-    oldmask = umask(mode);
-
-    ret = selinux_mkstemp_of(filepath, &tmpfile);
+    ret = selinux_mkstemp_for(filepath, mode, &tmpfile);
     if (ret != EOK) {
         ERROR("Unable to create temporary file for [%s] [%d]: %s",
               filepath, ret, strerror(ret));
-        goto done;
+        return ret;
     }
 
     ret = template_write(tmpfile, content, mode);
-    if (ret != EOK) {
-        goto done;
-    }
-
-    *_tmpfile = tmpfile;
-
-    ret = EOK;
-
-done:
-    umask(oldmask);
-
     if (ret != EOK) {
         free(tmpfile);
+        return ret;
     }
 
-    return ret;
+    *_tmpfile = tmpfile;
+
+    return EOK;
 }
 
 bool
-- 
2.17.2