]> granicus.if.org Git - sudo/commitdiff
Use non-existing allocators in the passwd/group cache functions.
authorTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 27 May 2015 16:26:49 +0000 (10:26 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 27 May 2015 16:26:49 +0000 (10:26 -0600)
lib/util/aix.c
plugins/sudoers/pwutil.c
plugins/sudoers/pwutil_impl.c

index 42ab9d889ce33a65f82e141613b1be092adb88c8..dbf01728829d9ae5e37c572eb857602e68dc69f5 100644 (file)
@@ -28,6 +28,7 @@
 #  include <stdlib.h>
 # endif
 #endif /* STDC_HEADERS */
+#include <errno.h>
 #include <usersec.h>
 #include <uinfo.h>
 
@@ -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, &registry, 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
 
index 394bd63e5273b088d0bc108f2ea43fd00087cec2..8f65c432312b9c35d6638fe07e342180284e3fc0 100644 (file)
@@ -46,6 +46,7 @@
 #ifdef HAVE_SETAUTHDB
 # include <usersec.h>
 #endif /* HAVE_SETAUTHDB */
+#include <errno.h>
 #include <pwd.h>
 #include <grp.h>
 
@@ -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:
index 4e50d03421ea1ba4f774609492f1d244b4e085f0..511cd3e84dea500c5b421ac81eaba8d6d9b70847 100644 (file)
@@ -43,6 +43,7 @@
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif /* HAVE_UNISTD_H */
+#include <errno.h>
 #include <limits.h>
 #include <pwd.h>
 #include <grp.h>
@@ -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();