Example #1
0
struct kinfo_proc2 *
kvm_getproc2(kvm_t *kd, int op, int arg, size_t esize, int *cnt)
{
	int mib[6], st, nprocs;
	struct user user;
	size_t size;

	if ((ssize_t)esize < 0)
		return (NULL);

	if (kd->procbase2 != NULL) {
		free(kd->procbase2);
		/*
		 * Clear this pointer in case this call fails.  Otherwise,
		 * kvm_close() will free it again.
		 */
		kd->procbase2 = 0;
	}

	if (ISALIVE(kd)) {
		size = 0;
		mib[0] = CTL_KERN;
		mib[1] = KERN_PROC2;
		mib[2] = op;
		mib[3] = arg;
		mib[4] = esize;
		mib[5] = 0;
		st = sysctl(mib, 6, NULL, &size, NULL, 0);
		if (st == -1) {
			_kvm_syserr(kd, kd->program, "kvm_getproc2");
			return (NULL);
		}

		mib[5] = size / esize;
		kd->procbase2 = _kvm_malloc(kd, size);
		if (kd->procbase2 == 0)
			return (NULL);
		st = sysctl(mib, 6, kd->procbase2, &size, NULL, 0);
		if (st == -1) {
			_kvm_syserr(kd, kd->program, "kvm_getproc2");
			return (NULL);
		}
		nprocs = size / esize;
	} else {
		struct kinfo_proc2 kp2, *kp2p;
		struct kinfo_proc *kp;
		char *kp2c;
		int i;

		kp = kvm_getprocs(kd, op, arg, &nprocs);
		if (kp == NULL)
			return (NULL);

		kd->procbase2 = _kvm_malloc(kd, nprocs * esize);
		kp2c = (char *)kd->procbase2;
		kp2p = &kp2;
		for (i = 0; i < nprocs; i++, kp++) {
			memset(kp2p, 0, sizeof(kp2));
			kp2p->p_paddr = PTRTOINT64(kp->kp_eproc.e_paddr);

			kp2p->p_addr = PTRTOINT64(kp->kp_proc.p_addr);
			kp2p->p_fd = PTRTOINT64(kp->kp_proc.p_fd);
			kp2p->p_stats = PTRTOINT64(kp->kp_proc.p_stats);
			kp2p->p_limit = PTRTOINT64(kp->kp_eproc.e_limit);
			kp2p->p_vmspace = PTRTOINT64(kp->kp_proc.p_vmspace);
			kp2p->p_sigacts = PTRTOINT64(kp->kp_proc.p_sigacts);
			kp2p->p_sess = PTRTOINT64(kp->kp_eproc.e_sess);
			kp2p->p_tsess = 0;
			kp2p->p_ru = PTRTOINT64(kp->kp_proc.p_ru);

			kp2p->p_eflag = 0;
			kp2p->p_exitsig = kp->kp_proc.p_exitsig;
			kp2p->p_flag = kp->kp_proc.p_flag;

			kp2p->p_pid = kp->kp_proc.p_pid;

			kp2p->p_ppid = kp->kp_eproc.e_ppid;
#if 0
			kp2p->p_sid = kp->kp_eproc.e_sid;
#else
			kp2p->p_sid = -1; /* XXX */
#endif
			kp2p->p__pgid = kp->kp_eproc.e_pgid;

			kp2p->p_tpgid = -1;

			kp2p->p_uid = kp->kp_eproc.e_ucred.cr_uid;
			kp2p->p_ruid = kp->kp_eproc.e_pcred.p_ruid;
			kp2p->p_gid = kp->kp_eproc.e_ucred.cr_gid;
			kp2p->p_rgid = kp->kp_eproc.e_pcred.p_rgid;

			memcpy(kp2p->p_groups, kp->kp_eproc.e_ucred.cr_groups,
			    MIN(sizeof(kp2p->p_groups),
			    sizeof(kp->kp_eproc.e_ucred.cr_groups)));
			kp2p->p_ngroups = kp->kp_eproc.e_ucred.cr_ngroups;

			kp2p->p_jobc = kp->kp_eproc.e_jobc;
			kp2p->p_tdev = kp->kp_eproc.e_tdev;
			kp2p->p_tpgid = kp->kp_eproc.e_tpgid;
			kp2p->p_tsess = PTRTOINT64(kp->kp_eproc.e_tsess);

			kp2p->p_estcpu = kp->kp_proc.p_estcpu;
			kp2p->p_rtime_sec = kp->kp_proc.p_estcpu;
			kp2p->p_rtime_usec = kp->kp_proc.p_estcpu;
			kp2p->p_cpticks = kp->kp_proc.p_cpticks;
			kp2p->p_pctcpu = kp->kp_proc.p_pctcpu;
			kp2p->p_swtime = kp->kp_proc.p_swtime;
			kp2p->p_slptime = kp->kp_proc.p_slptime;
			kp2p->p_schedflags = 0;

			kp2p->p_uticks = kp->kp_proc.p_uticks;
			kp2p->p_sticks = kp->kp_proc.p_sticks;
			kp2p->p_iticks = kp->kp_proc.p_iticks;

			kp2p->p_tracep = PTRTOINT64(kp->kp_proc.p_tracep);
			kp2p->p_traceflag = kp->kp_proc.p_traceflag;

			kp2p->p_holdcnt = 1;

			kp2p->p_siglist = kp->kp_proc.p_siglist;
			kp2p->p_sigmask = kp->kp_proc.p_sigmask;
			kp2p->p_sigignore = kp->kp_proc.p_sigignore;
			kp2p->p_sigcatch = kp->kp_proc.p_sigcatch;

			kp2p->p_stat = kp->kp_proc.p_stat;
			kp2p->p_priority = kp->kp_proc.p_priority;
			kp2p->p_usrpri = kp->kp_proc.p_usrpri;
			kp2p->p_nice = kp->kp_proc.p_nice;

			kp2p->p_xstat = kp->kp_proc.p_xstat;
			kp2p->p_acflag = kp->kp_proc.p_acflag;

			strncpy(kp2p->p_comm, kp->kp_proc.p_comm,
			    MIN(sizeof(kp2p->p_comm), sizeof(kp->kp_proc.p_comm)));

			strncpy(kp2p->p_wmesg, kp->kp_eproc.e_wmesg,
			    sizeof(kp2p->p_wmesg));
			kp2p->p_wchan = PTRTOINT64(kp->kp_proc.p_wchan);

			strncpy(kp2p->p_login, kp->kp_eproc.e_login,
			    sizeof(kp2p->p_login));

			kp2p->p_vm_rssize = kp->kp_eproc.e_xrssize;
			kp2p->p_vm_tsize = kp->kp_eproc.e_vm.vm_tsize;
			kp2p->p_vm_dsize = kp->kp_eproc.e_vm.vm_dsize;
			kp2p->p_vm_ssize = kp->kp_eproc.e_vm.vm_ssize;

			kp2p->p_eflag = kp->kp_eproc.e_flag;

			if (P_ZOMBIE(&kp->kp_proc) || kp->kp_proc.p_addr == NULL ||
			    KREAD(kd, (u_long)kp->kp_proc.p_addr, &user)) {
				kp2p->p_uvalid = 0;
			} else {
				kp2p->p_uvalid = 1;

				kp2p->p_ustart_sec = user.u_stats.p_start.tv_sec;
				kp2p->p_ustart_usec = user.u_stats.p_start.tv_usec;

				kp2p->p_uutime_sec = user.u_stats.p_ru.ru_utime.tv_sec;
				kp2p->p_uutime_usec = user.u_stats.p_ru.ru_utime.tv_usec;
				kp2p->p_ustime_sec = user.u_stats.p_ru.ru_stime.tv_sec;
				kp2p->p_ustime_usec = user.u_stats.p_ru.ru_stime.tv_usec;

				kp2p->p_uru_maxrss = user.u_stats.p_ru.ru_maxrss;
				kp2p->p_uru_ixrss = user.u_stats.p_ru.ru_ixrss;
				kp2p->p_uru_idrss = user.u_stats.p_ru.ru_idrss;
				kp2p->p_uru_isrss = user.u_stats.p_ru.ru_isrss;
				kp2p->p_uru_minflt = user.u_stats.p_ru.ru_minflt;
				kp2p->p_uru_majflt = user.u_stats.p_ru.ru_majflt;
				kp2p->p_uru_nswap = user.u_stats.p_ru.ru_nswap;
				kp2p->p_uru_inblock = user.u_stats.p_ru.ru_inblock;
				kp2p->p_uru_oublock = user.u_stats.p_ru.ru_oublock;
				kp2p->p_uru_msgsnd = user.u_stats.p_ru.ru_msgsnd;
				kp2p->p_uru_msgrcv = user.u_stats.p_ru.ru_msgrcv;
				kp2p->p_uru_nsignals = user.u_stats.p_ru.ru_nsignals;
				kp2p->p_uru_nvcsw = user.u_stats.p_ru.ru_nvcsw;
				kp2p->p_uru_nivcsw = user.u_stats.p_ru.ru_nivcsw;

				kp2p->p_uctime_sec =
				    user.u_stats.p_cru.ru_utime.tv_sec +
				    user.u_stats.p_cru.ru_stime.tv_sec;
				kp2p->p_uctime_usec =
				    user.u_stats.p_cru.ru_utime.tv_usec +
				    user.u_stats.p_cru.ru_stime.tv_usec;
			}

			memcpy(kp2c, &kp2, esize);
			kp2c += esize;
		}

		free(kd->procbase);
	}
	*cnt = nprocs;
	return (kd->procbase2);
}
Example #2
0
/*
 * Read proc's from memory file into buffer bp, which has space to hold
 * at most maxcnt procs.
 */
static int
kvm_proclist(kvm_t *kd, int op, int arg, struct proc *p,
    char *bp, int maxcnt, size_t esize)
{
	struct kinfo_proc kp;
	struct session sess;
	struct pcred pcred;
	struct ucred ucred;
	struct proc proc, proc2;
	struct process process, process2;
	struct pgrp pgrp;
	struct tty tty;
	struct sigacts sa, *sap;
	struct vmspace vm, *vmp;
	struct plimit limits, *limp;
	pid_t process_pid, parent_pid, leader_pid;
	int cnt = 0;
	int dothreads = 0;

	dothreads = op & KERN_PROC_SHOW_THREADS;
	op &= ~KERN_PROC_SHOW_THREADS;

	for (; cnt < maxcnt && p != NULL; p = LIST_NEXT(&proc, p_list)) {
		if (KREAD(kd, (u_long)p, &proc)) {
			_kvm_err(kd, kd->program, "can't read proc at %x", p);
			return (-1);
		}
		if (KREAD(kd, (u_long)proc.p_p, &process)) {
			_kvm_err(kd, kd->program, "can't read process at %x",
			    proc.p_p);
			return (-1);
		}
		if (KREAD(kd, (u_long)process.ps_cred, &pcred)) {
			_kvm_err(kd, kd->program, "can't read pcred at %x",
			    process.ps_cred);
			return (-1);
		}
		if ((proc.p_flag & P_THREAD) == 0)
			process_pid = proc.p_pid;
		else {
			if (KREAD(kd, (u_long)process.ps_mainproc, &proc2)) {
				_kvm_err(kd, kd->program,
				    "can't read proc at %x",
				    process.ps_mainproc);
				return (-1);
			}
			process_pid = proc2.p_pid;
		}
		if (KREAD(kd, (u_long)pcred.pc_ucred, &ucred)) {
			_kvm_err(kd, kd->program, "can't read ucred at %x",
			    pcred.pc_ucred);
			return (-1);
		}
		if (KREAD(kd, (u_long)process.ps_pgrp, &pgrp)) {
			_kvm_err(kd, kd->program, "can't read pgrp at %x",
			    process.ps_pgrp);
			return (-1);
		}
		if (KREAD(kd, (u_long)pgrp.pg_session, &sess)) {
			_kvm_err(kd, kd->program, "can't read session at %x",
			    pgrp.pg_session);
			return (-1);
		}
		if ((process.ps_flags & PS_CONTROLT) && sess.s_ttyp != NULL &&
		    KREAD(kd, (u_long)sess.s_ttyp, &tty)) {
			_kvm_err(kd, kd->program,
			    "can't read tty at %x", sess.s_ttyp);
			return (-1);
		}
		if (process.ps_pptr) {
			if (KREAD(kd, (u_long)process.ps_pptr, &process2)) {
				_kvm_err(kd, kd->program,
				    "can't read process at %x",
				    process.ps_pptr);
				return (-1);
			}
			if (KREAD(kd, (u_long)process2.ps_mainproc, &proc2)) {
				_kvm_err(kd, kd->program,
				    "can't read proc at %x",
				    process2.ps_mainproc);
				return (-1);
			}
			parent_pid = proc2.p_pid;
		}
		else
			parent_pid = 0;
		if (sess.s_leader) {
			if (KREAD(kd, (u_long)sess.s_leader, &process2)) {
				_kvm_err(kd, kd->program,
				    "can't read proc at %x", sess.s_leader);
				return (-1);
			}
			if (KREAD(kd, (u_long)process2.ps_mainproc, &proc2)) {
				_kvm_err(kd, kd->program,
				    "can't read proc at %x",
				    process2.ps_mainproc);
				return (-1);
			}
			leader_pid = proc2.p_pid;
		}
		else
			leader_pid = 0;
		if (proc.p_sigacts) {
			if (KREAD(kd, (u_long)proc.p_sigacts, &sa)) {
				_kvm_err(kd, kd->program, "can't read sigacts at %x",
				    proc.p_sigacts);
				return (-1);
			}
			sap = &sa;
		}
		else
			sap = NULL;

		switch (op) {
		case KERN_PROC_PID:
			if (proc.p_pid != (pid_t)arg)
				continue;
			break;

		case KERN_PROC_PGRP:
			if (pgrp.pg_id != (pid_t)arg)
				continue;
			break;

		case KERN_PROC_SESSION:
			if (sess.s_leader == NULL ||
			    leader_pid != (pid_t)arg)
				continue;
			break;

		case KERN_PROC_TTY:
			if ((process.ps_flags & PS_CONTROLT) == 0 ||
			    sess.s_ttyp == NULL ||
			    tty.t_dev != (dev_t)arg)
				continue;
			break;

		case KERN_PROC_UID:
			if (ucred.cr_uid != (uid_t)arg)
				continue;
			break;

		case KERN_PROC_RUID:
			if (pcred.p_ruid != (uid_t)arg)
				continue;
			break;

		case KERN_PROC_ALL:
			if (proc.p_flag & P_SYSTEM)
				continue;
			break;

		case KERN_PROC_KTHREAD:
			/* no filtering */
			break;

		default:
			_kvm_err(kd, kd->program, "invalid filter");
			return (-1);
		}

		/*
		 * We're going to add another proc to the set.  If this
		 * will overflow the buffer, assume the reason is because
		 * nthreads (or the proc list) is corrupt and declare an error.
		 */
		if (cnt >= maxcnt) {
			_kvm_err(kd, kd->program, "nthreads corrupt");
			return (-1);
		}

		/* set up stuff that might not always be there */
		vmp = &vm;
		if (proc.p_stat == SIDL ||
		    P_ZOMBIE(&proc) ||
		    KREAD(kd, (u_long)proc.p_vmspace, &vm))
			vmp = NULL;

		limp = &limits;
		if (!process.ps_limit ||
		    KREAD(kd, (u_long)process.ps_limit, &limits))
			limp = NULL;

#define do_copy_str(_d, _s, _l)	kvm_read(kd, (u_long)(_s), (_d), (_l)-1)
		if ((proc.p_flag & P_THREAD) == 0) {
			FILL_KPROC(&kp, do_copy_str, &proc, &process, &pcred,
			    &ucred, &pgrp, p, proc.p_p, &sess, vmp, limp, sap,
			    0);

			/* stuff that's too painful to generalize */
			kp.p_pid = process_pid;
			kp.p_ppid = parent_pid;
			kp.p_sid = leader_pid;
			if ((process.ps_flags & PS_CONTROLT) && 
			    sess.s_ttyp != NULL) {
				kp.p_tdev = tty.t_dev;
				if (tty.t_pgrp != NULL &&
				    tty.t_pgrp != process.ps_pgrp &&
				    KREAD(kd, (u_long)tty.t_pgrp, &pgrp)) {
					_kvm_err(kd, kd->program,
					    "can't read tpgrp at &x",
					    tty.t_pgrp);
					return (-1);
				}
				kp.p_tpgid = tty.t_pgrp ? pgrp.pg_id : -1;
				kp.p_tsess = PTRTOINT64(tty.t_session);
			} else {
				kp.p_tpgid = -1;
				kp.p_tdev = NODEV;
			}

			memcpy(bp, &kp, esize);
			bp += esize;
			++cnt;
		}

		if (!dothreads)
			continue;

		FILL_KPROC(&kp, do_copy_str, &proc, &process, &pcred, &ucred,
		    &pgrp, p, proc.p_p, &sess, vmp, limp, sap, 1);

		/* stuff that's too painful to generalize into the macros */
		kp.p_pid = process_pid;
		kp.p_ppid = parent_pid;
		kp.p_sid = leader_pid;
		if ((process.ps_flags & PS_CONTROLT) && sess.s_ttyp != NULL) {
			kp.p_tdev = tty.t_dev;
			if (tty.t_pgrp != NULL &&
			    tty.t_pgrp != process.ps_pgrp &&
			    KREAD(kd, (u_long)tty.t_pgrp, &pgrp)) {
				_kvm_err(kd, kd->program,
				    "can't read tpgrp at &x", tty.t_pgrp);
				return (-1);
			}
			kp.p_tpgid = tty.t_pgrp ? pgrp.pg_id : -1;
			kp.p_tsess = PTRTOINT64(tty.t_session);
		} else {
			kp.p_tpgid = -1;
			kp.p_tdev = NODEV;
		}

		memcpy(bp, &kp, esize);
		bp += esize;
		++cnt;
#undef do_copy_str
	}
	return (cnt);
}