14f0285
From 2af05336edb5a2f86db22ee2937626a219f090f6 Mon Sep 17 00:00:00 2001
14f0285
From: Robbie Harwood <rharwood@redhat.com>
14f0285
Date: Tue, 23 Aug 2016 16:30:53 -0400
32ef372
Subject: [PATCH] krb5-1.13-selinux-label.patch
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.
14f0285
---
14f0285
 src/aclocal.m4                                     |  49 +++
14f0285
 src/build-tools/krb5-config.in                     |   3 +-
14f0285
 src/config/pre.in                                  |   3 +-
14f0285
 src/configure.in                                   |   2 +
14f0285
 src/include/k5-int.h                               |   1 +
14f0285
 src/include/k5-label.h                             |  32 ++
14f0285
 src/include/krb5/krb5.hin                          |   6 +
14f0285
 src/kadmin/dbutil/dump.c                           |  11 +-
14f0285
 src/kdc/main.c                                     |   2 +-
14f0285
 src/lib/kadm5/logger.c                             |   4 +-
14f0285
 src/lib/kdb/kdb_log.c                              |   2 +-
14f0285
 src/lib/krb5/ccache/cc_dir.c                       |  26 +-
14f0285
 src/lib/krb5/keytab/kt_file.c                      |   4 +-
14f0285
 src/lib/krb5/os/trace.c                            |   2 +-
14f0285
 src/lib/krb5/rcache/rc_dfl.c                       |  13 +
14f0285
 src/plugins/kdb/db2/adb_openclose.c                |   2 +-
14f0285
 src/plugins/kdb/db2/kdb_db2.c                      |   4 +-
14f0285
 src/plugins/kdb/db2/libdb2/btree/bt_open.c         |   3 +-
14f0285
 src/plugins/kdb/db2/libdb2/hash/hash.c             |   3 +-
14f0285
 src/plugins/kdb/db2/libdb2/recno/rec_open.c        |   4 +-
14f0285
 .../kdb/ldap/ldap_util/kdb5_ldap_services.c        |  11 +-
14f0285
 src/slave/kpropd.c                                 |   9 +
14f0285
 src/util/gss-kernel-lib/Makefile.in                |   5 +-
14f0285
 src/util/profile/prof_file.c                       |   3 +-
14f0285
 src/util/support/Makefile.in                       |   3 +-
14f0285
 src/util/support/selinux.c                         | 381 +++++++++++++++++++++
14f0285
 26 files changed, 566 insertions(+), 22 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
14f0285
index ce045ab..311f099 100644
14f0285
--- a/src/aclocal.m4
14f0285
+++ b/src/aclocal.m4
14f0285
@@ -87,6 +87,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
14f0285
@@ -1739,3 +1740,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.
a89bdde
+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
a89bdde
+
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
14f0285
index f6184da..c17cb5e 100755
14f0285
--- a/src/build-tools/krb5-config.in
14f0285
+++ b/src/build-tools/krb5-config.in
14f0285
@@ -41,6 +41,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@
14f0285
@@ -255,7 +256,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
14f0285
index b0d9015..63271e7 100644
14f0285
--- a/src/config/pre.in
14f0285
+++ b/src/config/pre.in
14f0285
@@ -174,6 +174,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=
14f0285
@@ -395,7 +396,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)
a89bdde
 # needs fixing if ever used on Mac OS X!
14f0285
diff --git a/src/configure.in b/src/configure.in
14f0285
index 8846ca0..9ec8d84 100644
14f0285
--- a/src/configure.in
14f0285
+++ b/src/configure.in
14f0285
@@ -1329,6 +1329,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
14f0285
index 41c3d1b..6b7b2e3 100644
14f0285
--- a/src/include/k5-int.h
14f0285
+++ b/src/include/k5-int.h
a89bdde
@@ -129,6 +129,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
14f0285
index 0000000..dfaaa84
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
14f0285
index e2c08ae..c93a0f2 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
14f0285
index 253bf3f..9c8c3dc 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
 
14f0285
@@ -194,7 +203,7 @@ prep_ok_file(krb5_context context, char *file_name, int *fd)
a89bdde
         return 0;
a89bdde
     }
a89bdde
 
a89bdde
-    *fd = open(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600);
a89bdde
+    *fd = THREEPARAMOPEN(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600);
a89bdde
     if (*fd == -1) {
a89bdde
         com_err(progname, errno, _("while creating 'ok' file, '%s'"), file_ok);
a89bdde
         exit_status++;
14f0285
diff --git a/src/kdc/main.c b/src/kdc/main.c
14f0285
index 82dfc0e..936f46b 100644
14f0285
--- a/src/kdc/main.c
14f0285
+++ b/src/kdc/main.c
14f0285
@@ -847,7 +847,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();
14f0285
diff --git a/src/lib/kadm5/logger.c b/src/lib/kadm5/logger.c
14f0285
index 19c4355..64f9641 100644
14f0285
--- a/src/lib/kadm5/logger.c
14f0285
+++ b/src/lib/kadm5/logger.c
14f0285
@@ -423,7 +423,7 @@ krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do
a89bdde
                      * Check for append/overwrite, then open the file.
a89bdde
                      */
a89bdde
                     if (cp[4] == ':' || cp[4] == '=') {
a89bdde
-                        f = fopen(&cp[5], (cp[4] == ':') ? "a" : "w");
a89bdde
+                        f = WRITABLEFOPEN(&cp[5], (cp[4] == ':') ? "a" : "w");
a89bdde
                         if (f) {
a89bdde
                             set_cloexec_file(f);
a89bdde
                             log_control.log_entries[i].lfu_filep = f;
14f0285
@@ -959,7 +959,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
14f0285
index 99cda59..523b99a 100644
14f0285
--- a/src/lib/kdb/kdb_log.c
14f0285
+++ b/src/lib/kdb/kdb_log.c
14f0285
@@ -476,7 +476,7 @@ ulog_map(krb5_context context, const char *logname, uint32_t ulogentries)
14f0285
     int ulogfd = -1;
14f0285
 
14f0285
     if (stat(logname, &st) == -1) {
14f0285
-        ulogfd = open(logname, O_RDWR | O_CREAT, 0600);
14f0285
+        ulogfd = THREEPARAMOPEN(logname, O_RDWR | O_CREAT, 0600);
14f0285
         if (ulogfd == -1)
14f0285
             return errno;
14f0285
 
14f0285
diff --git a/src/lib/krb5/ccache/cc_dir.c b/src/lib/krb5/ccache/cc_dir.c
14f0285
index bba64e5..73f0fe6 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
14f0285
index e105a51..ff1fc54 100644
14f0285
--- a/src/lib/krb5/keytab/kt_file.c
14f0285
+++ b/src/lib/krb5/keytab/kt_file.c
14f0285
@@ -1030,7 +1030,7 @@ 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),
a89bdde
                         (mode == KRB5_LOCKMODE_EXCLUSIVE) ?
a89bdde
                         fopen_mode_rbplus : fopen_mode_rb);
a89bdde
     if (!KTFILEP(id)) {
14f0285
@@ -1038,7 +1038,7 @@ krb5_ktfileint_open(krb5_context context, krb5_keytab id, int mode)
a89bdde
             /* try making it first time around */
a89bdde
             k5_create_secure_file(context, KTFILENAME(id));
a89bdde
             errno = 0;
a89bdde
-            KTFILEP(id) = fopen(KTFILENAME(id), fopen_mode_rbplus);
a89bdde
+            KTFILEP(id) = WRITABLEFOPEN(KTFILENAME(id), fopen_mode_rbplus);
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
14f0285
index 83c8d4d..a192461 100644
14f0285
--- a/src/lib/krb5/os/trace.c
14f0285
+++ b/src/lib/krb5/os/trace.c
14f0285
@@ -397,7 +397,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/lib/krb5/rcache/rc_dfl.c b/src/lib/krb5/rcache/rc_dfl.c
14f0285
index 2fb6aa0..c453189 100644
14f0285
--- a/src/lib/krb5/rcache/rc_dfl.c
14f0285
+++ b/src/lib/krb5/rcache/rc_dfl.c
14f0285
@@ -794,6 +794,9 @@ krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id)
14f0285
     krb5_error_code retval = 0;
14f0285
     krb5_rcache tmp;
14f0285
     krb5_deltat lifespan = t->lifespan;  /* save original lifespan */
14f0285
+#ifdef USE_SELINUX
14f0285
+    void *selabel;
14f0285
+#endif
14f0285
 
14f0285
     if (! t->recovering) {
14f0285
         name = t->name;
14f0285
@@ -815,7 +818,17 @@ krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id)
14f0285
     retval = krb5_rc_resolve(context, tmp, 0);
14f0285
     if (retval)
14f0285
         goto cleanup;
14f0285
+#ifdef USE_SELINUX
14f0285
+    if (t->d.fn != NULL)
14f0285
+        selabel = krb5int_push_fscreatecon_for(t->d.fn);
14f0285
+    else
14f0285
+        selabel = NULL;
14f0285
+#endif
14f0285
     retval = krb5_rc_initialize(context, tmp, lifespan);
14f0285
+#ifdef USE_SELINUX
14f0285
+    if (selabel != NULL)
14f0285
+        krb5int_pop_fscreatecon(selabel);
14f0285
+#endif
14f0285
     if (retval)
14f0285
         goto cleanup;
14f0285
     for (q = t->a; q; q = q->na) {
14f0285
diff --git a/src/plugins/kdb/db2/adb_openclose.c b/src/plugins/kdb/db2/adb_openclose.c
14f0285
index 7db30a3..2b9d019 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
14f0285
index e97b841..5d1cd61 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
14f0285
index 2977b17..d5809a5 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
14f0285
index 2a5b4f8..7239d03 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"
14f0285
@@ -140,7 +141,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
14f0285
index d8b26e7..b0daa7c 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
14f0285
index 64d0f91..5d5c0a6 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
14f0285
@@ -178,7 +178,7 @@ done:
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));
14f0285
@@ -219,6 +219,9 @@ done:
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
 
14f0285
@@ -230,7 +233,13 @@ done:
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/slave/kpropd.c b/src/slave/kpropd.c
14f0285
index 1383156..a950924 100644
14f0285
--- a/src/slave/kpropd.c
14f0285
+++ b/src/slave/kpropd.c
14f0285
@@ -464,6 +464,9 @@ doit(int fd)
a89bdde
     krb5_enctype etype;
a89bdde
     int database_fd;
a89bdde
     char host[INET6_ADDRSTRLEN + 1];
a89bdde
+#ifdef USE_SELINUX
a89bdde
+    void *selabel;
a89bdde
+#endif
a89bdde
 
a89bdde
     signal_wrapper(SIGALRM, alarm_handler);
a89bdde
     alarm(params.iprop_resync_timeout);
14f0285
@@ -520,9 +523,15 @@ doit(int fd)
a89bdde
         free(name);
a89bdde
         exit(1);
a89bdde
     }
a89bdde
+#ifdef USE_SELINUX
a89bdde
+    selabel = krb5int_push_fscreatecon_for(file);
a89bdde
+#endif
a89bdde
     omask = umask(077);
a89bdde
     lock_fd = open(temp_file_name, O_RDWR | O_CREAT, 0600);
a89bdde
     (void)umask(omask);
a89bdde
+#ifdef USE_SELINUX
a89bdde
+    krb5int_pop_fscreatecon(selabel);
a89bdde
+#endif
a89bdde
     retval = krb5_lock_file(kpropd_context, lock_fd,
a89bdde
                             KRB5_LOCKMODE_EXCLUSIVE | KRB5_LOCKMODE_DONTBLOCK);
a89bdde
     if (retval) {
14f0285
diff --git a/src/util/gss-kernel-lib/Makefile.in b/src/util/gss-kernel-lib/Makefile.in
14f0285
index f70f3c6..7a2f9cc 100644
14f0285
--- a/src/util/gss-kernel-lib/Makefile.in
14f0285
+++ b/src/util/gss-kernel-lib/Makefile.in
14f0285
@@ -61,6 +61,7 @@ HEADERS= \
14f0285
 	gssapi_err_generic.h \
14f0285
 	k5-int.h \
14f0285
 	k5-int-pkinit.h \
14f0285
+	k5-label.h \
14f0285
 	k5-thread.h \
14f0285
 	k5-platform.h \
14f0285
 	k5-buf.h \
14f0285
@@ -162,10 +163,12 @@ gssapi_generic.h: $(GSS_GENERIC)/gssapi_generic.h
14f0285
 	$(CP) $(GSS_GENERIC)/gssapi_generic.h $@
14f0285
 gssapi_err_generic.h: $(GSS_GENERIC_BUILD)/gssapi_err_generic.h
14f0285
 	$(CP) $(GSS_GENERIC_BUILD)/gssapi_err_generic.h $@
14f0285
-k5-int.h: $(INCLUDE)/k5-int.h
14f0285
+k5-int.h: $(INCLUDE)/k5-int.h k5-label.h
14f0285
 	$(CP) $(INCLUDE)/k5-int.h $@
14f0285
 k5-int-pkinit.h: $(INCLUDE)/k5-int-pkinit.h
14f0285
 	$(CP) $(INCLUDE)/k5-int-pkinit.h $@
14f0285
+k5-label.h: $(INCLUDE)/k5-label.h
14f0285
+	$(CP) $(INCLUDE)/k5-label.h $@
14f0285
 k5-thread.h: $(INCLUDE)/k5-thread.h
14f0285
 	$(CP) $(INCLUDE)/k5-thread.h $@
14f0285
 k5-platform.h: $(INCLUDE)/k5-platform.h
14f0285
diff --git a/src/util/profile/prof_file.c b/src/util/profile/prof_file.c
14f0285
index 907c119..0f5462a 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 */
14f0285
@@ -423,7 +424,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
14f0285
index 5181762..f77acd4 100644
14f0285
--- a/src/util/support/Makefile.in
14f0285
+++ b/src/util/support/Makefile.in
14f0285
@@ -59,6 +59,7 @@ IPC_SYMS= \
a89bdde
 
a89bdde
 STLIBOBJS= \
a89bdde
 	threads.o \
a89bdde
+	selinux.o \
a89bdde
 	init-addrinfo.o \
a89bdde
 	plugins.o \
a89bdde
 	errors.o \
14f0285
@@ -131,7 +132,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
14f0285
index 0000000..ffba6a9
14f0285
--- /dev/null
14f0285
+++ b/src/util/support/selinux.c
a89bdde
@@ -0,0 +1,381 @@
a89bdde
+/*
a89bdde
+ * Copyright 2007,2008,2009,2011,2012,2013 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.
a89bdde
+ * 
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>
a89bdde
+#include <sys/types.h>
a89bdde
+#include <sys/stat.h>
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>
a89bdde
+#include <selinux/selinux.h>
a89bdde
+#include <selinux/context.h>
a89bdde
+#ifdef HAVE_SELINUX_LABEL_H
a89bdde
+#include <selinux/label.h>
a89bdde
+#endif
a89bdde
+
a89bdde
+/* #define DEBUG 1 */
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
+{
a89bdde
+	k5_mutex_finish_init(&labeled_mutex);
a89bdde
+}
a89bdde
+
a89bdde
+#ifdef HAVE_SELINUX_LABEL_H
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
+{
a89bdde
+	if (selabel_ctx != NULL) {
a89bdde
+		selabel_close(selabel_ctx);
a89bdde
+		selabel_ctx = NULL;
a89bdde
+	}
a89bdde
+}
a89bdde
+#endif
a89bdde
+
a89bdde
+static security_context_t
a89bdde
+push_fscreatecon(const char *pathname, mode_t mode)
a89bdde
+{
a89bdde
+	security_context_t previous, configuredsc, currentsc, derivedsc;
a89bdde
+	context_t current, derived;
a89bdde
+	const char *fullpath, *currentuser;
a89bdde
+
a89bdde
+	previous = NULL;
a89bdde
+	if (is_selinux_enabled()) {
a89bdde
+		if (getfscreatecon(&previous) == 0) {
a89bdde
+			char *genpath;
a89bdde
+			genpath = NULL;
a89bdde
+			if (pathname[0] != '/') {
a89bdde
+				char *wd;
a89bdde
+				size_t len;
a89bdde
+				len = 0;
a89bdde
+				wd = getcwd(NULL, len);
a89bdde
+				if (wd == NULL) {
a89bdde
+					if (previous != NULL) {
a89bdde
+						freecon(previous);
a89bdde
+					}
a89bdde
+					return NULL;
a89bdde
+				}
a89bdde
+				len = strlen(wd) + 1 + strlen(pathname) + 1;
a89bdde
+				genpath = malloc(len);
a89bdde
+				if (genpath == NULL) {
a89bdde
+					free(wd);
a89bdde
+					if (previous != NULL) {
a89bdde
+						freecon(previous);
a89bdde
+					}
a89bdde
+					return NULL;
a89bdde
+				}
a89bdde
+				sprintf(genpath, "%s/%s", wd, pathname);
a89bdde
+				free(wd);
a89bdde
+				fullpath = genpath;
a89bdde
+			} else {
a89bdde
+				fullpath = pathname;
a89bdde
+			}
a89bdde
+#ifdef DEBUG
a89bdde
+			if (isatty(fileno(stderr))) {
a89bdde
+				fprintf(stderr, "Looking up context for "
a89bdde
+					"\"%s\"(%05o).\n", fullpath, mode);
a89bdde
+			}
a89bdde
+#endif
a89bdde
+			configuredsc = NULL;
a89bdde
+#ifdef HAVE_SELINUX_LABEL_H
a89bdde
+			if ((selabel_ctx != NULL) ||
a89bdde
+			    (selabel_last_changed == 0)) {
a89bdde
+				const char *cpath;
a89bdde
+				struct stat st;
a89bdde
+				int i = -1;
a89bdde
+				cpath = selinux_file_context_path();
a89bdde
+				if ((cpath == NULL) ||
a89bdde
+				    ((i = stat(cpath, &st)) != 0) ||
a89bdde
+				    (st.st_mtime != selabel_last_changed)) {
a89bdde
+					if (selabel_ctx != NULL) {
a89bdde
+						selabel_close(selabel_ctx);
a89bdde
+						selabel_ctx = NULL;
a89bdde
+					}
a89bdde
+					selabel_last_changed = i ?
a89bdde
+							       time(NULL) :
a89bdde
+							       st.st_mtime;
a89bdde
+				}
a89bdde
+			}
a89bdde
+			if (selabel_ctx == NULL) {
a89bdde
+				selabel_ctx = selabel_open(SELABEL_CTX_FILE,
a89bdde
+							   NULL, 0);
a89bdde
+			}
a89bdde
+			if (selabel_ctx != NULL) {
a89bdde
+				if (selabel_lookup(selabel_ctx, &configuredsc,
a89bdde
+						   fullpath, mode) != 0) {
a89bdde
+					free(genpath);
a89bdde
+					if (previous != NULL) {
a89bdde
+						freecon(previous);
a89bdde
+					}
a89bdde
+					return NULL;
a89bdde
+				}
a89bdde
+			}
a89bdde
+#else
a89bdde
+			if (matchpathcon(fullpath, mode, &configuredsc) != 0) {
a89bdde
+				free(genpath);
a89bdde
+				if (previous != NULL) {
a89bdde
+					freecon(previous);
a89bdde
+				}
a89bdde
+				return NULL;
a89bdde
+			}
a89bdde
+#endif
a89bdde
+			free(genpath);
a89bdde
+			if (configuredsc == NULL) {
a89bdde
+				if (previous != NULL) {
a89bdde
+					freecon(previous);
a89bdde
+				}
a89bdde
+				return NULL;
a89bdde
+			}
a89bdde
+			currentsc = NULL;
a89bdde
+			getcon(&currentsc);
a89bdde
+			if (currentsc != NULL) {
a89bdde
+				derived = context_new(configuredsc);
a89bdde
+				if (derived != NULL) {
a89bdde
+					current = context_new(currentsc);
a89bdde
+					if (current != NULL) {
a89bdde
+						currentuser = context_user_get(current);
a89bdde
+						if (currentuser != NULL) {
a89bdde
+							if (context_user_set(derived,
a89bdde
+									     currentuser) == 0) {
a89bdde
+								derivedsc = context_str(derived);
a89bdde
+								if (derivedsc != NULL) {
a89bdde
+									freecon(configuredsc);
a89bdde
+									configuredsc = strdup(derivedsc);
a89bdde
+								}
a89bdde
+							}
a89bdde
+						}
a89bdde
+						context_free(current);
a89bdde
+					}
a89bdde
+					context_free(derived);
a89bdde
+				}
a89bdde
+				freecon(currentsc);
a89bdde
+			}
a89bdde
+#ifdef DEBUG
a89bdde
+			if (isatty(fileno(stderr))) {
a89bdde
+				fprintf(stderr, "Setting file creation context "
a89bdde
+					"to \"%s\".\n", configuredsc);
a89bdde
+			}
a89bdde
+#endif
a89bdde
+			if (setfscreatecon(configuredsc) != 0) {
a89bdde
+				freecon(configuredsc);
a89bdde
+				if (previous != NULL) {
a89bdde
+					freecon(previous);
a89bdde
+				}
a89bdde
+				return NULL;
a89bdde
+			}
a89bdde
+			freecon(configuredsc);
a89bdde
+#ifdef DEBUG
a89bdde
+		} else {
a89bdde
+			if (isatty(fileno(stderr))) {
a89bdde
+				fprintf(stderr, "Unable to determine "
a89bdde
+					"current context.\n");
a89bdde
+			}
a89bdde
+#endif
a89bdde
+		}
a89bdde
+	}
a89bdde
+	return previous;
a89bdde
+}
a89bdde
+
a89bdde
+static void
a89bdde
+pop_fscreatecon(security_context_t previous)
a89bdde
+{
a89bdde
+	if (is_selinux_enabled()) {
a89bdde
+#ifdef DEBUG
a89bdde
+		if (isatty(fileno(stderr))) {
a89bdde
+			if (previous != NULL) {
a89bdde
+				fprintf(stderr, "Resetting file creation "
a89bdde
+					"context to \"%s\".\n", previous);
a89bdde
+			} else {
a89bdde
+				fprintf(stderr, "Resetting file creation "
a89bdde
+					"context to default.\n");
a89bdde
+			}
a89bdde
+		}
a89bdde
+#endif
a89bdde
+		setfscreatecon(previous);
a89bdde
+		if (previous != NULL) {
a89bdde
+			freecon(previous);
a89bdde
+		}
a89bdde
+	}
a89bdde
+}
a89bdde
+
a89bdde
+void *
a89bdde
+krb5int_push_fscreatecon_for(const char *pathname)
a89bdde
+{
a89bdde
+	struct stat st;
a89bdde
+	void *retval;
a89bdde
+	k5_once(&labeled_once, label_mutex_init);
a89bdde
+	k5_mutex_lock(&labeled_mutex);
a89bdde
+	if (stat(pathname, &st) != 0) {
a89bdde
+		st.st_mode = S_IRUSR | S_IWUSR;
a89bdde
+	}
a89bdde
+	retval = push_fscreatecon(pathname, st.st_mode);
a89bdde
+	return retval ? retval : (void *) -1;
a89bdde
+}
a89bdde
+
a89bdde
+void
a89bdde
+krb5int_pop_fscreatecon(void *con)
a89bdde
+{
a89bdde
+	if (con != NULL) {
a89bdde
+		pop_fscreatecon((con == (void *) -1) ? NULL : con);
a89bdde
+		k5_mutex_unlock(&labeled_mutex);
a89bdde
+	}
a89bdde
+}
a89bdde
+
a89bdde
+FILE *
a89bdde
+krb5int_labeled_fopen(const char *path, const char *mode)
a89bdde
+{
a89bdde
+	FILE *fp;
a89bdde
+	int errno_save;
a89bdde
+	security_context_t ctx;
a89bdde
+
a89bdde
+	if ((strcmp(mode, "r") == 0) ||
a89bdde
+	    (strcmp(mode, "rb") == 0)) {
a89bdde
+		return fopen(path, mode);
a89bdde
+	}
a89bdde
+
a89bdde
+	k5_once(&labeled_once, label_mutex_init);
a89bdde
+	k5_mutex_lock(&labeled_mutex);
a89bdde
+	ctx = push_fscreatecon(path, 0);
a89bdde
+	fp = fopen(path, mode);
a89bdde
+	errno_save = errno;
a89bdde
+	pop_fscreatecon(ctx);
a89bdde
+	k5_mutex_unlock(&labeled_mutex);
a89bdde
+	errno = errno_save;
a89bdde
+	return fp;
a89bdde
+}
a89bdde
+
a89bdde
+int
a89bdde
+krb5int_labeled_creat(const char *path, mode_t mode)
a89bdde
+{
a89bdde
+	int fd;
a89bdde
+	int errno_save;
a89bdde
+	security_context_t ctx;
a89bdde
+
a89bdde
+	k5_once(&labeled_once, label_mutex_init);
a89bdde
+	k5_mutex_lock(&labeled_mutex);
a89bdde
+	ctx = push_fscreatecon(path, 0);
a89bdde
+	fd = creat(path, mode);
a89bdde
+	errno_save = errno;
a89bdde
+	pop_fscreatecon(ctx);
a89bdde
+	k5_mutex_unlock(&labeled_mutex);
a89bdde
+	errno = errno_save;
a89bdde
+	return fd;
a89bdde
+}
a89bdde
+
a89bdde
+int
a89bdde
+krb5int_labeled_mknod(const char *path, mode_t mode, dev_t dev)
a89bdde
+{
a89bdde
+	int ret;
a89bdde
+	int errno_save;
a89bdde
+	security_context_t ctx;
a89bdde
+
a89bdde
+	k5_once(&labeled_once, label_mutex_init);
a89bdde
+	k5_mutex_lock(&labeled_mutex);
a89bdde
+	ctx = push_fscreatecon(path, mode);
a89bdde
+	ret = mknod(path, mode, dev);
a89bdde
+	errno_save = errno;
a89bdde
+	pop_fscreatecon(ctx);
a89bdde
+	k5_mutex_unlock(&labeled_mutex);
a89bdde
+	errno = errno_save;
a89bdde
+	return ret;
a89bdde
+}
a89bdde
+
a89bdde
+int
a89bdde
+krb5int_labeled_mkdir(const char *path, mode_t mode)
a89bdde
+{
a89bdde
+	int ret;
a89bdde
+	int errno_save;
a89bdde
+	security_context_t ctx;
a89bdde
+
a89bdde
+	k5_once(&labeled_once, label_mutex_init);
a89bdde
+	k5_mutex_lock(&labeled_mutex);
a89bdde
+	ctx = push_fscreatecon(path, S_IFDIR);
a89bdde
+	ret = mkdir(path, mode);
a89bdde
+	errno_save = errno;
a89bdde
+	pop_fscreatecon(ctx);
a89bdde
+	k5_mutex_unlock(&labeled_mutex);
a89bdde
+	errno = errno_save;
a89bdde
+	return ret;
a89bdde
+}
a89bdde
+
a89bdde
+int
a89bdde
+krb5int_labeled_open(const char *path, int flags, ...)
a89bdde
+{
a89bdde
+	int fd;
a89bdde
+	int errno_save;
a89bdde
+	security_context_t ctx;
a89bdde
+	mode_t mode;
a89bdde
+	va_list ap;
a89bdde
+
a89bdde
+	if ((flags & O_CREAT) == 0) {
a89bdde
+		return open(path, flags);
a89bdde
+	}
a89bdde
+
a89bdde
+	k5_once(&labeled_once, label_mutex_init);
a89bdde
+	k5_mutex_lock(&labeled_mutex);
a89bdde
+	ctx = push_fscreatecon(path, 0);
a89bdde
+
a89bdde
+	va_start(ap, flags);
a89bdde
+	mode = va_arg(ap, mode_t);
a89bdde
+	fd = open(path, flags, mode);
a89bdde
+	va_end(ap);
a89bdde
+
a89bdde
+	errno_save = errno;
a89bdde
+	pop_fscreatecon(ctx);
a89bdde
+	k5_mutex_unlock(&labeled_mutex);
a89bdde
+	errno = errno_save;
a89bdde
+	return fd;
a89bdde
+}
a89bdde
+
a89bdde
+#endif
14f0285
-- 
14f0285
2.9.3
14f0285