Blame SOURCES/0035-lib-label-temporary-files-with-correct-selinux-conte.patch

1756dc
From 721aa7e45ba56530c571743de4762605560f90cb Mon Sep 17 00:00:00 2001
1756dc
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
1756dc
Date: Thu, 10 Jan 2019 13:26:49 +0100
1756dc
Subject: [PATCH] lib: label temporary files with correct selinux context
1756dc
1756dc
Resolves:
1756dc
https://github.com/pbrezina/authselect/issues/128
1756dc
---
1756dc
 configure.ac                       |   1 +
1756dc
 rpm/authselect.spec.in             |   1 +
1756dc
 src/build_macros.m4                |  13 +++
1756dc
 src/lib/Makefile.am                |   3 +
1756dc
 src/lib/util/selinux.c             | 143 +++++++++++++++++++++++++++++
1756dc
 src/lib/util/{util.h => selinux.h} |  37 +++++---
1756dc
 src/lib/util/template.c            |  16 +---
1756dc
 src/lib/util/util.h                |   1 +
1756dc
 8 files changed, 192 insertions(+), 23 deletions(-)
1756dc
 create mode 100644 src/lib/util/selinux.c
1756dc
 copy src/lib/util/{util.h => selinux.h} (50%)
1756dc
1756dc
diff --git a/configure.ac b/configure.ac
1756dc
index 0ddb875439133d10a9ece8b92a2df1719065d349..667d41c1f67264850fd9e175598214d751078a7e 100644
1756dc
--- a/configure.ac
1756dc
+++ b/configure.ac
1756dc
@@ -37,6 +37,7 @@ m4_include(external/po4a.m4)
1756dc
 dnl Required libraries
1756dc
 REQUIRE_POPT
1756dc
 REQUIRE_CMOCKA
1756dc
+REQUIRE_SELINUX
1756dc
 
1756dc
 dnl Optional build dependencies - man pages generation
1756dc
 CHECK_ASCIIDOC_TOOLS
1756dc
diff --git a/rpm/authselect.spec.in b/rpm/authselect.spec.in
1756dc
index c56ad4e2e0e23c902471fbacdb8bc3742bd8fa2d..f47c77ac3768ccf9c049c9ba512209fad059e418 100644
1756dc
--- a/rpm/authselect.spec.in
1756dc
+++ b/rpm/authselect.spec.in
1756dc
@@ -24,6 +24,7 @@ BuildRequires:  gettext-devel
1756dc
 BuildRequires:  po4a
1756dc
 BuildRequires:  %{_bindir}/a2x
1756dc
 BuildRequires:  libcmocka-devel >= 1.0.0
1756dc
+BuildRequires:  libselinux-devel
1756dc
 Requires: authselect-libs%{?_isa} = %{version}-%{release}
1756dc
 Suggests: sssd
1756dc
 Suggests: samba-winbind
1756dc
diff --git a/src/build_macros.m4 b/src/build_macros.m4
1756dc
index 5da871ec8cadfa200630420b5fe932d8af0473a3..dfedd47fd84c7201cfad30621761a3c1c564bc18 100644
1756dc
--- a/src/build_macros.m4
1756dc
+++ b/src/build_macros.m4
1756dc
@@ -28,3 +28,16 @@ AC_DEFUN([REQUIRE_CMOCKA],
1756dc
     )
1756dc
     AM_CONDITIONAL([HAVE_CMOCKA], [test x$have_cmocka = xyes])
1756dc
 ])
1756dc
+
1756dc
+AC_DEFUN([REQUIRE_SELINUX],
1756dc
+[
1756dc
+  AC_CHECK_HEADERS(selinux/selinux.h,
1756dc
+    [AC_CHECK_LIB(selinux, is_selinux_enabled,
1756dc
+      [SELINUX_LIBS="-lselinux"],
1756dc
+      [AC_MSG_ERROR([SELinux library is missing])]
1756dc
+    )],
1756dc
+    [AC_MSG_ERROR([SELinux headers are missing])]
1756dc
+  )
1756dc
+  AC_SUBST(SELINUX_LIBS)
1756dc
+])
1756dc
+
1756dc
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
1756dc
index 2726062c421f7836ebc69fbbc0f5410cf3d19803..6c1191c702efbf52d45c7204311e4e9d1e64de3b 100644
1756dc
--- a/src/lib/Makefile.am
1756dc
+++ b/src/lib/Makefile.am
1756dc
@@ -15,6 +15,7 @@ noinst_HEADERS = \
1756dc
     files/files.h \
1756dc
     profiles/profiles.h \
1756dc
     util/file.h \
1756dc
+    util/selinux.h \
1756dc
     util/string_array.h \
1756dc
     util/string.h \
1756dc
     util/template.h \
1756dc
@@ -55,6 +56,7 @@ libauthselect_la_SOURCES = \
1756dc
     profiles/list.c \
1756dc
     profiles/read.c \
1756dc
     util/file.c \
1756dc
+    util/selinux.c \
1756dc
     util/string_array.c \
1756dc
     util/string.c \
1756dc
     util/template.c \
1756dc
@@ -62,6 +64,7 @@ libauthselect_la_SOURCES = \
1756dc
     $(NULL)
1756dc
 libauthselect_la_LIBADD = \
1756dc
     $(top_builddir)/src/common/libcommon.la \
1756dc
+    $(SELINUX_LIBS) \
1756dc
     $(NULL)
1756dc
 libauthselect_la_CFLAGS = \
1756dc
     $(AM_CFLAGS) \
1756dc
diff --git a/src/lib/util/selinux.c b/src/lib/util/selinux.c
1756dc
new file mode 100644
1756dc
index 0000000000000000000000000000000000000000..05c8d7b19b13e1eff6086faa58657c3e41a44cc0
1756dc
--- /dev/null
1756dc
+++ b/src/lib/util/selinux.c
1756dc
@@ -0,0 +1,143 @@
1756dc
+/*
1756dc
+    Authors:
1756dc
+        Pavel Březina <pbrezina@redhat.com>
1756dc
+
1756dc
+    Copyright (C) 2018 Red Hat
1756dc
+
1756dc
+    This program is free software; you can redistribute it and/or modify
1756dc
+    it under the terms of the GNU General Public License as published by
1756dc
+    the Free Software Foundation; either version 3 of the License, or
1756dc
+    (at your option) any later version.
1756dc
+
1756dc
+    This program is distributed in the hope that it will be useful,
1756dc
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
1756dc
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1756dc
+    GNU General Public License for more details.
1756dc
+
1756dc
+    You should have received a copy of the GNU General Public License
1756dc
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
1756dc
+*/
1756dc
+
1756dc
+#include <errno.h>
1756dc
+#include <string.h>
1756dc
+#include <stdlib.h>
1756dc
+#include <unistd.h>
1756dc
+#include <selinux/selinux.h>
1756dc
+#include <selinux/label.h>
1756dc
+
1756dc
+#include "common/common.h"
1756dc
+
1756dc
+errno_t
1756dc
+selinux_get_default_context(const char *path,
1756dc
+                            char **_context)
1756dc
+{
1756dc
+    struct selabel_handle *handle;
1756dc
+    char *context;
1756dc
+    errno_t ret;
1756dc
+
1756dc
+    handle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
1756dc
+    if (handle == NULL) {
1756dc
+        ret = errno;
1756dc
+        ERROR("Unable to create selable context [%d]: %s", ret, strerror(ret));
1756dc
+        return ret;
1756dc
+    }
1756dc
+
1756dc
+    ret = selabel_lookup(handle, &context, path, 0);
1756dc
+    if (ret != 0) {
1756dc
+        ret = errno;
1756dc
+        if (ret == ENOENT) {
1756dc
+            return ENOENT;
1756dc
+        }
1756dc
+
1756dc
+        ERROR("Unable to lookup selinux context [%d]: %s", ret, strerror(ret));
1756dc
+    } else {
1756dc
+        *_context = context;
1756dc
+        ret = EOK;
1756dc
+    }
1756dc
+
1756dc
+    selabel_close(handle);
1756dc
+
1756dc
+    return ret;
1756dc
+}
1756dc
+
1756dc
+errno_t
1756dc
+selinux_mkstemp_of(const char *filepath,
1756dc
+                   char **_tmpfile)
1756dc
+{
1756dc
+    char *original_context = NULL;
1756dc
+    char *default_context = NULL;
1756dc
+    char *tmpfile = NULL;
1756dc
+    errno_t ret;
1756dc
+    int seret;
1756dc
+    int fd;
1756dc
+
1756dc
+    seret = getfscreatecon(&original_context);
1756dc
+    if (seret != 0) {
1756dc
+        ERROR("Unable to get current fscreate selinux context!");
1756dc
+        return EIO;
1756dc
+    }
1756dc
+
1756dc
+    tmpfile = format("%s.XXXXXX", filepath);
1756dc
+    if (tmpfile == NULL) {
1756dc
+        ret = ENOMEM;
1756dc
+        goto done;
1756dc
+    }
1756dc
+
1756dc
+    ret = selinux_get_default_context(filepath, &default_context);
1756dc
+    if (ret == ENOENT) {
1756dc
+        default_context = NULL;
1756dc
+    } else if (ret != EOK) {
1756dc
+        ERROR("Unable to get default selinux context for [%s] [%d]: %s!",
1756dc
+              filepath, ret, strerror(ret));
1756dc
+        goto done;
1756dc
+    }
1756dc
+
1756dc
+    seret = setfscreatecon(default_context);
1756dc
+    if (seret != 0) {
1756dc
+        ERROR("Unable to set fscreate selinux context!");
1756dc
+        ret = EIO;
1756dc
+        goto done;
1756dc
+    }
1756dc
+
1756dc
+    fd = mkstemp(tmpfile);
1756dc
+    if (fd == -1) {
1756dc
+        ret = errno;
1756dc
+
1756dc
+        seret = setfscreatecon(original_context);
1756dc
+        if (seret != 0) {
1756dc
+            ERROR("Unable to restore fscreate selinux context!");
1756dc
+            ret = EIO;
1756dc
+            goto done;
1756dc
+        }
1756dc
+
1756dc
+        goto done;
1756dc
+    }
1756dc
+
1756dc
+    close(fd);
1756dc
+
1756dc
+    seret = setfscreatecon(original_context);
1756dc
+    if (seret != 0) {
1756dc
+        ERROR("Unable to restore fscreate selinux context!");
1756dc
+        ret = EIO;
1756dc
+        goto done;
1756dc
+    }
1756dc
+
1756dc
+    *_tmpfile = tmpfile;
1756dc
+
1756dc
+    ret = EOK;
1756dc
+
1756dc
+done:
1756dc
+    if (original_context != NULL) {
1756dc
+        freecon(original_context);
1756dc
+    }
1756dc
+
1756dc
+    if (default_context != NULL) {
1756dc
+        freecon(default_context);
1756dc
+    }
1756dc
+
1756dc
+    if (ret != EOK) {
1756dc
+        free(tmpfile);
1756dc
+    }
1756dc
+
1756dc
+    return ret;
1756dc
+}
1756dc
diff --git a/src/lib/util/util.h b/src/lib/util/selinux.h
1756dc
similarity index 50%
1756dc
copy from src/lib/util/util.h
1756dc
copy to src/lib/util/selinux.h
1756dc
index b81990722d62ccf466c0687454c82ea3ee171436..26f2374140562dd085145845ed3092a0ddcf924e 100644
1756dc
--- a/src/lib/util/util.h
1756dc
+++ b/src/lib/util/selinux.h
1756dc
@@ -18,20 +18,33 @@
1756dc
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
1756dc
 */
1756dc
 
1756dc
-#ifndef _UTIL_H_
1756dc
-#define _UTIL_H_
1756dc
+#ifndef _SELINUX_H_
1756dc
+#define _SELINUX_H_
1756dc
+
1756dc
+#include "common/errno_t.h"
1756dc
 
1756dc
 /**
1756dc
- * Many of the utility functions are not as effective as they can be but
1756dc
- * this is OK since authselect works only with small configuration files
1756dc
- * therefore we can prefer clean and simple code over performance.
1756dc
+ * Get default security context for @path.
1756dc
+ *
1756dc
+ * @param path Path to the file.
1756dc
+ *
1756dc
+ * @return EOK on success, ENOENT if context was not found, other errno code
1756dc
+ *         is returned on failure.
1756dc
  */
1756dc
+errno_t
1756dc
+selinux_get_default_context(const char *path);
1756dc
 
1756dc
-#include "common/common.h"
1756dc
-#include "lib/util/file.h"
1756dc
-#include "lib/util/string.h"
1756dc
-#include "lib/util/string_array.h"
1756dc
-#include "lib/util/template.h"
1756dc
-#include "lib/util/textfile.h"
1756dc
+/**
1756dc
+ * Create temporary file created on @filepath.XXXXXX with security context
1756dc
+ * set to default security context of @filepath.
1756dc
+ *
1756dc
+ * @param filepath File for which a temporary file should be created.
1756dc
+ * @param _tmpfile Create temporary file.
1756dc
+ *
1756dc
+ * @return EOK on success, other errno code on failure.
1756dc
+ */
1756dc
+errno_t
1756dc
+selinux_mkstemp_of(const char *filepath,
1756dc
+                   char **_tmpfile);
1756dc
 
1756dc
-#endif /* _UTIL_H_ */
1756dc
+#endif /* _SELINUX_H_ */
1756dc
diff --git a/src/lib/util/template.c b/src/lib/util/template.c
1756dc
index 0eedd2b04146f201a5c37f45c1d08f01c079d61f..9773dcbf1ecbde4fe2408f1b816dce129747806f 100644
1756dc
--- a/src/lib/util/template.c
1756dc
+++ b/src/lib/util/template.c
1756dc
@@ -27,6 +27,7 @@
1756dc
 #include "common/common.h"
1756dc
 #include "lib/util/template.h"
1756dc
 #include "lib/util/textfile.h"
1756dc
+#include "lib/util/selinux.h"
1756dc
 #include "lib/util/string.h"
1756dc
 #include "lib/util/string_array.h"
1756dc
 
1756dc
@@ -594,23 +595,16 @@ template_write_temporary(const char *filepath,
1756dc
     mode_t oldmask;
1756dc
     char *tmpfile;
1756dc
     errno_t ret;
1756dc
-    int fd;
1756dc
-
1756dc
-    tmpfile = format("%s.XXXXXX", filepath);
1756dc
-    if (tmpfile == NULL) {
1756dc
-        return ENOMEM;
1756dc
-    }
1756dc
 
1756dc
     oldmask = umask(mode);
1756dc
 
1756dc
-    fd = mkstemp(tmpfile);;
1756dc
-    if (fd == -1) {
1756dc
-        ret = errno;
1756dc
+    ret = selinux_mkstemp_of(filepath, &tmpfile);
1756dc
+    if (ret != EOK) {
1756dc
+        ERROR("Unable to create temporary file for [%s] [%d]: %s",
1756dc
+              filepath, ret, strerror(ret));
1756dc
         goto done;
1756dc
     }
1756dc
 
1756dc
-    close(fd);
1756dc
-
1756dc
     ret = template_write(tmpfile, content, mode);
1756dc
     if (ret != EOK) {
1756dc
         goto done;
1756dc
diff --git a/src/lib/util/util.h b/src/lib/util/util.h
1756dc
index b81990722d62ccf466c0687454c82ea3ee171436..e75afaef316fc8f8fd4d2aabbab7be1aa24e9ac7 100644
1756dc
--- a/src/lib/util/util.h
1756dc
+++ b/src/lib/util/util.h
1756dc
@@ -29,6 +29,7 @@
1756dc
 
1756dc
 #include "common/common.h"
1756dc
 #include "lib/util/file.h"
1756dc
+#include "lib/util/selinux.h"
1756dc
 #include "lib/util/string.h"
1756dc
 #include "lib/util/string_array.h"
1756dc
 #include "lib/util/template.h"
1756dc
-- 
1756dc
2.17.2
1756dc