From 6e4b2fe25d9b53912f035736342cc0372eb0cd81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Fri, 9 Apr 2021 18:20:41 +0200 Subject: [PATCH 1/7] struct commonio_db[selinux]: do not use deprecated type security_context_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The typedef security_context_t is deprecated, see https://github.com/SELinuxProject/selinux/commit/9eb9c9327563014ad6a807814e7975424642d5b9 Signed-off-by: Christian Göttsche Acked-by: James Carter --- lib/commonio.h | 6 +----- src/useradd.c | 3 +++ src/userdel.c | 3 +++ src/usermod.c | 3 +++ 4 files changed, 10 insertions(+), 5 deletions(-) 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/src/useradd.c b/src/useradd.c index a0369cd8..dcda3196 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 */ 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 From c0aa8a876e8d90c00ec870663776b2af38cd2a7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Fri, 9 Apr 2021 18:20:49 +0200 Subject: [PATCH 2/7] vipw[selinux]: do not use deprecated typedef and skip context translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This retrieved context is just passed to libselinux functions and not printed or otherwise made available to the outside, so a context translation to human readable MCS/MLS labels is not needed. (see man:setrans.conf(5)) The typedef security_context_t is deprecated, see https://github.com/SELinuxProject/selinux/commit/9eb9c9327563014ad6a807814e7975424642d5b9 Signed-off-by: Christian Göttsche Acked-by: James Carter --- src/vipw.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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); } } From 95fd179683e414db4f6ebd9467476e45d94decda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Fri, 9 Apr 2021 18:20:51 +0200 Subject: [PATCH 3/7] selinux.c: do not use deprecated typedef and skip context translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These retrieved contexts are just passed to libselinux functions and not printed or otherwise made available to the outside, so a context translation to human readable MCS/MLS labels is not needed. (see man:setrans.conf(5)) The typedef security_context_t is deprecated, see https://github.com/SELinuxProject/selinux/commit/9eb9c9327563014ad6a807814e7975424642d5b9 Signed-off-by: Christian Göttsche Acked-by: James Carter --- lib/selinux.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/selinux.c b/lib/selinux.c index c60cbed5..e31a5f92 100644 --- a/lib/selinux.c +++ b/lib/selinux.c @@ -53,7 +53,7 @@ static bool selinux_enabled; */ int set_selinux_file_context (const char *dst_name) { - /*@null@*/security_context_t scontext = NULL; + /*@null@*/char *scontext = NULL; if (!selinux_checked) { selinux_enabled = is_selinux_enabled () > 0; @@ -93,7 +93,7 @@ int reset_selinux_file_context (void) selinux_checked = true; } if (selinux_enabled) { - if (setfscreatecon (NULL) != 0) { + if (setfscreatecon_raw (NULL) != 0) { return 1; } } @@ -175,7 +175,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 +184,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 +194,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; } From e367d111e513a61495213028e8d4ab2e36775790 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Fri, 9 Apr 2021 18:20:53 +0200 Subject: [PATCH 4/7] selinux.c:reset_selinux_file_context(): do not fail in permissive mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Return 0 on setfscreatecon(3) failure, like set_selinux_file_context(). Signed-off-by: Christian Göttsche Acked-by: James Carter --- lib/selinux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/selinux.c b/lib/selinux.c index e31a5f92..a2ea91c8 100644 --- a/lib/selinux.c +++ b/lib/selinux.c @@ -94,7 +94,7 @@ int reset_selinux_file_context (void) } if (selinux_enabled) { if (setfscreatecon_raw (NULL) != 0) { - return 1; + return security_getenforce () != 0; } } return 0; From 5f7649fb37bfe66544bc3141c047f5d09c8eaef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Fri, 9 Apr 2021 18:20:55 +0200 Subject: [PATCH 5/7] selinux.c: use modern selabel interface instead of deprecated matchpathcon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit matchpathcon(3) is deprecated in favor of selabel_lookup(3). Signed-off-by: Christian Göttsche Acked-by: James Carter --- lib/selinux.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/lib/selinux.c b/lib/selinux.c index a2ea91c8..41f4371d 100644 --- a/lib/selinux.c +++ b/lib/selinux.c @@ -35,7 +35,7 @@ #include "defines.h" #include -#include +#include #include "prototypes.h" static bool selinux_checked = false; @@ -53,8 +53,6 @@ static bool selinux_enabled; */ int set_selinux_file_context (const char *dst_name) { - /*@null@*/char *scontext = NULL; - if (!selinux_checked) { selinux_enabled = is_selinux_enabled () > 0; selinux_checked = true; @@ -62,19 +60,33 @@ 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; + struct selabel_handle *hnd; + int r; + + hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0); + if (hnd == NULL) { + return security_getenforce () != 0; } + + r = selabel_lookup_raw(hnd, &fcontext_raw, dst_name, 0); + selabel_close(hnd); + 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; } From eb1d2de0e9bd9e1262080312f0bca9c7e6a36d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Fri, 9 Apr 2021 18:21:00 +0200 Subject: [PATCH 6/7] set_selinux_file_context(): prepare context for actual file type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Search the SELinux selabel database for the file type to be created. Not specifying the file mode can cause an incorrect file context to be returned. Also prepare contexts in commonio_close() for the generic database filename, not with the backup suffix appended, to ensure the desired file context after the final rename. Closes: #322 Signed-off-by: Christian Göttsche Acked-by: James Carter --- lib/commonio.c | 4 ++-- lib/prototypes.h | 2 +- lib/selinux.c | 4 ++-- libmisc/copydir.c | 8 ++++---- src/useradd.c | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) 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/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 41f4371d..719acda3 100644 --- a/lib/selinux.c +++ b/lib/selinux.c @@ -51,7 +51,7 @@ 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) { if (!selinux_checked) { selinux_enabled = is_selinux_enabled () > 0; @@ -70,7 +70,7 @@ int set_selinux_file_context (const char *dst_name) return security_getenforce () != 0; } - r = selabel_lookup_raw(hnd, &fcontext_raw, dst_name, 0); + r = selabel_lookup_raw(hnd, &fcontext_raw, dst_name, mode); selabel_close(hnd); if (r < 0) { /* No context specified for the searched path */ 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 dcda3196..b3fff895 100644 --- a/src/useradd.c +++ b/src/useradd.c @@ -2177,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); @@ -2305,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); From dfe95bd08b2419826cf82b8fcdcc7b6ef3cead18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Tue, 13 Apr 2021 14:13:11 +0200 Subject: [PATCH 7/7] selinux: only open selabel database once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Once opened, keep the selabel database open for further lookups. Register an exit handler to close the database. Signed-off-by: Christian Göttsche Acked-by: James Carter --- lib/selinux.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/selinux.c b/lib/selinux.c index 719acda3..28ca5fff 100644 --- a/lib/selinux.c +++ b/lib/selinux.c @@ -40,6 +40,15 @@ 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 @@ -62,16 +71,17 @@ int set_selinux_file_context (const char *dst_name, mode_t mode) /* Get the default security context for this file */ /*@null@*/char *fcontext_raw = NULL; - struct selabel_handle *hnd; int r; - hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0); - if (hnd == NULL) { - return security_getenforce () != 0; + 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(hnd, &fcontext_raw, dst_name, mode); - selabel_close(hnd); + r = selabel_lookup_raw(selabel_hnd, &fcontext_raw, dst_name, mode); if (r < 0) { /* No context specified for the searched path */ if (errno == ENOENT) {