Blame SOURCES/krb5-1.15-beta1-selinux-label.patch

fab64b
From 71fe21b5aeac1834df824ff5c6475e653ceb8b6b Mon Sep 17 00:00:00 2001
8c1676
From: Robbie Harwood <rharwood@redhat.com>
fab64b
Date: Wed, 4 Jan 2017 13:17:28 -0500
fab64b
Subject: [PATCH] krb5-1.15-beta1-selinux-label.patch
8c1676
8c1676
---
665228
 src/aclocal.m4                                |  49 +++
665228
 src/build-tools/krb5-config.in                |   3 +-
665228
 src/config/pre.in                             |   3 +-
665228
 src/configure.in                              |   2 +
665228
 src/include/k5-int.h                          |   1 +
665228
 src/include/k5-label.h                        |  32 ++
665228
 src/include/krb5/krb5.hin                     |   6 +
665228
 src/kadmin/dbutil/dump.c                      |  11 +-
665228
 src/kdc/main.c                                |   2 +-
665228
 src/lib/kadm5/logger.c                        |   4 +-
665228
 src/lib/kdb/kdb_log.c                         |   2 +-
665228
 src/lib/krb5/ccache/cc_dir.c                  |  26 +-
665228
 src/lib/krb5/keytab/kt_file.c                 |   4 +-
665228
 src/lib/krb5/os/trace.c                       |   2 +-
665228
 src/lib/krb5/rcache/rc_dfl.c                  |  13 +
665228
 src/plugins/kdb/db2/adb_openclose.c           |   2 +-
665228
 src/plugins/kdb/db2/kdb_db2.c                 |   4 +-
665228
 src/plugins/kdb/db2/libdb2/btree/bt_open.c    |   3 +-
665228
 src/plugins/kdb/db2/libdb2/hash/hash.c        |   3 +-
665228
 src/plugins/kdb/db2/libdb2/recno/rec_open.c   |   4 +-
665228
 .../kdb/ldap/ldap_util/kdb5_ldap_services.c   |  11 +-
665228
 src/slave/kpropd.c                            |   9 +
665228
 src/util/profile/prof_file.c                  |   3 +-
665228
 src/util/support/Makefile.in                  |   3 +-
665228
 src/util/support/selinux.c                    | 406 ++++++++++++++++++
fab64b
 25 files changed, 587 insertions(+), 21 deletions(-)
8c1676
 create mode 100644 src/include/k5-label.h
8c1676
 create mode 100644 src/util/support/selinux.c
8c1676
8c1676
diff --git a/src/aclocal.m4 b/src/aclocal.m4
fab64b
index 508e5fe90..607859f17 100644
8c1676
--- a/src/aclocal.m4
8c1676
+++ b/src/aclocal.m4
fab64b
@@ -89,6 +89,7 @@ AC_SUBST_FILE(libnodeps_frag)
8c1676
 dnl
8c1676
 KRB5_AC_PRAGMA_WEAK_REF
8c1676
 WITH_LDAP
8c1676
+KRB5_WITH_SELINUX
8c1676
 KRB5_LIB_PARAMS
8c1676
 KRB5_AC_INITFINI
8c1676
 KRB5_AC_ENABLE_THREADS
fab64b
@@ -1742,3 +1743,51 @@ AC_SUBST(PAM_LIBS)
8c1676
 AC_SUBST(PAM_MAN)
8c1676
 AC_SUBST(NON_PAM_MAN)
8c1676
 ])dnl
8c1676
+dnl
8c1676
+dnl Use libselinux to set file contexts on newly-created files.
8c1676
+dnl
8c1676
+AC_DEFUN(KRB5_WITH_SELINUX,[
8c1676
+AC_ARG_WITH(selinux,[AC_HELP_STRING(--with-selinux,[compile with SELinux labeling support])],
8c1676
+           withselinux="$withval",withselinux=auto)
8c1676
+old_LIBS="$LIBS"
8c1676
+if test "$withselinux" != no ; then
8c1676
+       AC_MSG_RESULT([checking for libselinux...])
8c1676
+       SELINUX_LIBS=
8c1676
+       AC_CHECK_HEADERS(selinux/selinux.h selinux/label.h)
8c1676
+       if test "x$ac_cv_header_selinux_selinux_h" != xyes ; then
8c1676
+               if test "$withselinux" = auto ; then
8c1676
+                       AC_MSG_RESULT([Unable to locate selinux/selinux.h.])
8c1676
+                       withselinux=no
8c1676
+               else
8c1676
+                       AC_MSG_ERROR([Unable to locate selinux/selinux.h.])
8c1676
+               fi
8c1676
+       fi
8c1676
+
8c1676
+       LIBS=
8c1676
+       unset ac_cv_func_setfscreatecon
8c1676
+       AC_CHECK_FUNCS(setfscreatecon selabel_open)
8c1676
+       if test "x$ac_cv_func_setfscreatecon" = xno ; then
8c1676
+               AC_CHECK_LIB(selinux,setfscreatecon)
8c1676
+               unset ac_cv_func_setfscreatecon
8c1676
+               AC_CHECK_FUNCS(setfscreatecon selabel_open)
8c1676
+               if test "x$ac_cv_func_setfscreatecon" = xyes ; then
8c1676
+                       SELINUX_LIBS="$LIBS"
8c1676
+               else
8c1676
+                       if test "$withselinux" = auto ; then
8c1676
+                               AC_MSG_RESULT([Unable to locate libselinux.])
8c1676
+                               withselinux=no
8c1676
+                       else
8c1676
+                               AC_MSG_ERROR([Unable to locate libselinux.])
8c1676
+                       fi
8c1676
+               fi
8c1676
+       fi
8c1676
+       if test "$withselinux" != no ; then
8c1676
+               AC_MSG_NOTICE([building with SELinux labeling support])
8c1676
+               AC_DEFINE(USE_SELINUX,1,[Define if Kerberos-aware tools should set SELinux file contexts when creating files.])
8c1676
+               SELINUX_LIBS="$LIBS"
8c1676
+		EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_labeled_open krb5int_labeled_fopen krb5int_push_fscreatecon_for krb5int_pop_fscreatecon"
8c1676
+       fi
8c1676
+fi
8c1676
+LIBS="$old_LIBS"
8c1676
+AC_SUBST(SELINUX_LIBS)
8c1676
+])dnl
8c1676
diff --git a/src/build-tools/krb5-config.in b/src/build-tools/krb5-config.in
fab64b
index f6184da3f..c17cb5eb5 100755
8c1676
--- a/src/build-tools/krb5-config.in
8c1676
+++ b/src/build-tools/krb5-config.in
8c1676
@@ -41,6 +41,7 @@ DL_LIB='@DL_LIB@'
8c1676
 DEFCCNAME='@DEFCCNAME@'
8c1676
 DEFKTNAME='@DEFKTNAME@'
8c1676
 DEFCKTNAME='@DEFCKTNAME@'
8c1676
+SELINUX_LIBS='@SELINUX_LIBS@'
8c1676
 
8c1676
 LIBS='@LIBS@'
8c1676
 GEN_LIB=@GEN_LIB@
8c1676
@@ -255,7 +256,7 @@ if test -n "$do_libs"; then
8c1676
     fi
8c1676
 
8c1676
     # If we ever support a flag to generate output suitable for static
8c1676
-    # linking, we would output "-lkrb5support $GEN_LIB $LIBS $DL_LIB"
8c1676
+    # linking, we would output "-lkrb5support $GEN_LIB $LIBS $SELINUX_LIBS $DL_LIB"
8c1676
     # here.
8c1676
 
8c1676
     echo $lib_flags
8c1676
diff --git a/src/config/pre.in b/src/config/pre.in
fab64b
index e0626320c..fcea229bd 100644
8c1676
--- a/src/config/pre.in
8c1676
+++ b/src/config/pre.in
fab64b
@@ -177,6 +177,7 @@ LD = $(PURE) @LD@
8c1676
 KRB_INCLUDES = -I$(BUILDTOP)/include -I$(top_srcdir)/include
8c1676
 LDFLAGS = @LDFLAGS@
8c1676
 LIBS = @LIBS@
8c1676
+SELINUX_LIBS=@SELINUX_LIBS@
8c1676
 
8c1676
 INSTALL=@INSTALL@
8c1676
 INSTALL_STRIP=
fab64b
@@ -399,7 +400,7 @@ SUPPORT_LIB			= -l$(SUPPORT_LIBNAME)
8c1676
 # HESIOD_LIBS is -lhesiod...
8c1676
 HESIOD_LIBS	= @HESIOD_LIBS@
8c1676
 
8c1676
-KRB5_BASE_LIBS	= $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(DL_LIB)
8c1676
+KRB5_BASE_LIBS	= $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(SELINUX_LIBS) $(DL_LIB)
8c1676
 KDB5_LIBS	= $(KDB5_LIB) $(GSSRPC_LIBS)
8c1676
 GSS_LIBS	= $(GSS_KRB5_LIB)
8c1676
 # needs fixing if ever used on Mac OS X!
8c1676
diff --git a/src/configure.in b/src/configure.in
fab64b
index daabd12c8..acf3a458b 100644
8c1676
--- a/src/configure.in
8c1676
+++ b/src/configure.in
fab64b
@@ -1338,6 +1338,8 @@ AC_PATH_PROG(GROFF, groff)
8c1676
 
8c1676
 KRB5_WITH_PAM
8c1676
 
8c1676
+KRB5_WITH_SELINUX
8c1676
+
8c1676
 # Make localedir work in autoconf 2.5x.
8c1676
 if test "${localedir+set}" != set; then
8c1676
     localedir='$(datadir)/locale'
8c1676
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
fab64b
index 64991738a..173cb0264 100644
8c1676
--- a/src/include/k5-int.h
8c1676
+++ b/src/include/k5-int.h
fab64b
@@ -128,6 +128,7 @@ typedef unsigned char   u_char;
8c1676
 
8c1676
 
8c1676
 #include "k5-platform.h"
8c1676
+#include "k5-label.h"
8c1676
 
8c1676
 #define KRB5_KDB_MAX_LIFE       (60*60*24) /* one day */
8c1676
 #define KRB5_KDB_MAX_RLIFE      (60*60*24*7) /* one week */
8c1676
diff --git a/src/include/k5-label.h b/src/include/k5-label.h
8c1676
new file mode 100644
fab64b
index 000000000..dfaaa847c
8c1676
--- /dev/null
8c1676
+++ b/src/include/k5-label.h
8c1676
@@ -0,0 +1,32 @@
8c1676
+#ifndef _KRB5_LABEL_H
8c1676
+#define _KRB5_LABEL_H
8c1676
+
8c1676
+#ifdef THREEPARAMOPEN
8c1676
+#undef THREEPARAMOPEN
8c1676
+#endif
8c1676
+#ifdef WRITABLEFOPEN
8c1676
+#undef WRITABLEFOPEN
8c1676
+#endif
8c1676
+
8c1676
+/* Wrapper functions which help us create files and directories with the right
8c1676
+ * context labels. */
8c1676
+#ifdef USE_SELINUX
8c1676
+#include <sys/types.h>
8c1676
+#include <sys/stat.h>
8c1676
+#include <fcntl.h>
8c1676
+#include <stdio.h>
8c1676
+#include <unistd.h>
8c1676
+FILE *krb5int_labeled_fopen(const char *path, const char *mode);
8c1676
+int krb5int_labeled_creat(const char *path, mode_t mode);
8c1676
+int krb5int_labeled_open(const char *path, int flags, ...);
8c1676
+int krb5int_labeled_mkdir(const char *path, mode_t mode);
8c1676
+int krb5int_labeled_mknod(const char *path, mode_t mode, dev_t device);
8c1676
+#define THREEPARAMOPEN(x,y,z) krb5int_labeled_open(x,y,z)
8c1676
+#define WRITABLEFOPEN(x,y) krb5int_labeled_fopen(x,y)
8c1676
+void *krb5int_push_fscreatecon_for(const char *pathname);
8c1676
+void krb5int_pop_fscreatecon(void *previous);
8c1676
+#else
8c1676
+#define WRITABLEFOPEN(x,y) fopen(x,y)
8c1676
+#define THREEPARAMOPEN(x,y,z) open(x,y,z)
8c1676
+#endif
8c1676
+#endif
8c1676
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
fab64b
index ac22f4c55..cf60d6c41 100644
8c1676
--- a/src/include/krb5/krb5.hin
8c1676
+++ b/src/include/krb5/krb5.hin
8c1676
@@ -87,6 +87,12 @@
8c1676
 #define THREEPARAMOPEN(x,y,z) open(x,y,z)
8c1676
 #endif
8c1676
 
8c1676
+#if KRB5_PRIVATE
8c1676
+#ifndef WRITABLEFOPEN
8c1676
+#define WRITABLEFOPEN(x,y) fopen(x,y)
8c1676
+#endif
8c1676
+#endif
8c1676
+
8c1676
 #define KRB5_OLD_CRYPTO
8c1676
 
8c1676
 #include <stdlib.h>
8c1676
diff --git a/src/kadmin/dbutil/dump.c b/src/kadmin/dbutil/dump.c
fab64b
index f7889bd23..cad53cfbf 100644
8c1676
--- a/src/kadmin/dbutil/dump.c
8c1676
+++ b/src/kadmin/dbutil/dump.c
8c1676
@@ -148,12 +148,21 @@ create_ofile(char *ofile, char **tmpname)
8c1676
 {
8c1676
     int fd = -1;
8c1676
     FILE *f;
8c1676
+#ifdef USE_SELINUX
8c1676
+    void *selabel;
8c1676
+#endif
8c1676
 
8c1676
     *tmpname = NULL;
8c1676
     if (asprintf(tmpname, "%s-XXXXXX", ofile) < 0)
8c1676
         goto error;
8c1676
 
8c1676
+#ifdef USE_SELINUX
8c1676
+    selabel = krb5int_push_fscreatecon_for(ofile);
8c1676
+#endif
8c1676
     fd = mkstemp(*tmpname);
8c1676
+#ifdef USE_SELINUX
8c1676
+    krb5int_pop_fscreatecon(selabel);
8c1676
+#endif
8c1676
     if (fd == -1)
8c1676
         goto error;
8c1676
 
8c1676
@@ -194,7 +203,7 @@ prep_ok_file(krb5_context context, char *file_name, int *fd)
8c1676
         return 0;
8c1676
     }
8c1676
 
8c1676
-    *fd = open(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600);
8c1676
+    *fd = THREEPARAMOPEN(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600);
8c1676
     if (*fd == -1) {
8c1676
         com_err(progname, errno, _("while creating 'ok' file, '%s'"), file_ok);
8c1676
         exit_status++;
8c1676
diff --git a/src/kdc/main.c b/src/kdc/main.c
fab64b
index ebc852bba..a4dffb29a 100644
8c1676
--- a/src/kdc/main.c
8c1676
+++ b/src/kdc/main.c
fab64b
@@ -872,7 +872,7 @@ write_pid_file(const char *path)
8c1676
     FILE *file;
8c1676
     unsigned long pid;
8c1676
 
8c1676
-    file = fopen(path, "w");
8c1676
+    file = WRITABLEFOPEN(path, "w");
8c1676
     if (file == NULL)
8c1676
         return errno;
8c1676
     pid = (unsigned long) getpid();
8c1676
diff --git a/src/lib/kadm5/logger.c b/src/lib/kadm5/logger.c
fab64b
index ce79fabf7..c53a5743f 100644
8c1676
--- a/src/lib/kadm5/logger.c
8c1676
+++ b/src/lib/kadm5/logger.c
fab64b
@@ -414,7 +414,7 @@ krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do
8c1676
                      */
fab64b
                     append = (cp[4] == ':') ? O_APPEND : 0;
fab64b
                     if (append || cp[4] == '=') {
fab64b
-                        fd = open(&cp[5], O_CREAT | O_WRONLY | append,
fab64b
+                        fd = THREEPARAMOPEN(&cp[5], O_CREAT | O_WRONLY | append,
fab64b
                                   S_IRUSR | S_IWUSR | S_IRGRP);
fab64b
                         if (fd != -1)
fab64b
                             f = fdopen(fd, append ? "a" : "w");
fab64b
@@ -918,7 +918,7 @@ krb5_klog_reopen(krb5_context kcontext)
8c1676
              * In case the old logfile did not get moved out of the
8c1676
              * way, open for append to prevent squashing the old logs.
8c1676
              */
8c1676
-            f = fopen(log_control.log_entries[lindex].lfu_fname, "a+");
8c1676
+            f = WRITABLEFOPEN(log_control.log_entries[lindex].lfu_fname, "a+");
8c1676
             if (f) {
8c1676
                 set_cloexec_file(f);
8c1676
                 log_control.log_entries[lindex].lfu_filep = f;
8c1676
diff --git a/src/lib/kdb/kdb_log.c b/src/lib/kdb/kdb_log.c
fab64b
index 766d3002a..6466417b7 100644
8c1676
--- a/src/lib/kdb/kdb_log.c
8c1676
+++ b/src/lib/kdb/kdb_log.c
fab64b
@@ -476,7 +476,7 @@ ulog_map(krb5_context context, const char *logname, uint32_t ulogentries)
8c1676
     int ulogfd = -1;
8c1676
 
8c1676
     if (stat(logname, &st) == -1) {
8c1676
-        ulogfd = open(logname, O_RDWR | O_CREAT, 0600);
8c1676
+        ulogfd = THREEPARAMOPEN(logname, O_RDWR | O_CREAT, 0600);
8c1676
         if (ulogfd == -1)
8c1676
             return errno;
8c1676
 
8c1676
diff --git a/src/lib/krb5/ccache/cc_dir.c b/src/lib/krb5/ccache/cc_dir.c
fab64b
index bba64e516..73f0fe62d 100644
8c1676
--- a/src/lib/krb5/ccache/cc_dir.c
8c1676
+++ b/src/lib/krb5/ccache/cc_dir.c
8c1676
@@ -183,10 +183,19 @@ write_primary_file(const char *primary_path, const char *contents)
8c1676
     char *newpath = NULL;
8c1676
     FILE *fp = NULL;
8c1676
     int fd = -1, status;
8c1676
+#ifdef USE_SELINUX
8c1676
+    void *selabel;
8c1676
+#endif
8c1676
 
8c1676
     if (asprintf(&newpath, "%s.XXXXXX", primary_path) < 0)
8c1676
         return ENOMEM;
8c1676
+#ifdef USE_SELINUX
8c1676
+    selabel = krb5int_push_fscreatecon_for(primary_path);
8c1676
+#endif
8c1676
     fd = mkstemp(newpath);
8c1676
+#ifdef USE_SELINUX
8c1676
+    krb5int_pop_fscreatecon(selabel);
8c1676
+#endif
8c1676
     if (fd < 0)
8c1676
         goto cleanup;
8c1676
 #ifdef HAVE_CHMOD
8c1676
@@ -221,10 +230,23 @@ static krb5_error_code
8c1676
 verify_dir(krb5_context context, const char *dirname)
8c1676
 {
8c1676
     struct stat st;
8c1676
+    int status;
8c1676
+#ifdef USE_SELINUX
8c1676
+    void *selabel;
8c1676
+#endif
8c1676
 
8c1676
     if (stat(dirname, &st) < 0) {
8c1676
-        if (errno == ENOENT && mkdir(dirname, S_IRWXU) == 0)
8c1676
-            return 0;
8c1676
+        if (errno == ENOENT) {
8c1676
+#ifdef USE_SELINUX
8c1676
+            selabel = krb5int_push_fscreatecon_for(dirname);
8c1676
+#endif
8c1676
+            status = mkdir(dirname, S_IRWXU);
8c1676
+#ifdef USE_SELINUX
8c1676
+            krb5int_pop_fscreatecon(selabel);
8c1676
+#endif
8c1676
+            if (status == 0)
8c1676
+                return 0;
8c1676
+        }
8c1676
         k5_setmsg(context, KRB5_FCC_NOFILE,
8c1676
                   _("Credential cache directory %s does not exist"),
8c1676
                   dirname);
8c1676
diff --git a/src/lib/krb5/keytab/kt_file.c b/src/lib/krb5/keytab/kt_file.c
fab64b
index 6a42f267d..674d88bab 100644
8c1676
--- a/src/lib/krb5/keytab/kt_file.c
8c1676
+++ b/src/lib/krb5/keytab/kt_file.c
fab64b
@@ -1022,14 +1022,14 @@ krb5_ktfileint_open(krb5_context context, krb5_keytab id, int mode)
8c1676
 
8c1676
     KTCHECKLOCK(id);
8c1676
     errno = 0;
8c1676
-    KTFILEP(id) = fopen(KTFILENAME(id),
8c1676
+    KTFILEP(id) = WRITABLEFOPEN(KTFILENAME(id),
fab64b
                         (mode == KRB5_LOCKMODE_EXCLUSIVE) ? "rb+" : "rb");
8c1676
     if (!KTFILEP(id)) {
fab64b
         if ((mode == KRB5_LOCKMODE_EXCLUSIVE) && (errno == ENOENT)) {
8c1676
             /* try making it first time around */
8c1676
             k5_create_secure_file(context, KTFILENAME(id));
8c1676
             errno = 0;
fab64b
-            KTFILEP(id) = fopen(KTFILENAME(id), "rb+");
fab64b
+            KTFILEP(id) = WRITABLEFOPEN(KTFILENAME(id), "rb+");
8c1676
             if (!KTFILEP(id))
8c1676
                 goto report_errno;
8c1676
             writevno = 1;
8c1676
diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c
fab64b
index 83c8d4db8..a19246128 100644
8c1676
--- a/src/lib/krb5/os/trace.c
8c1676
+++ b/src/lib/krb5/os/trace.c
8c1676
@@ -397,7 +397,7 @@ krb5_set_trace_filename(krb5_context context, const char *filename)
8c1676
     fd = malloc(sizeof(*fd));
8c1676
     if (fd == NULL)
8c1676
         return ENOMEM;
8c1676
-    *fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, 0600);
8c1676
+    *fd = THREEPARAMOPEN(filename, O_WRONLY|O_CREAT|O_APPEND, 0600);
8c1676
     if (*fd == -1) {
8c1676
         free(fd);
8c1676
         return errno;
8c1676
diff --git a/src/lib/krb5/rcache/rc_dfl.c b/src/lib/krb5/rcache/rc_dfl.c
fab64b
index c4d2c744d..c0f12ed9d 100644
8c1676
--- a/src/lib/krb5/rcache/rc_dfl.c
8c1676
+++ b/src/lib/krb5/rcache/rc_dfl.c
8c1676
@@ -794,6 +794,9 @@ krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id)
8c1676
     krb5_error_code retval = 0;
8c1676
     krb5_rcache tmp;
8c1676
     krb5_deltat lifespan = t->lifespan;  /* save original lifespan */
8c1676
+#ifdef USE_SELINUX
8c1676
+    void *selabel;
8c1676
+#endif
8c1676
 
8c1676
     if (! t->recovering) {
8c1676
         name = t->name;
8c1676
@@ -815,7 +818,17 @@ krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id)
8c1676
     retval = krb5_rc_resolve(context, tmp, 0);
8c1676
     if (retval)
8c1676
         goto cleanup;
8c1676
+#ifdef USE_SELINUX
8c1676
+    if (t->d.fn != NULL)
8c1676
+        selabel = krb5int_push_fscreatecon_for(t->d.fn);
8c1676
+    else
8c1676
+        selabel = NULL;
8c1676
+#endif
8c1676
     retval = krb5_rc_initialize(context, tmp, lifespan);
8c1676
+#ifdef USE_SELINUX
8c1676
+    if (selabel != NULL)
8c1676
+        krb5int_pop_fscreatecon(selabel);
8c1676
+#endif
8c1676
     if (retval)
8c1676
         goto cleanup;
8c1676
     for (q = t->a; q; q = q->na) {
8c1676
diff --git a/src/plugins/kdb/db2/adb_openclose.c b/src/plugins/kdb/db2/adb_openclose.c
fab64b
index 7db30a33b..2b9d01921 100644
8c1676
--- a/src/plugins/kdb/db2/adb_openclose.c
8c1676
+++ b/src/plugins/kdb/db2/adb_openclose.c
fab64b
@@ -152,7 +152,7 @@ osa_adb_init_db(osa_adb_db_t *dbp, char *filename, char *lockfilename,
fab64b
          * needs be open read/write so that write locking can work with
8c1676
          * POSIX systems
8c1676
          */
8c1676
-        if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r+")) == NULL) {
8c1676
+        if ((lockp->lockinfo.lockfile = WRITABLEFOPEN(lockfilename, "r+")) == NULL) {
8c1676
             /*
8c1676
              * maybe someone took away write permission so we could only
8c1676
              * get shared locks?
8c1676
diff --git a/src/plugins/kdb/db2/kdb_db2.c b/src/plugins/kdb/db2/kdb_db2.c
fab64b
index 4c4036eb4..d90bdeaba 100644
8c1676
--- a/src/plugins/kdb/db2/kdb_db2.c
8c1676
+++ b/src/plugins/kdb/db2/kdb_db2.c
fab64b
@@ -694,8 +694,8 @@ ctx_create_db(krb5_context context, krb5_db2_context *dbc)
8c1676
     if (retval)
8c1676
         return retval;
8c1676
 
8c1676
-    dbc->db_lf_file = open(dbc->db_lf_name, O_CREAT | O_RDWR | O_TRUNC,
8c1676
-                           0600);
8c1676
+    dbc->db_lf_file = THREEPARAMOPEN(dbc->db_lf_name,
8c1676
+                                     O_CREAT | O_RDWR | O_TRUNC, 0600);
8c1676
     if (dbc->db_lf_file < 0) {
8c1676
         retval = errno;
8c1676
         goto cleanup;
8c1676
diff --git a/src/plugins/kdb/db2/libdb2/btree/bt_open.c b/src/plugins/kdb/db2/libdb2/btree/bt_open.c
fab64b
index 2977b17f3..d5809a5a9 100644
8c1676
--- a/src/plugins/kdb/db2/libdb2/btree/bt_open.c
8c1676
+++ b/src/plugins/kdb/db2/libdb2/btree/bt_open.c
8c1676
@@ -60,6 +60,7 @@ static char sccsid[] = "@(#)bt_open.c	8.11 (Berkeley) 11/2/95";
8c1676
 #include <string.h>
8c1676
 #include <unistd.h>
8c1676
 
8c1676
+#include "k5-int.h"
8c1676
 #include "db-int.h"
8c1676
 #include "btree.h"
8c1676
 
8c1676
@@ -203,7 +204,7 @@ __bt_open(fname, flags, mode, openinfo, dflags)
8c1676
 			goto einval;
8c1676
 		}
8c1676
 
8c1676
-		if ((t->bt_fd = open(fname, flags | O_BINARY, mode)) < 0)
8c1676
+		if ((t->bt_fd = THREEPARAMOPEN(fname, flags | O_BINARY, mode)) < 0)
8c1676
 			goto err;
8c1676
 
8c1676
 	} else {
8c1676
diff --git a/src/plugins/kdb/db2/libdb2/hash/hash.c b/src/plugins/kdb/db2/libdb2/hash/hash.c
fab64b
index 76f5d4709..1fa8b8389 100644
8c1676
--- a/src/plugins/kdb/db2/libdb2/hash/hash.c
8c1676
+++ b/src/plugins/kdb/db2/libdb2/hash/hash.c
8c1676
@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)hash.c	8.12 (Berkeley) 11/7/95";
8c1676
 #include <assert.h>
8c1676
 #endif
8c1676
 
8c1676
+#include "k5-int.h"
8c1676
 #include "db-int.h"
8c1676
 #include "hash.h"
8c1676
 #include "page.h"
8c1676
@@ -140,7 +141,7 @@ __kdb2_hash_open(file, flags, mode, info, dflags)
8c1676
 		new_table = 1;
8c1676
 	}
8c1676
 	if (file) {
8c1676
-		if ((hashp->fp = open(file, flags|O_BINARY, mode)) == -1)
8c1676
+		if ((hashp->fp = THREEPARAMOPEN(file, flags|O_BINARY, mode)) == -1)
8c1676
 			RETURN_ERROR(errno, error0);
8c1676
 		(void)fcntl(hashp->fp, F_SETFD, 1);
8c1676
 	}
8c1676
diff --git a/src/plugins/kdb/db2/libdb2/recno/rec_open.c b/src/plugins/kdb/db2/libdb2/recno/rec_open.c
fab64b
index d8b26e701..b0daa7c02 100644
8c1676
--- a/src/plugins/kdb/db2/libdb2/recno/rec_open.c
8c1676
+++ b/src/plugins/kdb/db2/libdb2/recno/rec_open.c
8c1676
@@ -51,6 +51,7 @@ static char sccsid[] = "@(#)rec_open.c	8.12 (Berkeley) 11/18/94";
8c1676
 #include <stdio.h>
8c1676
 #include <unistd.h>
8c1676
 
8c1676
+#include "k5-int.h"
8c1676
 #include "db-int.h"
8c1676
 #include "recno.h"
8c1676
 
8c1676
@@ -68,7 +69,8 @@ __rec_open(fname, flags, mode, openinfo, dflags)
8c1676
 	int rfd = -1, sverrno;
8c1676
 
8c1676
 	/* Open the user's file -- if this fails, we're done. */
8c1676
-	if (fname != NULL && (rfd = open(fname, flags | O_BINARY, mode)) < 0)
8c1676
+	if (fname != NULL &&
8c1676
+            (rfd = THREEPARAMOPEN(fname, flags | O_BINARY, mode)) < 0)
8c1676
 		return (NULL);
8c1676
 
8c1676
 	if (fname != NULL && fcntl(rfd, F_SETFD, 1) == -1) {
8c1676
diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
fab64b
index 022156a5e..3d6994c67 100644
8c1676
--- a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
8c1676
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
fab64b
@@ -203,7 +203,7 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
8c1676
 
8c1676
     /* set password in the file */
8c1676
     old_mode = umask(0177);
8c1676
-    pfile = fopen(file_name, "a+");
8c1676
+    pfile = WRITABLEFOPEN(file_name, "a+");
8c1676
     if (pfile == NULL) {
8c1676
         com_err(me, errno, _("Failed to open file %s: %s"), file_name,
8c1676
                 strerror (errno));
fab64b
@@ -244,6 +244,9 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
8c1676
          * Delete the existing entry and add the new entry
8c1676
          */
8c1676
         FILE *newfile;
8c1676
+#ifdef USE_SELINUX
8c1676
+        void *selabel;
8c1676
+#endif
8c1676
 
8c1676
         mode_t omask;
8c1676
 
fab64b
@@ -255,7 +258,13 @@ kdb5_ldap_stash_service_password(int argc, char **argv)
8c1676
         }
8c1676
 
8c1676
         omask = umask(077);
8c1676
+#ifdef USE_SELINUX
8c1676
+        selabel = krb5int_push_fscreatecon_for(file_name);
8c1676
+#endif
8c1676
         newfile = fopen(tmp_file, "w");
8c1676
+#ifdef USE_SELINUX
8c1676
+        krb5int_pop_fscreatecon(selabel);
8c1676
+#endif
8c1676
         umask (omask);
8c1676
         if (newfile == NULL) {
8c1676
             com_err(me, errno, _("Error creating file %s"), tmp_file);
8c1676
diff --git a/src/slave/kpropd.c b/src/slave/kpropd.c
fab64b
index 056c31a42..b78c3d9e5 100644
8c1676
--- a/src/slave/kpropd.c
8c1676
+++ b/src/slave/kpropd.c
8c1676
@@ -464,6 +464,9 @@ doit(int fd)
8c1676
     krb5_enctype etype;
8c1676
     int database_fd;
8c1676
     char host[INET6_ADDRSTRLEN + 1];
8c1676
+#ifdef USE_SELINUX
8c1676
+    void *selabel;
8c1676
+#endif
8c1676
 
8c1676
     signal_wrapper(SIGALRM, alarm_handler);
8c1676
     alarm(params.iprop_resync_timeout);
8c1676
@@ -520,9 +523,15 @@ doit(int fd)
8c1676
         free(name);
8c1676
         exit(1);
8c1676
     }
8c1676
+#ifdef USE_SELINUX
8c1676
+    selabel = krb5int_push_fscreatecon_for(file);
8c1676
+#endif
8c1676
     omask = umask(077);
8c1676
     lock_fd = open(temp_file_name, O_RDWR | O_CREAT, 0600);
8c1676
     (void)umask(omask);
8c1676
+#ifdef USE_SELINUX
8c1676
+    krb5int_pop_fscreatecon(selabel);
8c1676
+#endif
8c1676
     retval = krb5_lock_file(kpropd_context, lock_fd,
8c1676
                             KRB5_LOCKMODE_EXCLUSIVE | KRB5_LOCKMODE_DONTBLOCK);
8c1676
     if (retval) {
8c1676
diff --git a/src/util/profile/prof_file.c b/src/util/profile/prof_file.c
fab64b
index 907c119bb..0f5462aea 100644
8c1676
--- a/src/util/profile/prof_file.c
8c1676
+++ b/src/util/profile/prof_file.c
8c1676
@@ -33,6 +33,7 @@
8c1676
 #endif
8c1676
 
8c1676
 #include "k5-platform.h"
8c1676
+#include "k5-label.h"
8c1676
 
8c1676
 struct global_shared_profile_data {
8c1676
     /* This is the head of the global list of shared trees */
8c1676
@@ -423,7 +424,7 @@ static errcode_t write_data_to_file(prf_data_t data, const char *outfile,
8c1676
 
8c1676
     errno = 0;
8c1676
 
8c1676
-    f = fopen(new_file, "w");
8c1676
+    f = WRITABLEFOPEN(new_file, "w");
8c1676
     if (!f) {
8c1676
         retval = errno;
8c1676
         if (retval == 0)
8c1676
diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in
fab64b
index 6239e4176..17bcd2a67 100644
8c1676
--- a/src/util/support/Makefile.in
8c1676
+++ b/src/util/support/Makefile.in
fab64b
@@ -69,6 +69,7 @@ IPC_SYMS= \
8c1676
 
8c1676
 STLIBOBJS= \
8c1676
 	threads.o \
8c1676
+	selinux.o \
8c1676
 	init-addrinfo.o \
8c1676
 	plugins.o \
8c1676
 	errors.o \
fab64b
@@ -148,7 +149,7 @@ SRCS=\
8c1676
 
8c1676
 SHLIB_EXPDEPS =
8c1676
 # Add -lm if dumping thread stats, for sqrt.
8c1676
-SHLIB_EXPLIBS= $(LIBS) $(DL_LIB)
8c1676
+SHLIB_EXPLIBS= $(LIBS) $(SELINUX_LIBS) $(DL_LIB)
8c1676
 
8c1676
 DEPLIBS=
8c1676
 
8c1676
diff --git a/src/util/support/selinux.c b/src/util/support/selinux.c
8c1676
new file mode 100644
fab64b
index 000000000..230263421
8c1676
--- /dev/null
8c1676
+++ b/src/util/support/selinux.c
fab64b
@@ -0,0 +1,406 @@
8c1676
+/*
8c1676
+ * Copyright 2007,2008,2009,2011,2012,2013,2016 Red Hat, Inc.  All Rights Reserved.
8c1676
+ *
8c1676
+ * Redistribution and use in source and binary forms, with or without
8c1676
+ * modification, are permitted provided that the following conditions are met:
8c1676
+ *
8c1676
+ *  Redistributions of source code must retain the above copyright notice, this
8c1676
+ *  list of conditions and the following disclaimer.
8c1676
+ *
8c1676
+ *  Redistributions in binary form must reproduce the above copyright notice,
8c1676
+ *  this list of conditions and the following disclaimer in the documentation
8c1676
+ *  and/or other materials provided with the distribution.
8c1676
+ *
8c1676
+ *  Neither the name of Red Hat, Inc. nor the names of its contributors may be
8c1676
+ *  used to endorse or promote products derived from this software without
8c1676
+ *  specific prior written permission.
8c1676
+ *
8c1676
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
8c1676
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8c1676
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8c1676
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
8c1676
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
8c1676
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
8c1676
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
8c1676
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
8c1676
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
8c1676
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
8c1676
+ * POSSIBILITY OF SUCH DAMAGE.
8c1676
+ *
8c1676
+ * File-opening wrappers for creating correctly-labeled files.  So far, we can
8c1676
+ * assume that this is Linux-specific, so we make many simplifying assumptions.
8c1676
+ */
8c1676
+
8c1676
+#include "../../include/autoconf.h"
8c1676
+
8c1676
+#ifdef USE_SELINUX
8c1676
+
8c1676
+#include <k5-label.h>
8c1676
+#include <k5-platform.h>
8c1676
+
8c1676
+#include <sys/types.h>
8c1676
+#include <sys/stat.h>
8c1676
+
8c1676
+#include <errno.h>
8c1676
+#include <fcntl.h>
8c1676
+#include <limits.h>
8c1676
+#include <pthread.h>
8c1676
+#include <stdarg.h>
8c1676
+#include <stdio.h>
8c1676
+#include <stdlib.h>
8c1676
+#include <string.h>
8c1676
+#include <unistd.h>
8c1676
+
8c1676
+#include <selinux/selinux.h>
8c1676
+#include <selinux/context.h>
8c1676
+#include <selinux/label.h>
8c1676
+
8c1676
+/* #define DEBUG 1 */
8c1676
+static void
8c1676
+debug_log(const char *fmt, ...)
8c1676
+{
8c1676
+#ifdef DEBUG
8c1676
+    va_list ap;
8c1676
+    va_start(ap, str);
8c1676
+    if (isatty(fileno(stderr))) {
8c1676
+        vfprintf(stderr, fmt, ap);
8c1676
+    }
8c1676
+    va_end(ap);
8c1676
+#endif
8c1676
+
8c1676
+    return;
8c1676
+}
8c1676
+
8c1676
+/* Mutex used to serialize use of the process-global file creation context. */
8c1676
+k5_mutex_t labeled_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
8c1676
+
8c1676
+/* Make sure we finish initializing that mutex before attempting to use it. */
8c1676
+k5_once_t labeled_once = K5_ONCE_INIT;
8c1676
+static void
8c1676
+label_mutex_init(void)
8c1676
+{
8c1676
+    k5_mutex_finish_init(&labeled_mutex);
8c1676
+}
8c1676
+
8c1676
+static struct selabel_handle *selabel_ctx;
8c1676
+static time_t selabel_last_changed;
8c1676
+
8c1676
+MAKE_FINI_FUNCTION(cleanup_fscreatecon);
8c1676
+
8c1676
+static void
8c1676
+cleanup_fscreatecon(void)
8c1676
+{
8c1676
+    if (selabel_ctx != NULL) {
8c1676
+        selabel_close(selabel_ctx);
8c1676
+        selabel_ctx = NULL;
8c1676
+    }
8c1676
+}
8c1676
+
8c1676
+static security_context_t
8c1676
+push_fscreatecon(const char *pathname, mode_t mode)
8c1676
+{
8c1676
+    security_context_t previous, configuredsc, currentsc, derivedsc;
8c1676
+    context_t current, derived;
8c1676
+    const char *fullpath, *currentuser;
8c1676
+    char *genpath;
8c1676
+
8c1676
+    previous = configuredsc = currentsc = derivedsc = NULL;
8c1676
+    current = derived = NULL;
8c1676
+    genpath = NULL;
8c1676
+
8c1676
+    fullpath = pathname;
8c1676
+
8c1676
+    if (!is_selinux_enabled()) {
8c1676
+        goto fail;
8c1676
+    }
8c1676
+
8c1676
+    if (getfscreatecon(&previous) != 0) {
8c1676
+        goto fail;
8c1676
+    }
8c1676
+
8c1676
+    /* Canonicalize pathname */
8c1676
+    if (pathname[0] != '/') {
8c1676
+        char *wd;
8c1676
+        size_t len;
8c1676
+        len = 0;
8c1676
+
8c1676
+        wd = getcwd(NULL, len);
8c1676
+        if (wd == NULL) {
8c1676
+            goto fail;
8c1676
+        }
8c1676
+
8c1676
+        len = strlen(wd) + 1 + strlen(pathname) + 1;
8c1676
+        genpath = malloc(len);
8c1676
+        if (genpath == NULL) {
8c1676
+            free(wd);
8c1676
+            goto fail;
8c1676
+        }
8c1676
+
8c1676
+        sprintf(genpath, "%s/%s", wd, pathname);
8c1676
+        free(wd);
8c1676
+        fullpath = genpath;
8c1676
+    }
8c1676
+
8c1676
+    debug_log("Looking up context for \"%s\"(%05o).\n", fullpath, mode);
8c1676
+
8c1676
+    /* Check whether context file has changed under us */
8c1676
+    if (selabel_ctx != NULL || selabel_last_changed == 0) {
8c1676
+        const char *cpath;
8c1676
+        struct stat st;
8c1676
+        int i = -1;
8c1676
+
8c1676
+        cpath = selinux_file_context_path();
8c1676
+        if (cpath == NULL || (i = stat(cpath, &st)) != 0 ||
8c1676
+            st.st_mtime != selabel_last_changed) {
8c1676
+            cleanup_fscreatecon();
8c1676
+
8c1676
+            selabel_last_changed = i ? time(NULL) : st.st_mtime;
8c1676
+        }
8c1676
+    }
8c1676
+
8c1676
+    if (selabel_ctx == NULL) {
8c1676
+        selabel_ctx = selabel_open(SELABEL_CTX_FILE, NULL, 0);
8c1676
+    }
8c1676
+
8c1676
+    if (selabel_ctx != NULL &&
8c1676
+        selabel_lookup(selabel_ctx, &configuredsc, fullpath, mode) != 0) {
8c1676
+        goto fail;
8c1676
+    }
8c1676
+
8c1676
+    if (genpath != NULL) {
8c1676
+        free(genpath);
8c1676
+        genpath = NULL;
8c1676
+    }
8c1676
+
8c1676
+    if (configuredsc == NULL) {
8c1676
+        goto fail;
8c1676
+    }
8c1676
+
8c1676
+    getcon(&currentsc);
8c1676
+
8c1676
+    /* AAAAAAAA */
8c1676
+    if (currentsc != NULL) {
8c1676
+        derived = context_new(configuredsc);
8c1676
+
8c1676
+        if (derived != NULL) {
8c1676
+            current = context_new(currentsc);
8c1676
+
8c1676
+            if (current != NULL) {
8c1676
+                currentuser = context_user_get(current);
8c1676
+
8c1676
+                if (currentuser != NULL) {
8c1676
+                    if (context_user_set(derived,
8c1676
+                                         currentuser) == 0) {
8c1676
+                        derivedsc = context_str(derived);
8c1676
+
8c1676
+                        if (derivedsc != NULL) {
8c1676
+                            freecon(configuredsc);
8c1676
+                            configuredsc = strdup(derivedsc);
8c1676
+                        }
8c1676
+                    }
8c1676
+                }
8c1676
+
8c1676
+                context_free(current);
8c1676
+            }
8c1676
+
8c1676
+            context_free(derived);
8c1676
+        }
8c1676
+
8c1676
+        freecon(currentsc);
8c1676
+    }
8c1676
+
8c1676
+    debug_log("Setting file creation context to \"%s\".\n", configuredsc);
8c1676
+    if (setfscreatecon(configuredsc) != 0) {
8c1676
+        debug_log("Unable to determine current context.\n");
8c1676
+        goto fail;
8c1676
+    }
8c1676
+
8c1676
+    freecon(configuredsc);
8c1676
+    return previous;
8c1676
+
8c1676
+fail:
8c1676
+    if (previous != NULL) {
8c1676
+        freecon(previous);
8c1676
+    }
8c1676
+    if (genpath != NULL) {
8c1676
+        free(genpath);
8c1676
+    }
8c1676
+    if (configuredsc != NULL) {
8c1676
+        freecon(configuredsc);
8c1676
+    }
8c1676
+
8c1676
+    cleanup_fscreatecon();
8c1676
+    return NULL;
8c1676
+}
8c1676
+
8c1676
+static void
8c1676
+pop_fscreatecon(security_context_t previous)
8c1676
+{
8c1676
+    if (!is_selinux_enabled()) {
8c1676
+        return;
8c1676
+    }
8c1676
+
8c1676
+    if (previous != NULL) {
fab64b
+        debug_log("Resetting file creation context to \"%s\".\n", previous);
8c1676
+    } else {
8c1676
+        debug_log("Resetting file creation context to default.\n");
8c1676
+    }
8c1676
+
8c1676
+    /* NULL resets to default */
8c1676
+    setfscreatecon(previous);
8c1676
+
8c1676
+    if (previous != NULL) {
8c1676
+        freecon(previous);
8c1676
+    }
8c1676
+
8c1676
+    /* Need to clean this up here otherwise it leaks */
8c1676
+    cleanup_fscreatecon();
8c1676
+}
8c1676
+
8c1676
+void *
8c1676
+krb5int_push_fscreatecon_for(const char *pathname)
8c1676
+{
8c1676
+    struct stat st;
8c1676
+    void *retval;
8c1676
+
8c1676
+    k5_once(&labeled_once, label_mutex_init);
8c1676
+    k5_mutex_lock(&labeled_mutex);
8c1676
+
8c1676
+    if (stat(pathname, &st) != 0) {
8c1676
+        st.st_mode = S_IRUSR | S_IWUSR;
8c1676
+    }
8c1676
+
8c1676
+    retval = push_fscreatecon(pathname, st.st_mode);
8c1676
+    return retval ? retval : (void *) -1;
8c1676
+}
8c1676
+
8c1676
+void
8c1676
+krb5int_pop_fscreatecon(void *con)
8c1676
+{
8c1676
+    if (con != NULL) {
8c1676
+        pop_fscreatecon((con == (void *) -1) ? NULL : con);
8c1676
+        k5_mutex_unlock(&labeled_mutex);
8c1676
+    }
8c1676
+}
8c1676
+
8c1676
+FILE *
8c1676
+krb5int_labeled_fopen(const char *path, const char *mode)
8c1676
+{
8c1676
+    FILE *fp;
8c1676
+    int errno_save;
8c1676
+    security_context_t ctx;
8c1676
+
8c1676
+    if ((strcmp(mode, "r") == 0) ||
8c1676
+        (strcmp(mode, "rb") == 0)) {
8c1676
+        return fopen(path, mode);
8c1676
+    }
8c1676
+
8c1676
+    k5_once(&labeled_once, label_mutex_init);
8c1676
+    k5_mutex_lock(&labeled_mutex);
8c1676
+    ctx = push_fscreatecon(path, 0);
8c1676
+
8c1676
+    fp = fopen(path, mode);
8c1676
+    errno_save = errno;
8c1676
+
8c1676
+    pop_fscreatecon(ctx);
8c1676
+    k5_mutex_unlock(&labeled_mutex);
8c1676
+
8c1676
+    errno = errno_save;
8c1676
+    return fp;
8c1676
+}
8c1676
+
8c1676
+int
8c1676
+krb5int_labeled_creat(const char *path, mode_t mode)
8c1676
+{
8c1676
+    int fd;
8c1676
+    int errno_save;
8c1676
+    security_context_t ctx;
8c1676
+
8c1676
+    k5_once(&labeled_once, label_mutex_init);
8c1676
+    k5_mutex_lock(&labeled_mutex);
8c1676
+    ctx = push_fscreatecon(path, 0);
8c1676
+
8c1676
+    fd = creat(path, mode);
8c1676
+    errno_save = errno;
8c1676
+
8c1676
+    pop_fscreatecon(ctx);
8c1676
+    k5_mutex_unlock(&labeled_mutex);
8c1676
+
8c1676
+    errno = errno_save;
8c1676
+    return fd;
8c1676
+}
8c1676
+
8c1676
+int
8c1676
+krb5int_labeled_mknod(const char *path, mode_t mode, dev_t dev)
8c1676
+{
8c1676
+    int ret;
8c1676
+    int errno_save;
8c1676
+    security_context_t ctx;
8c1676
+
8c1676
+    k5_once(&labeled_once, label_mutex_init);
8c1676
+    k5_mutex_lock(&labeled_mutex);
8c1676
+    ctx = push_fscreatecon(path, mode);
8c1676
+
8c1676
+    ret = mknod(path, mode, dev);
8c1676
+    errno_save = errno;
8c1676
+
8c1676
+    pop_fscreatecon(ctx);
8c1676
+    k5_mutex_unlock(&labeled_mutex);
8c1676
+
8c1676
+    errno = errno_save;
8c1676
+    return ret;
8c1676
+}
8c1676
+
8c1676
+int
8c1676
+krb5int_labeled_mkdir(const char *path, mode_t mode)
8c1676
+{
8c1676
+    int ret;
8c1676
+    int errno_save;
8c1676
+    security_context_t ctx;
8c1676
+
8c1676
+    k5_once(&labeled_once, label_mutex_init);
8c1676
+    k5_mutex_lock(&labeled_mutex);
8c1676
+    ctx = push_fscreatecon(path, S_IFDIR);
8c1676
+
8c1676
+    ret = mkdir(path, mode);
8c1676
+    errno_save = errno;
8c1676
+
8c1676
+    pop_fscreatecon(ctx);
8c1676
+    k5_mutex_unlock(&labeled_mutex);
8c1676
+
8c1676
+    errno = errno_save;
8c1676
+    return ret;
8c1676
+}
8c1676
+
8c1676
+int
8c1676
+krb5int_labeled_open(const char *path, int flags, ...)
8c1676
+{
8c1676
+    int fd;
8c1676
+    int errno_save;
8c1676
+    security_context_t ctx;
8c1676
+    mode_t mode;
8c1676
+    va_list ap;
8c1676
+
8c1676
+    if ((flags & O_CREAT) == 0) {
8c1676
+        return open(path, flags);
8c1676
+    }
8c1676
+
8c1676
+    k5_once(&labeled_once, label_mutex_init);
8c1676
+    k5_mutex_lock(&labeled_mutex);
8c1676
+    ctx = push_fscreatecon(path, 0);
8c1676
+
8c1676
+    va_start(ap, flags);
8c1676
+    mode = va_arg(ap, mode_t);
8c1676
+    fd = open(path, flags, mode);
8c1676
+    va_end(ap);
8c1676
+
8c1676
+    errno_save = errno;
8c1676
+
8c1676
+    pop_fscreatecon(ctx);
8c1676
+    k5_mutex_unlock(&labeled_mutex);
8c1676
+
8c1676
+    errno = errno_save;
8c1676
+    return fd;
8c1676
+}
8c1676
+
8c1676
+#endif /* USE_SELINUX */