1/*
2 * dproc.c - Darwin process access functions for /dev/kmem-based lsof
3 */
4
5
6/*
7 * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana
8 * 47907.  All rights reserved.
9 *
10 * Written by Victor A. Abell
11 *
12 * This software is not subject to any license of the American Telephone
13 * and Telegraph Company or the Regents of the University of California.
14 *
15 * Permission is granted to anyone to use this software for any purpose on
16 * any computer system, and to alter it and redistribute it freely, subject
17 * to the following restrictions:
18 *
19 * 1. Neither the authors nor Purdue University are responsible for any
20 *    consequences of the use of this software.
21 *
22 * 2. The origin of this software must not be misrepresented, either by
23 *    explicit claim or by omission.  Credit to the authors and Purdue
24 *    University must appear in documentation and sources.
25 *
26 * 3. Altered versions must be plainly marked as such, and must not be
27 *    misrepresented as being the original software.
28 *
29 * 4. This notice may not be removed or altered.
30 */
31
32#ifndef lint
33static char copyright[] =
34"@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n";
35static char *rcsid = "$Id: dproc.c,v 1.8 2005/11/01 20:24:51 abe Exp $";
36#endif
37
38#include "lsof.h"
39
40#include <mach/mach_traps.h>
41#include <mach/mach_init.h>
42#include <mach/message.h>
43#include <mach/vm_map.h>
44
45
46/*
47 * Local definitions
48 */
49
50#define	NPHASH	1024				/* Phash bucket count --
51						 * MUST BE A POWER OF 2!!! */
52#define PHASH(a)	(((int)((a * 31415) >> 3)) & (NPHASH - 1))
53#define PINCRSZ		256			/* Proc[] size inrement */
54
55
56/*
57 * Local structures
58 */
59
60struct phash {
61    KA_T ka;					/* kernel proc struct address */
62    struct proc *la;				/* local proc struct address */
63    struct phash *next;				/* next phash entry */
64};
65
66
67/*
68 * Local function prototypes
69 */
70
71_PROTOTYPE(static pid_t get_parent_pid,(KA_T kpa));
72_PROTOTYPE(static int read_procs,());
73_PROTOTYPE(static void process_map,(pid_t pid));
74_PROTOTYPE(static void enter_vn_text,(KA_T va, int *n));
75
76#if	DARWINV>=700
77_PROTOTYPE(static char *getcmdnm,(pid_t pid));
78#endif	/* DARWINV>=700 */
79
80_PROTOTYPE(static void get_kernel_access,(void));
81
82
83/*
84 * Local static values
85 */
86
87static KA_T Akp = (KA_T)NULL;		/* kernel allproc chain address */
88static int Np = 0;			/* PA[] and Proc[] entry count */
89static int Npa = 0;			/* Proc[] structure allocation count */
90static MALLOC_S Nv = 0;			/* allocated Vp[] entries */
91static KA_T *Pa = (KA_T *)NULL;		/* Proc[] addresses */
92struct phash **Phash = (struct phash **)NULL;
93					/* kernel proc address hash pointers */
94static struct proc *Proc = (struct proc *)NULL;
95					/* local copy of prc struct chain */
96static KA_T *Vp = NULL;			/* vnode address cache */
97
98
99/*
100 * enter_vn_text() - enter a vnode text reference
101 */
102
103static void
104enter_vn_text(va, n)
105	KA_T va;			/* vnode address */
106	int *n;				/* Vp[] entries in use */
107{
108	int i;
109/*
110 * Ignore the request if the vnode has already been entered.
111 */
112	for (i = 0; i < *n; i++) {
113	    if (va == Vp[i])
114		return;
115	}
116/*
117 * Save the text file information.
118 */
119	alloc_lfile(" txt", -1);
120	Cfp = (struct file *)NULL;
121	process_node(va);
122	if (Lf->sf)
123	    link_lfile();
124	if (i >= Nv) {
125
126	/*
127	 * Allocate space for remembering the vnode.
128	 */
129	    Nv += 10;
130	    if (!Vp)
131		Vp=(KA_T *)malloc((MALLOC_S)(sizeof(struct vnode *)*10));
132	    else
133		Vp=(KA_T *)realloc((MALLOC_P *)Vp,(MALLOC_S)(Nv*sizeof(KA_T)));
134	    if (!Vp) {
135		(void) fprintf(stderr, "%s: no txt ptr space, PID %d\n",
136		    Pn, Lp->pid);
137		Exit(1);
138	    }
139	}
140/*
141 * Remember the vnode.
142 */
143	Vp[*n] = va;
144	(*n)++;
145}
146
147
148/*
149 * gather_proc_info() -- gather process information
150 */
151
152void
153gather_proc_info()
154{
155	char *cmd;
156	struct filedesc fd;
157	int i, nf;
158	MALLOC_S nb;
159	static struct file **ofb = NULL;
160	static int ofbb = 0;
161	struct proc *p;
162	int pgid;
163	int ppid = 0;
164	static char *pof = (char *)NULL;
165	static int pofb = 0;
166	short pss, sf;
167	int px;
168	uid_t uid;
169
170#if	DARWINV<800
171	struct pcred pc;
172#else	/* DARWINV>=800 */
173	struct ucred uc;
174#endif	/* DARWINV<800 */
175
176/*
177 * Read the process table.
178 */
179	if (read_procs()) {
180	    (void) fprintf(stderr, "%s: can't read process table\n", Pn);
181	    Exit(1);
182	}
183/*
184 * Examine proc structures and their associated information.
185 */
186	for (p = Proc, px = 0; px < Np; p++, px++)
187	{
188
189#if	DARWINV<800
190	    if (!p->p_cred || kread((KA_T)p->p_cred, (char *)&pc, sizeof(pc)))
191		continue;
192	    pgid = pc.p_rgid;
193	    uid = pc.p_ruid;
194#else	/* DARWINV>=800 */
195	    if (!p->p_ucred || kread((KA_T)p->p_ucred, (char *)&uc, sizeof(uc)))
196		continue;
197	    pgid = uc.cr_rgid;
198	    uid = uc.cr_uid;
199#endif	/* DARWINV<800 */
200
201#if	defined(HASPPID)
202	    ppid = get_parent_pid((KA_T)p->p_pptr);
203#endif	/* defined(HASPPID) */
204
205	/*
206	 * Get the command name.
207	 */
208
209#if	DARWINV<700
210	    cmd = p->P_COMM;
211#else	/* DARWINV>=700 */
212	   if (!strcmp(p->p_comm, "LaunchCFMApp")) {
213		if (!(cmd = getcmdnm(p->p_pid)))
214		    cmd = p->p_comm;
215	   } else
216		cmd = p->p_comm;
217#endif	/* DARWINV<700 */
218
219	/*
220	 * See if process is excluded.
221	 *
222	 * Read file structure pointers.
223	 */
224	    if (is_proc_excl(p->p_pid, pgid, (UID_ARG)uid, &pss, &sf))
225		continue;
226	    if (!p->p_fd ||  kread((KA_T)p->p_fd, (char *)&fd, sizeof(fd)))
227		continue;
228	    if (!fd.fd_refcnt || fd.fd_lastfile > fd.fd_nfiles)
229		continue;
230	/*
231	 * Allocate a local process structure.
232	 *
233	 * Set kernel's proc structure address.
234	 */
235	    if (is_cmd_excl(cmd, &pss, &sf))
236		continue;
237	    alloc_lproc(p->p_pid, pgid, ppid, (UID_ARG)uid, cmd, (int)pss,
238			(int)sf);
239	    Plf = (struct lfile *)NULL;
240	    Kpa = Pa[px];
241	/*
242	 * Save current working directory information.
243	 */
244	    if (fd.fd_cdir) {
245		alloc_lfile(CWD, -1);
246		Cfp = (struct file *)NULL;
247		process_node((KA_T)fd.fd_cdir);
248		if (Lf->sf)
249		    link_lfile();
250	    }
251	/*
252	 * Save root directory information.
253	 */
254	    if (fd.fd_rdir) {
255		alloc_lfile(RTD, -1);
256		Cfp = (struct file *)NULL;
257		process_node((KA_T)fd.fd_rdir);
258		if (Lf->sf)
259		    link_lfile();
260	    }
261	/*
262	 * Process the VM map.
263	 */
264	    process_map(p->p_pid);
265	/*
266	 * Read open file structure pointers.
267	 */
268	    if (!fd.fd_ofiles || (nf = fd.fd_nfiles) <= 0)
269		continue;
270	    nb = (MALLOC_S)(sizeof(struct file *) * nf);
271	    if (nb > ofbb) {
272		if (!ofb)
273		    ofb = (struct file **)malloc(nb);
274		else
275		    ofb = (struct file **)realloc((MALLOC_P *)ofb, nb);
276		if (!ofb) {
277		    (void) fprintf(stderr, "%s: PID %d, no file * space\n",
278			Pn, p->p_pid);
279		    Exit(1);
280		}
281		ofbb = nb;
282	    }
283	    if (kread((KA_T)fd.fd_ofiles, (char *)ofb, nb))
284		continue;
285
286	    nb = (MALLOC_S)(sizeof(char) * nf);
287	    if (nb > pofb) {
288		if (!pof)
289		    pof = (char *)malloc(nb);
290		else
291		    pof = (char *)realloc((MALLOC_P *)pof, nb);
292		if (!pof) {
293		    (void) fprintf(stderr, "%s: PID %d, no file flag space\n",
294			Pn, p->p_pid);
295		    Exit(1);
296		}
297		pofb = nb;
298	    }
299	    if (!fd.fd_ofileflags || kread((KA_T)fd.fd_ofileflags, pof, nb))
300		zeromem(pof, nb);
301
302	/*
303	 * Save information on file descriptors.
304	 */
305	    for (i = 0; i < nf; i++) {
306		if (ofb[i] && !(pof[i] & UF_RESERVED)) {
307		    alloc_lfile(NULL, i);
308		    process_file((KA_T)(Cfp = ofb[i]));
309		    if (Lf->sf) {
310
311#if	defined(HASFSTRUCT)
312			if (Fsv & FSV_FG)
313			    Lf->pof = (long)pof[i];
314#endif	/* defined(HASFSTRUCT) */
315
316			link_lfile();
317		    }
318		}
319	    }
320	/*
321	 * Examine results.
322	 */
323	    if (examine_lproc())
324		return;
325	}
326}
327
328
329#if	DARWINV>=700
330static char *
331getcmdnm(pid)
332	pid_t pid;			/* process ID */
333{
334	static int am;
335	static char *ap = (char *)NULL;
336	char *cp, *ep, *sp;
337	int mib[3];
338	size_t sz;
339
340	if (!ap) {
341
342	/*
343	 * Allocate space for the maximum argument size.
344	 */
345	    mib[0] = CTL_KERN;
346	    mib[1] = KERN_ARGMAX;
347	    sz = sizeof(am);
348	    if (sysctl(mib, 2, &am, &sz, NULL, 0) == -1) {
349		(void) fprintf(stderr, "%s: can't get arg max, PID %d\n",
350		    Pn, pid);
351		Exit(1);
352	    }
353	    if (!(ap = (char *)malloc((MALLOC_S)am))) {
354		(void) fprintf(stderr, "%s: no arg ptr (%d) space, PID %d\n",
355		    Pn, am, pid);
356		Exit(1);
357	    }
358	}
359/*
360 * Get the arguments for the process.
361 */
362	mib[0] = CTL_KERN;
363	mib[1] = KERN_PROCARGS;
364	mib[2] = pid;
365	sz = (size_t)am;
366	if (sysctl(mib, 3, ap, &sz, NULL, 0) == -1)
367	    return((char *)NULL);
368/*
369 * Skip to the first NUL character, which should end the saved exec path.
370 */
371	for (cp = ap; *cp && (cp < (ap + sz)); cp++) {
372	    ;
373	}
374	if (cp >= (ap + sz))
375	    return((char *)NULL);
376/*
377 * Skip trailing NULs, which should find the beginning of the command.
378 */
379	while (!*cp && (cp < (ap + sz))) {
380	    cp++;
381	}
382	if (cp >= (ap + sz))
383	    return((char *)NULL);
384/*
385 * Make sure that the command is NUL-terminated.
386 */
387	for (sp = cp; *cp && (cp < (ap + sz)); cp++) {
388	    ;
389	}
390	if (cp >= (ap + sz))
391	    return((char *)NULL);
392	ep = cp;
393/*
394 * Locate the start of the command's base name and return it.
395 */
396	for (ep = cp, cp--; cp >= sp; cp--) {
397	    if (*cp == '/') {
398		return(cp + 1);
399	    }
400	}
401	return(sp);
402}
403#endif	/* DARWINV>=700 */
404
405
406/*
407 * get_kernel_access() - get access to kernel memory
408 */
409
410static void
411get_kernel_access()
412{
413
414/*
415 * Check kernel version.
416 */
417	(void) ckkv("Darwin", LSOF_VSTR, (char *)NULL, (char *)NULL);
418/*
419 * Set name list file path.
420 */
421	if (!Nmlst)
422	    Nmlst = N_UNIX;
423
424#if	defined(WILLDROPGID)
425/*
426 * If kernel memory isn't coming from KMEM, drop setgid permission
427 * before attempting to open the (Memory) file.
428 */
429	if (Memory)
430	    (void) dropgid();
431#else	/* !defined(WILLDROPGID) */
432/*
433 * See if the non-KMEM memory and the name list files are readable.
434 */
435	if ((Memory && !is_readable(Memory, 1))
436	||  (Nmlst && !is_readable(Nmlst, 1)))
437	    Exit(1);
438#endif	/* defined(WILLDROPGID) */
439
440/*
441 * Open kernel memory access.
442 */
443	if ((Kd = open(Memory ? Memory : KMEM, O_RDONLY, 0)) < 0)
444	{
445	    (void) fprintf(stderr, "%s: open(%s): %s\n", Pn,
446	        Memory ? Memory : KMEM,
447		strerror(errno));
448	    Exit(1);
449	}
450	(void) build_Nl(Drive_Nl);
451	if (nlist(Nmlst, Nl) < 0) {
452	    (void) fprintf(stderr, "%s: can't read namelist from %s\n",
453		Pn, Nmlst);
454	    Exit(1);
455	}
456
457#if	defined(WILLDROPGID)
458/*
459 * Drop setgid permission, if necessary.
460 */
461	if (!Memory)
462	    (void) dropgid();
463#endif	/* defined(WILLDROPGID) */
464
465}
466
467
468/*
469 * get_parent_pid() - get parent process PID
470 */
471
472static pid_t
473get_parent_pid(kpa)
474	KA_T kpa;			/* kernel parent process address */
475{
476	struct phash *ph;
477
478	if (kpa) {
479	    for (ph = Phash[PHASH(kpa)]; ph; ph = ph->next) {
480		if (ph->ka == kpa)
481		    return((pid_t)ph->la->p_pid);
482	    }
483	}
484	return((pid_t)0);
485}
486
487
488/*
489 * initialize() - perform all initialization
490 */
491
492void
493initialize()
494{
495	get_kernel_access();
496}
497
498
499/*
500 * kread() - read from kernel memory
501 */
502
503int
504kread(addr, buf, len)
505	KA_T addr;			/* kernel memory address */
506	char *buf;			/* buffer to receive data */
507	READLEN_T len;			/* length to read */
508{
509	int br;
510
511	if ((off_t)addr & (off_t)0x3) {
512
513	/*
514	 * No read is possible if the address is not aligned on a word
515	 * boundary.
516	 */
517	    return(1);
518	}
519	if (lseek(Kd, (off_t)addr, SEEK_SET) == (off_t)-1)
520	    return(1);
521	br = read(Kd, buf, len);
522	return((br == len) ? 0 : 1);
523}
524
525
526/*
527 * prcess_map() - process VM map
528 */
529
530static void
531process_map(pid)
532	pid_t pid;			/* process id */
533{
534	vm_address_t address = 0;
535	mach_msg_type_number_t count;
536	vm_region_extended_info_data_t e_info;
537	int n = 0;
538	mach_port_t object_name;
539	vm_size_t size = 0;
540	vm_map_t task;
541	vm_region_top_info_data_t t_info;
542
543	struct vm_object {		/* should come from <vm/vm_object.h> */
544
545#if	DARWINV<800
546	    KA_T		Dummy1[15];
547#else	/* DARWINV>=800 */
548	    KA_T		Dummy1[14];
549#endif	/* DARWINV>=800 */
550
551	    memory_object_t	pager;
552	} vmo;
553
554	struct vnode_pager {		/* from <osfmk/vm/bsd_vm.c> */
555	    KA_T		Dummy1[4];
556	    struct vnode	*vnode;
557	} vp;
558
559/*
560 * Get the task port associated with the process
561 */
562	if (task_for_pid((mach_port_name_t)mach_task_self(), pid,
563			 (mach_port_name_t *)&task)
564	!= KERN_SUCCESS) {
565	    return;
566	}
567/*
568 * Go through the task's address space, looking for blocks of memory
569 * backed by an external pager (i.e, a "vnode")
570 */
571	for (address = 0;; address += size) {
572	    count = VM_REGION_EXTENDED_INFO_COUNT;
573	    if (vm_region(task, &address, &size, VM_REGION_EXTENDED_INFO,
574			  (vm_region_info_t)&e_info, &count, &object_name)
575	    != KERN_SUCCESS) {
576		break;
577	    }
578	    if (!e_info.external_pager)
579		continue;
580	    count = VM_REGION_TOP_INFO_COUNT;
581	    if (vm_region(task, &address, &size, VM_REGION_TOP_INFO,
582			  (vm_region_info_t)&t_info, &count, &object_name)
583	    != KERN_SUCCESS) {
584		break;
585	    }
586	/*
587	 * The returned "obj_id" is the "vm_object_t" address.
588	 */
589	    if (!t_info.obj_id)
590		continue;
591	    if (kread(t_info.obj_id, (char *)&vmo, sizeof(vmo)))
592		break;
593	/*
594	 * If the "pager" is backed by a vnode then the "vm_object_t"
595	 * "memory_object_t" address is actually a "struct vnode_pager *".
596	 */
597	    if (!vmo.pager)
598		continue;
599	    if (kread((KA_T)vmo.pager, (char *)&vp, sizeof(vp)))
600		break;
601	    (void) enter_vn_text((KA_T)vp.vnode, &n);
602	}
603	return;
604}
605
606
607/*
608 * read_procs() - read proc structures
609 */
610
611static int
612read_procs()
613{
614	int h, i, np, pe;
615	KA_T kp, kpn;
616	MALLOC_S msz;
617	struct proc *p;
618	struct phash *ph, *phn;
619
620	if (!Akp) {
621
622	/*
623	 * Get kernel allproc structure pointer once.
624	 */
625	    if (get_Nl_value("aproc", Drive_Nl, &Akp) < 0 || !Akp) {
626		(void) fprintf(stderr, "%s: can't get proc table address\n",
627		    Pn);
628		Exit(1);
629	    }
630	}
631/*
632 * Get the current number of processes and calculate PA and Proc[] allocation
633 * sizes large enough to handle it.
634 */
635	if (get_Nl_value("nproc", Drive_Nl, &kp) < 0 || !kp) {
636	    (void) fprintf(stderr, "%s: can't get nproc address\n", Pn);
637	    Exit(1);
638	}
639	if (kread(kp, (char *)&np, sizeof(np))) {
640	    (void) fprintf(stderr, "%s: can't read process count from %s\n",
641		Pn, print_kptr(kp, (char *)NULL, 0));
642	    Exit(1);
643	}
644	for (np += np, pe = PINCRSZ; pe < np; pe += PINCRSZ)
645	    ;
646/*
647 * Allocate or reallocate the Pa[] and Proc[] tables.
648 */
649	msz = (MALLOC_S)(pe * sizeof(struct proc));
650	if (!Proc)
651	    Proc = (struct proc *)malloc(msz);
652	else if (pe > Npa)
653	    Proc = (struct proc *)realloc((MALLOC_P *)Proc, msz);
654	if (!Proc) {
655	    (void) fprintf(stderr, "%s: no space for proc table\n", Pn);
656	    Exit(1);
657	}
658	msz = (MALLOC_S)(pe * sizeof(KA_T));
659	if (!Pa)
660	    Pa = (KA_T *)malloc(msz);
661	else if (pe > Npa)
662	    Pa = (KA_T *)realloc((MALLOC_P *)Pa, msz);
663	if (!Pa) {
664	    (void) fprintf(stderr, "%s: no space for proc addr table\n", Pn);
665	    Exit(1);
666	}
667	Npa = pe;
668/*
669 * Allocate or reset the Phash[] table.
670 */
671	if (!Phash) {
672	    Phash = (struct phash **)calloc(NPHASH, sizeof(struct phash *));
673	} else {
674	    for (h = 0; h < NPHASH; h++) {
675		for (ph = Phash[h]; ph; ph = phn) {
676		    phn = ph->next;
677		    (void) free((MALLOC_P *)ph);
678		}
679		Phash[h] = (struct phash *)NULL;
680	    }
681	}
682	if (!Phash) {
683	    (void) fprintf(stderr, "%s: no space for proc address hash\n", Pn);
684	    Exit(1);
685	}
686/*
687 * Read the proc structures on the kernel's chain.
688 */
689	for (i = Np = 0, kp = Akp, p = Proc, pe += pe;
690	     kp && i < pe;
691	     i++, kp = kpn)
692	{
693	    if (kread(kp, (char *)p, sizeof(struct proc)))
694		break;
695	    kpn = (KA_T)(((KA_T)p->p_list.le_next == Akp) ? NULL
696							  : p->p_list.le_next);
697	    if (p->p_stat == 0 || p->p_stat == SZOMB)
698		continue;
699	/*
700	 * Cache the proc structure's addresses.
701	 */
702	    h = PHASH(kp);
703	    if (!(ph = (struct phash *)malloc((MALLOC_S)sizeof(struct phash))))
704	    {
705		(void) fprintf(stderr, "%s: no space for phash struct\n", Pn);
706		Exit(1);
707	    }
708	    ph->ka = kp;
709	    ph->la = p;
710	    ph->next = Phash[h];
711	    Phash[h] = ph;
712	    p++;
713	    Pa[Np++] = kp;
714	    if (Np >= Npa) {
715
716	    /*
717	     * Enlarge Pa[] and Proc[].
718	     */
719		msz = (int)((Npa + PINCRSZ) * sizeof(struct proc));
720		if (!(Proc = (struct proc *)realloc((MALLOC_P *)Proc, msz))) {
721		    (void) fprintf(stderr, "%s: no additional proc space\n",
722			Pn);
723		    Exit(1);
724		}
725		msz = (int)((Npa + PINCRSZ) * sizeof(KA_T));
726		if (!(Pa = (KA_T *)realloc((MALLOC_P *)Pa, msz))) {
727		    (void) fprintf(stderr,
728			"%s: no additional proc addr space\n", Pn);
729		    Exit(1);
730		}
731		Npa += PINCRSZ;
732	    }
733	}
734/*
735 * If too many processes were read, the chain following probably failed;
736 * report that and exit.
737 */
738	if (i >= pe) {
739	    (void) fprintf(stderr, "%s: can't follow kernel proc chain\n", Pn);
740	    Exit(1);
741	}
742/*
743 * If not in repeat mode, reduce Pa[] and Proc[] to their minimums.
744 */
745	if (Np < Npa && !RptTm) {
746	    msz = (MALLOC_S)(Np * sizeof(struct proc));
747	    if (!(Proc = (struct proc *)realloc((MALLOC_P *)Proc, msz))) {
748		(void) fprintf(stderr, "%s: can't reduce proc table\n", Pn);
749		Exit(1);
750	    }
751	    msz = (MALLOC_S)(Np * sizeof(KA_T));
752	    if (!(Pa = (KA_T *)realloc((MALLOC_P *)Pa, msz))) {
753		(void) fprintf(stderr, "%s: can't reduce proc addr table\n",
754		    Pn);
755		Exit(1);
756	    }
757	    Npa = Np;
758	}
759/*
760 * Return 0 if any processes were loaded; 1 if none were.
761 */
762	return((Np > 0) ? 0 : 1);
763}
764