From patchwork Mon Aug 22 21:03:05 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gary Tierney X-Patchwork-Id: 9294389 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 27775608A7 for ; Mon, 22 Aug 2016 21:04:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 156DF28A82 for ; Mon, 22 Aug 2016 21:04:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 09FBA28AA9; Mon, 22 Aug 2016 21:04:12 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from emsm-gh1-uea11.nsa.gov (emsm-gh1-uea11.nsa.gov [8.44.101.9]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A0EA228A82 for ; Mon, 22 Aug 2016 21:04:10 +0000 (UTC) X-IronPort-AV: E=Sophos;i="5.28,562,1464652800"; d="scan'208";a="18662377" IronPort-PHdr: =?us-ascii?q?9a23=3AhR5qfRE9h+/UQvhukoT63p1GYnF86YWxBRYc798d?= =?us-ascii?q?s5kLTJ75oM+wAkXT6L1XgUPTWs2DsrQf2rOQ6PqrBzBIoc7Y9itTKNoUD15NoP?= =?us-ascii?q?5VtjRoONSCB0z/IayiRA0BN+MGamVY+WqmO1NeAsf0ag6aiHSz6TkPBke3blIt?= =?us-ascii?q?dazLE4Lfx/66y/q1s8WKJV4Z3XzmO/gscF329VyX7ZhOx9M6a+4Y8VjgmjNwYe?= =?us-ascii?q?NYxGdldxq4vi3XwYOOxqNl6DlaoPk79sRNAu3QdqU8SqFEXnx9azhmrPDxsVH/?= =?us-ascii?q?aSfHpj5FCiRF2iZPVhPI6BD8Q4fZrjrxtu073jKTe8LxU+MaQzOnuohiUg6gtC?= =?us-ascii?q?YKLTg04SmDhcVqneRHoR+7oRFu64HRcMeeM/8oLfCVRs8TWWcUBpUZbCdGGI7p?= =?us-ascii?q?KtJXAg=3D=3D?= X-IPAS-Result: =?us-ascii?q?A2GJBABgaLtX/wHyM5BdGgEBAQGDJoFSuX8dh21MAQEBAQE?= =?us-ascii?q?BAQIBAlsngjIEAxGCFQIEAQIkExQgDgMJAQEXIQEBBggIAwEtCwoRDgsFGASHd?= =?us-ascii?q?QEDFwSiL5cSAYUWHoYNhxCBTxEBZAEFhQ0Fjh+LKYFkiiWDGIluhWCQN1SCEhy?= =?us-ascii?q?BTW+FOA0XgR8BAQE?= Received: from unknown (HELO tarius.tycho.ncsc.mil) ([144.51.242.1]) by emsm-gh1-uea11.nsa.gov with ESMTP; 22 Aug 2016 21:04:02 +0000 Received: from prometheus.infosec.tycho.ncsc.mil (prometheus [192.168.25.40]) by tarius.tycho.ncsc.mil (8.14.4/8.14.4) with ESMTP id u7ML3vN6020048; Mon, 22 Aug 2016 17:03:57 -0400 Received: from tarius.tycho.ncsc.mil (tarius.infosec.tycho.ncsc.mil [144.51.242.1]) by prometheus.infosec.tycho.ncsc.mil (8.15.2/8.15.2) with ESMTP id u7ML3DRg107587 for ; Mon, 22 Aug 2016 17:03:13 -0400 Received: from goalie.tycho.ncsc.mil (goalie [144.51.242.250]) by tarius.tycho.ncsc.mil (8.14.4/8.14.4) with ESMTP id u7ML3CfB019975 for ; Mon, 22 Aug 2016 17:03:13 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A1AlAwAvZ7tXhw8P49RdGgEBAQGEeKRSBJEhhAyGHQKBZ0wBAQEBAQEBAhMBAQEIDQkJGYUOAgEDJ1IQOQEBFjwbGYgWAQMboi6XEwGEZQEBCCcehg2HEIJFAQWFDQWOH4spgWSKJYMYj06QN4JmEQuBTW+FOA0XgR8BAQE X-IPAS-Result: A1AlAwAvZ7tXhw8P49RdGgEBAQGEeKRSBJEhhAyGHQKBZ0wBAQEBAQEBAhMBAQEIDQkJGYUOAgEDJ1IQOQEBFjwbGYgWAQMboi6XEwGEZQEBCCcehg2HEIJFAQWFDQWOH4spgWSKJYMYj06QN4JmEQuBTW+FOA0XgR8BAQE X-IronPort-AV: E=Sophos;i="5.28,562,1464667200"; d="scan'208";a="5658916" Received: from emsm-gh1-uea10.corp.nsa.gov (HELO emsm-gh1-uea10.nsa.gov) ([10.208.41.36]) by goalie.tycho.ncsc.mil with ESMTP; 22 Aug 2016 17:03:13 -0400 IronPort-PHdr: =?us-ascii?q?9a23=3AbiLZ/xJeg+phBPZuFNmcpTZWNBhigK39O0sv0rFi?= =?us-ascii?q?tYgUL/TxwZ3uMQTl6Ol3ixeRBMOAuqsC0LCd7fyoGTRZp83Q6DZaKN0EfiRGoP?= =?us-ascii?q?1epxYnDs+BBB+zB9/RRAt+Iv5/UkR49WqwK0lfFZW2TVTTpnqv8WxaQU2nZkJL?= =?us-ascii?q?L+j4UrTfk96wn7jrvcaCOkMT3nHjPfsydEzw9lSJ8JFOwMNLEeUY8lPxuHxGeu?= =?us-ascii?q?BblytDBGm4uFLC3Pq254Np6C9KuvgspIZqWKT+eLkkH/QDVGx1ezN92Mq+rhTH?= =?us-ascii?q?TA2S9lMAQ24WlVxOGAGD4xbkDbnrtS6vmeNnyWGmPMDsS70lEWCt5r16DgPphT?= =?us-ascii?q?0BOi8R/2THzMd3ifQI81qauxVjztuMM8muP/1kc/aFcA=3D=3D?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0HjAgAYaLtXhw8P49RdGwEBAYR4pFIEk?= =?us-ascii?q?SGEDIYdAoFnTAEBAQEBAQECAQIQAQEBCA0JCRkvgjIWghcCAQMnUhA5AQEWPBs?= =?us-ascii?q?ZiBYBAxuiL5cTAYRlAQEIJx6GDYcQgkUBBYUNBY4fiymBZIolgxiPTpA3gmYRC?= =?us-ascii?q?4FNb4U4DReBHwEBAQ?= X-IPAS-Result: =?us-ascii?q?A0HjAgAYaLtXhw8P49RdGwEBAYR4pFIEkSGEDIYdAoFnTAE?= =?us-ascii?q?BAQEBAQECAQIQAQEBCA0JCRkvgjIWghcCAQMnUhA5AQEWPBsZiBYBAxuiL5cTA?= =?us-ascii?q?YRlAQEIJx6GDYcQgkUBBYUNBY4fiymBZIolgxiPTpA3gmYRC4FNb4U4DReBHwE?= =?us-ascii?q?BAQ?= X-IronPort-AV: E=Sophos;i="5.28,562,1464652800"; d="scan'208";a="16828356" Received: from mout.gmx.net ([212.227.15.15]) by emsm-gh1-uea10.nsa.gov with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 22 Aug 2016 21:03:11 +0000 Received: from home ([79.71.36.116]) by mail.gmx.com (mrgmx003) with ESMTPA (Nemesis) id 0MBWTO-1bTfBI1ncs-00AV4x; Mon, 22 Aug 2016 23:03:10 +0200 From: Gary Tierney To: selinux@tycho.nsa.gov Subject: [PATCH v3 2/2] genhomedircon: add support for %group syntax Date: Mon, 22 Aug 2016 22:03:05 +0100 Message-Id: <1471899785-22194-3-git-send-email-gary.tierney@gmx.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1471899785-22194-1-git-send-email-gary.tierney@gmx.com> References: <1471899785-22194-1-git-send-email-gary.tierney@gmx.com> X-Provags-ID: V03:K0:6IRvuJ4EY4/V7KI5t46a9iOcOquVBRaiSSBiESFg24SGATtyDIy JM3acPmiBpcNUZ8GJGA+QGWPI2mWZpX2E+Fv+blJtLFSr4eTImS0D/CK+MBkIBcE6SKscHa I86wAmkDvLCkJoXJ7NE41BZAs/TypMhif1E4lrlQZmtUi5g5v3HEtVMPvmQJHahPA3UjwVH kYn3frTUztW3wbBzjaQuw== X-UI-Out-Filterresults: notjunk:1; V01:K0:3VW4e/GP/eA=:L2EZv19eoPgKQAurqu4Q3M zHtcyTuyC2wA9rqogBUIjLZa+r7LIqAjksiiulCKn2VIEj1LWEMbcUoVd6LHp8o1ZX2qSgh31 /vyvElzDHQulfJtSTcYZIgoGL+KZBPOX1uOu66l1ydAAsxSnMzCbPGQK3PePUKOxSoj7OnCQV a8/aVa1K4e50u0SKOTVJINm2VEW95YGa/sonnty/o0awpi5adE7/SgbXmMyp0NRj9mLt3HxiH mzJAXNQac32jCQ+HrF9fDzMj76IcgdE3dKbO0js4TnJ4UzqvskxOwho98xRkyv0Iw91jykhhH UPFNEo7HnrAZBcHhYrEbcJQCSoNzb0peq7pbsN6A/3M6i87R9b166gKq8HlINBRAw/zKTDrIu IY0s1YUhw7JXF5JmbMN3XZ5cmebUVoO+xlKbfg/M0yv9UKNLx6lWKP1N8jEP/XYrg2ZJomhnP L8O9H1LF3xvRyg6n5wY8XE8xwD+qoDZcRwnJLBOyhchrLzKl+lIJU8xSW984fWM8WaLg82T46 RVFAhz1nG32Ns+aO5qFNk2b1sJVYtJzTTChzuSF38CvpmaphXXVu+S3JkGyI6tVwnAbyNW3FZ cR/GTiLTMuzPynHDx9WCeIqaesPEM7vG8uiApB6C3tPNLef9IZYKnXauVNwTh8UTccxXtH2A1 WlzIFn8Xbjacj/CyYCppnw/7vShPmP39IGlvQMHDQQaN8W/K2OBcuNMSVlZiS4hsXKNyd5ZY9 R3PkJ423Kx7+Xdig4zuQCss6PDVte1GdWKkR0cIC59CARxzSWFVM09A3kLM= X-BeenThere: selinux@tycho.nsa.gov X-Mailman-Version: 2.1.20 Precedence: list List-Id: "Security-Enhanced Linux \(SELinux\) mailing list" List-Post: List-Help: MIME-Version: 1.0 Errors-To: selinux-bounces@tycho.nsa.gov Sender: "Selinux" X-Virus-Scanned: ClamAV using ClamSMTP semanage-login supports login mappings using the %group syntax, but genhomedircon does not expand groups to the users belonging to them. This commit adds support for generating home directory contexts for login mappings using the group syntax and adds error reporting for handling cases where there is ambiguity due to a user belonging to multiple groups mapped by semanage-login. If a login mapping is added for the user which belongs to multiple groups it will take precedence and resolve the ambiguity issue. Signed-off-by: Gary Tierney --- libsemanage/src/genhomedircon.c | 311 +++++++++++++++++++++++++++++++--------- 1 file changed, 243 insertions(+), 68 deletions(-) diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c index 698b907..cce3884 100644 --- a/libsemanage/src/genhomedircon.c +++ b/libsemanage/src/genhomedircon.c @@ -48,6 +48,8 @@ #include #include #include +#include +#include /* paths used in get_home_dirs() */ #define PATH_ETC_USERADD "/etc/default/useradd" @@ -98,6 +100,7 @@ typedef struct user_entry { char *prefix; char *home; char *level; + char *login; struct user_entry *next; } genhomedircon_user_entry_t; @@ -486,6 +489,11 @@ static int USER_CONTEXT_PRED(const char *string) return (int)(strstr(string, TEMPLATE_USER) != NULL); } +static int STR_COMPARATOR(const void *a, const void *b) +{ + return strcmp((const char *) a, (const char *) b); +} + /* make_tempate * @param s the settings holding the paths to various files * @param pred function pointer to function to use as filter for slurp @@ -652,6 +660,24 @@ static int write_user_context(genhomedircon_settings_t * s, FILE * out, return write_replacements(s, out, tpl, repl); } +static int seuser_sort_func(const void *arg1, const void *arg2) +{ + const semanage_seuser_t **u1 = (const semanage_seuser_t **) arg1; + const semanage_seuser_t **u2 = (const semanage_seuser_t **) arg2;; + const char *name1 = semanage_seuser_get_name(*u1); + const char *name2 = semanage_seuser_get_name(*u2); + + if (name1[0] == '%' && name2[0] == '%') { + return 0; + } else if (name1[0] == '%') { + return 1; + } else if (name2[0] == '%') { + return -1; + } + + return strcmp(name1, name2); +} + static int user_sort_func(semanage_user_t ** arg1, semanage_user_t ** arg2) { return strcmp(semanage_user_get_name(*arg1), @@ -665,7 +691,8 @@ static int name_user_cmp(char *key, semanage_user_t ** val) static int push_user_entry(genhomedircon_user_entry_t ** list, const char *n, const char *u, const char *g, const char *sen, - const char *pre, const char *h, const char *l) + const char *pre, const char *h, const char *l, + const char *ln) { genhomedircon_user_entry_t *temp = NULL; char *name = NULL; @@ -675,6 +702,7 @@ static int push_user_entry(genhomedircon_user_entry_t ** list, const char *n, char *prefix = NULL; char *home = NULL; char *level = NULL; + char *lname = NULL; temp = malloc(sizeof(genhomedircon_user_entry_t)); if (!temp) @@ -700,6 +728,9 @@ static int push_user_entry(genhomedircon_user_entry_t ** list, const char *n, level = strdup(l); if (!level) goto cleanup; + lname = strdup(ln); + if (!lname) + goto cleanup; temp->name = name; temp->uid = uid; @@ -708,6 +739,7 @@ static int push_user_entry(genhomedircon_user_entry_t ** list, const char *n, temp->prefix = prefix; temp->home = home; temp->level = level; + temp->login = lname; temp->next = (*list); (*list) = temp; @@ -721,6 +753,7 @@ static int push_user_entry(genhomedircon_user_entry_t ** list, const char *n, free(prefix); free(home); free(level); + free(lname); free(temp); return STATUS_ERR; } @@ -741,6 +774,7 @@ static void pop_user_entry(genhomedircon_user_entry_t ** list) free(temp->prefix); free(temp->home); free(temp->level); + free(temp->login); free(temp); } @@ -790,7 +824,8 @@ static int setup_fallback_user(genhomedircon_settings_t * s) if (push_user_entry(&(s->fallback), FALLBACK_NAME, FALLBACK_UIDGID, FALLBACK_UIDGID, - seuname, prefix, "", level) != 0) + seuname, prefix, "", level, + FALLBACK_NAME) != 0) errors = STATUS_ERR; semanage_user_key_free(key); if (u) @@ -806,6 +841,202 @@ static int setup_fallback_user(genhomedircon_settings_t * s) return errors; } +static genhomedircon_user_entry_t *find_user(genhomedircon_user_entry_t *head, + const char *name) +{ + for(; head; head = head->next) { + if (strcmp(head->name, name) == 0) { + return head; + } + } + + return NULL; +} + +static int add_user(genhomedircon_settings_t * s, + genhomedircon_user_entry_t **head, + semanage_user_t *user, + const char *name, + const char *sename, + const char *selogin) +{ + if (selogin[0] == '%') { + genhomedircon_user_entry_t *orig = find_user(*head, name); + if (orig != NULL && orig->login[0] == '%') { + ERR(s->h_semanage, "User %s is already mapped to" + " group %s, but also belongs to group %s. Add an" + " explicit mapping for this user to" + " override group mappings.", + name, orig->login + 1, selogin + 1); + return STATUS_ERR; + } else if (orig != NULL) { + // user mappings take precedence + return STATUS_SUCCESS; + } + } + + int retval = STATUS_ERR; + + char *rbuf = NULL; + long rbuflen; + struct passwd pwstorage, *pwent = NULL; + const char *prefix = NULL; + const char *level = NULL; + char uid[11]; + char gid[11]; + + /* Allocate space for the getpwnam_r buffer */ + rbuflen = sysconf(_SC_GETPW_R_SIZE_MAX); + if (rbuflen <= 0) + goto cleanup; + rbuf = malloc(rbuflen); + if (rbuf == NULL) + goto cleanup; + + if (user) { + prefix = semanage_user_get_prefix(user); + level = semanage_user_get_mlslevel(user); + + if (!level) { + level = FALLBACK_LEVEL; + } + } else { + prefix = name; + level = FALLBACK_LEVEL; + } + + retval = getpwnam_r(name, &pwstorage, rbuf, rbuflen, &pwent); + if (retval != 0 || pwent == NULL) { + if (retval != 0 && retval != ENOENT) { + goto cleanup; + } + + WARN(s->h_semanage, + "user %s not in password file", name); + retval = STATUS_SUCCESS; + goto cleanup; + } + + int len = strlen(pwent->pw_dir) -1; + for(; len > 0 && pwent->pw_dir[len] == '/'; len--) { + pwent->pw_dir[len] = '\0'; + } + + if (strcmp(pwent->pw_dir, "/") == 0) { + /* don't relabel / genhomdircon checked to see if root + * was the user and if so, set his home directory to + * /root */ + retval = STATUS_SUCCESS; + goto cleanup; + } + + if (ignore(pwent->pw_dir)) { + retval = STATUS_SUCCESS; + goto cleanup; + } + + len = snprintf(uid, sizeof(uid), "%u", pwent->pw_uid); + if (len < 0 || len >= (int)sizeof(uid)) { + goto cleanup; + } + + len = snprintf(gid, sizeof(gid), "%u", pwent->pw_gid); + if (len < 0 || len >= (int)sizeof(gid)) { + goto cleanup; + } + + retval = push_user_entry(head, name, uid, gid, sename, prefix, + pwent->pw_dir, level, selogin); +cleanup: + free(rbuf); + return retval; +} + +static int get_group_users(genhomedircon_settings_t * s, + genhomedircon_user_entry_t **head, + semanage_user_t *user, + const char *sename, + const char *selogin) +{ + int retval = STATUS_ERR; + unsigned int i; + + long grbuflen; + char *grbuf = NULL; + struct group grstorage, *group = NULL; + + long prbuflen; + char *pwbuf = NULL; + struct passwd pwstorage, *pw = NULL; + + grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX); + if (grbuflen <= 0) + goto cleanup; + grbuf = malloc(grbuflen); + if (grbuf == NULL) + goto cleanup; + + const char *grname = selogin + 1; + + if (getgrnam_r(grname, &grstorage, grbuf, + (size_t) grbuflen, &group) != 0) { + goto cleanup; + } + + if (group == NULL) { + ERR(s->h_semanage, "Can't find group named %s\n", grname); + goto cleanup; + } + + size_t nmembers = 0; + char **members = group->gr_mem; + + while (*members != NULL) { + nmembers++; + members++; + } + + for (i = 0; i < nmembers; i++) { + const char *uname = group->gr_mem[i]; + + if (add_user(s, head, user, uname, sename, selogin) < 0) { + goto cleanup; + } + } + + prbuflen = sysconf(_SC_GETPW_R_SIZE_MAX); + if (prbuflen <= 0) + goto cleanup; + pwbuf = malloc(prbuflen); + if (pwbuf == NULL) + goto cleanup; + + setpwent(); + while ((retval = getpwent_r(&pwstorage, pwbuf, prbuflen, &pw)) == 0) { + // skip users who also have this group as their + // primary group + if (lfind(pw->pw_name, group->gr_mem, &nmembers, + sizeof(char *), &STR_COMPARATOR)) { + continue; + } + + if (group->gr_gid == pw->pw_gid) { + if (add_user(s, head, user, pw->pw_name, + sename, selogin) < 0) { + goto cleanup; + } + } + } + + retval = STATUS_SUCCESS; +cleanup: + endpwent(); + free(pwbuf); + free(grbuf); + + return retval; +} + static genhomedircon_user_entry_t *get_users(genhomedircon_settings_t * s, int *errors) { @@ -817,14 +1048,7 @@ static genhomedircon_user_entry_t *get_users(genhomedircon_settings_t * s, semanage_user_t **u = NULL; const char *name = NULL; const char *seuname = NULL; - const char *prefix = NULL; - const char *level = NULL; - char uid[11]; - char gid[11]; - struct passwd pwstorage, *pwent = NULL; unsigned int i; - long rbuflen; - char *rbuf = NULL; int retval; *errors = 0; @@ -838,17 +1062,11 @@ static genhomedircon_user_entry_t *get_users(genhomedircon_settings_t * s, nusers = 0; } + qsort(seuser_list, nseusers, sizeof(semanage_seuser_t *), + &seuser_sort_func); qsort(user_list, nusers, sizeof(semanage_user_t *), (int (*)(const void *, const void *))&user_sort_func); - /* Allocate space for the getpwnam_r buffer */ - rbuflen = sysconf(_SC_GETPW_R_SIZE_MAX); - if (rbuflen <= 0) - goto cleanup; - rbuf = malloc(rbuflen); - if (rbuf == NULL) - goto cleanup; - for (i = 0; i < nseusers; i++) { seuname = semanage_seuser_get_sename(seuser_list[i]); name = semanage_seuser_get_name(seuser_list[i]); @@ -859,70 +1077,27 @@ static genhomedircon_user_entry_t *get_users(genhomedircon_settings_t * s, if (strcmp(name, TEMPLATE_SEUSER) == 0) continue; - /* %groupname syntax */ - if (name[0] == '%') - continue; - /* find the user structure given the name */ u = bsearch(seuname, user_list, nusers, sizeof(semanage_user_t *), (int (*)(const void *, const void *)) &name_user_cmp); - if (u) { - prefix = semanage_user_get_prefix(*u); - level = semanage_user_get_mlslevel(*u); - if (!level) - level = FALLBACK_LEVEL; - } else { - prefix = name; - level = FALLBACK_LEVEL; - } - - retval = getpwnam_r(name, &pwstorage, rbuf, rbuflen, &pwent); - if (retval != 0 || pwent == NULL) { - if (retval != 0 && retval != ENOENT) { - *errors = STATUS_ERR; - goto cleanup; - } - - WARN(s->h_semanage, - "user %s not in password file", name); - continue; - } - int len = strlen(pwent->pw_dir) -1; - for(; len > 0 && pwent->pw_dir[len] == '/'; len--) { - pwent->pw_dir[len] = '\0'; + /* %groupname syntax */ + if (name[0] == '%') { + retval = get_group_users(s, &head, *u, seuname, + name); + } else { + retval = add_user(s, &head, *u, name, + seuname, name); } - if (strcmp(pwent->pw_dir, "/") == 0) { - /* don't relabel / genhomdircon checked to see if root - * was the user and if so, set his home directory to - * /root */ - continue; - } - if (ignore(pwent->pw_dir)) - continue; - - len = snprintf(uid, sizeof(uid), "%u", pwent->pw_uid); - if (len < 0 || len >= (int)sizeof(uid)) { + if (retval != 0) { *errors = STATUS_ERR; goto cleanup; } - len = snprintf(gid, sizeof(gid), "%u", pwent->pw_gid); - if (len < 0 || len >= (int)sizeof(gid)) { - *errors = STATUS_ERR; - goto cleanup; - } - - if (push_user_entry(&head, name, uid, gid, seuname, - prefix, pwent->pw_dir, level) != STATUS_SUCCESS) { - *errors = STATUS_ERR; - break; - } } cleanup: - free(rbuf); if (*errors) { for (; head; pop_user_entry(&head)) { /* the pop function takes care of all the cleanup