Blame SOURCES/0066-su-clean-up-groups-initialization.patch

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