From b2a41801904c4b281a717dde7f5e146cbd4500b3 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 15 Feb 2016 13:55:37 +0100 Subject: [PATCH 66/84] su: clean up groups initialization This patch does not change any su/runuser behaviour, code changes: * don't use huge groups[NGROUPS_MAX]; the array has 256k, but we need it only occasionally when -G/-g specified. * the current code uses groups[0] for -g and the rest for -G, this patch adds 'gid' to remember -g argument to avoid memmove() * add function add_supp_group() to simplify su_main() * add note about -G and -g relation to the man pages (undocumented now) Upstream: http://github.com/karelzak/util-linux/commit/c619d3d167115990e9228b27851e0cc2faa8f936 Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1304426 Signed-off-by: Karel Zak --- login-utils/runuser.1 | 5 ++-- login-utils/su-common.c | 68 +++++++++++++++++++++++++++---------------------- login-utils/su.1 | 5 ++-- 3 files changed, 44 insertions(+), 34 deletions(-) diff --git a/login-utils/runuser.1 b/login-utils/runuser.1 index 7201ff0..d82dbb0 100644 --- a/login-utils/runuser.1 +++ b/login-utils/runuser.1 @@ -75,8 +75,9 @@ shell. \fB\-g\fR, \fB\-\-group\fR=\fIgroup\fR\fR specify the primary group, this option is allowed for root user only .TP -\fB\-G\fR, \fB\-\-supp-group\fR=\fIgroup\fR\fR -specify a supplemental group, this option is allowed for root user only +.BR \-G , " \-\-supp\-group" = \fIgroup +Specify a supplemental group. This option is available to the root user only. The first specified +supplementary group is also used as a primary group if the option \fB\-\-group\fR is unspecified. .TP \fB\-\fR, \fB\-l\fR, \fB\-\-login\fR Starts the shell as login shell with an environment similar to a real diff --git a/login-utils/su-common.c b/login-utils/su-common.c index dd87804..d53d690 100644 --- a/login-utils/su-common.c +++ b/login-utils/su-common.c @@ -535,7 +535,7 @@ modify_environment (const struct passwd *pw, const char *shell) /* Become the user and group(s) specified by PW. */ static void -init_groups (const struct passwd *pw, gid_t *groups, int num_groups) +init_groups (const struct passwd *pw, gid_t *groups, size_t num_groups) { int retval; @@ -707,6 +707,28 @@ evaluate_uid(void) return (uid_t) 0 == ruid && ruid == euid ? 0 : 1; } +static gid_t +add_supp_group(const char *name, gid_t **groups, size_t *ngroups) +{ + struct group *gr; + + if (*ngroups >= NGROUPS_MAX) + errx(EXIT_FAILURE, + P_("specifying more than %d supplemental group is not possible", + "specifying more than %d supplemental groups is not possible", + NGROUPS_MAX - 1), NGROUPS_MAX - 1); + + gr = getgrnam(name); + if (!gr) + errx(EXIT_FAILURE, _("group %s does not exist"), name); + + *groups = xrealloc(*groups, sizeof(gid_t) * (*ngroups + 1)); + (*groups)[*ngroups] = gr->gr_gid; + (*ngroups)++; + + return gr->gr_gid; +} + int su_main (int argc, char **argv, int mode) { @@ -717,10 +739,12 @@ su_main (int argc, char **argv, int mode) char *shell = NULL; struct passwd *pw; struct passwd pw_copy; - struct group *gr; - gid_t groups[NGROUPS_MAX]; - int num_supp_groups = 0; - int use_gid = 0; + + gid_t *groups = NULL; + size_t ngroups = 0; + bool use_supp = false; + bool use_gid = false; + gid_t gid = 0; static const struct option longopts[] = { {"command", required_argument, NULL, 'c'}, @@ -765,23 +789,13 @@ su_main (int argc, char **argv, int mode) break; case 'g': - gr = getgrnam(optarg); - if (!gr) - errx(EXIT_FAILURE, _("group %s does not exist"), optarg); - use_gid = 1; - groups[0] = gr->gr_gid; + use_gid = true; + gid = add_supp_group(optarg, &groups, &ngroups); break; case 'G': - num_supp_groups++; - if (num_supp_groups >= NGROUPS_MAX) - errx(EXIT_FAILURE, - _("can't specify more than %d supplemental groups"), - NGROUPS_MAX - 1); - gr = getgrnam(optarg); - if (!gr) - errx(EXIT_FAILURE, _("group %s does not exist"), optarg); - groups[num_supp_groups] = gr->gr_gid; + use_supp = true; + add_supp_group(optarg, &groups, &ngroups); break; case 'l': @@ -852,7 +866,7 @@ su_main (int argc, char **argv, int mode) break; } - if ((num_supp_groups || use_gid) && restricted) + if ((use_supp || use_gid) && restricted) errx(EXIT_FAILURE, _("only root can specify alternative groups")); logindefs_load_defaults = load_config; @@ -878,16 +892,10 @@ su_main (int argc, char **argv, int mode) : DEFAULT_SHELL); endpwent (); - if (num_supp_groups && !use_gid) - { - pw->pw_gid = groups[1]; - memmove (groups, groups + 1, sizeof(gid_t) * num_supp_groups); - } - else if (use_gid) - { + if (use_supp && !use_gid) pw->pw_gid = groups[0]; - num_supp_groups++; - } + else if (use_gid) + pw->pw_gid = gid; authenticate (pw); @@ -912,7 +920,7 @@ su_main (int argc, char **argv, int mode) shell = xstrdup (shell ? shell : pw->pw_shell); } - init_groups (pw, groups, num_supp_groups); + init_groups (pw, groups, ngroups); if (!simulate_login || command) suppress_pam_info = 1; /* don't print PAM info messages */ diff --git a/login-utils/su.1 b/login-utils/su.1 index eab1a6f..1f69868 100644 --- a/login-utils/su.1 +++ b/login-utils/su.1 @@ -62,8 +62,9 @@ shell. \fB\-g\fR, \fB\-\-group\fR=\fIgroup\fR\fR specify the primary group, this option is allowed for root user only .TP -\fB\-G\fR, \fB\-\-supp-group\fR=\fIgroup\fR\fR -specify a supplemental group, this option is allowed for root user only +.BR \-G , " \-\-supp\-group" = \fIgroup +Specify a supplemental group. This option is available to the root user only. The first specified +supplementary group is also used as a primary group if the option \fB\-\-group\fR is unspecified. .TP \fB\-\fR, \fB\-l\fR, \fB\-\-login\fR Starts the shell as login shell with an environment similar to a real -- 2.7.4