Print this page
4078 groupadd execs getent unnecessarily
Reviewed by: Rich Lowe <richlowe@richlowe.net>
Reviewed by: Gary Mills <gary_mills@fastmail.fm>
Reviewed by: Milan Jurik <milan.jurik@xylab.cz>
Reviewed by: Gordon Ross <Gordon.W.Ross@gmail.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/oamuser/group/gid.c
          +++ new/usr/src/lib/libcmdutils/common/gid.c
↓ open down ↓ 14 lines elided ↑ open up ↑
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
       25 +
  25   26  /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  26   27  /*        All Rights Reserved   */
  27   28  
       29 +/*
       30 + * Copyright (c) 2013 RackTop Systems.
       31 + */
  28   32  
  29      -#pragma ident   "%Z%%M% %I%     %E% SMI"        /* SVr4.0 1.5 */
  30      -
       33 +#include <errno.h>
  31   34  #include <sys/types.h>
  32   35  #include <stdio.h>
  33   36  #include <userdefs.h>
       37 +#include <grp.h>
       38 +#include <libcmdutils.h>
  34   39  
  35      -#include <sys/param.h>
  36      -#ifndef MAXUID
  37      -#include <limits.h>
  38      -#ifdef UID_MAX
  39      -#define MAXUID  UID_MAX
  40      -#else
  41      -#define MAXUID  60000
  42      -#endif
  43      -#endif
       40 +static int findunusedgid(gid_t start, gid_t stop, gid_t *ret);
       41 +static boolean_t isreservedgid(gid_t gid);
  44   42  
  45   43  /*
  46      - * Check to see that the gid is not a reserved gid
       44 + * Find the highest unused uid. If the highest unused gid is "stop",
       45 + * then attempt to find a hole in the range. Returns 0 on success.
       46 + */
       47 +int
       48 +findnextgid(gid_t start, gid_t stop, gid_t *ret)
       49 +{
       50 +        gid_t gid = start;
       51 +        struct group *grp;
       52 +        boolean_t overflow = B_FALSE;
       53 +
       54 +        setgrent();
       55 +        for (grp = getgrent(); grp != NULL; grp = getgrent()) {
       56 +                if (isreservedgid(grp->gr_gid))         /* Skip reserved IDs */
       57 +                        continue;
       58 +                if (grp->gr_gid >= gid) {
       59 +                        if (grp->gr_gid == stop) {      /* Overflow check */
       60 +                                overflow = B_TRUE;
       61 +                                break;
       62 +                        }
       63 +                        gid = grp->gr_gid + 1;
       64 +                }
       65 +        }
       66 +        if (grp == NULL && errno != 0) {
       67 +                endgrent();
       68 +                return (-1);
       69 +        }
       70 +        endgrent();
       71 +        if (overflow == B_TRUE)                         /* Find a hole */
       72 +                return (findunusedgid(start, stop, ret));
       73 +        while (isreservedgid(gid) && gid < stop)        /* Skip reserved IDs */
       74 +                gid++;
       75 +        *ret = gid;
       76 +        return (0);
       77 +}
       78 +
       79 +/*
       80 + * Check to see whether the gid is a reserved gid
  47   81   * -- nobody, noaccess or nogroup
  48   82   */
  49      -static int
  50      -isvalidgid(gid_t gid)
       83 +static boolean_t
       84 +isreservedgid(gid_t gid)
  51   85  {
  52      -        return (gid != 60001 && gid != 60002 && gid != 65534);
       86 +        return (gid == 60001 || gid == 60002 || gid == 65534);
  53   87  }
  54   88  
  55      -gid_t
  56      -findnextgid()
       89 +/*
       90 + * findunusedgid() attempts to return the next valid usable id between the
       91 + * supplied upper and lower limits. Returns 0 on success.
       92 + */
       93 +static int
       94 +findunusedgid(gid_t start, gid_t stop, gid_t *ret)
  57   95  {
  58      -        FILE *fptr;
  59      -        gid_t last, next;
  60   96          gid_t gid;
  61   97  
  62      -        /*
  63      -         * Sort the used GIDs in decreasing order to return MAXUSED + 1
  64      -         */
  65      -        if ((fptr = popen("exec sh -c "
  66      -            "\"getent group|cut -f3 -d:|sort -nr|uniq \" 2>/dev/null",
  67      -            "r")) == NULL)
  68      -                return (-1);
  69      -
  70      -        if (fscanf(fptr, "%u\n", &next) == EOF) {
  71      -                (void) pclose(fptr);
  72      -                return (DEFRID + 1);
  73      -        }
  74      -
  75      -        /*
  76      -         * 'next' is now the highest allocated gid.
  77      -         *
  78      -         * The simplest allocation is where we just add one, and obtain
  79      -         * a valid gid.  If this fails look for a hole in the gid range ..
  80      -         */
  81      -
  82      -        last = MAXUID;          /* upper limit */
  83      -        gid = -1;               /* start invalid */
  84      -        do {
  85      -                if (!isvalidgid(next))
       98 +        for (gid = start; gid <= stop; gid++) {
       99 +                if (isreservedgid(gid))
  86  100                          continue;
  87      -
  88      -                if (next <= DEFRID) {
  89      -                        if (last != DEFRID + 1)
  90      -                                gid = DEFRID + 1;
      101 +                if (getgrgid(gid) == NULL) {
      102 +                        if (errno != 0)
      103 +                                return (-1);
  91  104                          break;
  92  105                  }
  93      -
  94      -                if ((gid = next + 1) != last) {
  95      -                        while (!isvalidgid(gid))
  96      -                                gid++;
  97      -                        if (gid > 0 && gid < last)
  98      -                                break;
  99      -                }
 100      -
 101      -                gid = -1;
 102      -                last = next;
 103      -
 104      -        } while (fscanf(fptr, "%u\n", &next) != EOF);
 105      -
 106      -        (void) pclose(fptr);
 107      -
 108      -        return (gid);
      106 +        }
      107 +        if (gid > stop)
      108 +                return (-1);
      109 +        *ret = gid;
      110 +        return (0);
 109  111  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX