[comp.sys.sun] How to find the real uid/gid of a process?

chris@bilby.cs.uwa.oz.au (chris mcdonald) (05/24/91)

Me again, still trying to understand the SunOS kvm_* routines.

I would like to determine the real uid and gid of each process, but can't
seem to access them from each struct proc returned by kvm_nextproc();

Assuming:
	    struct proc theproc;

when I attempt to access theproc->p_cred I get a Memory Fault, and when I
access it as root I get a Segv.  I see in <sys/ucred.h> there are some
nice functions, such as crget(), but that these are only accessible in the
kernel.

Is there any way to get real uids and gids from the proc or user structs?
Unfortunately Leffler is no help on this.  While you're here, why are the
cred #defines actually in <sys/user.h> and not <sys/proc.h> ?

Thanks,

Department of Computer Science,   ACSnet: chris@budgie.cs.uwa.oz.au
University of Western Australia,  ARPA:   chris%budgie.cs.uwa.oz.au@uunet.uu.net
Mounts Bay Road,                  FTP:    bison.cs.uwa.oz.au,  130.95.1.23
Crawley, Western Australia, 6009. SCUD:   (31.97 +/-10% S, 115.81 +/-10% E)
PHONE:  ((+61) 09) 380 2533       FAX:    ((+61) 09) 382 1688

jim@cs.strath.ac.uk (Jim Reid) (06/05/91)

In article <2884@brchh104.bnr.ca> chris@bilby.cs.uwa.oz.au (chris mcdonald) writes:

   Me again, still trying to understand the SunOS kvm_* routines.

   I would like to determine the real uid and gid of each process, but can't
   seem to access them from each struct proc returned by kvm_nextproc();

   Assuming:
	       struct proc theproc;

   when I attempt to access theproc->p_cred I get a Memory Fault, and when I
   access it as root I get a Segv.  I see in <sys/ucred.h> there are some
   nice functions, such as crget(), but that these are only accessible in the
   kernel.

   Is there any way to get real uids and gids from the proc or user structs?

Yes. The address pointed at by proc->p_cred is a kernel virtual
address. It is therefore a mistake to dereference this pointer unless
a process is in the kernel (which yours isn't). You need to use
kvm_read() to fish out this data from the kernel:

	#include <sys/types.h>
	#include <sys/proc.h>
	#include <sys/ucred.h>
	#include <kvm.h>

	struct proc *pp;
	struct ucred mycred;
	kvm_t *kd;

	kd = kvm_open(......);
	pp = kvm_getproc(kd, XXX);
	kvm_read(kd, pp->p_cred, &mycred, sizeof(struct ucred));
	/*
	 * if this completes sucessfully, "mycred" contains a
	 * copy of process no. XXX's credential structure
	 */

   Unfortunately Leffler is no help on this.

Considering that SunOS != 4.3 BSD, this is hardly surprising. 

   While you're here, why are the cred #defines actually in
   <sys/user.h> and not <sys/proc.h> ?

This is for reasons of backwards compatibility. In the old days, the
per-process area (struct user) contained the uid and gid information
about a process. In some versions of UNIX, it still does. Sun
introduced a cred structure to hold this information some time ago. In
earlier SunOS releases, each process had its own credentials structure
stored inside its per-process user area. Now Sun have removed this
structure from the per-process user area, adding a pointer to a
credentials structure to the proc structure. [This is so that several
processes belonging to the same user can share the same credentials
structure.]

Now lots of kernel code was written with the old assumption that the
per-process user area still holds uid/gid information.

	if (u.u_uid == 0)
		/* current process is root */
	else
		/* it isn't */

That code is still in use at many sites - in fact it sometimes helps
"portability" of a device driver since modern UNIX installations will
provide #defines to convert canonical code like that to whatever is
appropriate for the actual kernel. [In other words, hide gory
implementation and/or version specific details.]

The #defines in <sys/user.h> are there to stop old code like this from
breaking: i.e. u.u_uid gets munged by the C preprocessor to
u.u_procp->p_cred->cr_uid which is where the process a ID is now
located in SunOS.

		Jim

dupuy@cs.columbia.edu (06/05/91)

> I would like to determine the real uid and gid of each process, but can't
> seem to access them from each struct proc returned by kvm_nextproc();
> 
> Assuming:
> 	       struct proc theproc;
> 
> when I attempt to access theproc->p_cred I get a Memory Fault, and when I
> access it as root I get a Segv.

This is because theproc->p_cred is a pointer which is valid in the kernel's
address space - not in your process's address space.  You should use kvm_read
to get the data:

	kvm_t kmem = kvm_open(NULL, NULL, NULL, O_RDONLY, argv[0])
	struct proc *theproc = kvm_nextproc(kmem);
	struct ucred *cred = malloc (sizeof struct ucred);

	kvm_read(kmem, theproc->p_cred, cred, sizeof struct ucred);
	theproc->p_cred = cred;

@alex
--
inet: dupuy@cs.columbia.edu