]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
src/groupmems.c: SELinux file context for fail_exit()
authorIker Pedrosa <ipedrosa@redhat.com>
Tue, 1 Jul 2025 14:14:08 +0000 (16:14 +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/groupmems.c

index c3de13f410e5c16407672cf75e9d3d4c14993c92..3890e023c89cea07b18ae06d16094712f00fbdc9 100644 (file)
@@ -74,15 +74,17 @@ static bool sgr_locked = false;
 /* local function prototypes */
 static char *whoami (void);
 static void add_user (const char *user,
-                      const struct group *grp);
+                      const struct group *grp,
+                      bool process_selinux);
 static void remove_user (const char *user,
-                         const struct group *grp);
-static void purge_members (const struct group *grp);
+                         const struct group *grp,
+                         bool process_selinux);
+static void purge_members (const struct group *grp, bool process_selinux);
 static void display_members (const char *const *members);
 NORETURN static void usage (int status);
 static void process_flags (int argc, char **argv, struct option_flags *flags);
-static void check_perms (void);
-NORETURN static void fail_exit (int code);
+static void check_perms (bool process_selinux);
+NORETURN static void fail_exit (int code, bool process_selinux);
 #define isroot()               (getuid () == 0)
 
 static char *whoami (void)
@@ -105,7 +107,8 @@ static char *whoami (void)
  * add_user - Add a user to the specified group
  */
 static void add_user (const char *user,
-                      const struct group *grp)
+                      const struct group *grp,
+                      bool process_selinux)
 {
        struct group *newgrp;
 
@@ -114,7 +117,7 @@ static void add_user (const char *user,
                fprintf (stderr,
                         _("%s: user '%s' is already a member of '%s'\n"),
                         Prog, user, grp->gr_name);
-               fail_exit (EXIT_MEMBER_EXISTS);
+               fail_exit (EXIT_MEMBER_EXISTS, process_selinux);
        }
 
        newgrp = __gr_dup(grp);
@@ -122,7 +125,7 @@ static void add_user (const char *user,
                fprintf (stderr,
                         _("%s: Out of memory. Cannot update %s.\n"),
                         Prog, gr_dbname ());
-               fail_exit (13);
+               fail_exit (13, process_selinux);
        }
 
        /* Add the user to the /etc/group group */
@@ -152,7 +155,7 @@ static void add_user (const char *user,
                                fprintf (stderr,
                                         _("%s: Out of memory. Cannot update %s.\n"),
                                         Prog, sgr_dbname ());
-                               fail_exit (13);
+                               fail_exit (13, process_selinux);
                        }
                        /* Add the user to the members */
                        newsg->sg_mem = add_list (newsg->sg_mem, user);
@@ -163,7 +166,7 @@ static void add_user (const char *user,
                        fprintf (stderr,
                                 _("%s: failed to prepare the new %s entry '%s'\n"),
                                 Prog, sgr_dbname (), newsg->sg_namp);
-                       fail_exit (13);
+                       fail_exit (13, process_selinux);
                }
        }
 #endif
@@ -172,7 +175,7 @@ static void add_user (const char *user,
                fprintf (stderr,
                         _("%s: failed to prepare the new %s entry '%s'\n"),
                         Prog, gr_dbname (), newgrp->gr_name);
-               fail_exit (13);
+               fail_exit (13, process_selinux);
        }
 }
 
@@ -180,7 +183,8 @@ static void add_user (const char *user,
  * remove_user - Remove a user from a given group
  */
 static void remove_user (const char *user,
-                         const struct group *grp)
+                         const struct group *grp,
+                         bool process_selinux)
 {
        struct group *newgrp;
 
@@ -189,7 +193,7 @@ static void remove_user (const char *user,
                fprintf (stderr,
                         _("%s: user '%s' is not a member of '%s'\n"),
                         Prog, user, grp->gr_name);
-               fail_exit (EXIT_NOT_MEMBER);
+               fail_exit (EXIT_NOT_MEMBER, process_selinux);
        }
 
        newgrp = __gr_dup (grp);
@@ -197,7 +201,7 @@ static void remove_user (const char *user,
                fprintf (stderr,
                         _("%s: Out of memory. Cannot update %s.\n"),
                         Prog, gr_dbname ());
-               fail_exit (13);
+               fail_exit (13, process_selinux);
        }
 
        /* Remove the user from the /etc/group group */
@@ -227,7 +231,7 @@ static void remove_user (const char *user,
                                fprintf (stderr,
                                         _("%s: Out of memory. Cannot update %s.\n"),
                                         Prog, sgr_dbname ());
-                               fail_exit (13);
+                               fail_exit (13, process_selinux);
                        }
                        /* Remove the user from the members */
                        newsg->sg_mem = del_list (newsg->sg_mem, user);
@@ -239,7 +243,7 @@ static void remove_user (const char *user,
                        fprintf (stderr,
                                 _("%s: failed to prepare the new %s entry '%s'\n"),
                                 Prog, sgr_dbname (), newsg->sg_namp);
-                       fail_exit (13);
+                       fail_exit (13, process_selinux);
                }
        }
 #endif
@@ -248,14 +252,14 @@ static void remove_user (const char *user,
                fprintf (stderr,
                         _("%s: failed to prepare the new %s entry '%s'\n"),
                         Prog, gr_dbname (), newgrp->gr_name);
-               fail_exit (13);
+               fail_exit (13, process_selinux);
        }
 }
 
 /*
  * purge_members - Remove every members of the specified group
  */
-static void purge_members (const struct group *grp)
+static void purge_members (const struct group *grp, bool process_selinux)
 {
        struct group *newgrp = __gr_dup (grp);
 
@@ -263,7 +267,7 @@ static void purge_members (const struct group *grp)
                fprintf (stderr,
                         _("%s: Out of memory. Cannot update %s.\n"),
                         Prog, gr_dbname ());
-               fail_exit (13);
+               fail_exit (13, process_selinux);
        }
 
        /* Remove all the members of the /etc/group group */
@@ -294,7 +298,7 @@ static void purge_members (const struct group *grp)
                                fprintf (stderr,
                                         _("%s: Out of memory. Cannot update %s.\n"),
                                         Prog, sgr_dbname ());
-                               fail_exit (13);
+                               fail_exit (13, process_selinux);
                        }
                        /* Remove all the members of the /etc/gshadow
                         * group */
@@ -308,7 +312,7 @@ static void purge_members (const struct group *grp)
                        fprintf (stderr,
                                 _("%s: failed to prepare the new %s entry '%s'\n"),
                                 Prog, sgr_dbname (), newsg->sg_namp);
-                       fail_exit (13);
+                       fail_exit (13, process_selinux);
                }
        }
 #endif
@@ -317,7 +321,7 @@ static void purge_members (const struct group *grp)
                fprintf (stderr,
                         _("%s: failed to prepare the new %s entry '%s'\n"),
                         Prog, gr_dbname (), newgrp->gr_name);
-               fail_exit (13);
+               fail_exit (13, process_selinux);
        }
 }
 
@@ -418,12 +422,12 @@ static void process_flags (int argc, char **argv, struct option_flags *flags)
            && (getpwnam (adduser) == NULL)) {
                fprintf (stderr, _("%s: user '%s' does not exist\n"),
                         Prog, adduser);
-               fail_exit (EXIT_INVALID_USER);
+               fail_exit (EXIT_INVALID_USER, !flags->chroot);
        }
 
 }
 
-static void check_perms (void)
+static void check_perms (bool process_selinux)
 {
        if (!list) {
 #ifdef USE_PAM
@@ -436,7 +440,7 @@ static void check_perms (void)
                        fprintf (stderr,
                                 _("%s: Cannot determine your user name.\n"),
                                 Prog);
-                       fail_exit (1);
+                       fail_exit (1, process_selinux);
                }
 
                retval = pam_start (Prog, pampw->pw_name, &conv, &pamh);
@@ -456,17 +460,17 @@ static void check_perms (void)
                        if (NULL != pamh) {
                                (void) pam_end (pamh, retval);
                        }
-                       fail_exit (1);
+                       fail_exit (1, process_selinux);
                }
                (void) pam_end (pamh, retval);
 #endif
        }
 }
 
-static void fail_exit (int code)
+static void fail_exit (int code, bool process_selinux)
 {
        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 ());
@@ -477,7 +481,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 ());
@@ -490,14 +494,14 @@ static void fail_exit (int code)
        exit (code);
 }
 
-static void open_files (void)
+static void open_files (bool process_selinux)
 {
        if (!list) {
                if (gr_lock () == 0) {
                        fprintf (stderr,
                                 _("%s: cannot lock %s; try again later.\n"),
                                 Prog, gr_dbname ());
-                       fail_exit (EXIT_GROUP_FILE);
+                       fail_exit (EXIT_GROUP_FILE, process_selinux);
                }
                gr_locked = true;
 
@@ -507,7 +511,7 @@ static void open_files (void)
                                fprintf (stderr,
                                         _("%s: cannot lock %s; try again later.\n"),
                                         Prog, sgr_dbname ());
-                               fail_exit (EXIT_GROUP_FILE);
+                               fail_exit (EXIT_GROUP_FILE, process_selinux);
                        }
                        sgr_locked = true;
                }
@@ -516,14 +520,14 @@ static void open_files (void)
 
        if (gr_open (list ? O_RDONLY : O_CREAT | O_RDWR) == 0) {
                fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
-               fail_exit (EXIT_GROUP_FILE);
+               fail_exit (EXIT_GROUP_FILE, process_selinux);
        }
 
 #ifdef SHADOWGRP
        if (is_shadowgrp) {
                if (sgr_open (list ? O_RDONLY : O_CREAT | O_RDWR) == 0) {
                        fprintf (stderr, _("%s: cannot open %s\n"), Prog, sgr_dbname ());
-                       fail_exit (EXIT_GROUP_FILE);
+                       fail_exit (EXIT_GROUP_FILE, process_selinux);
                }
        }
 #endif
@@ -538,7 +542,7 @@ static void close_files (struct option_flags *flags)
        if ((gr_close (process_selinux) == 0) && !list) {
                fprintf (stderr, _("%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_GROUP_FILE);
+               fail_exit (EXIT_GROUP_FILE, process_selinux);
        }
        if (gr_locked) {
                if (gr_unlock (process_selinux) == 0) {
@@ -554,7 +558,7 @@ static void close_files (struct option_flags *flags)
                if ((sgr_close (process_selinux) == 0) && !list) {
                        fprintf (stderr, _("%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_GROUP_FILE);
+                       fail_exit (EXIT_GROUP_FILE, process_selinux);
                }
                if (sgr_locked) {
                        if (sgr_unlock (process_selinux) == 0) {
@@ -573,6 +577,7 @@ int main (int argc, char **argv)
        char *name;
        const struct group *grp;
        struct option_flags  flags;
+       bool process_selinux;
 
        log_set_progname(Prog);
        log_set_logfd(stderr);
@@ -590,40 +595,41 @@ int main (int argc, char **argv)
 #endif
 
        process_flags (argc, argv, &flags);
+       process_selinux = !flags.chroot;
 
        if (NULL == thisgroup) {
                name = whoami ();
                if (!list && (NULL == name)) {
                        fprintf (stderr, _("%s: your groupname does not match your username\n"), Prog);
-                       fail_exit (EXIT_NOT_PRIMARY);
+                       fail_exit (EXIT_NOT_PRIMARY, process_selinux);
                }
        } else {
                name = thisgroup;
                if (!list && !isroot ()) {
                        fprintf (stderr, _("%s: only root can use the -g/--group option\n"), Prog);
-                       fail_exit (EXIT_NOT_ROOT);
+                       fail_exit (EXIT_NOT_ROOT, process_selinux);
                }
        }
 
-       check_perms ();
+       check_perms (process_selinux);
 
-       open_files ();
+       open_files (process_selinux);
 
        grp = gr_locate (name);
        if (NULL == grp) {
                fprintf (stderr, _("%s: group '%s' does not exist in %s\n"),
                         Prog, name, gr_dbname ());
-               fail_exit (EXIT_INVALID_GROUP);
+               fail_exit (EXIT_INVALID_GROUP, process_selinux);
        }
 
        if (list) {
                display_members ((const char *const *)grp->gr_mem);
        } else if (NULL != adduser) {
-               add_user (adduser, grp);
+               add_user (adduser, grp, process_selinux);
        } else if (NULL != deluser) {
-               remove_user (deluser, grp);
+               remove_user (deluser, grp, process_selinux);
        } else if (purge) {
-               purge_members (grp);
+               purge_members (grp, process_selinux);
        }
 
        close_files (&flags);