PR/35506: Chuck Silvers: ps doesn't work on crash dumps, libkvm doesn't

know about kauth

Implemented _kvm_convertcred() to handle copying kauth_cred_t to userspace
and converting it to the appropriate 'struct eproc' members ('pcred' and
'ucred' respectively).

Okay mlelstv@.
This commit is contained in:
elad 2007-02-06 21:21:51 +00:00
parent 0ce1424e8f
commit eb3ad821f0
1 changed files with 61 additions and 9 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: kvm_proc.c,v 1.64 2007/01/28 21:31:13 chs Exp $ */
/* $NetBSD: kvm_proc.c,v 1.65 2007/02/06 21:21:51 elad Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -74,7 +74,7 @@
#if 0
static char sccsid[] = "@(#)kvm_proc.c 8.3 (Berkeley) 9/23/93";
#else
__RCSID("$NetBSD: kvm_proc.c,v 1.64 2007/01/28 21:31:13 chs Exp $");
__RCSID("$NetBSD: kvm_proc.c,v 1.65 2007/02/06 21:21:51 elad Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@ -150,6 +150,26 @@ struct miniproc {
(p)->p_vmspace = (void *)(long)(kp)->p_vmspace; \
} while (/*CONSTCOND*/0);
/*
* NetBSD uses kauth(9) to manage credentials, which are stored in kauth_cred_t,
* a kernel-only opaque type. This is an embedded version which is *INTERNAL* to
* kvm(3) so dumps can be read properly.
*
* Whenever NetBSD starts exporting credentials to userland consistently (using
* 'struct uucred', or something) this will have to be updated again.
*/
struct kvm_kauth_cred {
struct simplelock cr_lock; /* lock on cr_refcnt */
u_int cr_refcnt; /* reference count */
uid_t cr_uid; /* user id */
uid_t cr_euid; /* effective user id */
uid_t cr_svuid; /* saved effective user id */
gid_t cr_gid; /* group id */
gid_t cr_egid; /* effective group id */
gid_t cr_svgid; /* saved effective group id */
u_int cr_ngroups; /* number of groups */
gid_t cr_groups[NGROUPS]; /* group memberships */
};
#define KREAD(kd, addr, obj) \
(kvm_read(kd, addr, (obj), sizeof(*obj)) != sizeof(*obj))
@ -278,6 +298,40 @@ _kvm_uread(kd, p, va, cnt)
return (_kvm_ureadm(kd, &mp, va, cnt));
}
/*
* Convert credentials located in kernel space address 'cred' and store
* them in the appropriate members of 'eproc'.
*/
static int
_kvm_convertcred(kvm_t *kd, u_long cred, struct eproc *eproc)
{
struct kvm_kauth_cred kauthcred;
struct pcred *pc = &eproc->e_pcred;
struct ucred *uc = &eproc->e_ucred;
if (KREAD(kd, cred, &kauthcred) != 0)
return (-1);
/* inlined version of kauth_cred_to_pcred, see kauth(9). */
pc->p_ruid = kauthcred.cr_uid;
pc->p_svuid = kauthcred.cr_svuid;
pc->p_rgid = kauthcred.cr_gid;
pc->p_svgid = kauthcred.cr_svgid;
pc->p_refcnt = kauthcred.cr_refcnt;
pc->pc_ucred = (void *)cred;
/* inlined version of kauth_cred_to_ucred(), see kauth(9). */
uc->cr_ref = kauthcred.cr_refcnt;
uc->cr_uid = kauthcred.cr_euid;
uc->cr_gid = kauthcred.cr_egid;
uc->cr_ngroups = MIN(kauthcred.cr_ngroups,
sizeof(uc->cr_groups) / sizeof(uc->cr_groups[0]));
memcpy(uc->cr_groups, kauthcred.cr_groups,
uc->cr_ngroups * sizeof(uc->cr_groups[0]));
return (0);
}
/*
* Read proc's from memory file into buffer bp, which has space to hold
* at most maxcnt procs.
@ -304,13 +358,11 @@ kvm_proclist(kd, what, arg, p, bp, maxcnt)
_kvm_err(kd, kd->program, "can't read proc at %p", p);
return (-1);
}
if (KREAD(kd, (u_long)proc.p_cred, &eproc.e_pcred) == 0)
if (KREAD(kd, (u_long)eproc.e_pcred.pc_ucred,
&eproc.e_ucred)) {
_kvm_err(kd, kd->program,
"can't read proc credentials at %p", p);
return (-1);
}
if (_kvm_convertcred(kd, (u_long)proc.p_cred, &eproc) != 0) {
_kvm_err(kd, kd->program,
"can't read proc credentials at %p", p);
return (-1);
}
switch (what) {