0b340d0
From dfbac76ab7bb7e6e2c3171eefcaa93573e6b630e Mon Sep 17 00:00:00 2001
14f0285
From: Robbie Harwood <rharwood@redhat.com>
14f0285
Date: Tue, 23 Aug 2016 16:30:53 -0400
8fb4697
Subject: [PATCH] [downstream] SELinux integration
14f0285
a89bdde
SELinux bases access to files on the domain of the requesting process,
a89bdde
the operation being performed, and the context applied to the file.
a89bdde
a89bdde
In many cases, applications needn't be SELinux aware to work properly,
a89bdde
because SELinux can apply a default label to a file based on the label
a89bdde
of the directory in which it's created.
a89bdde
a89bdde
In the case of files such as /etc/krb5.keytab, however, this isn't
a89bdde
sufficient, as /etc/krb5.keytab will almost always need to be given a
a89bdde
label which differs from that of /etc/issue or /etc/resolv.conf.  The
a89bdde
the kdb stash file needs a different label than the database for which
a89bdde
it's holding a master key, even though both typically live in the same
a89bdde
directory.
a89bdde
a89bdde
To give the file the correct label, we can either force a "restorecon"
a89bdde
call to fix a file's label after it's created, or create the file with
a89bdde
the right label, as we attempt to do here.  We lean on THREEPARAMOPEN
a89bdde
and define a similar macro named WRITABLEFOPEN with which we replace
a89bdde
several uses of fopen().
a89bdde
a89bdde
The file creation context that we're manipulating here is a process-wide
a89bdde
attribute.  While for the most part, applications which need to label
a89bdde
files when they're created have tended to be single-threaded, there's
a89bdde
not much we can do to avoid interfering with an application that
a89bdde
manipulates the creation context directly.  Right now we're mediating
a89bdde
access using a library-local mutex, but that can only work for consumers
a89bdde
that are part of this package -- an unsuspecting application will still
a89bdde
stomp all over us.
a89bdde
a89bdde
The selabel APIs for looking up the context should be thread-safe (per
a89bdde
Red Hat #273081), so switching to using them instead of matchpathcon(),
a89bdde
which we used earlier, is some improvement.
8fb4697
56cee50
Last-updated: krb5-1.20.1
56cee50
[jrische@redhat.com: Replace deprecated security_context_t by char *:
56cee50
    - src/util/support/selinux.c]
14f0285
---
7f642b1
 src/aclocal.m4                                |  48 +++
492b910
 src/build-tools/krb5-config.in                |   3 +-
492b910
 src/config/pre.in                             |   3 +-
7f642b1
 src/configure.ac                              |   2 +
492b910
 src/include/k5-int.h                          |   1 +
492b910
 src/include/k5-label.h                        |  32 ++
492b910
 src/include/krb5/krb5.hin                     |   6 +
492b910
 src/kadmin/dbutil/dump.c                      |  11 +-
492b910
 src/kdc/main.c                                |   2 +-
f745542
 src/kprop/kpropd.c                            |   9 +
492b910
 src/lib/kadm5/logger.c                        |   4 +-
492b910
 src/lib/kdb/kdb_log.c                         |   2 +-
492b910
 src/lib/krb5/ccache/cc_dir.c                  |  26 +-
492b910
 src/lib/krb5/keytab/kt_file.c                 |   4 +-
492b910
 src/lib/krb5/os/trace.c                       |   2 +-
492b910
 src/plugins/kdb/db2/adb_openclose.c           |   2 +-
492b910
 src/plugins/kdb/db2/kdb_db2.c                 |   4 +-
492b910
 src/plugins/kdb/db2/libdb2/btree/bt_open.c    |   3 +-
492b910
 src/plugins/kdb/db2/libdb2/hash/hash.c        |   3 +-
492b910
 src/plugins/kdb/db2/libdb2/recno/rec_open.c   |   4 +-
492b910
 .../kdb/ldap/ldap_util/kdb5_ldap_services.c   |  11 +-
492b910
 src/util/profile/prof_file.c                  |   3 +-
492b910
 src/util/support/Makefile.in                  |   3 +-
56cee50
 src/util/support/selinux.c                    | 405 ++++++++++++++++++
56cee50
 24 files changed, 572 insertions(+), 21 deletions(-)
14f0285
 create mode 100644 src/include/k5-label.h
14f0285
 create mode 100644 src/util/support/selinux.c
a89bdde
14f0285
diff --git a/src/aclocal.m4 b/src/aclocal.m4
0b340d0
index ce3c5a9bac..3331970930 100644
14f0285
--- a/src/aclocal.m4
14f0285
+++ b/src/aclocal.m4
5facc9d
@@ -85,6 +85,7 @@ AC_SUBST_FILE(libnodeps_frag)
a89bdde
 dnl
a89bdde
 KRB5_AC_PRAGMA_WEAK_REF
a89bdde
 WITH_LDAP
a89bdde
+KRB5_WITH_SELINUX
a89bdde
 KRB5_LIB_PARAMS
a89bdde
 KRB5_AC_INITFINI
a89bdde
 KRB5_AC_ENABLE_THREADS
56cee50
@@ -1526,4 +1527,51 @@ AC_SUBST(PAM_LIBS)
a89bdde
 AC_SUBST(PAM_MAN)
a89bdde
 AC_SUBST(NON_PAM_MAN)
a89bdde
 ])dnl
a89bdde
+dnl
a89bdde
+dnl Use libselinux to set file contexts on newly-created files.
821dac4
+dnl
a89bdde
+AC_DEFUN(KRB5_WITH_SELINUX,[
a89bdde
+AC_ARG_WITH(selinux,[AC_HELP_STRING(--with-selinux,[compile with SELinux labeling support])],
a89bdde
+           withselinux="$withval",withselinux=auto)
a89bdde
+old_LIBS="$LIBS"
a89bdde
+if test "$withselinux" != no ; then
a89bdde
+       AC_MSG_RESULT([checking for libselinux...])
a89bdde
+       SELINUX_LIBS=
a89bdde
+       AC_CHECK_HEADERS(selinux/selinux.h selinux/label.h)
a89bdde
+       if test "x$ac_cv_header_selinux_selinux_h" != xyes ; then
a89bdde
+               if test "$withselinux" = auto ; then
a89bdde
+                       AC_MSG_RESULT([Unable to locate selinux/selinux.h.])
a89bdde
+                       withselinux=no
a89bdde
+               else
a89bdde
+                       AC_MSG_ERROR([Unable to locate selinux/selinux.h.])
a89bdde
+               fi
a89bdde
+       fi
7f642b1
 
a89bdde
+       LIBS=
a89bdde
+       unset ac_cv_func_setfscreatecon
a89bdde
+       AC_CHECK_FUNCS(setfscreatecon selabel_open)
a89bdde
+       if test "x$ac_cv_func_setfscreatecon" = xno ; then
a89bdde
+               AC_CHECK_LIB(selinux,setfscreatecon)
a89bdde
+               unset ac_cv_func_setfscreatecon
a89bdde
+               AC_CHECK_FUNCS(setfscreatecon selabel_open)
a89bdde
+               if test "x$ac_cv_func_setfscreatecon" = xyes ; then
a89bdde
+                       SELINUX_LIBS="$LIBS"
a89bdde
+               else
a89bdde
+                       if test "$withselinux" = auto ; then
a89bdde
+                               AC_MSG_RESULT([Unable to locate libselinux.])
a89bdde
+                               withselinux=no
a89bdde
+                       else
a89bdde
+                               AC_MSG_ERROR([Unable to locate libselinux.])
a89bdde
+                       fi
a89bdde
+               fi
a89bdde
+       fi
a89bdde
+       if test "$withselinux" != no ; then
a89bdde
+               AC_MSG_NOTICE([building with SELinux labeling support])
a89bdde
+               AC_DEFINE(USE_SELINUX,1,[Define if Kerberos-aware tools should set SELinux file contexts when creating files.])
a89bdde
+               SELINUX_LIBS="$LIBS"
a89bdde
+		EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_labeled_open krb5int_labeled_fopen krb5int_push_fscreatecon_for krb5int_pop_fscreatecon"
a89bdde
+       fi
a89bdde
+fi
a89bdde
+LIBS="$old_LIBS"
a89bdde
+AC_SUBST(SELINUX_LIBS)
a89bdde
+])dnl
14f0285
diff --git a/src/build-tools/krb5-config.in b/src/build-tools/krb5-config.in
0b340d0
index 8e6eb86601..7677f37359 100755
14f0285
--- a/src/build-tools/krb5-config.in
14f0285
+++ b/src/build-tools/krb5-config.in
0b340d0
@@ -40,6 +40,7 @@ DL_LIB='@DL_LIB@'
14f0285
 DEFCCNAME='@DEFCCNAME@'
14f0285
 DEFKTNAME='@DEFKTNAME@'
14f0285
 DEFCKTNAME='@DEFCKTNAME@'
14f0285
+SELINUX_LIBS='@SELINUX_LIBS@'
14f0285
 
14f0285
 LIBS='@LIBS@'
14f0285
 GEN_LIB=@GEN_LIB@
0b340d0
@@ -253,7 +254,7 @@ if test -n "$do_libs"; then
14f0285
     fi
14f0285
 
14f0285
     # If we ever support a flag to generate output suitable for static
14f0285
-    # linking, we would output "-lkrb5support $GEN_LIB $LIBS $DL_LIB"
14f0285
+    # linking, we would output "-lkrb5support $GEN_LIB $LIBS $SELINUX_LIBS $DL_LIB"
14f0285
     # here.
14f0285
 
14f0285
     echo $lib_flags
14f0285
diff --git a/src/config/pre.in b/src/config/pre.in
56cee50
index a0c60c70b3..7eaa2f351c 100644
14f0285
--- a/src/config/pre.in
14f0285
+++ b/src/config/pre.in
821dac4
@@ -177,6 +177,7 @@ LD = $(PURE) @LD@
a89bdde
 KRB_INCLUDES = -I$(BUILDTOP)/include -I$(top_srcdir)/include
a89bdde
 LDFLAGS = @LDFLAGS@
a89bdde
 LIBS = @LIBS@
a89bdde
+SELINUX_LIBS=@SELINUX_LIBS@
a89bdde
 
a89bdde
 INSTALL=@INSTALL@
a89bdde
 INSTALL_STRIP=
56cee50
@@ -379,7 +380,7 @@ SUPPORT_LIB			= -l$(SUPPORT_LIBNAME)
a89bdde
 # HESIOD_LIBS is -lhesiod...
a89bdde
 HESIOD_LIBS	= @HESIOD_LIBS@
a89bdde
 
a89bdde
-KRB5_BASE_LIBS	= $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(DL_LIB)
a89bdde
+KRB5_BASE_LIBS	= $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(SELINUX_LIBS) $(DL_LIB)
a89bdde
 KDB5_LIBS	= $(KDB5_LIB) $(GSSRPC_LIBS)
a89bdde
 GSS_LIBS	= $(GSS_KRB5_LIB)
533a73f
 # needs fixing if ever used on macOS!
7f642b1
diff --git a/src/configure.ac b/src/configure.ac
0b340d0
index 587221936e..69be9030f8 100644
7f642b1
--- a/src/configure.ac
7f642b1
+++ b/src/configure.ac
0b340d0
@@ -1401,6 +1401,8 @@ AC_PATH_PROG(GROFF, groff)
a89bdde
 
a89bdde
 KRB5_WITH_PAM
a89bdde
 
a89bdde
+KRB5_WITH_SELINUX
a89bdde
+
a89bdde
 # Make localedir work in autoconf 2.5x.
a89bdde
 if test "${localedir+set}" != set; then
a89bdde
     localedir='$(datadir)/locale'
14f0285
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
0b340d0
index 2f7791b775..9c534faa8a 100644
14f0285
--- a/src/include/k5-int.h
14f0285
+++ b/src/include/k5-int.h
821dac4
@@ -128,6 +128,7 @@ typedef unsigned char   u_char;
a89bdde
 
a89bdde
 
a89bdde
 #include "k5-platform.h"
a89bdde
+#include "k5-label.h"
a89bdde
 
a89bdde
 #define KRB5_KDB_MAX_LIFE       (60*60*24) /* one day */
a89bdde
 #define KRB5_KDB_MAX_RLIFE      (60*60*24*7) /* one week */
14f0285
diff --git a/src/include/k5-label.h b/src/include/k5-label.h
14f0285
new file mode 100644
56cee50
index 0000000000..dfaaa847cb
14f0285
--- /dev/null
14f0285
+++ b/src/include/k5-label.h
a89bdde
@@ -0,0 +1,32 @@
a89bdde
+#ifndef _KRB5_LABEL_H
a89bdde
+#define _KRB5_LABEL_H
a89bdde
+
a89bdde
+#ifdef THREEPARAMOPEN
a89bdde
+#undef THREEPARAMOPEN
a89bdde
+#endif
a89bdde
+#ifdef WRITABLEFOPEN
a89bdde
+#undef WRITABLEFOPEN
a89bdde
+#endif
a89bdde
+
a89bdde
+/* Wrapper functions which help us create files and directories with the right
a89bdde
+ * context labels. */
a89bdde
+#ifdef USE_SELINUX
a89bdde
+#include <sys/types.h>
a89bdde
+#include <sys/stat.h>
a89bdde
+#include <fcntl.h>
a89bdde
+#include <stdio.h>
a89bdde
+#include <unistd.h>
a89bdde
+FILE *krb5int_labeled_fopen(const char *path, const char *mode);
a89bdde
+int krb5int_labeled_creat(const char *path, mode_t mode);
a89bdde
+int krb5int_labeled_open(const char *path, int flags, ...);
a89bdde
+int krb5int_labeled_mkdir(const char *path, mode_t mode);
a89bdde
+int krb5int_labeled_mknod(const char *path, mode_t mode, dev_t device);
a89bdde
+#define THREEPARAMOPEN(x,y,z) krb5int_labeled_open(x,y,z)
a89bdde
+#define WRITABLEFOPEN(x,y) krb5int_labeled_fopen(x,y)
a89bdde
+void *krb5int_push_fscreatecon_for(const char *pathname);
a89bdde
+void krb5int_pop_fscreatecon(void *previous);
a89bdde
+#else
a89bdde
+#define WRITABLEFOPEN(x,y) fopen(x,y)
a89bdde
+#define THREEPARAMOPEN(x,y,z) open(x,y,z)
a89bdde
+#endif
a89bdde
+#endif
14f0285
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
0b340d0
index 9c76780181..dd6430ece8 100644
14f0285
--- a/src/include/krb5/krb5.hin
14f0285
+++ b/src/include/krb5/krb5.hin
a89bdde
@@ -87,6 +87,12 @@
a89bdde
 #define THREEPARAMOPEN(x,y,z) open(x,y,z)
a89bdde
 #endif
a89bdde
 
a89bdde
+#if KRB5_PRIVATE
a89bdde
+#ifndef WRITABLEFOPEN
a89bdde
+#define WRITABLEFOPEN(x,y) fopen(x,y)
a89bdde
+#endif
a89bdde
+#endif
a89bdde
+
a89bdde
 #define KRB5_OLD_CRYPTO
a89bdde
 
a89bdde
 #include <stdlib.h>
14f0285
diff --git a/src/kadmin/dbutil/dump.c b/src/kadmin/dbutil/dump.c
56cee50
index a89b5144f6..4d6cc0bdf9 100644
14f0285
--- a/src/kadmin/dbutil/dump.c
14f0285
+++ b/src/kadmin/dbutil/dump.c
14f0285
@@ -148,12 +148,21 @@ create_ofile(char *ofile, char **tmpname)
a89bdde
 {
a89bdde
     int fd = -1;
a89bdde
     FILE *f;
a89bdde
+#ifdef USE_SELINUX
a89bdde
+    void *selabel;
a89bdde
+#endif
a89bdde
 
a89bdde
     *tmpname = NULL;
a89bdde
     if (asprintf(tmpname, "%s-XXXXXX", ofile) < 0)
a89bdde
         goto error;
a89bdde
 
a89bdde
+#ifdef USE_SELINUX
a89bdde
+    selabel = krb5int_push_fscreatecon_for(ofile);
a89bdde
+#endif
a89bdde
     fd = mkstemp(*tmpname);
a89bdde
+#ifdef USE_SELINUX
a89bdde
+    krb5int_pop_fscreatecon(selabel);
a89bdde
+#endif
a89bdde
     if (fd == -1)
a89bdde
         goto error;
a89bdde
 
f745542
@@ -197,7 +206,7 @@ prep_ok_file(krb5_context context, char *file_name, int *fd_out)
f745542
         goto cleanup;
a89bdde
     }
a89bdde
 
f745542
-    fd = open(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600);
f745542
+    fd = THREEPARAMOPEN(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600);
f745542
     if (fd == -1) {
a89bdde
         com_err(progname, errno, _("while creating 'ok' file, '%s'"), file_ok);
f745542
         goto cleanup;
14f0285
diff --git a/src/kdc/main.c b/src/kdc/main.c
0b340d0
index bfdfef5c48..b43fe9a082 100644
14f0285
--- a/src/kdc/main.c
14f0285
+++ b/src/kdc/main.c
0b340d0
@@ -844,7 +844,7 @@ write_pid_file(const char *path)
14f0285
     FILE *file;
14f0285
     unsigned long pid;
a89bdde
 
14f0285
-    file = fopen(path, "w");
14f0285
+    file = WRITABLEFOPEN(path, "w");
14f0285
     if (file == NULL)
14f0285
         return errno;
14f0285
     pid = (unsigned long) getpid();
f745542
diff --git a/src/kprop/kpropd.c b/src/kprop/kpropd.c
0b340d0
index aa3c81ea30..cb9785aaeb 100644
f745542
--- a/src/kprop/kpropd.c
f745542
+++ b/src/kprop/kpropd.c
56cee50
@@ -488,6 +488,9 @@ doit(int fd)
f745542
     krb5_enctype etype;
f745542
     int database_fd;
f745542
     char host[INET6_ADDRSTRLEN + 1];
f745542
+#ifdef USE_SELINUX
f745542
+    void *selabel;
f745542
+#endif
f745542
 
f745542
     signal_wrapper(SIGALRM, alarm_handler);
f745542
     alarm(params.iprop_resync_timeout);
56cee50
@@ -543,9 +546,15 @@ doit(int fd)
f745542
         free(name);
f745542
         exit(1);
f745542
     }
f745542
+#ifdef USE_SELINUX
f745542
+    selabel = krb5int_push_fscreatecon_for(file);
f745542
+#endif
f745542
     omask = umask(077);
f745542
     lock_fd = open(temp_file_name, O_RDWR | O_CREAT, 0600);
f745542
     (void)umask(omask);
f745542
+#ifdef USE_SELINUX
f745542
+    krb5int_pop_fscreatecon(selabel);
f745542
+#endif
f745542
     retval = krb5_lock_file(kpropd_context, lock_fd,
f745542
                             KRB5_LOCKMODE_EXCLUSIVE | KRB5_LOCKMODE_DONTBLOCK);
f745542
     if (retval) {
14f0285
diff --git a/src/lib/kadm5/logger.c b/src/lib/kadm5/logger.c
0b340d0
index e14da53790..b879a4049b 100644
14f0285
--- a/src/lib/kadm5/logger.c
14f0285
+++ b/src/lib/kadm5/logger.c
0b340d0
@@ -310,7 +310,7 @@ krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do
a89bdde
                      */
821dac4
                     append = (cp[4] == ':') ? O_APPEND : 0;
821dac4
                     if (append || cp[4] == '=') {
821dac4
-                        fd = open(&cp[5], O_CREAT | O_WRONLY | append,
821dac4
+                        fd = THREEPARAMOPEN(&cp[5], O_CREAT | O_WRONLY | append,
821dac4
                                   S_IRUSR | S_IWUSR | S_IRGRP);
821dac4
                         if (fd != -1)
821dac4
                             f = fdopen(fd, append ? "a" : "w");
0b340d0
@@ -777,7 +777,7 @@ krb5_klog_reopen(krb5_context kcontext)
a89bdde
              * In case the old logfile did not get moved out of the
a89bdde
              * way, open for append to prevent squashing the old logs.
a89bdde
              */
a89bdde
-            f = fopen(log_control.log_entries[lindex].lfu_fname, "a+");
a89bdde
+            f = WRITABLEFOPEN(log_control.log_entries[lindex].lfu_fname, "a+");
a89bdde
             if (f) {
a89bdde
                 set_cloexec_file(f);
a89bdde
                 log_control.log_entries[lindex].lfu_filep = f;
14f0285
diff --git a/src/lib/kdb/kdb_log.c b/src/lib/kdb/kdb_log.c
56cee50
index 2659a25018..e9b95fce59 100644
14f0285
--- a/src/lib/kdb/kdb_log.c
14f0285
+++ b/src/lib/kdb/kdb_log.c
f745542
@@ -480,7 +480,7 @@ ulog_map(krb5_context context, const char *logname, uint32_t ulogentries)
f745542
         return ENOMEM;
14f0285
 
14f0285
     if (stat(logname, &st) == -1) {
f745542
-        log_ctx->ulogfd = open(logname, O_RDWR | O_CREAT, 0600);
f745542
+        log_ctx->ulogfd = THREEPARAMOPEN(logname, O_RDWR | O_CREAT, 0600);
f745542
         if (log_ctx->ulogfd == -1) {
f745542
             retval = errno;
f745542
             goto cleanup;
14f0285
diff --git a/src/lib/krb5/ccache/cc_dir.c b/src/lib/krb5/ccache/cc_dir.c
56cee50
index 1da40b51d0..f3ab7340a6 100644
14f0285
--- a/src/lib/krb5/ccache/cc_dir.c
14f0285
+++ b/src/lib/krb5/ccache/cc_dir.c
14f0285
@@ -183,10 +183,19 @@ write_primary_file(const char *primary_path, const char *contents)
14f0285
     char *newpath = NULL;
14f0285
     FILE *fp = NULL;
14f0285
     int fd = -1, status;
14f0285
+#ifdef USE_SELINUX
14f0285
+    void *selabel;
14f0285
+#endif
14f0285
 
14f0285
     if (asprintf(&newpath, "%s.XXXXXX", primary_path) < 0)
14f0285
         return ENOMEM;
14f0285
+#ifdef USE_SELINUX
14f0285
+    selabel = krb5int_push_fscreatecon_for(primary_path);
14f0285
+#endif
14f0285
     fd = mkstemp(newpath);
14f0285
+#ifdef USE_SELINUX
14f0285
+    krb5int_pop_fscreatecon(selabel);
14f0285
+#endif
14f0285
     if (fd < 0)
14f0285
         goto cleanup;
14f0285
 #ifdef HAVE_CHMOD
14f0285
@@ -221,10 +230,23 @@ static krb5_error_code
14f0285
 verify_dir(krb5_context context, const char *dirname)
14f0285
 {
14f0285
     struct stat st;
14f0285
+    int status;
14f0285
+#ifdef USE_SELINUX
14f0285
+    void *selabel;
14f0285
+#endif
14f0285
 
14f0285
     if (stat(dirname, &st) < 0) {
14f0285
-        if (errno == ENOENT && mkdir(dirname, S_IRWXU) == 0)
14f0285
-            return 0;
14f0285
+        if (errno == ENOENT) {
14f0285
+#ifdef USE_SELINUX
14f0285
+            selabel = krb5int_push_fscreatecon_for(dirname);
14f0285
+#endif
14f0285
+            status = mkdir(dirname, S_IRWXU);
14f0285
+#ifdef USE_SELINUX
14f0285
+            krb5int_pop_fscreatecon(selabel);
14f0285
+#endif
14f0285
+            if (status == 0)
14f0285
+                return 0;
14f0285
+        }
14f0285
         k5_setmsg(context, KRB5_FCC_NOFILE,
14f0285
                   _("Credential cache directory %s does not exist"),
14f0285
                   dirname);
14f0285
diff --git a/src/lib/krb5/keytab/kt_file.c b/src/lib/krb5/keytab/kt_file.c
56cee50
index e510211fc5..f3ea28c8ec 100644
14f0285
--- a/src/lib/krb5/keytab/kt_file.c
14f0285
+++ b/src/lib/krb5/keytab/kt_file.c
7f642b1
@@ -735,14 +735,14 @@ krb5_ktfileint_open(krb5_context context, krb5_keytab id, int mode)
a89bdde
 
a89bdde
     KTCHECKLOCK(id);
a89bdde
     errno = 0;
a89bdde
-    KTFILEP(id) = fopen(KTFILENAME(id),
a89bdde
+    KTFILEP(id) = WRITABLEFOPEN(KTFILENAME(id),
821dac4
                         (mode == KRB5_LOCKMODE_EXCLUSIVE) ? "rb+" : "rb");
a89bdde
     if (!KTFILEP(id)) {
821dac4
         if ((mode == KRB5_LOCKMODE_EXCLUSIVE) && (errno == ENOENT)) {
a89bdde
             /* try making it first time around */
a89bdde
             k5_create_secure_file(context, KTFILENAME(id));
a89bdde
             errno = 0;
821dac4
-            KTFILEP(id) = fopen(KTFILENAME(id), "rb+");
821dac4
+            KTFILEP(id) = WRITABLEFOPEN(KTFILENAME(id), "rb+");
a89bdde
             if (!KTFILEP(id))
a89bdde
                 goto report_errno;
a89bdde
             writevno = 1;
14f0285
diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c
0b340d0
index 4cbbbb270a..c4058ddc96 100644
14f0285
--- a/src/lib/krb5/os/trace.c
14f0285
+++ b/src/lib/krb5/os/trace.c
0b340d0
@@ -460,7 +460,7 @@ krb5_set_trace_filename(krb5_context context, const char *filename)
14f0285
     fd = malloc(sizeof(*fd));
14f0285
     if (fd == NULL)
14f0285
         return ENOMEM;
14f0285
-    *fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, 0600);
14f0285
+    *fd = THREEPARAMOPEN(filename, O_WRONLY|O_CREAT|O_APPEND, 0600);
14f0285
     if (*fd == -1) {
14f0285
         free(fd);
14f0285
         return errno;
14f0285
diff --git a/src/plugins/kdb/db2/adb_openclose.c b/src/plugins/kdb/db2/adb_openclose.c
0b340d0
index 9a506e9d44..f92ab47143 100644
14f0285
--- a/src/plugins/kdb/db2/adb_openclose.c
14f0285
+++ b/src/plugins/kdb/db2/adb_openclose.c
14f0285
@@ -152,7 +152,7 @@ osa_adb_init_db(osa_adb_db_t *dbp, char *filename, char *lockfilename,
14f0285
          * needs be open read/write so that write locking can work with
a89bdde
          * POSIX systems
a89bdde
          */
a89bdde
-        if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r+")) == NULL) {
a89bdde
+        if ((lockp->lockinfo.lockfile = WRITABLEFOPEN(lockfilename, "r+")) == NULL) {
a89bdde
             /*
a89bdde
              * maybe someone took away write permission so we could only
a89bdde
              * get shared locks?
14f0285
diff --git a/src/plugins/kdb/db2/kdb_db2.c b/src/plugins/kdb/db2/kdb_db2.c
56cee50
index 2c163d91cc..9a344a603e 100644
14f0285
--- a/src/plugins/kdb/db2/kdb_db2.c
14f0285
+++ b/src/plugins/kdb/db2/kdb_db2.c
14f0285
@@ -694,8 +694,8 @@ ctx_create_db(krb5_context context, krb5_db2_context *dbc)
14f0285
     if (retval)
14f0285
         return retval;
14f0285
 
14f0285
-    dbc->db_lf_file = open(dbc->db_lf_name, O_CREAT | O_RDWR | O_TRUNC,
14f0285
-                           0600);
14f0285
+    dbc->db_lf_file = THREEPARAMOPEN(dbc->db_lf_name,
14f0285
+                                     O_CREAT | O_RDWR | O_TRUNC, 0600);
14f0285
     if (dbc->db_lf_file < 0) {
14f0285
         retval = errno;
14f0285
         goto cleanup;
14f0285
diff --git a/src/plugins/kdb/db2/libdb2/btree/bt_open.c b/src/plugins/kdb/db2/libdb2/btree/bt_open.c
56cee50
index 2977b17f3a..d5809a5a93 100644
14f0285
--- a/src/plugins/kdb/db2/libdb2/btree/bt_open.c
14f0285
+++ b/src/plugins/kdb/db2/libdb2/btree/bt_open.c
14f0285
@@ -60,6 +60,7 @@ static char sccsid[] = "@(#)bt_open.c	8.11 (Berkeley) 11/2/95";
a89bdde
 #include <string.h>
a89bdde
 #include <unistd.h>
a89bdde
 
a89bdde
+#include "k5-int.h"
a89bdde
 #include "db-int.h"
a89bdde
 #include "btree.h"
a89bdde
 
14f0285
@@ -203,7 +204,7 @@ __bt_open(fname, flags, mode, openinfo, dflags)
a89bdde
 			goto einval;
a89bdde
 		}
a89bdde
 
a89bdde
-		if ((t->bt_fd = open(fname, flags | O_BINARY, mode)) < 0)
a89bdde
+		if ((t->bt_fd = THREEPARAMOPEN(fname, flags | O_BINARY, mode)) < 0)
a89bdde
 			goto err;
a89bdde
 
a89bdde
 	} else {
14f0285
diff --git a/src/plugins/kdb/db2/libdb2/hash/hash.c b/src/plugins/kdb/db2/libdb2/hash/hash.c
56cee50
index 862dbb1640..686a960c96 100644
14f0285
--- a/src/plugins/kdb/db2/libdb2/hash/hash.c
14f0285
+++ b/src/plugins/kdb/db2/libdb2/hash/hash.c
14f0285
@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)hash.c	8.12 (Berkeley) 11/7/95";
a89bdde
 #include <assert.h>
a89bdde
 #endif
a89bdde
 
a89bdde
+#include "k5-int.h"
a89bdde
 #include "db-int.h"
a89bdde
 #include "hash.h"
a89bdde
 #include "page.h"
533a73f
@@ -129,7 +130,7 @@ __kdb2_hash_open(file, flags, mode, info, dflags)
a89bdde
 		new_table = 1;
a89bdde
 	}
a89bdde
 	if (file) {
a89bdde
-		if ((hashp->fp = open(file, flags|O_BINARY, mode)) == -1)
a89bdde
+		if ((hashp->fp = THREEPARAMOPEN(file, flags|O_BINARY, mode)) == -1)
a89bdde
 			RETURN_ERROR(errno, error0);
a89bdde
 		(void)fcntl(hashp->fp, F_SETFD, 1);
a89bdde
 	}
14f0285
diff --git a/src/plugins/kdb/db2/libdb2/recno/rec_open.c b/src/plugins/kdb/db2/libdb2/recno/rec_open.c
56cee50
index d8b26e7011..b0daa7c021 100644
14f0285
--- a/src/plugins/kdb/db2/libdb2/recno/rec_open.c
14f0285
+++ b/src/plugins/kdb/db2/libdb2/recno/rec_open.c
14f0285
@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)rec_open.c	8.12 (Berkeley) 11/18/94";
14f0285
 #include <stdio.h>
14f0285
 #include <unistd.h>
14f0285
 
14f0285
+#include "k5-int.h"
14f0285
 #include "db-int.h"
14f0285
 #include "recno.h"
14f0285
 
14f0285
@@ -68,7 +69,8 @@ __rec_open(fname, flags, mode, openinfo, dflags)
14f0285
 	int rfd = -1, sverrno;
14f0285
 
14f0285
 	/* Open the user's file -- if this fails, we're done. */
14f0285
-	if (fname != NULL && (rfd = open(fname, flags | O_BINARY, mode)) < 0)
14f0285
+	if (fname != NULL &&
14f0285
+            (rfd = THREEPARAMOPEN(fname, flags | O_BINARY, mode)) < 0)
14f0285
 		return (NULL);
14f0285
 
14f0285
 	if (fname != NULL && fcntl(rfd, F_SETFD, 1) == -1) {
14f0285
diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
56cee50
index e87688d666..30f7c00ab5 100644
14f0285
--- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
14f0285
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
7f642b1
@@ -190,7 +190,7 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
a89bdde
 
a89bdde
     /* set password in the file */
a89bdde
     old_mode = umask(0177);
a89bdde
-    pfile = fopen(file_name, "a+");
a89bdde
+    pfile = WRITABLEFOPEN(file_name, "a+");
a89bdde
     if (pfile == NULL) {
a89bdde
         com_err(me, errno, _("Failed to open file %s: %s"), file_name,
a89bdde
                 strerror (errno));
7f642b1
@@ -231,6 +231,9 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
a89bdde
          * Delete the existing entry and add the new entry
a89bdde
          */
a89bdde
         FILE *newfile;
a89bdde
+#ifdef USE_SELINUX
a89bdde
+        void *selabel;
a89bdde
+#endif
a89bdde
 
a89bdde
         mode_t omask;
a89bdde
 
7f642b1
@@ -242,7 +245,13 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
a89bdde
         }
a89bdde
 
a89bdde
         omask = umask(077);
a89bdde
+#ifdef USE_SELINUX
a89bdde
+        selabel = krb5int_push_fscreatecon_for(file_name);
a89bdde
+#endif
a89bdde
         newfile = fopen(tmp_file, "w");
a89bdde
+#ifdef USE_SELINUX
a89bdde
+        krb5int_pop_fscreatecon(selabel);
a89bdde
+#endif
a89bdde
         umask (omask);
a89bdde
         if (newfile == NULL) {
a89bdde
             com_err(me, errno, _("Error creating file %s"), tmp_file);
14f0285
diff --git a/src/util/profile/prof_file.c b/src/util/profile/prof_file.c
56cee50
index aa951df05f..79f9500f69 100644
14f0285
--- a/src/util/profile/prof_file.c
14f0285
+++ b/src/util/profile/prof_file.c
14f0285
@@ -33,6 +33,7 @@
a89bdde
 #endif
a89bdde
 
a89bdde
 #include "k5-platform.h"
a89bdde
+#include "k5-label.h"
a89bdde
 
a89bdde
 struct global_shared_profile_data {
a89bdde
     /* This is the head of the global list of shared trees */
f745542
@@ -391,7 +392,7 @@ static errcode_t write_data_to_file(prf_data_t data, const char *outfile,
a89bdde
 
a89bdde
     errno = 0;
a89bdde
 
a89bdde
-    f = fopen(new_file, "w");
a89bdde
+    f = WRITABLEFOPEN(new_file, "w");
a89bdde
     if (!f) {
a89bdde
         retval = errno;
a89bdde
         if (retval == 0)
14f0285
diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in
56cee50
index 86d5a950a6..1052d53a1e 100644
14f0285
--- a/src/util/support/Makefile.in
14f0285
+++ b/src/util/support/Makefile.in
7f642b1
@@ -74,6 +74,7 @@ IPC_SYMS= \
a89bdde
 
a89bdde
 STLIBOBJS= \
a89bdde
 	threads.o \
a89bdde
+	selinux.o \
a89bdde
 	init-addrinfo.o \
a89bdde
 	plugins.o \
a89bdde
 	errors.o \
7f642b1
@@ -168,7 +169,7 @@ SRCS=\
a89bdde
 
a89bdde
 SHLIB_EXPDEPS =
a89bdde
 # Add -lm if dumping thread stats, for sqrt.
a89bdde
-SHLIB_EXPLIBS= $(LIBS) $(DL_LIB)
a89bdde
+SHLIB_EXPLIBS= $(LIBS) $(SELINUX_LIBS) $(DL_LIB)
a89bdde
 
a89bdde
 DEPLIBS=
a89bdde
 
14f0285
diff --git a/src/util/support/selinux.c b/src/util/support/selinux.c
14f0285
new file mode 100644
56cee50
index 0000000000..807d039da3
14f0285
--- /dev/null
14f0285
+++ b/src/util/support/selinux.c
56cee50
@@ -0,0 +1,405 @@
a89bdde
+/*
821dac4
+ * Copyright 2007,2008,2009,2011,2012,2013,2016 Red Hat, Inc.  All Rights Reserved.
a89bdde
+ *
a89bdde
+ * Redistribution and use in source and binary forms, with or without
a89bdde
+ * modification, are permitted provided that the following conditions are met:
a89bdde
+ *
a89bdde
+ *  Redistributions of source code must retain the above copyright notice, this
a89bdde
+ *  list of conditions and the following disclaimer.
a89bdde
+ *
a89bdde
+ *  Redistributions in binary form must reproduce the above copyright notice,
a89bdde
+ *  this list of conditions and the following disclaimer in the documentation
a89bdde
+ *  and/or other materials provided with the distribution.
a89bdde
+ *
a89bdde
+ *  Neither the name of Red Hat, Inc. nor the names of its contributors may be
a89bdde
+ *  used to endorse or promote products derived from this software without
a89bdde
+ *  specific prior written permission.
a89bdde
+ *
a89bdde
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
a89bdde
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
a89bdde
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
a89bdde
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
a89bdde
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
a89bdde
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
a89bdde
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
a89bdde
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
a89bdde
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
a89bdde
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
a89bdde
+ * POSSIBILITY OF SUCH DAMAGE.
821dac4
+ *
a89bdde
+ * File-opening wrappers for creating correctly-labeled files.  So far, we can
a89bdde
+ * assume that this is Linux-specific, so we make many simplifying assumptions.
a89bdde
+ */
a89bdde
+
a89bdde
+#include "../../include/autoconf.h"
a89bdde
+
a89bdde
+#ifdef USE_SELINUX
a89bdde
+
a89bdde
+#include <k5-label.h>
a89bdde
+#include <k5-platform.h>
821dac4
+
a89bdde
+#include <sys/types.h>
a89bdde
+#include <sys/stat.h>
821dac4
+
a89bdde
+#include <errno.h>
a89bdde
+#include <fcntl.h>
a89bdde
+#include <limits.h>
a89bdde
+#include <pthread.h>
a89bdde
+#include <stdarg.h>
a89bdde
+#include <stdio.h>
a89bdde
+#include <stdlib.h>
a89bdde
+#include <string.h>
a89bdde
+#include <unistd.h>
821dac4
+
a89bdde
+#include <selinux/selinux.h>
a89bdde
+#include <selinux/context.h>
a89bdde
+#include <selinux/label.h>
a89bdde
+
a89bdde
+/* #define DEBUG 1 */
821dac4
+static void
821dac4
+debug_log(const char *fmt, ...)
821dac4
+{
821dac4
+#ifdef DEBUG
821dac4
+    va_list ap;
58aed41
+    va_start(ap, fmt);
821dac4
+    if (isatty(fileno(stderr))) {
821dac4
+        vfprintf(stderr, fmt, ap);
821dac4
+    }
821dac4
+    va_end(ap);
821dac4
+#endif
821dac4
+
821dac4
+    return;
821dac4
+}
a89bdde
+
a89bdde
+/* Mutex used to serialize use of the process-global file creation context. */
a89bdde
+k5_mutex_t labeled_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
a89bdde
+
a89bdde
+/* Make sure we finish initializing that mutex before attempting to use it. */
a89bdde
+k5_once_t labeled_once = K5_ONCE_INIT;
a89bdde
+static void
a89bdde
+label_mutex_init(void)
a89bdde
+{
821dac4
+    k5_mutex_finish_init(&labeled_mutex);
a89bdde
+}
a89bdde
+
a89bdde
+static struct selabel_handle *selabel_ctx;
a89bdde
+static time_t selabel_last_changed;
a89bdde
+
a89bdde
+MAKE_FINI_FUNCTION(cleanup_fscreatecon);
a89bdde
+
a89bdde
+static void
a89bdde
+cleanup_fscreatecon(void)
a89bdde
+{
821dac4
+    if (selabel_ctx != NULL) {
821dac4
+        selabel_close(selabel_ctx);
821dac4
+        selabel_ctx = NULL;
821dac4
+    }
a89bdde
+}
a89bdde
+
56cee50
+static char *
a89bdde
+push_fscreatecon(const char *pathname, mode_t mode)
a89bdde
+{
56cee50
+    char *previous, *configuredsc, *currentsc, *genpath;
56cee50
+    const char *derivedsc, *fullpath, *currentuser;
821dac4
+    context_t current, derived;
821dac4
+
56cee50
+    previous = configuredsc = currentsc = genpath = NULL;
56cee50
+    derivedsc = NULL;
821dac4
+    current = derived = NULL;
821dac4
+
821dac4
+    fullpath = pathname;
821dac4
+
821dac4
+    if (!is_selinux_enabled()) {
821dac4
+        goto fail;
821dac4
+    }
821dac4
+
821dac4
+    if (getfscreatecon(&previous) != 0) {
821dac4
+        goto fail;
821dac4
+    }
821dac4
+
821dac4
+    /* Canonicalize pathname */
821dac4
+    if (pathname[0] != '/') {
821dac4
+        char *wd;
821dac4
+        size_t len;
821dac4
+        len = 0;
821dac4
+
821dac4
+        wd = getcwd(NULL, len);
821dac4
+        if (wd == NULL) {
821dac4
+            goto fail;
821dac4
+        }
821dac4
+
821dac4
+        len = strlen(wd) + 1 + strlen(pathname) + 1;
821dac4
+        genpath = malloc(len);
821dac4
+        if (genpath == NULL) {
821dac4
+            free(wd);
821dac4
+            goto fail;
821dac4
+        }
821dac4
+
821dac4
+        sprintf(genpath, "%s/%s", wd, pathname);
821dac4
+        free(wd);
821dac4
+        fullpath = genpath;
821dac4
+    }
821dac4
+
821dac4
+    debug_log("Looking up context for \"%s\"(%05o).\n", fullpath, mode);
821dac4
+
821dac4
+    /* Check whether context file has changed under us */
821dac4
+    if (selabel_ctx != NULL || selabel_last_changed == 0) {
821dac4
+        const char *cpath;
821dac4
+        struct stat st;
821dac4
+        int i = -1;
821dac4
+
821dac4
+        cpath = selinux_file_context_path();
821dac4
+        if (cpath == NULL || (i = stat(cpath, &st)) != 0 ||
821dac4
+            st.st_mtime != selabel_last_changed) {
821dac4
+            cleanup_fscreatecon();
821dac4
+
821dac4
+            selabel_last_changed = i ? time(NULL) : st.st_mtime;
821dac4
+        }
821dac4
+    }
821dac4
+
821dac4
+    if (selabel_ctx == NULL) {
821dac4
+        selabel_ctx = selabel_open(SELABEL_CTX_FILE, NULL, 0);
821dac4
+    }
821dac4
+
821dac4
+    if (selabel_ctx != NULL &&
821dac4
+        selabel_lookup(selabel_ctx, &configuredsc, fullpath, mode) != 0) {
821dac4
+        goto fail;
821dac4
+    }
821dac4
+
821dac4
+    if (genpath != NULL) {
821dac4
+        free(genpath);
821dac4
+        genpath = NULL;
821dac4
+    }
821dac4
+
821dac4
+    if (configuredsc == NULL) {
821dac4
+        goto fail;
821dac4
+    }
821dac4
+
821dac4
+    getcon(&currentsc);
821dac4
+
821dac4
+    /* AAAAAAAA */
821dac4
+    if (currentsc != NULL) {
821dac4
+        derived = context_new(configuredsc);
821dac4
+
821dac4
+        if (derived != NULL) {
821dac4
+            current = context_new(currentsc);
821dac4
+
821dac4
+            if (current != NULL) {
821dac4
+                currentuser = context_user_get(current);
821dac4
+
821dac4
+                if (currentuser != NULL) {
821dac4
+                    if (context_user_set(derived,
821dac4
+                                         currentuser) == 0) {
821dac4
+                        derivedsc = context_str(derived);
821dac4
+
821dac4
+                        if (derivedsc != NULL) {
821dac4
+                            freecon(configuredsc);
821dac4
+                            configuredsc = strdup(derivedsc);
821dac4
+                        }
821dac4
+                    }
821dac4
+                }
821dac4
+
821dac4
+                context_free(current);
821dac4
+            }
821dac4
+
821dac4
+            context_free(derived);
821dac4
+        }
821dac4
+
821dac4
+        freecon(currentsc);
821dac4
+    }
821dac4
+
821dac4
+    debug_log("Setting file creation context to \"%s\".\n", configuredsc);
821dac4
+    if (setfscreatecon(configuredsc) != 0) {
821dac4
+        debug_log("Unable to determine current context.\n");
821dac4
+        goto fail;
821dac4
+    }
821dac4
+
821dac4
+    freecon(configuredsc);
821dac4
+    return previous;
821dac4
+
821dac4
+fail:
821dac4
+    if (previous != NULL) {
821dac4
+        freecon(previous);
821dac4
+    }
821dac4
+    if (genpath != NULL) {
821dac4
+        free(genpath);
821dac4
+    }
821dac4
+    if (configuredsc != NULL) {
821dac4
+        freecon(configuredsc);
821dac4
+    }
821dac4
+
821dac4
+    cleanup_fscreatecon();
821dac4
+    return NULL;
a89bdde
+}
a89bdde
+
a89bdde
+static void
56cee50
+pop_fscreatecon(char *previous)
a89bdde
+{
821dac4
+    if (!is_selinux_enabled()) {
821dac4
+        return;
821dac4
+    }
821dac4
+
821dac4
+    if (previous != NULL) {
821dac4
+        debug_log("Resetting file creation context to \"%s\".\n", previous);
821dac4
+    } else {
821dac4
+        debug_log("Resetting file creation context to default.\n");
821dac4
+    }
821dac4
+
821dac4
+    /* NULL resets to default */
821dac4
+    setfscreatecon(previous);
821dac4
+
821dac4
+    if (previous != NULL) {
821dac4
+        freecon(previous);
821dac4
+    }
821dac4
+
821dac4
+    /* Need to clean this up here otherwise it leaks */
821dac4
+    cleanup_fscreatecon();
a89bdde
+}
a89bdde
+
a89bdde
+void *
a89bdde
+krb5int_push_fscreatecon_for(const char *pathname)
a89bdde
+{
821dac4
+    struct stat st;
821dac4
+    void *retval;
821dac4
+
821dac4
+    k5_once(&labeled_once, label_mutex_init);
821dac4
+    k5_mutex_lock(&labeled_mutex);
821dac4
+
821dac4
+    if (stat(pathname, &st) != 0) {
821dac4
+        st.st_mode = S_IRUSR | S_IWUSR;
821dac4
+    }
821dac4
+
821dac4
+    retval = push_fscreatecon(pathname, st.st_mode);
821dac4
+    return retval ? retval : (void *) -1;
a89bdde
+}
a89bdde
+
a89bdde
+void
a89bdde
+krb5int_pop_fscreatecon(void *con)
a89bdde
+{
821dac4
+    if (con != NULL) {
821dac4
+        pop_fscreatecon((con == (void *) -1) ? NULL : con);
821dac4
+        k5_mutex_unlock(&labeled_mutex);
821dac4
+    }
a89bdde
+}
a89bdde
+
a89bdde
+FILE *
a89bdde
+krb5int_labeled_fopen(const char *path, const char *mode)
a89bdde
+{
821dac4
+    FILE *fp;
821dac4
+    int errno_save;
56cee50
+    char *ctx;
821dac4
+
821dac4
+    if ((strcmp(mode, "r") == 0) ||
821dac4
+        (strcmp(mode, "rb") == 0)) {
821dac4
+        return fopen(path, mode);
821dac4
+    }
821dac4
+
821dac4
+    k5_once(&labeled_once, label_mutex_init);
821dac4
+    k5_mutex_lock(&labeled_mutex);
821dac4
+    ctx = push_fscreatecon(path, 0);
821dac4
+
821dac4
+    fp = fopen(path, mode);
821dac4
+    errno_save = errno;
821dac4
+
821dac4
+    pop_fscreatecon(ctx);
821dac4
+    k5_mutex_unlock(&labeled_mutex);
821dac4
+
821dac4
+    errno = errno_save;
821dac4
+    return fp;
a89bdde
+}
a89bdde
+
a89bdde
+int
a89bdde
+krb5int_labeled_creat(const char *path, mode_t mode)
a89bdde
+{
821dac4
+    int fd;
821dac4
+    int errno_save;
56cee50
+    char *ctx;
821dac4
+
821dac4
+    k5_once(&labeled_once, label_mutex_init);
821dac4
+    k5_mutex_lock(&labeled_mutex);
821dac4
+    ctx = push_fscreatecon(path, 0);
821dac4
+
821dac4
+    fd = creat(path, mode);
821dac4
+    errno_save = errno;
821dac4
+
821dac4
+    pop_fscreatecon(ctx);
821dac4
+    k5_mutex_unlock(&labeled_mutex);
821dac4
+
821dac4
+    errno = errno_save;
821dac4
+    return fd;
a89bdde
+}
a89bdde
+
a89bdde
+int
a89bdde
+krb5int_labeled_mknod(const char *path, mode_t mode, dev_t dev)
a89bdde
+{
821dac4
+    int ret;
821dac4
+    int errno_save;
56cee50
+    char *ctx;
821dac4
+
821dac4
+    k5_once(&labeled_once, label_mutex_init);
821dac4
+    k5_mutex_lock(&labeled_mutex);
821dac4
+    ctx = push_fscreatecon(path, mode);
821dac4
+
821dac4
+    ret = mknod(path, mode, dev);
821dac4
+    errno_save = errno;
821dac4
+
821dac4
+    pop_fscreatecon(ctx);
821dac4
+    k5_mutex_unlock(&labeled_mutex);
821dac4
+
821dac4
+    errno = errno_save;
821dac4
+    return ret;
a89bdde
+}
a89bdde
+
a89bdde
+int
a89bdde
+krb5int_labeled_mkdir(const char *path, mode_t mode)
a89bdde
+{
821dac4
+    int ret;
821dac4
+    int errno_save;
56cee50
+    char *ctx;
821dac4
+
821dac4
+    k5_once(&labeled_once, label_mutex_init);
821dac4
+    k5_mutex_lock(&labeled_mutex);
821dac4
+    ctx = push_fscreatecon(path, S_IFDIR);
821dac4
+
821dac4
+    ret = mkdir(path, mode);
821dac4
+    errno_save = errno;
821dac4
+
821dac4
+    pop_fscreatecon(ctx);
821dac4
+    k5_mutex_unlock(&labeled_mutex);
821dac4
+
821dac4
+    errno = errno_save;
821dac4
+    return ret;
a89bdde
+}
a89bdde
+
a89bdde
+int
a89bdde
+krb5int_labeled_open(const char *path, int flags, ...)
a89bdde
+{
821dac4
+    int fd;
821dac4
+    int errno_save;
56cee50
+    char *ctx;
821dac4
+    mode_t mode;
821dac4
+    va_list ap;
821dac4
+
821dac4
+    if ((flags & O_CREAT) == 0) {
821dac4
+        return open(path, flags);
821dac4
+    }
821dac4
+
821dac4
+    k5_once(&labeled_once, label_mutex_init);
821dac4
+    k5_mutex_lock(&labeled_mutex);
821dac4
+    ctx = push_fscreatecon(path, 0);
821dac4
+
821dac4
+    va_start(ap, flags);
821dac4
+    mode = va_arg(ap, mode_t);
821dac4
+    fd = open(path, flags, mode);
821dac4
+    va_end(ap);
821dac4
+
821dac4
+    errno_save = errno;
821dac4
+
821dac4
+    pop_fscreatecon(ctx);
821dac4
+    k5_mutex_unlock(&labeled_mutex);
821dac4
+
821dac4
+    errno = errno_save;
821dac4
+    return fd;
a89bdde
+}
a89bdde
+
821dac4
+#endif /* USE_SELINUX */
56cee50
-- 
0b340d0
2.40.1
56cee50