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