From c80788a3ac092bc5abfa89ff48060d3f95cd5812 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Sat, 1 Apr 2023 14:34:56 +0200 Subject: [PATCH] useradd/usermod: add --selinux-range argument Add a command line argument to useradd(8) and usermod(8) to specify the MLS range for a SELinux user mapping. Improves: #676 --- lib/prototypes.h | 2 +- lib/semanage.c | 34 +++++++++++++++++++++++++++++----- man/useradd.8.xml | 20 +++++++++++++++++++- man/usermod.8.xml | 17 +++++++++++++++++ src/useradd.c | 16 +++++++++++++++- src/usermod.c | 19 +++++++++++++++++-- 6 files changed, 98 insertions(+), 10 deletions(-) diff --git a/lib/prototypes.h b/lib/prototypes.h index 21df6f61..012652a9 100644 --- a/lib/prototypes.h +++ b/lib/prototypes.h @@ -385,7 +385,7 @@ extern int check_selinux_permit (const char *perm_name); /* semanage.c */ #ifdef WITH_SELINUX -extern int set_seuser(const char *login_name, const char *seuser_name); +extern int set_seuser(const char *login_name, const char *seuser_name, const char *serange); extern int del_seuser(const char *login_name); #endif diff --git a/lib/semanage.c b/lib/semanage.c index bbb3f993..5d336b08 100644 --- a/lib/semanage.c +++ b/lib/semanage.c @@ -105,7 +105,8 @@ fail: static int semanage_user_mod (semanage_handle_t *handle, semanage_seuser_key_t *key, const char *login_name, - const char *seuser_name) + const char *seuser_name, + const char *serange) { int ret; semanage_seuser_t *seuser = NULL; @@ -118,6 +119,17 @@ static int semanage_user_mod (semanage_handle_t *handle, goto done; } + if (serange && semanage_mls_enabled(handle)) { + ret = semanage_seuser_set_mlsrange (handle, seuser, serange); + if (ret != 0) { + fprintf (shadow_logfd, + _("Could not set serange for %s to %s\n"), + login_name, serange); + ret = 1; + goto done; + } + } + ret = semanage_seuser_set_sename (handle, seuser, seuser_name); if (ret != 0) { fprintf (shadow_logfd, @@ -146,7 +158,8 @@ done: static int semanage_user_add (semanage_handle_t *handle, semanage_seuser_key_t *key, const char *login_name, - const char *seuser_name) + const char *seuser_name, + const char *serange) { int ret; semanage_seuser_t *seuser = NULL; @@ -167,6 +180,17 @@ static int semanage_user_add (semanage_handle_t *handle, goto done; } + if (serange && semanage_mls_enabled(handle)) { + ret = semanage_seuser_set_mlsrange (handle, seuser, serange); + if (ret != 0) { + fprintf (shadow_logfd, + _("Could not set serange for %s to %s\n"), + login_name, serange); + ret = 1; + goto done; + } + } + ret = semanage_seuser_set_sename (handle, seuser, seuser_name); if (ret != 0) { fprintf (shadow_logfd, @@ -192,7 +216,7 @@ done: } -int set_seuser (const char *login_name, const char *seuser_name) +int set_seuser (const char *login_name, const char *seuser_name, const char *serange) { semanage_handle_t *handle = NULL; semanage_seuser_key_t *key = NULL; @@ -226,7 +250,7 @@ int set_seuser (const char *login_name, const char *seuser_name) } if (0 != seuser_exists) { - ret = semanage_user_mod (handle, key, login_name, seuser_name); + ret = semanage_user_mod (handle, key, login_name, seuser_name, serange); if (ret != 0) { fprintf (shadow_logfd, _("Cannot modify SELinux user mapping\n")); @@ -234,7 +258,7 @@ int set_seuser (const char *login_name, const char *seuser_name) goto done; } } else { - ret = semanage_user_add (handle, key, login_name, seuser_name); + ret = semanage_user_add (handle, key, login_name, seuser_name, serange); if (ret != 0) { fprintf (shadow_logfd, _("Cannot add SELinux user mapping\n")); diff --git a/man/useradd.8.xml b/man/useradd.8.xml index 05e939a6..51705285 100644 --- a/man/useradd.8.xml +++ b/man/useradd.8.xml @@ -570,13 +570,31 @@ defines the SELinux user for the new account. Without this - option, a SELinux uses the default user. Note that the + option, SELinux uses the default user. Note that the shadow system doesn't store the selinux-user, it uses semanage 8 for that. + + +  SERANGE + + + + defines the SELinux MLS range for the new account. Without this + option, SELinux uses the default range. Note that the + shadow system doesn't store the selinux-range, it uses + semanage + 8 for that. + + + This option is only valid if the (or + ) option is specified. + + + diff --git a/man/usermod.8.xml b/man/usermod.8.xml index 78092898..349248b6 100644 --- a/man/usermod.8.xml +++ b/man/usermod.8.xml @@ -510,6 +510,23 @@ + + +  SERANGE + + + + defines the SELinux MLS range for the new account. + Note that the shadow system doesn't store the selinux-range, + it uses semanage + 8 for that. + + + This option is only valid if the (or + ) option is specified. + + + diff --git a/src/useradd.c b/src/useradd.c index c0d8eda9..152b4e53 100644 --- a/src/useradd.c +++ b/src/useradd.c @@ -113,6 +113,7 @@ static const char *prefix_user_home = NULL; #ifdef WITH_SELINUX static /*@notnull@*/const char *user_selinux = ""; +static const char *user_selinux_range = NULL; #endif /* WITH_SELINUX */ static long user_expire = -1; @@ -997,6 +998,7 @@ static void usage (int status) (void) fputs (_(" -U, --user-group create a group with the same name as the user\n"), usageout); #ifdef WITH_SELINUX (void) fputs (_(" -Z, --selinux-user SEUSER use a specific SEUSER for the SELinux user mapping\n"), usageout); + (void) fputs (_(" --selinux-range SERANGE use a specific MLS range for the SELinux user mapping\n"), usageout); #endif /* WITH_SELINUX */ (void) fputs ("\n", usageout); exit (status); @@ -1280,6 +1282,7 @@ static void process_flags (int argc, char **argv) {"user-group", no_argument, NULL, 'U'}, #ifdef WITH_SELINUX {"selinux-user", required_argument, NULL, 'Z'}, + {"selinux-range", required_argument, NULL, 202}, #endif /* WITH_SELINUX */ {NULL, 0, NULL, '\0'} }; @@ -1529,6 +1532,9 @@ static void process_flags (int argc, char **argv) exit (E_BAD_ARG); } break; + case 202: + user_selinux_range = optarg; + break; #endif /* WITH_SELINUX */ default: usage (E_USAGE); @@ -1576,6 +1582,14 @@ static void process_flags (int argc, char **argv) Prog, "-m", "-M"); usage (E_USAGE); } +#ifdef WITH_SELINUX + if (user_selinux_range && !Zflg) { + fprintf (stderr, + _("%s: %s flag is only allowed with the %s flag\n"), + Prog, "--selinux-range", "--selinux-user"); + usage (E_USAGE); + } +#endif /* WITH_SELINUX */ /* * Either -D or username is required. Defaults can be set with -D @@ -2760,7 +2774,7 @@ int main (int argc, char **argv) #ifdef WITH_SELINUX if (Zflg) { - if (set_seuser (user_name, user_selinux) != 0) { + if (set_seuser (user_name, user_selinux, user_selinux_range) != 0) { fprintf (stderr, _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), Prog, user_name, user_selinux); diff --git a/src/usermod.c b/src/usermod.c index 05cc28fb..87c93d93 100644 --- a/src/usermod.c +++ b/src/usermod.c @@ -100,6 +100,7 @@ static char *user_newhome; static char *user_shell; #ifdef WITH_SELINUX static const char *user_selinux = ""; +static const char *user_selinux_range = NULL; #endif /* WITH_SELINUX */ static char *user_newshell; static long user_expire; @@ -405,6 +406,7 @@ usage (int status) #endif /* ENABLE_SUBIDS */ #ifdef WITH_SELINUX (void) fputs (_(" -Z, --selinux-user SEUSER new SELinux user mapping for the user account\n"), usageout); + (void) fputs (_(" --selinux-range SERANGE new SELinux MLS range for the user account\n"), usageout); #endif /* WITH_SELINUX */ (void) fputs ("\n", usageout); exit (status); @@ -1004,7 +1006,8 @@ static void process_flags (int argc, char **argv) {"del-subgids", required_argument, NULL, 'W'}, #endif /* ENABLE_SUBIDS */ #ifdef WITH_SELINUX - {"selinux-user", required_argument, NULL, 'Z'}, + {"selinux-user", required_argument, NULL, 'Z'}, + {"selinux-range", required_argument, NULL, 202}, #endif /* WITH_SELINUX */ {NULL, 0, NULL, '\0'} }; @@ -1214,6 +1217,9 @@ static void process_flags (int argc, char **argv) exit (E_BAD_ARG); } break; + case 202: + user_selinux_range = optarg; + break; #endif /* WITH_SELINUX */ default: usage (E_USAGE); @@ -1354,6 +1360,15 @@ static void process_flags (int argc, char **argv) usage (E_USAGE); } +#ifdef WITH_SELINUX + if (user_selinux_range && !Zflg) { + fprintf (stderr, + _("%s: %s flag is only allowed with the %s flag\n"), + Prog, "--selinux-range", "--selinux-user"); + usage (E_USAGE); + } +#endif /* WITH_SELINUX */ + if (user_newid == user_id) { uflg = false; oflg = false; @@ -2304,7 +2319,7 @@ int main (int argc, char **argv) #ifdef WITH_SELINUX if (Zflg) { if ('\0' != *user_selinux) { - if (set_seuser (user_name, user_selinux) != 0) { + if (set_seuser (user_name, user_selinux, user_selinux_range) != 0) { fprintf (stderr, _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"), Prog, user_name, user_selinux);