Blame SOURCES/0002-downstream-SELinux-integration.patch

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