]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
src/newusers.c: SELinux file context for fail_exit()
authorIker Pedrosa <ipedrosa@redhat.com>
Tue, 1 Jul 2025 13:55:54 +0000 (15:55 +0200)
committerIker Pedrosa <ipedrosa@redhat.com>
Tue, 7 Oct 2025 09:04:40 +0000 (11:04 +0200)
Do not process SELinux file context when running fail_exit() when chroot
or prefix options are selected.

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
src/newusers.c

index 0a744952b788b4be4071dcfa77da7e2104cff247..d60c92f74316aabda5005c04e634c448cf9f7880 100644 (file)
@@ -106,7 +106,7 @@ static bool sub_gid_locked = false;
 
 /* local function prototypes */
 NORETURN static void usage (int status);
-NORETURN static void fail_exit (int);
+NORETURN static void fail_exit (int, bool);
 static int add_group (const char *, const char *, gid_t *, gid_t);
 static int get_user_id (const char *, uid_t *);
 static int add_user (const char *, uid_t, gid_t);
@@ -116,8 +116,8 @@ static int update_passwd (struct passwd *, const char *);
 static int add_passwd (struct passwd *, const char *);
 static void process_flags (int argc, char **argv, struct option_flags *flags);
 static void check_flags (void);
-static void check_perms (void);
-static void open_files (void);
+static void check_perms (struct option_flags *flags);
+static void open_files (bool process_selinux);
 static void close_files (struct option_flags *flags);
 
 extern int allow_bad_names;
@@ -167,24 +167,24 @@ static void usage (int status)
 /*
  * fail_exit - undo as much as possible
  */
-static void fail_exit (int code)
+static void fail_exit (int code, bool process_selinux)
 {
        if (spw_locked) {
-               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 ()));
                        /* continue */
                }
        }
        if (pw_locked) {
-               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 ()));
                        /* continue */
                }
        }
        if (gr_locked) {
-               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 ()));
                        /* continue */
@@ -192,7 +192,7 @@ static void fail_exit (int code)
        }
 #ifdef SHADOWGRP
        if (sgr_locked) {
-               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 ()));
                        /* continue */
@@ -201,14 +201,14 @@ static void fail_exit (int code)
 #endif
 #ifdef ENABLE_SUBIDS
        if (sub_uid_locked) {
-               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 ()));
                        /* continue */
                }
        }
        if (sub_gid_locked) {
-               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 ()));
                        /* continue */
@@ -737,7 +737,7 @@ static void process_flags (int argc, char **argv, struct option_flags *flags)
 
                        SNPRINTF(buf, "%s: %s", Prog, argv[1]);
                        perror (buf);
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, !flags->chroot);
                }
        }
 
@@ -796,20 +796,23 @@ static void check_flags (void)
  *
  *     It will not return if the user is not allowed.
  */
-static void check_perms (void)
+static void check_perms (struct option_flags *flags)
 {
 #ifdef ACCT_TOOLS_SETUID
 #ifdef USE_PAM
        pam_handle_t *pamh = NULL;
        int retval;
        struct passwd *pampw;
+       bool process_selinux;
+
+       process_selinux = !flags->chroot;
 
        pampw = getpwuid (getuid ()); /* local, no need for xgetpwuid */
        if (NULL == pampw) {
                fprintf (stderr,
                         _("%s: Cannot determine your user name.\n"),
                         Prog);
-               fail_exit (EXIT_FAILURE);
+               fail_exit (EXIT_FAILURE, process_selinux);
        }
 
        retval = pam_start ("newusers", pampw->pw_name, &conv, &pamh);
@@ -829,7 +832,7 @@ static void check_perms (void)
                if (NULL != pamh) {
                        (void) pam_end (pamh, retval);
                }
-               fail_exit (EXIT_FAILURE);
+               fail_exit (EXIT_FAILURE, process_selinux);
        }
        (void) pam_end (pamh, retval);
 #endif                         /* USE_PAM */
@@ -839,7 +842,7 @@ static void check_perms (void)
 /*
  * open_files - lock and open the password, group and shadow databases
  */
-static void open_files (void)
+static void open_files (bool process_selinux)
 {
        /*
         * Lock the password files and open them for update. This will bring
@@ -851,7 +854,7 @@ static void open_files (void)
                fprintf (stderr,
                         _("%s: cannot lock %s; try again later.\n"),
                         Prog, pw_dbname ());
-               fail_exit (EXIT_FAILURE);
+               fail_exit (EXIT_FAILURE, process_selinux);
        }
        pw_locked = true;
        if (is_shadow) {
@@ -859,7 +862,7 @@ static void open_files (void)
                        fprintf (stderr,
                                 _("%s: cannot lock %s; try again later.\n"),
                                 Prog, spw_dbname ());
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, process_selinux);
                }
                spw_locked = true;
        }
@@ -867,7 +870,7 @@ static void open_files (void)
                fprintf (stderr,
                         _("%s: cannot lock %s; try again later.\n"),
                         Prog, gr_dbname ());
-               fail_exit (EXIT_FAILURE);
+               fail_exit (EXIT_FAILURE, process_selinux);
        }
        gr_locked = true;
 #ifdef SHADOWGRP
@@ -876,7 +879,7 @@ static void open_files (void)
                        fprintf (stderr,
                                 _("%s: cannot lock %s; try again later.\n"),
                                 Prog, sgr_dbname ());
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, process_selinux);
                }
                sgr_locked = true;
        }
@@ -887,7 +890,7 @@ static void open_files (void)
                        fprintf (stderr,
                                 _("%s: cannot lock %s; try again later.\n"),
                                 Prog, sub_uid_dbname ());
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, process_selinux);
                }
                sub_uid_locked = true;
        }
@@ -896,7 +899,7 @@ static void open_files (void)
                        fprintf (stderr,
                                 _("%s: cannot lock %s; try again later.\n"),
                                 Prog, sub_gid_dbname ());
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, process_selinux);
                }
                sub_gid_locked = true;
        }
@@ -904,20 +907,20 @@ static void open_files (void)
 
        if (pw_open (O_CREAT | O_RDWR) == 0) {
                fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ());
-               fail_exit (EXIT_FAILURE);
+               fail_exit (EXIT_FAILURE, process_selinux);
        }
        if (is_shadow && (spw_open (O_CREAT | O_RDWR) == 0)) {
                fprintf (stderr, _("%s: cannot open %s\n"), Prog, spw_dbname ());
-               fail_exit (EXIT_FAILURE);
+               fail_exit (EXIT_FAILURE, process_selinux);
        }
        if (gr_open (O_CREAT | O_RDWR) == 0) {
                fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
-               fail_exit (EXIT_FAILURE);
+               fail_exit (EXIT_FAILURE, process_selinux);
        }
 #ifdef SHADOWGRP
        if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) {
                fprintf (stderr, _("%s: cannot open %s\n"), Prog, sgr_dbname ());
-               fail_exit (EXIT_FAILURE);
+               fail_exit (EXIT_FAILURE, process_selinux);
        }
 #endif
 #ifdef ENABLE_SUBIDS
@@ -926,7 +929,7 @@ static void open_files (void)
                        fprintf (stderr,
                                 _("%s: cannot open %s\n"),
                                 Prog, sub_uid_dbname ());
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, process_selinux);
                }
        }
        if (is_sub_gid) {
@@ -934,7 +937,7 @@ static void open_files (void)
                        fprintf (stderr,
                                 _("%s: cannot open %s\n"),
                                 Prog, sub_gid_dbname ());
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, process_selinux);
                }
        }
 #endif                         /* ENABLE_SUBIDS */
@@ -952,7 +955,7 @@ static void close_files (struct option_flags *flags)
        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 (EXIT_FAILURE);
+               fail_exit (EXIT_FAILURE, process_selinux);
        }
        if (pw_unlock (process_selinux) == 0) {
                fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
@@ -967,7 +970,7 @@ static void close_files (struct option_flags *flags)
                                 _("%s: failure while writing changes to %s\n"),
                                 Prog, spw_dbname ());
                        SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ()));
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, process_selinux);
                }
                if (spw_unlock (process_selinux) == 0) {
                        fprintf (stderr,
@@ -984,20 +987,20 @@ static void close_files (struct option_flags *flags)
                         _("%s: failure while writing changes to %s\n"),
                         Prog, gr_dbname ());
                SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ()));
-               fail_exit (EXIT_FAILURE);
+               fail_exit (EXIT_FAILURE, process_selinux);
        }
 #ifdef ENABLE_SUBIDS
        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 (EXIT_FAILURE);
+               fail_exit (EXIT_FAILURE, process_selinux);
        }
        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 ()));
-               fail_exit (EXIT_FAILURE);
+               fail_exit (EXIT_FAILURE, process_selinux);
        }
 #endif                         /* ENABLE_SUBIDS */
 
@@ -1017,7 +1020,7 @@ static void close_files (struct option_flags *flags)
                                 _("%s: failure while writing changes to %s\n"),
                                 Prog, sgr_dbname ());
                        SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ()));
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, process_selinux);
                }
                if (sgr_unlock (process_selinux) == 0) {
                        fprintf (stderr,
@@ -1065,6 +1068,7 @@ int main (int argc, char **argv)
        size_t nusers = 0;
 #endif                         /* USE_PAM */
        struct option_flags  flags;
+       bool process_selinux;
 
        log_set_progname(Prog);
        log_set_logfd(stderr);
@@ -1079,8 +1083,9 @@ int main (int argc, char **argv)
        OPENLOG ("newusers");
 
        process_flags (argc, argv, &flags);
+       process_selinux = !flags.chroot;
 
-       check_perms ();
+       check_perms (&flags);
 
        is_shadow = spw_file_present ();
 
@@ -1092,7 +1097,7 @@ int main (int argc, char **argv)
        is_sub_gid = want_subgid_file() && sub_gid_file_present() && !rflg;
 #endif                         /* ENABLE_SUBIDS */
 
-       open_files ();
+       open_files (process_selinux);
 
        /*
         * Read each line. The line has the same format as a password file
@@ -1108,13 +1113,13 @@ int main (int argc, char **argv)
                if (stpsep(buf, "\n") == NULL && feof(stdin) == 0) {
                        fprintf (stderr, _("%s: line %jd: line too long\n"),
                                 Prog, line);
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, process_selinux);
                }
 
                if (STRSEP2ARR(buf, ":", fields) == -1) {
                        fprintf (stderr, _("%s: line %jd: invalid line\n"),
                                 Prog, line);
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, process_selinux);
                }
 
                /*
@@ -1126,14 +1131,14 @@ int main (int argc, char **argv)
                        fprintf (stderr,
                                 _("%s: cannot update the entry of user %s (not in the passwd database)\n"),
                                 Prog, fields[0]);
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, process_selinux);
                }
 
                if (NULL == pw && get_user_id(fields[2], &uid) != 0) {
                        fprintf (stderr,
                                 _("%s: line %jd: can't create user\n"),
                                 Prog, line);
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, process_selinux);
                }
 
                /*
@@ -1153,7 +1158,7 @@ int main (int argc, char **argv)
                        fprintf (stderr,
                                 _("%s: line %jd: can't create group\n"),
                                 Prog, line);
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, process_selinux);
                }
 
                /*
@@ -1168,7 +1173,7 @@ int main (int argc, char **argv)
                        fprintf (stderr,
                                 _("%s: line %jd: can't create user\n"),
                                 Prog, line);
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, process_selinux);
                }
 
                /*
@@ -1180,7 +1185,7 @@ int main (int argc, char **argv)
                        fprintf (stderr,
                                 _("%s: line %jd: user '%s' does not exist in %s\n"),
                                 Prog, line, fields[0], pw_dbname ());
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, process_selinux);
                }
                newpw = *pw;
 
@@ -1194,7 +1199,7 @@ int main (int argc, char **argv)
                        fprintf (stderr,
                                 _("%s: line %jd: %s\n"),
                                 Prog, line, strerror(errno));
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, process_selinux);
                }
                lines[nusers-1]     = line;
                usernames[nusers-1] = xstrdup(fields[0]);
@@ -1204,7 +1209,7 @@ int main (int argc, char **argv)
                        fprintf (stderr,
                                 _("%s: line %jd: can't update password\n"),
                                 Prog, line);
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, process_selinux);
                }
                if (!streq(fields[4], "")) {
                        newpw.pw_gecos = fields[4];
@@ -1227,7 +1232,7 @@ int main (int argc, char **argv)
                                fprintf(stderr,
                                        _("%s: line %jd: homedir must be an absolute path\n"),
                                        Prog, line);
-                               fail_exit (EXIT_FAILURE);
+                               fail_exit (EXIT_FAILURE, process_selinux);
                        }
                        if (mkdir (newpw.pw_dir, mode) != 0) {
                                fprintf (stderr,
@@ -1235,7 +1240,7 @@ int main (int argc, char **argv)
                                         Prog, line, newpw.pw_dir,
                                         strerror (errno));
                                if (errno != EEXIST) {
-                                       fail_exit (EXIT_FAILURE);
+                                       fail_exit (EXIT_FAILURE, process_selinux);
                                }
                        }
                        if (chown(newpw.pw_dir, newpw.pw_uid, newpw.pw_gid) != 0)
@@ -1244,7 +1249,7 @@ int main (int argc, char **argv)
                                         _("%s: line %jd: chown %s failed: %s\n"),
                                         Prog, line, newpw.pw_dir,
                                         strerror (errno));
-                               fail_exit (EXIT_FAILURE);
+                               fail_exit (EXIT_FAILURE, process_selinux);
                        }
                }
 
@@ -1255,7 +1260,7 @@ int main (int argc, char **argv)
                        fprintf (stderr,
                                 _("%s: line %jd: can't update entry\n"),
                                 Prog, line);
-                       fail_exit (EXIT_FAILURE);
+                       fail_exit (EXIT_FAILURE, process_selinux);
                }
 
 #ifdef ENABLE_SUBIDS
@@ -1270,14 +1275,14 @@ int main (int argc, char **argv)
                                fprintf (stderr,
                                        _("%s: can't find subordinate user range\n"),
                                        Prog);
-                               fail_exit (EXIT_FAILURE);
+                               fail_exit (EXIT_FAILURE, process_selinux);
                        }
                        if (sub_uid_add(fields[0], sub_uid_start, sub_uid_count) == 0)
                        {
                                fprintf (stderr,
                                        _("%s: failed to prepare new %s entry\n"),
                                        Prog, sub_uid_dbname ());
-                               fail_exit (EXIT_FAILURE);
+                               fail_exit (EXIT_FAILURE, process_selinux);
                        }
                }
 
@@ -1291,13 +1296,13 @@ int main (int argc, char **argv)
                                fprintf (stderr,
                                        _("%s: can't find subordinate group range\n"),
                                        Prog);
-                               fail_exit (EXIT_FAILURE);
+                               fail_exit (EXIT_FAILURE, process_selinux);
                        }
                        if (sub_gid_add(fields[0], sub_gid_start, sub_gid_count) == 0) {
                                fprintf (stderr,
                                        _("%s: failed to prepare new %s entry\n"),
                                        Prog, sub_uid_dbname ());
-                               fail_exit (EXIT_FAILURE);
+                               fail_exit (EXIT_FAILURE, process_selinux);
                        }
                }
 #endif                         /* ENABLE_SUBIDS */