diff --git a/lib/commonio.c b/lib/commonio.c index c5b3d104..3c81c796 100644 --- a/lib/commonio.c +++ b/lib/commonio.c @@ -974,7 +974,7 @@ int commonio_close (struct commonio_db *db) snprintf (buf, sizeof buf, "%s-", db->filename); #ifdef WITH_SELINUX - if (set_selinux_file_context (buf) != 0) { + if (set_selinux_file_context (db->filename, S_IFREG) != 0) { errors++; } #endif @@ -1007,7 +1007,7 @@ int commonio_close (struct commonio_db *db) snprintf (buf, sizeof buf, "%s+", db->filename); #ifdef WITH_SELINUX - if (set_selinux_file_context (buf) != 0) { + if (set_selinux_file_context (db->filename, S_IFREG) != 0) { errors++; } #endif diff --git a/lib/commonio.h b/lib/commonio.h index 64e83073..2bad47a5 100644 --- a/lib/commonio.h +++ b/lib/commonio.h @@ -34,10 +34,6 @@ #ifndef COMMONIO_H #define COMMONIO_H -#ifdef WITH_SELINUX -#include -#endif - #include "defines.h" /* bool */ /* @@ -121,7 +117,7 @@ struct commonio_db { /*@dependent@*/ /*@null@*/FILE *fp; #ifdef WITH_SELINUX - /*@null@*/security_context_t scontext; + /*@null@*/char *scontext; #endif /* * Default permissions and owner for newly created data file. diff --git a/lib/prototypes.h b/lib/prototypes.h index 0c42bcc2..d187660e 100644 --- a/lib/prototypes.h +++ b/lib/prototypes.h @@ -403,7 +403,7 @@ extern /*@observer@*/const char *crypt_make_salt (/*@null@*//*@observer@*/const /* selinux.c */ #ifdef WITH_SELINUX -extern int set_selinux_file_context (const char *dst_name); +extern int set_selinux_file_context (const char *dst_name, mode_t mode); extern int reset_selinux_file_context (void); extern int check_selinux_permit (const char *perm_name); #endif diff --git a/lib/selinux.c b/lib/selinux.c index c60cbed5..28ca5fff 100644 --- a/lib/selinux.c +++ b/lib/selinux.c @@ -35,11 +35,20 @@ #include "defines.h" #include -#include +#include #include "prototypes.h" static bool selinux_checked = false; static bool selinux_enabled; +static /*@null@*/struct selabel_handle *selabel_hnd = NULL; + +static void cleanup(void) +{ + if (selabel_hnd) { + selabel_close(selabel_hnd); + selabel_hnd = NULL; + } +} /* * set_selinux_file_context - Set the security context before any file or @@ -51,10 +60,8 @@ static bool selinux_enabled; * Callers may have to Reset SELinux to create files with default * contexts with reset_selinux_file_context */ -int set_selinux_file_context (const char *dst_name) +int set_selinux_file_context (const char *dst_name, mode_t mode) { - /*@null@*/security_context_t scontext = NULL; - if (!selinux_checked) { selinux_enabled = is_selinux_enabled () > 0; selinux_checked = true; @@ -62,19 +69,34 @@ int set_selinux_file_context (const char *dst_name) if (selinux_enabled) { /* Get the default security context for this file */ - if (matchpathcon (dst_name, 0, &scontext) < 0) { - if (security_getenforce () != 0) { - return 1; + + /*@null@*/char *fcontext_raw = NULL; + int r; + + if (selabel_hnd == NULL) { + selabel_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0); + if (selabel_hnd == NULL) { + return security_getenforce () != 0; } + (void) atexit(cleanup); } + + r = selabel_lookup_raw(selabel_hnd, &fcontext_raw, dst_name, mode); + if (r < 0) { + /* No context specified for the searched path */ + if (errno == ENOENT) { + return 0; + } + + return security_getenforce () != 0; + } + /* Set the security context for the next created file */ - if (setfscreatecon (scontext) < 0) { - if (security_getenforce () != 0) { - freecon (scontext); - return 1; - } + r = setfscreatecon_raw (fcontext_raw); + freecon (fcontext_raw); + if (r < 0) { + return security_getenforce () != 0; } - freecon (scontext); } return 0; } @@ -93,8 +115,8 @@ int reset_selinux_file_context (void) selinux_checked = true; } if (selinux_enabled) { - if (setfscreatecon (NULL) != 0) { - return 1; + if (setfscreatecon_raw (NULL) != 0) { + return security_getenforce () != 0; } } return 0; @@ -175,7 +197,7 @@ skip_syslog: */ int check_selinux_permit (const char *perm_name) { - char *user_context_str; + char *user_context_raw; int r; if (0 == is_selinux_enabled ()) { @@ -184,7 +206,7 @@ int check_selinux_permit (const char *perm_name) selinux_set_callback (SELINUX_CB_LOG, (union selinux_callback) selinux_log_cb); - if (getprevcon (&user_context_str) != 0) { + if (getprevcon_raw (&user_context_raw) != 0) { fprintf (stderr, _("%s: can not get previous SELinux process context: %s\n"), Prog, strerror (errno)); @@ -194,8 +216,8 @@ int check_selinux_permit (const char *perm_name) return (security_getenforce () != 0); } - r = selinux_check_access (user_context_str, user_context_str, "passwd", perm_name, NULL); - freecon (user_context_str); + r = selinux_check_access (user_context_raw, user_context_raw, "passwd", perm_name, NULL); + freecon (user_context_raw); return r; } diff --git a/libmisc/copydir.c b/libmisc/copydir.c index e6aac6ec..1ca98b67 100644 --- a/libmisc/copydir.c +++ b/libmisc/copydir.c @@ -484,7 +484,7 @@ static int copy_dir (const char *src, const char *dst, */ #ifdef WITH_SELINUX - if (set_selinux_file_context (dst) != 0) { + if (set_selinux_file_context (dst, S_IFDIR) != 0) { return -1; } #endif /* WITH_SELINUX */ @@ -605,7 +605,7 @@ static int copy_symlink (const char *src, const char *dst, } #ifdef WITH_SELINUX - if (set_selinux_file_context (dst) != 0) { + if (set_selinux_file_context (dst, S_IFLNK) != 0) { free (oldlink); return -1; } @@ -684,7 +684,7 @@ static int copy_special (const char *src, const char *dst, int err = 0; #ifdef WITH_SELINUX - if (set_selinux_file_context (dst) != 0) { + if (set_selinux_file_context (dst, statp->st_mode & S_IFMT) != 0) { return -1; } #endif /* WITH_SELINUX */ @@ -744,7 +744,7 @@ static int copy_file (const char *src, const char *dst, return -1; } #ifdef WITH_SELINUX - if (set_selinux_file_context (dst) != 0) { + if (set_selinux_file_context (dst, S_IFREG) != 0) { return -1; } #endif /* WITH_SELINUX */ diff --git a/src/useradd.c b/src/useradd.c index a0369cd8..b3fff895 100644 --- a/src/useradd.c +++ b/src/useradd.c @@ -69,6 +69,9 @@ #include "sgroupio.h" #endif #include "shadowio.h" +#ifdef WITH_SELINUX +#include +#endif /* WITH_SELINUX */ #ifdef ENABLE_SUBIDS #include "subordinateio.h" #endif /* ENABLE_SUBIDS */ @@ -2174,7 +2177,7 @@ static void create_home (void) ++bhome; #ifdef WITH_SELINUX - if (set_selinux_file_context (prefix_user_home) != 0) { + if (set_selinux_file_context (prefix_user_home, S_IFDIR) != 0) { fprintf (stderr, _("%s: cannot set SELinux context for home directory %s\n"), Prog, user_home); @@ -2302,7 +2305,7 @@ static void create_mail (void) sprintf (file, "%s/%s", spool, user_name); #ifdef WITH_SELINUX - if (set_selinux_file_context (file) != 0) { + if (set_selinux_file_context (file, S_IFREG) != 0) { fprintf (stderr, _("%s: cannot set SELinux context for mailbox file %s\n"), Prog, file); diff --git a/src/userdel.c b/src/userdel.c index 4248ab80..92bca499 100644 --- a/src/userdel.c +++ b/src/userdel.c @@ -59,6 +59,9 @@ #ifdef SHADOWGRP #include "sgroupio.h" #endif /* SHADOWGRP */ +#ifdef WITH_SELINUX +#include +#endif /* WITH_SELINUX */ #ifdef WITH_TCB #include #include "tcbfuncs.h" diff --git a/src/usermod.c b/src/usermod.c index 3ba011c2..15c70b5c 100644 --- a/src/usermod.c +++ b/src/usermod.c @@ -68,6 +68,9 @@ #ifdef ENABLE_SUBIDS #include "subordinateio.h" #endif /* ENABLE_SUBIDS */ +#ifdef WITH_SELINUX +#include +#endif /* WITH_SELINUX */ #ifdef WITH_TCB #include "tcbfuncs.h" #endif diff --git a/src/vipw.c b/src/vipw.c index 04f0b233..465698d1 100644 --- a/src/vipw.c +++ b/src/vipw.c @@ -243,13 +243,13 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void)) /* if SE Linux is enabled then set the context of all new files to be the context of the file we are editing */ if (is_selinux_enabled () != 0) { - security_context_t passwd_context=NULL; + char *passwd_context_raw = NULL; int ret = 0; - if (getfilecon (file, &passwd_context) < 0) { + if (getfilecon_raw (file, &passwd_context_raw) < 0) { vipwexit (_("Couldn't get file context"), errno, 1); } - ret = setfscreatecon (passwd_context); - freecon (passwd_context); + ret = setfscreatecon_raw (passwd_context_raw); + freecon (passwd_context_raw); if (0 != ret) { vipwexit (_("setfscreatecon () failed"), errno, 1); } @@ -401,7 +401,7 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void)) #ifdef WITH_SELINUX /* unset the fscreatecon */ if (is_selinux_enabled () != 0) { - if (setfscreatecon (NULL) != 0) { + if (setfscreatecon_raw (NULL) != 0) { vipwexit (_("setfscreatecon () failed"), errno, 1); } }