Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 23 Jan 2018 22:18:45 +0000 (UTC)
From:      Kirk McKusick <mckusick@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r328304 - in head/lib/libc: gen sys
Message-ID:  <201801232218.w0NMIjV3089843@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mckusick
Date: Tue Jan 23 22:18:45 2018
New Revision: 328304
URL: https://svnweb.freebsd.org/changeset/base/328304

Log:
  In the C library, the setting up of the group array by various
  utilities is done by calling gr_addgid() for each group to be
  added (usually found by traversing /etc/group) then calling the
  setgroups() system call after the group set has been created.
  The gr_addgid() function (helpfully?) deduplicates the addition
  of group members. So, if you call it to add a group member that
  already exists, it is just dropped. Because group[0] is the
  effective group-ID and is over-written when a setgid program
  is run, The value in group[0] is usually duplicated so that
  group value is not lost when a setgid program is run.
  
  Historically this happened because the group value indicated
  in the password file also appears in /etc/group (e.g., if you
  are group staff in the password file, you will also appear in
  the staff line in /etc/group). But, with the addition of the
  deduplication, the attempt to add group staff was lost because
  it already appeared in group[0]. So, the fix is to deduplicate
  starting from group[1] which allows a duplicate of the entry in
  group[0], but not in later entries.
  
  There is some confusion about the setgroups system call because in
  BSD it has (always) set the entire group including the egid group
  (in group[0]). However, in Linux, it skips over group[0] and starts
  setting from group[1]. See this comment from linux_setgroups:
  
        /*
         * cr_groups[0] holds egid. Setting the whole set from
         * the supplied set will cause egid to be changed too.
         * Keep cr_groups[0] unchanged to prevent that.
         */
  
  To make it clear what the BSD setgroups system call does, I
  added the following paragraph to the setgroups(2) manual page:
  
     The first entry of the group array (gidset[0]) is used as the effective
     group-ID for the process.  This entry is over-written when a setgid
     program is run.  To avoid losing access to the privileges of the
     gidset[0] entry, it should be duplicated later in the group array.
     By convention, this happens because the group value indicated in the
     password file also appears in /etc/group.  The group value in the
     password file is placed in gidset[0] and that value then gets added a
     second time when the /etc/group file is scanned to create the group set.
  
  Reported by: Paul McMath  paulm at tetrardus.net
  Reviewed by: kib
  MFC after:   2 weeks

Modified:
  head/lib/libc/gen/getgrent.c
  head/lib/libc/sys/setgroups.2

Modified: head/lib/libc/gen/getgrent.c
==============================================================================
--- head/lib/libc/gen/getgrent.c	Tue Jan 23 21:36:26 2018	(r328303)
+++ head/lib/libc/gen/getgrent.c	Tue Jan 23 22:18:45 2018	(r328304)
@@ -436,7 +436,7 @@ gr_addgid(gid_t gid, gid_t *groups, int maxgrp, int *g
 {
 	int     ret, dupc;
 
-	for (dupc = 0; dupc < MIN(maxgrp, *grpcnt); dupc++) {
+	for (dupc = 1; dupc < MIN(maxgrp, *grpcnt); dupc++) {
 		if (groups[dupc] == gid)
 			return 1;
 	}

Modified: head/lib/libc/sys/setgroups.2
==============================================================================
--- head/lib/libc/sys/setgroups.2	Tue Jan 23 21:36:26 2018	(r328303)
+++ head/lib/libc/sys/setgroups.2	Tue Jan 23 22:18:45 2018	(r328304)
@@ -56,6 +56,23 @@ more than
 .Dv {NGROUPS_MAX}+1 .
 .Pp
 Only the super-user may set a new group list.
+.Pp
+The first entry of the group array
+.Pq Va gidset[0]
+is used as the effective group-ID for the process.
+This entry is over-written when a setgid program is run.
+To avoid losing access to the privileges of the
+.Va gidset[0]
+entry, it should be duplicated later in the group array.
+By convention,
+this happens because the group value indicated
+in the password file also appears in
+.Pa /etc/group .
+The group value in the password file is placed in
+.Va gidset[0]
+and that value then gets added a second time when the
+.Pa /etc/group
+file is scanned to create the group set.
 .Sh RETURN VALUES
 .Rv -std setgroups
 .Sh ERRORS



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201801232218.w0NMIjV3089843>