[comp.unix.wizards] Another "why won't this work" program

BKEHOE@widener (08/16/90)

/*
 * This is being run on a Sun SS1 under 4.0.3.
 *  Theoretically, according to the Design & Implementation of 4.3BSD Unix,
 * this should print out the ascii version of each process's current
 * directory...instead, it chokes on u->u_cwd->cw_dir, which is in the
 * u struct in sys/user.h .. any help, suggestions, etc would be greatly
 * appreciated.

 */

/*
 * cc -o cwd cwd.c -lkvm
 */

#include <stdio.h>
#include <kvm.h>
#include <fcntl.h>
#include <ctype.h>
#include <pwd.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/proc.h>
#include <sys/user.h>

main (argc, argv)


{






			*argv);
		exit (1);
	}

	(void) printf("Name\t\tDir\n");
	kvm_setproc (kd);
	while ((proc = kvm_nextproc (kd)))
		if (proc->p_stat != SZOMB && proc->p_uid) {
			if (!(user = kvm_getu(kd, proc)))
				continue;
			(void) printf("%s\n", (getpwuid(proc->p_uid))->pw_name);
/* Curtains & Slow Music */
			(void) printf("%s\n", user->u_cwd->cw_dir);
/* It dies, but the user structure's fine (printing user->u_comm works); I
   stepped thru it with gdb & discovered that the pointer user->u_cwd is off in
   never-never-land; is it a valid entry in
the user structure? */
		}
}

kucharsk@number6.Solbourne.COM (William Kucharski) (08/16/90)

In article <24183@adm.BRL.MIL> BKEHOE@widener writes:
 >/*
 > * This is being run on a Sun SS1 under 4.0.3.
 > *  Theoretically, according to the Design & Implementation of 4.3BSD Unix,
 > * this should print out the ascii version of each process's current
 > * directory...instead, it chokes on u->u_cwd->cw_dir, which is in the
 > * u struct in sys/user.h .. any help, suggestions, etc would be greatly
 > * appreciated.
 >
 > */
 >
 >/*
 > * cc -o cwd cwd.c -lkvm
 > */
 >
 >#include <stdio.h>
 >#include <kvm.h>
 >#include <fcntl.h>
 >#include <ctype.h>
 >#include <pwd.h>
 >#include <sys/param.h>
 >#include <sys/time.h>
 >#include <sys/proc.h>
 >#include <sys/user.h>

...

 >	(void) printf("Name\t\tDir\n");
 >	kvm_setproc (kd);
 >	while ((proc = kvm_nextproc (kd)))
 >		if (proc->p_stat != SZOMB && proc->p_uid) {
 >			if (!(user = kvm_getu(kd, proc)))
 >				continue;
 >			(void) printf("%s\n", (getpwuid(proc->p_uid))->pw_name);
 >/* Curtains & Slow Music */
 >			(void) printf("%s\n", user->u_cwd->cw_dir);
 >/* It dies, but the user structure's fine (printing user->u_comm works); I
 >   stepped thru it with gdb & discovered that the pointer user->u_cwd is off in
 >   never-never-land; is it a valid entry in
 >the user structure? */
 >		}
 >}

That's because the user->u_cwd pointer is really a pointer into the kernel's
memory space, rather than user memory space.  You need to do something like
the following to read the contents of the kernel memory in question into user
space:

...

char dir[MAXPATHLEN];
char rootdir[MAXPATHLEN];
struct ucwd cwd;

if (kvm_read(kd, (unsigned long)userp->u_cwd, (char *)&cwd,
    sizeof(struct ucwd)) == sizeof(struct ucwd)) {

    if ((kvm_read(kd, (unsigned long)cwd.cw_dir, dir, MAXPATHLEN)
     == MAXPATHLEN) && (kvm_read(kd, (unsigned long)cwd.cw_root, rootdir,
     MAXPATHLEN) == MAXPATHLEN)) {
	if ((*rootdir) || (*dir))
	    printf("cwd: %s%s\n", rootdir, dir);
	else
	    printf("cwd: /\n");
    }
}

...

--
===============================================================================
| Internet:   kucharsk@Solbourne.COM	      |	William Kucharski             |
| uucp:	...!{boulder,sun,uunet}!stan!kucharsk |	Solbourne Computer, Inc.      |
=== The sentiments expressed above are MY opinions, NOT those of Solbourne. ===

guy@auspex.auspex.com (Guy Harris) (08/17/90)

"BKEHOE@widener" isn't a very usable email address, and the Path: line
ended with "news", so I was unable to mail this.  Methinks you should
have a talk with your mail or netnews administrator, asking them to fix
the From: line on outgoing postings....

>/*
> * This is being run on a Sun SS1 under 4.0.3.
> *  Theoretically, according to the Design & Implementation of 4.3BSD Unix,
> * this should print out the ascii version of each process's current
> * directory...instead, it chokes on u->u_cwd->cw_dir, which is in the
> * u struct in sys/user.h .. any help, suggestions, etc would be greatly
> * appreciated.

Well, actually, 4.3BSD UNIX doesn't *have* a "u_cwd" member of the "u"
structure, so I'd hope that the BSD book *doesn't* suggest that it should
work.  That field is a SunOS-ism, introduced as part of the C2 security
stuff so that the auditing code can get the full pathname of a file.

>	while ((proc = kvm_nextproc (kd)))
>		if (proc->p_stat != SZOMB && proc->p_uid) {
>			if (!(user = kvm_getu(kd, proc)))
>				continue;
>			(void) printf("%s\n", (getpwuid(proc->p_uid))->pw_name);

Well, you probably want to call "getpwuid()" and store the result
somewhere, and then check if it's NULL, before using it; it may not be
*likely* to fail, but it *can* fail.

>/* Curtains & Slow Music */
>			(void) printf("%s\n", user->u_cwd->cw_dir);
>/* It dies, but the user structure's fine (printing user->u_comm works); I
>   stepped thru it with gdb & discovered that the pointer user->u_cwd
>   is off in never-never-land; is it a valid entry in the user structure? */

Do you mean "is 'u_cwd' a valid entry in the user structure?"  Well,
maybe.  I'm not sure if it's kept up-to-date if you haven't configured
the C2 security stuff into your kernel (SYSAUDIT).

However, even if it *is* kept up-to-date, it doesn't quite point into
user-mode data, obviously.  You'll have to grab the pointer value from
"u_cwd" and use "kvm_read()" to read it from the *kernel's* address space
into a private copy.  Then, once you've done that, bear in mind that the
"cw_dir" and "cw_root" members of the structure pointed to by "u_cwd"
are *themselves* pointers into the kernel's address space, and read the
strings to which they point using "kvm_read()" as well.

Stepping through kernel data structures is more subtle than you might
think.  Pointers in kernel data structures *cannot*, in most systems,
simply be dereferenced; even if the kernel-mode and user-mode address
spaces are common, the kernel data is probably read-protected (for
obvious reasons!).