It was brought to my attention a crash just like this one. Here is my analsysis:
## INTRODUCTION
# From plugins/sudoers/pwutil.c:
/*
* Get a password entry by uid and allocate space for it.
*/
struct passwd *
sudo_getpwuid(uid_t uid)
{
struct cache_item key, *item;
struct rbnode *node;
debug_decl(sudo_getpwuid, SUDOERS_DEBUG_NSS)
It was brought to my attention a crash just like this one. Here is my analsysis:
## INTRODUCTION
# From plugins/ sudoers/ pwutil. c:
/* decl(sudo_ getpwuid, SUDOERS_DEBUG_NSS)
* Get a password entry by uid and allocate space for it.
*/
struct passwd *
sudo_getpwuid(uid_t uid)
{
struct cache_item key, *item;
struct rbnode *node;
debug_
key.k.uid = uid; stry(IDtouser( uid), key.registry); pwcache_ byuid, &key)) != NULL) {
sudo_debug_ printf( SUDO_DEBUG_ DEBUG,
(unsigned int)uid, key.registry, item->d. pw->pw_ name,
item- >registry) ;
getauthregi
if ((node = rbfind(
item = node->data;
"%s: uid %u [%s] -> user %s [%s] (cache hit)", __func__,
goto done;
}
being the last frame in the debugger:
#0 0x00007fa01c0a6944 in sudo_getgrgid (gid=7241) at /build/ sudo-g3ghsu/ sudo-1. 8.16/plugins/ sudoers/ pwutil. c:462 000\000\ 330\f\005L\ 027V\000\ 000\000\ 000\000" , k = {uid = 7241, c49>}, d = {
sudo_debug_ subsys = 0
key = {refcnt = 1275378544, registry = "\000V\
gid = 7241, name = 0x28b4cb5700001c49 <error: Cannot access memory at address 0x28b4cb5700001
pw = 0x7ffffd9d43d0, gr = 0x7ffffd9d43d0, grlist = 0x7ffffd9d43d0}}
item = 0x56174c050700
node = <optimized out>
__func__ = "sudo_getgrgid"
We can see that all local variables are accessible but an union:
/*
* Generic cache element.
*/
struct cache_item {
unsigned int refcnt;
char registry[16];
/* key */
union {
uid_t uid;
gid_t gid;
char *name;
} k;
/* datum */
union {
struct passwd *pw;
struct group *gr;
struct group_list *grlist;
} d;
};
(gdb) print item
$35 = (struct cache_item *) 0x56174c050700
(gdb) print item->d
$36 = {pw = 0x0, gr = 0x0, grlist = 0x0}
The union pointer "d" could be either a struct passwd, a struct group or a struct group_list (union nature).
BUT, we can see that, from sudo_getpwuid, it is being used as a struct passwd (d.pw):
"%s: uid %u [%s] -> user %s [%s] (cache hit)", __func__,
Meaning that, probably, the password structure, for this user, wasn't filled in.
I can tell that because the "node" (from the tree) seems good:
if ((node = rbfind( pwcache_ byuid, &key)) != NULL) {
item = node->data;
(gdb) print item->k
$38 = {uid = 7241, gid = 7241, name = 0x1c49 ""}
since uid 7241 and gid 7241 seems reasonable.
But not the "item->d" union.
So we are only missing:
struct passwd *pw;
From the node.
"struct passwd" is (from /usr/include/ pwd.h):
/* The passwd structure. */
struct passwd
{
char *pw_name; /* Username. */
char *pw_passwd; /* Password. */
__uid_t pw_uid; /* User ID. */
__gid_t pw_gid; /* Group ID. */
char *pw_gecos; /* Real name. */
char *pw_dir; /* Home directory. */
char *pw_shell; /* Shell program. */
};
And tells us that it is/was an easy way for the debug message to get username from uid.
Now, lets check when this struct should have been filled in:
item comes from "node->data", a generic redblack tree node.