Makefile | 4 ++-- pam_mktemp.c | 36 ++++++++++++++++++++++++++---------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 55dd81e..9afcfea 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ RM = rm -f MKDIR = mkdir -p INSTALL = install -c CFLAGS = -Wall -O2 -fPIC -LDFLAGS = -s --shared -Wl,--version-script,$(MAP) +LDFLAGS = --shared -Wl,--version-script,$(MAP) LDLIBS = -lpam # This requires GNU make @@ -23,7 +23,7 @@ endif TITLE = pam_mktemp PAM_SO_SUFFIX = LIBSHARED = $(TITLE).so$(PAM_SO_SUFFIX) -SHLIBMODE = 755 +SHLIBMODE = 644 SECUREDIR = /lib/security DESTDIR = diff --git a/pam_mktemp.c b/pam_mktemp.c index bf95512..7546bc4 100644 --- a/pam_mktemp.c +++ b/pam_mktemp.c @@ -23,6 +23,7 @@ * is built with SELinux support, it creates directories in the proper context. */ #include +#include #endif /* USE_SELINUX */ #ifndef HAVE_APPEND_FL @@ -107,9 +108,9 @@ static int ext2fs_chflags(const char *name, int set, int clear) #endif /* HAVE_APPEND_FL */ #ifdef USE_SELINUX -static int check_scontext(const security_context_t scontext, const char *file) +static int check_scontext(const char *scontext, const char *file) { - security_context_t fscon = NULL; + char *fscon = NULL; int ret; if (getfilecon(file, &fscon) < 0) @@ -146,10 +147,13 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, const char *user; char *userdir = NULL; int usergroups; + int mode; int status; #ifdef USE_SELINUX - security_context_t old_fscreatecon, new_fscreatecon = NULL; + char *old_fscreatecon = NULL; + char *new_fscreatecon = NULL; int fscreatecon_saved = 0, selinux_enabled; + struct selabel_handle *label_handle = NULL; #endif /* USE_SELINUX */ if (geteuid() != 0) @@ -188,8 +192,11 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, * selinux_enabled will be reset to 0, to skip subsequent SELinux * function calls. */ selinux_enabled = is_selinux_enabled() > 0; - if (selinux_enabled && matchpathcon_init_prefix(NULL, PRIVATE_PREFIX)) - selinux_enabled = 0; + if (selinux_enabled) { + label_handle = selabel_open(SELABEL_CTX_FILE, NULL, 0); + if (label_handle == NULL) + selinux_enabled = 0; + } /* Save current file creation context. */ if (selinux_enabled) { @@ -200,15 +207,21 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, } /* Set file creation context before mkdir() call. */ if (selinux_enabled) { - if (matchpathcon(PRIVATE_PREFIX, S_IFDIR, &new_fscreatecon) || + if (selabel_lookup(label_handle, &new_fscreatecon, PRIVATE_PREFIX, S_IFDIR) || setfscreatecon(new_fscreatecon)) selinux_enabled = 0; } #endif /* USE_SELINUX */ + /* Inherit PRIVATE_PREFIX directory permissions from /home. */ + if (stat("/home", &st)) + mode = 0711; + else + mode = (st.st_mode | 0711) & 0755; + /* This directory should be created at system installation or bootup time and * never removed, or there's the obvious DoS possibility here. */ - if (mkdir(PRIVATE_PREFIX, 0711) && errno != EEXIST) + if (mkdir(PRIVATE_PREFIX, mode) && errno != EEXIST) goto out; if (lstat(PRIVATE_PREFIX, &st) || @@ -216,7 +229,9 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, st.st_uid != 0) goto out; - if ((st.st_mode & 0777) != 0711 && chmod(PRIVATE_PREFIX, 0711)) + if ((st.st_mode & 0777) != mode && + chmod(PRIVATE_PREFIX, mode) && + (st.st_mode & 0777 & ~mode) != 0) goto out; #ifdef USE_SELINUX @@ -247,7 +262,7 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, if (selinux_enabled) { freecon(new_fscreatecon); new_fscreatecon = NULL; - if (matchpathcon(userdir, S_IFDIR, &new_fscreatecon) || + if (selabel_lookup(label_handle, &new_fscreatecon, userdir, S_IFDIR) || setfscreatecon(new_fscreatecon)) selinux_enabled = 0; } @@ -293,7 +308,8 @@ out: freecon(old_fscreatecon); } freecon(new_fscreatecon); - matchpathcon_fini(); + if (label_handle) + selabel_close(label_handle); #endif /* USE_SELINUX */ free(userdir);