From: Iker Pedrosa Date: Fri, 25 Apr 2025 14:32:42 +0000 (+0200) Subject: src/useradd.c: chroot or prefix SELinux file context X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c0c9485d9a5a434c37165a5e9190ea09d57f303b;p=thirdparty%2Fshadow.git src/useradd.c: chroot or prefix SELinux file context Do not process SELinux file context during file closure when chroot or prefix options are selected. Closes: https://github.com/shadow-maint/shadow/issues/940 Signed-off-by: Iker Pedrosa --- diff --git a/src/useradd.c b/src/useradd.c index d631a8fae..2b1764ab8 100644 --- a/src/useradd.c +++ b/src/useradd.c @@ -89,6 +89,13 @@ #define NEW_USER_FILE "/etc/default/nuaddXXXXXX" #endif +/* + * Structures + */ +struct option_flags { + bool chroot; + bool prefix; +}; /* * Global variables @@ -218,10 +225,10 @@ static bool home_added = false; /* local function prototypes */ NORETURN static void fail_exit (int); -static void get_defaults (void); +static void get_defaults (struct option_flags *); static void show_defaults (void); static int set_defaults (void); -static int get_groups (char *); +static int get_groups (char *, struct option_flags *); static struct group * get_local_group (char * grp_name); NORETURN static void usage (int status); static void new_pwent (struct passwd *); @@ -229,10 +236,10 @@ static void new_pwent (struct passwd *); static void new_spent (struct spwd *); static void grp_update (void); -static void process_flags (int argc, char **argv); -static void close_files (void); -static void close_group_files (void); -static void unlock_group_files (void); +static void process_flags (int argc, char **argv, struct option_flags *flags); +static void close_files (struct option_flags *flags); +static void close_group_files (bool process_selinux); +static void unlock_group_files (bool process_selinux); static void open_files (void); static void open_group_files (void); static void open_shadow (void); @@ -320,7 +327,7 @@ static void fail_exit (int code) * file does not exist. */ static void -get_defaults(void) +get_defaults(struct option_flags *flags) { FILE *fp; char *default_file = USER_DEFAULTS_FILE; @@ -375,7 +382,7 @@ get_defaults(void) ccp = cp; if (streq(buf, DGROUPS)) { - if (get_groups (cp) != 0) { + if (get_groups (cp, flags) != 0) { fprintf (stderr, _("%s: the '%s=' configuration in %s has an invalid group, ignoring the bad group\n"), Prog, DGROUPS, default_file); @@ -734,11 +741,14 @@ err_free_new: * converts it to a NULL-terminated array. Any unknown group * names are reported as errors. */ -static int get_groups (char *list) +static int get_groups (char *list, struct option_flags *flags) { struct group *grp; bool errors = false; int ngroups = 0; + bool process_selinux; + + process_selinux = !flags->chroot && !flags->prefix; /* * Free previous group list before creating a new one. @@ -813,8 +823,8 @@ static int get_groups (char *list) gr_free (grp); } - close_group_files (); - unlock_group_files (); + close_group_files (process_selinux); + unlock_group_files (process_selinux); user_groups[ngroups] = NULL; @@ -1119,7 +1129,7 @@ static void grp_update (void) * the values that the user will be created with accordingly. The * values are checked for sanity. */ -static void process_flags (int argc, char **argv) +static void process_flags (int argc, char **argv, struct option_flags *flags) { const struct group *grp; bool anyflag = false; @@ -1294,7 +1304,7 @@ static void process_flags (int argc, char **argv) gflg = true; break; case 'G': - if (get_groups (optarg) != 0) { + if (get_groups (optarg, flags) != 0) { exit (E_NOTFOUND); } if (NULL != user_groups[0]) { @@ -1354,8 +1364,10 @@ static void process_flags (int argc, char **argv) rflg = true; break; case 'R': /* no-op, handled in process_root_flag () */ + flags->chroot = true; break; case 'P': /* no-op, handled in process_prefix_flag () */ + flags->prefix = true; break; case 's': if ( ( !VALID (optarg) ) @@ -1560,30 +1572,34 @@ static void process_flags (int argc, char **argv) * close_files() closes all of the files that were opened for this * new user. This causes any modified entries to be written out. */ -static void close_files (void) +static void close_files (struct option_flags *flags) { - if (pw_close (true) == 0) { + bool process_selinux; + + process_selinux = !flags->chroot && !flags->prefix; + + if (pw_close (process_selinux) == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); fail_exit (E_PW_UPDATE); } - if (is_shadow_pwd && (spw_close (true) == 0)) { + if (is_shadow_pwd && (spw_close (process_selinux) == 0)) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); fail_exit (E_PW_UPDATE); } - close_group_files (); + close_group_files (process_selinux); #ifdef ENABLE_SUBIDS - if (is_sub_uid && (sub_uid_close (true) == 0)) { + if (is_sub_uid && (sub_uid_close (process_selinux) == 0)) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); fail_exit (E_SUB_UID_UPDATE); } - if (is_sub_gid && (sub_gid_close (true) == 0)) { + if (is_sub_gid && (sub_gid_close (process_selinux) == 0)) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); @@ -1591,7 +1607,7 @@ static void close_files (void) } #endif /* ENABLE_SUBIDS */ if (is_shadow_pwd) { - if (spw_unlock (true) == 0) { + if (spw_unlock (process_selinux) == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); #ifdef WITH_AUDIT @@ -1604,7 +1620,7 @@ static void close_files (void) } spw_locked = false; } - if (pw_unlock (true) == 0) { + if (pw_unlock (process_selinux) == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); #ifdef WITH_AUDIT @@ -1617,11 +1633,11 @@ static void close_files (void) } pw_locked = false; - unlock_group_files (); + unlock_group_files (process_selinux); #ifdef ENABLE_SUBIDS if (is_sub_uid) { - if (sub_uid_unlock (true) == 0) { + if (sub_uid_unlock (process_selinux) == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); #ifdef WITH_AUDIT @@ -1635,7 +1651,7 @@ static void close_files (void) sub_uid_locked = false; } if (is_sub_gid) { - if (sub_gid_unlock (true) == 0) { + if (sub_gid_unlock (process_selinux) == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); #ifdef WITH_AUDIT @@ -1657,12 +1673,12 @@ static void close_files (void) * close_group_files() closes all of the files that were opened related * with groups. This causes any modified entries to be written out. */ -static void close_group_files (void) +static void close_group_files (bool process_selinux) { if (!do_grp_update) return; - if (gr_close(true) == 0) { + if (gr_close(process_selinux) == 0) { fprintf(stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname()); @@ -1670,7 +1686,7 @@ static void close_group_files (void) fail_exit(E_GRP_UPDATE); } #ifdef SHADOWGRP - if (is_shadow_grp && sgr_close(true) == 0) { + if (is_shadow_grp && sgr_close(process_selinux) == 0) { fprintf(stderr, _("%s: failure while writing changes to %s\n"), Prog, sgr_dbname()); @@ -1686,9 +1702,9 @@ static void close_group_files (void) * unlock_group_files() unlocks all of the files that were locked related * with groups. This causes any modified entries to be written out. */ -static void unlock_group_files (void) +static void unlock_group_files (bool process_selinux) { - if (gr_unlock (true) == 0) { + if (gr_unlock (process_selinux) == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); #ifdef WITH_AUDIT @@ -1702,7 +1718,7 @@ static void unlock_group_files (void) gr_locked = false; #ifdef SHADOWGRP if (is_shadow_grp) { - if (sgr_unlock (true) == 0) { + if (sgr_unlock (process_selinux) == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); #ifdef WITH_AUDIT @@ -2407,6 +2423,7 @@ int main (int argc, char **argv) #endif unsigned long subuid_count = 0; unsigned long subgid_count = 0; + struct option_flags flags; log_set_progname(Prog); log_set_logfd(stderr); @@ -2437,9 +2454,9 @@ int main (int argc, char **argv) is_shadow_grp = sgr_file_present (); #endif - get_defaults (); + get_defaults (&flags); - process_flags (argc, argv); + process_flags (argc, argv, &flags); #ifdef ENABLE_SUBIDS uid_min = getdef_ulong ("UID_MIN", 1000UL); @@ -2611,7 +2628,7 @@ int main (int argc, char **argv) usr_update (subuid_count, subgid_count); - close_files (); + close_files (&flags); nscd_flush_cache ("passwd"); nscd_flush_cache ("group");