Comment 6 for bug 1565567

Revision history for this message
Rafael David Tinoco (rafaeldtinoco) wrote :

Following execution path I get:

====

(1)

mode_run -> policy_check -> sudoers_policy_main -> sudoers_policy_init:
 - init_vars (fills global variable sudo_user)
 - sudo_user->pwd (from global struct passwd) will be used in "user_in_group" as "struct passwd" of executing user
 - it will check whether the executing user is in a certain group (pre-reqs for sudo execution)

/*
 * Get a local copy of the user's struct passwd if we don't already
 * have one.
 */
if (sudo_user.pw == NULL) {
    if ((sudo_user.pw = sudo_getpwnam(user_name)) == NULL) {
        /*
         * It is not unusual for users to place "sudo -k" in a .logout
         * file which can cause sudo to be run during reboot after the
         * YP/NIS/NIS+/LDAP/etc daemon has died.
         */
        if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) {
            sudo_warnx(U_("unknown uid: %u"), (unsigned int) user_uid);
            debug_return_bool(false);
        }

        /* Need to make a fake struct passwd for the call to log_warningx(). */
        sudo_user.pw = sudo_mkpwent(user_name, user_uid, user_gid, NULL, NULL);
        unknown_user = true;
    }
}

so sudo_user->pwd comes from sudo_mkpwent(user_name).

At this time, impossible that sudo_mkpwent has cached values so we have:

...
item = sudo_make_pwitem((uid_t)-1, name);

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);
    }
    item->refcnt = 1;
    item->k.name = (char *) item + sizeof(*item);
    memcpy(item->k.name, name, len);
    /* item->d.pw = NULL; */
}
strlcpy(item->registry, key.registry, sizeof(item->registry));
switch (rbinsert(pwcache_byname, item, NULL)) {
...

Since sudo_make_pwitem relies on local authentication, and user is coming from ldap... item = NULL.

With item being NULL, cache item item->d (union) will be filled of zeroes.
With that, item->d>pw will be a NULL pointer.

PROBLEM:

In the future, when this cache item is recovered from redblack tree, any reference to item->d>pw will fail.