From: Todd C. Miller Date: Wed, 27 May 2015 16:26:49 +0000 (-0600) Subject: Use non-existing allocators in the passwd/group cache functions. X-Git-Tag: SUDO_1_8_14^2~106 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6b7be032affb87ce1b6f47a1455380f73861a247;p=sudo Use non-existing allocators in the passwd/group cache functions. --- diff --git a/lib/util/aix.c b/lib/util/aix.c index 42ab9d889..dbf017288 100644 --- a/lib/util/aix.c +++ b/lib/util/aix.c @@ -28,6 +28,7 @@ # include # endif #endif /* STDC_HEADERS */ +#include #include #include @@ -147,43 +148,53 @@ int usrinfo(int cmd, char *buf, int count); * Look up administrative domain for user (SYSTEM in /etc/security/user) and * set it as the default for the process. This ensures that password and * group lookups are made against the correct source (files, NIS, LDAP, etc). + * Does not modify errno even on error since callers do not check rval. */ int aix_setauthdb_v1(char *user) { char *registry; + int serrno = errno; + int rval = -1; debug_decl(aix_setauthdb, SUDO_DEBUG_UTIL) if (user != NULL) { if (setuserdb(S_READ) != 0) { sudo_warn(U_("unable to open userdb")); - debug_return_int(-1); + goto done; } if (getuserattr(user, S_REGISTRY, ®istry, SEC_CHAR) == 0) { if (setauthdb(registry, NULL) != 0) { sudo_warn(U_("unable to switch to registry \"%s\" for %s"), registry, user); - debug_return_int(-1); + goto done; } } enduserdb(); } - debug_return_int(0); + rval = 0; +done: + errno = serrno; + debug_return_int(rval); } /* * Restore the saved administrative domain, if any. + * Does not modify errno even on error since callers do not check rval. */ int aix_restoreauthdb_v1(void) { + int serrno = errno; + int rval = 0; debug_decl(aix_setauthdb, SUDO_DEBUG_UTIL) if (setauthdb(NULL, NULL) != 0) { sudo_warn(U_("unable to restore registry")); - debug_return_int(-1); + rval = -1; } - debug_return_int(0); + errno = serrno; + debug_return_int(rval); } #endif diff --git a/plugins/sudoers/pwutil.c b/plugins/sudoers/pwutil.c index 394bd63e5..8f65c4323 100644 --- a/plugins/sudoers/pwutil.c +++ b/plugins/sudoers/pwutil.c @@ -46,6 +46,7 @@ #ifdef HAVE_SETAUTHDB # include #endif /* HAVE_SETAUTHDB */ +#include #include #include @@ -103,7 +104,7 @@ sudo_pw_delref_item(void *v) debug_decl(sudo_pw_delref_item, SUDOERS_DEBUG_NSS) if (--item->refcnt == 0) - sudo_efree(item); + free(item); debug_return; } @@ -138,9 +139,11 @@ sudo_getpwuid(uid_t uid) aix_setauthdb(IDtouser(uid)); #endif item = sudo_make_pwitem(uid, NULL); +#ifdef HAVE_SETAUTHDB + aix_restoreauthdb(); +#endif if (item == NULL) { - item = calloc(1, sizeof(*item)); - if (item == NULL) { + if (errno != ENOENT || (item = calloc(1, sizeof(*item))) == NULL) { sudo_warnx(U_("unable to cache uid %u, out of memory"), (unsigned int) uid); debug_return_ptr(NULL); @@ -163,9 +166,6 @@ sudo_getpwuid(uid_t uid) item->refcnt = 0; break; } -#ifdef HAVE_SETAUTHDB - aix_restoreauthdb(); -#endif done: item->refcnt++; debug_return_ptr(item->d.pw); @@ -179,7 +179,6 @@ sudo_getpwnam(const char *name) { struct cache_item key, *item; struct rbnode *node; - size_t len; debug_decl(sudo_getpwnam, SUDOERS_DEBUG_NSS) key.k.name = (char *) name; @@ -194,10 +193,12 @@ sudo_getpwnam(const char *name) aix_setauthdb((char *) name); #endif item = sudo_make_pwitem((uid_t)-1, name); +#ifdef HAVE_SETAUTHDB + aix_restoreauthdb(); +#endif if (item == NULL) { - len = strlen(name) + 1; - item = calloc(1, sizeof(*item) + len); - if (item == NULL) { + const size_t len = strlen(name) + 1; + if (errno != ENOENT || (item = calloc(1, sizeof(*item) + len)) == NULL) { sudo_warnx(U_("unable to cache user %s, out of memory"), name); debug_return_ptr(NULL); } @@ -218,9 +219,6 @@ sudo_getpwnam(const char *name) item->refcnt = 0; break; } -#ifdef HAVE_SETAUTHDB - aix_restoreauthdb(); -#endif done: item->refcnt++; debug_return_ptr(item->d.pw); @@ -258,7 +256,11 @@ sudo_mkpwent(const char *user, uid_t uid, gid_t gid, const char *home, struct rbtree *pwcache; struct rbnode *node; - pwitem = sudo_ecalloc(1, len); + pwitem = calloc(1, len); + if (pwitem == NULL) { + sudo_warnx(U_("unable to cache user %s, out of memory"), user); + debug_return_ptr(NULL); + } pw = &pwitem->pw; pw->pw_uid = uid; pw->pw_gid = gid; @@ -295,7 +297,7 @@ sudo_mkpwent(const char *user, uid_t uid, gid_t gid, const char *home, item = node->data = &pwitem->cache; } else { /* Good entry, discard our fake one. */ - sudo_efree(pwitem); + free(pwitem); } break; case -1: @@ -399,7 +401,7 @@ sudo_gr_delref_item(void *v) debug_decl(sudo_gr_delref_item, SUDOERS_DEBUG_NSS) if (--item->refcnt == 0) - sudo_efree(item); + free(item); debug_return; } @@ -432,7 +434,11 @@ sudo_getgrgid(gid_t gid) */ item = sudo_make_gritem(gid, NULL); if (item == NULL) { - item = sudo_ecalloc(1, sizeof(*item)); + if (errno != ENOENT || (item = calloc(1, sizeof(*item))) == NULL) { + sudo_warnx(U_("unable to cache gid %u, out of memory"), + (unsigned int) gid); + debug_return_ptr(NULL); + } item->refcnt = 1; item->k.gid = gid; /* item->d.gr = NULL; */ @@ -464,7 +470,6 @@ sudo_getgrnam(const char *name) { struct cache_item key, *item; struct rbnode *node; - size_t len; debug_decl(sudo_getgrnam, SUDOERS_DEBUG_NSS) key.k.name = (char *) name; @@ -477,8 +482,11 @@ sudo_getgrnam(const char *name) */ item = sudo_make_gritem((gid_t)-1, name); if (item == NULL) { - len = strlen(name) + 1; - item = sudo_ecalloc(1, sizeof(*item) + len); + const size_t len = strlen(name) + 1; + if (errno != ENOENT || (item = calloc(1, sizeof(*item) + len)) == NULL) { + sudo_warnx(U_("unable to cache group %s, out of memory"), name); + debug_return_ptr(NULL); + } item->refcnt = 1; item->k.name = (char *) item + sizeof(*item); memcpy(item->k.name, name, len); @@ -522,7 +530,11 @@ sudo_fakegrnam(const char *group) struct rbtree *grcache; struct rbnode *node; - gritem = sudo_ecalloc(1, len); + gritem = calloc(1, len); + if (gritem == NULL) { + sudo_warnx(U_("unable to cache group %s, out of memory"), group); + debug_return_ptr(NULL); + } gr = &gritem->gr; gr->gr_gid = (gid_t) sudo_strtoid(group + 1, NULL, NULL, &errstr); gr->gr_name = (char *)(gritem + 1); @@ -530,7 +542,7 @@ sudo_fakegrnam(const char *group) if (errstr != NULL) { sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_DIAG, "gid %s %s", group, errstr); - sudo_efree(gritem); + free(gritem); debug_return_ptr(NULL); } @@ -556,7 +568,7 @@ sudo_fakegrnam(const char *group) item = node->data = &gritem->cache; } else { /* Good entry, discard our fake one. */ - sudo_efree(gritem); + free(gritem); } break; case -1: @@ -585,7 +597,7 @@ sudo_grlist_delref_item(void *v) debug_decl(sudo_gr_delref_item, SUDOERS_DEBUG_NSS) if (--item->refcnt == 0) - sudo_efree(item); + free(item); debug_return; } @@ -654,7 +666,6 @@ sudo_get_grlist(const struct passwd *pw) { struct cache_item key, *item; struct rbnode *node; - size_t len; debug_decl(sudo_get_grlist, SUDOERS_DEBUG_NSS) key.k.name = pw->pw_name; @@ -667,13 +678,8 @@ sudo_get_grlist(const struct passwd *pw) */ item = sudo_make_grlist_item(pw, NULL, NULL); if (item == NULL) { - /* Should not happen. */ - len = strlen(pw->pw_name) + 1; - item = sudo_ecalloc(1, sizeof(*item) + len); - item->refcnt = 1; - item->k.name = (char *) item + sizeof(*item); - memcpy(item->k.name, pw->pw_name, len); - /* item->d.grlist = NULL; */ + /* Out of memory? */ + debug_return_ptr(NULL); } switch (rbinsert(grlist_cache, item, NULL)) { case 1: diff --git a/plugins/sudoers/pwutil_impl.c b/plugins/sudoers/pwutil_impl.c index 4e50d0342..511cd3e84 100644 --- a/plugins/sudoers/pwutil_impl.c +++ b/plugins/sudoers/pwutil_impl.c @@ -43,6 +43,7 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ +#include #include #include #include @@ -79,6 +80,8 @@ do { \ * Dynamically allocate space for a struct item plus the key and data * elements. If name is non-NULL it is used as the key, else the * uid is the key. Fills in datum from struct password. + * Returns NULL on malloc error or unknown name/id, setting errno + * to ENOMEM or ENOENT respectively. */ struct cache_item * sudo_make_pwitem(uid_t uid, const char *name) @@ -92,8 +95,10 @@ sudo_make_pwitem(uid_t uid, const char *name) /* Look up by name or uid. */ pw = name ? getpwnam(name) : getpwuid(uid); - if (pw == NULL) + if (pw == NULL) { + errno = ENOENT; debug_return_ptr(NULL); + } /* If shell field is empty, expand to _PATH_BSHELL. */ pw_shell = (pw->pw_shell == NULL || pw->pw_shell[0] == '\0') @@ -116,7 +121,8 @@ sudo_make_pwitem(uid_t uid, const char *name) total += strlen(name) + 1; /* Allocate space for struct item, struct passwd and the strings. */ - pwitem = sudo_ecalloc(1, total); + if ((pwitem = calloc(1, total)) == NULL) + debug_return_ptr(NULL); newpw = &pwitem->pw; /* @@ -154,6 +160,8 @@ sudo_make_pwitem(uid_t uid, const char *name) * Dynamically allocate space for a struct item plus the key and data * elements. If name is non-NULL it is used as the key, else the * gid is the key. Fills in datum from struct group. + * Returns NULL on malloc error or unknown name/id, setting errno + * to ENOMEM or ENOENT respectively. */ struct cache_item * sudo_make_gritem(gid_t gid, const char *name) @@ -166,8 +174,10 @@ sudo_make_gritem(gid_t gid, const char *name) /* Look up by name or gid. */ gr = name ? getgrnam(name) : getgrgid(gid); - if (gr == NULL) + if (gr == NULL) { + errno = ENOENT; debug_return_ptr(NULL); + } /* Allocate in one big chunk for easy freeing. */ nsize = psize = nmem = 0; @@ -183,7 +193,8 @@ sudo_make_gritem(gid_t gid, const char *name) if (name != NULL) total += strlen(name) + 1; - gritem = sudo_ecalloc(1, total); + if ((gritem = calloc(1, total)) == NULL) + debug_return_ptr(NULL); /* * Copy in group contents and make strings relative to space @@ -233,7 +244,7 @@ sudo_make_grlist_item(const struct passwd *pw, char * const *unused1, struct cache_item_grlist *grlitem; struct group_list *grlist; GETGROUPS_T *gids; - struct group *grp; + struct group *grp = NULL; int i, ngids, groupname_len; debug_decl(sudo_make_grlist_item, SUDOERS_DEBUG_NSS) @@ -245,30 +256,33 @@ sudo_make_grlist_item(const struct passwd *pw, char * const *unused1, } else { if (sudo_user.max_groups > 0) { ngids = sudo_user.max_groups; - gids = sudo_emallocarray(ngids, sizeof(GETGROUPS_T)); + gids = reallocarray(NULL, ngids, sizeof(GETGROUPS_T)); + if (gids == NULL) + debug_return_ptr(NULL); (void)getgrouplist(pw->pw_name, pw->pw_gid, gids, &ngids); } else { ngids = (int)sysconf(_SC_NGROUPS_MAX) * 2; if (ngids < 0) ngids = NGROUPS_MAX * 2; - gids = sudo_emallocarray(ngids, sizeof(GETGROUPS_T)); + gids = reallocarray(NULL, ngids, sizeof(GETGROUPS_T)); + if (gids == NULL) + debug_return_ptr(NULL); if (getgrouplist(pw->pw_name, pw->pw_gid, gids, &ngids) == -1) { - sudo_efree(gids); - gids = sudo_emallocarray(ngids, sizeof(GETGROUPS_T)); + free(gids); + gids = reallocarray(NULL, ngids, sizeof(GETGROUPS_T)); + if (gids == NULL) + debug_return_ptr(NULL); if (getgrouplist(pw->pw_name, pw->pw_gid, gids, &ngids) == -1) ngids = -1; } } } if (ngids <= 0) { - sudo_efree(gids); + free(gids); + errno = ENOENT; debug_return_ptr(NULL); } -#ifdef HAVE_SETAUTHDB - aix_setauthdb((char *) pw->pw_name); -#endif - #ifdef _SC_LOGIN_NAME_MAX groupname_len = MAX((int)sysconf(_SC_LOGIN_NAME_MAX), 32); #else @@ -283,7 +297,10 @@ sudo_make_grlist_item(const struct passwd *pw, char * const *unused1, total += groupname_len * ngids; again: - grlitem = sudo_ecalloc(1, total); + if ((grlitem = calloc(1, total)) == NULL) { + free(gids); + debug_return_ptr(NULL); + } /* * Copy in group list and make pointers relative to space @@ -314,13 +331,17 @@ again: /* * Resolve and store group names by ID. */ +#ifdef HAVE_SETAUTHDB + if (grp == NULL) + aix_setauthdb((char *) pw->pw_name); +#endif ngroups = 0; for (i = 0; i < ngids; i++) { if ((grp = sudo_getgrgid(gids[i])) != NULL) { len = strlen(grp->gr_name) + 1; if (cp - (char *)grlitem + len > total) { total += len + groupname_len; - sudo_efree(grlitem); + free(grlitem); sudo_gr_delref(grp); goto again; } @@ -331,7 +352,7 @@ again: } } grlist->ngroups = ngroups; - sudo_efree(gids); + free(gids); #ifdef HAVE_SETAUTHDB aix_restoreauthdb();