Esempio n. 1
0
/*
 * code for returning process's command line arguments
 */
int
procfs_docmdline(
    struct lwp *curl,
    struct proc *p,
    struct pfsnode *pfs,
    struct uio *uio
)
{
	size_t len, start;
	int error;

	/* Don't allow writing. */
	if (uio->uio_rw != UIO_READ)
		return (EOPNOTSUPP);

	/*
	 * Zombies don't have a stack, so we can't read their psstrings.
	 * System processes also don't have a user stack.  This is what
	 * ps(1) would display.
	 */
	if (P_ZOMBIE(p) || (p->p_flag & PK_SYSTEM) != 0) {
		static char msg[] = "()";
		error = 0;
		if (0 == uio->uio_offset) {
			error = uiomove(msg, 1, uio);
			if (error)
				return (error);
		}
		len = strlen(p->p_comm);
		if (len >= uio->uio_offset) {
			start = uio->uio_offset - 1;
			error = uiomove(p->p_comm + start, len - start, uio);
			if (error)
				return (error);
		}
		if (len + 2 >= uio->uio_offset) {
			start = uio->uio_offset - 1 - len;
			error = uiomove(msg + 1 + start, 2 - start, uio);
		}
		return (error);
	}

	len = uio->uio_offset + uio->uio_resid;

	error = copy_procargs(p, KERN_PROC_ARGV, &len,
	    procfs_docmdline_helper, uio);
	return error;
}
void
db_proc_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
{
	struct lwp *l;
	struct proc *p;

	l = curlwp;
	if (have_addr)
		l = (struct lwp *) addr;

	if (l == NULL) {
		db_printf("no current process\n");
		return;
	}

	p = l->l_proc;

	db_printf("LWP %p: ", l);
	db_printf("PID:%d.%d CPU:%d stat:%d vmspace:%p", p->p_pid,
	    l->l_lid, l->l_cpu->ci_cpuid, l->l_stat, p->p_vmspace);
	if (!P_ZOMBIE(p))
		db_printf(" ctx: %p cpuset %x",
			  p->p_vmspace->vm_map.pmap->pm_ctx,
			  p->p_vmspace->vm_map.pmap->pm_cpuset);
	db_printf("\npmap:%p wchan:%p pri:%d epri:%d\n",
		  p->p_vmspace->vm_map.pmap,
		  l->l_wchan, l->l_priority, lwp_eprio(l));
	db_printf("maxsaddr:%p ssiz:%d pg or %llxB\n",
		  p->p_vmspace->vm_maxsaddr, p->p_vmspace->vm_ssize,
		  (unsigned long long)ctob(p->p_vmspace->vm_ssize));
	db_printf("profile timer: %lld sec %ld nsec\n",
		  p->p_stats->p_timer[ITIMER_PROF].it_value.tv_sec,
		  p->p_stats->p_timer[ITIMER_PROF].it_value.tv_nsec);
	db_printf("pcb: %p\n", lwp_getpcb(l));
	return;
}
struct kinfo_proc2 *
kvm_getproc2(kvm_t *kd, int op, int arg, size_t esize, int *cnt)
{
	size_t size;
	int mib[6], st, nprocs;
	struct pstats pstats;

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

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

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

		size = nprocs * esize;
		KVM_ALLOC(kd, procbase2, size);
		kp2c = (char *)(void *)kd->procbase2;
		kp2p = &kp2;
		for (i = 0; i < nprocs; i++, kp++) {
			struct timeval tv;

			kl = kvm_getlwps(kd, kp->kp_proc.p_pid,
			    (u_long)PTRTOUINT64(kp->kp_eproc.e_paddr),
			    sizeof(struct kinfo_lwp), &nlwps);

			if (kl == NULL) {
				_kvm_syserr(kd, NULL,
					"kvm_getlwps() failed on process %u\n",
					kp->kp_proc.p_pid);
				if (nlwps == 0)
					return NULL;
				else
					continue;
			}

			/* We use kl[0] as the "representative" LWP */
			memset(kp2p, 0, sizeof(kp2));
			kp2p->p_forw = kl[0].l_forw;
			kp2p->p_back = kl[0].l_back;
			kp2p->p_paddr = PTRTOUINT64(kp->kp_eproc.e_paddr);
			kp2p->p_addr = kl[0].l_addr;
			kp2p->p_fd = PTRTOUINT64(kp->kp_proc.p_fd);
			kp2p->p_cwdi = PTRTOUINT64(kp->kp_proc.p_cwdi);
			kp2p->p_stats = PTRTOUINT64(kp->kp_proc.p_stats);
			kp2p->p_limit = PTRTOUINT64(kp->kp_proc.p_limit);
			kp2p->p_vmspace = PTRTOUINT64(kp->kp_proc.p_vmspace);
			kp2p->p_sigacts = PTRTOUINT64(kp->kp_proc.p_sigacts);
			kp2p->p_sess = PTRTOUINT64(kp->kp_eproc.e_sess);
			kp2p->p_tsess = 0;
#if 1 /* XXX: dsl - p_ru was only ever non-zero for zombies */
			kp2p->p_ru = 0;
#else
			kp2p->p_ru = PTRTOUINT64(pstats.p_ru);
#endif

			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;
			kp2p->p_sid = kp->kp_eproc.e_sid;
			kp2p->p__pgid = kp->kp_eproc.e_pgid;

			kp2p->p_tpgid = -1 /* XXX NO_PGID! */;

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

			/*CONSTCOND*/
			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 = PTRTOUINT64(kp->kp_eproc.e_tsess);

			kp2p->p_estcpu = 0;
			bintime2timeval(&kp->kp_proc.p_rtime, &tv);
			kp2p->p_rtime_sec = (uint32_t)tv.tv_sec;
			kp2p->p_rtime_usec = (uint32_t)tv.tv_usec;
			kp2p->p_cpticks = kl[0].l_cpticks;
			kp2p->p_pctcpu = kp->kp_proc.p_pctcpu;
			kp2p->p_swtime = kl[0].l_swtime;
			kp2p->p_slptime = kl[0].l_slptime;
#if 0 /* XXX thorpej */
			kp2p->p_schedflags = kp->kp_proc.p_schedflags;
#else
			kp2p->p_schedflags = 0;
#endif

			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 = PTRTOUINT64(kp->kp_proc.p_tracep);
			kp2p->p_traceflag = kp->kp_proc.p_traceflag;

			kp2p->p_holdcnt = kl[0].l_holdcnt;

			memcpy(&kp2p->p_siglist,
			    &kp->kp_proc.p_sigpend.sp_set,
			    sizeof(ki_sigset_t));
			memset(&kp2p->p_sigmask, 0,
			    sizeof(ki_sigset_t));
			memcpy(&kp2p->p_sigignore,
			    &kp->kp_proc.p_sigctx.ps_sigignore,
			    sizeof(ki_sigset_t));
			memcpy(&kp2p->p_sigcatch,
			    &kp->kp_proc.p_sigctx.ps_sigcatch,
			    sizeof(ki_sigset_t));

			kp2p->p_stat = kl[0].l_stat;
			kp2p->p_priority = kl[0].l_priority;
			kp2p->p_usrpri = kl[0].l_priority;
			kp2p->p_nice = kp->kp_proc.p_nice;

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

			/*CONSTCOND*/
			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 = kl[0].l_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_vm_vsize = kp->kp_eproc.e_vm.vm_map.size
			    / kd->nbpg;
			/* Adjust mapped size */
			kp2p->p_vm_msize =
			    (kp->kp_eproc.e_vm.vm_map.size / kd->nbpg) -
			    kp->kp_eproc.e_vm.vm_issize +
			    kp->kp_eproc.e_vm.vm_ssize;

			kp2p->p_eflag = (int32_t)kp->kp_eproc.e_flag;

			kp2p->p_realflag = kp->kp_proc.p_flag;
			kp2p->p_nlwps = kp->kp_proc.p_nlwps;
			kp2p->p_nrlwps = kp->kp_proc.p_nrlwps;
			kp2p->p_realstat = kp->kp_proc.p_stat;

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

				kp2p->p_ustart_sec = (u_int32_t)
				    pstats.p_start.tv_sec;
				kp2p->p_ustart_usec = (u_int32_t)
				    pstats.p_start.tv_usec;

				kp2p->p_uutime_sec = (u_int32_t)
				    pstats.p_ru.ru_utime.tv_sec;
				kp2p->p_uutime_usec = (u_int32_t)
				    pstats.p_ru.ru_utime.tv_usec;
				kp2p->p_ustime_sec = (u_int32_t)
				    pstats.p_ru.ru_stime.tv_sec;
				kp2p->p_ustime_usec = (u_int32_t)
				    pstats.p_ru.ru_stime.tv_usec;

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

				kp2p->p_uctime_sec = (u_int32_t)
				    (pstats.p_cru.ru_utime.tv_sec +
				    pstats.p_cru.ru_stime.tv_sec);
				kp2p->p_uctime_usec = (u_int32_t)
				    (pstats.p_cru.ru_utime.tv_usec +
				    pstats.p_cru.ru_stime.tv_usec);
			}

			memcpy(kp2c, &kp2, esize);
			kp2c += esize;
		}
	}
	*cnt = nprocs;
	return (kd->procbase2);
}
Esempio n. 4
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);
}
Esempio n. 5
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);
}
Esempio n. 6
0
/*
 * code for returning process's command line arguments
 */
int
procfs_docmdline(
    struct lwp *curl,
    struct proc *p,
    struct pfsnode *pfs,
    struct uio *uio
)
{
	struct ps_strings pss;
	int count, error;
	size_t i, len, xlen, upper_bound;
	struct uio auio;
	struct iovec aiov;
	struct vmspace *vm;
	vaddr_t argv;
	char *arg;

	/* Don't allow writing. */
	if (uio->uio_rw != UIO_READ)
		return (EOPNOTSUPP);

	/*
	 * Allocate a temporary buffer to hold the arguments.
	 */
	arg = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);

	/*
	 * Zombies don't have a stack, so we can't read their psstrings.
	 * System processes also don't have a user stack.  This is what
	 * ps(1) would display.
	 */
	if (P_ZOMBIE(p) || (p->p_flag & PK_SYSTEM) != 0) {
		len = snprintf(arg, PAGE_SIZE, "(%s)", p->p_comm) + 1;
		error = uiomove_frombuf(arg, len, uio);
		free(arg, M_TEMP);
		return (error);
	}

	/*
	 * NOTE: Don't bother doing a process_checkioperm() here
	 * because the psstrings info is available by using ps(1),
	 * so it's not like there's anything to protect here.
	 */

	/*
	 * Lock the process down in memory.
	 */
	if ((error = proc_vmspace_getref(p, &vm)) != 0) {
		free(arg, M_TEMP);
		return (error);
	}

	/*
	 * Read in the ps_strings structure.
	 */
	aiov.iov_base = &pss;
	aiov.iov_len = sizeof(pss);
	auio.uio_iov = &aiov;
	auio.uio_iovcnt = 1;
	auio.uio_offset = (vaddr_t)p->p_psstr;
	auio.uio_resid = sizeof(pss);
	auio.uio_rw = UIO_READ;
	UIO_SETUP_SYSSPACE(&auio);
	error = uvm_io(&vm->vm_map, &auio);
	if (error)
		goto bad;

	/*
	 * Now read the address of the argument vector.
	 */
	aiov.iov_base = &argv;
	aiov.iov_len = sizeof(argv);
	auio.uio_iov = &aiov;
	auio.uio_iovcnt = 1;
	auio.uio_offset = (vaddr_t)pss.ps_argvstr;
	auio.uio_resid = sizeof(argv);
	auio.uio_rw = UIO_READ;
	UIO_SETUP_SYSSPACE(&auio);
	error = uvm_io(&vm->vm_map, &auio);
	if (error)
		goto bad;

	/*
	 * Now copy in the actual argument vector, one page at a time,
	 * since we don't know how long the vector is (though, we do
	 * know how many NUL-terminated strings are in the vector).
	 */
	len = 0;
	count = pss.ps_nargvstr;
	upper_bound = round_page(uio->uio_offset + uio->uio_resid);
	for (; count && len < upper_bound; len += xlen) {
		aiov.iov_base = arg;
		aiov.iov_len = PAGE_SIZE;
		auio.uio_iov = &aiov;
		auio.uio_iovcnt = 1;
		auio.uio_offset = argv + len;
		xlen = PAGE_SIZE - ((argv + len) & PAGE_MASK);
		auio.uio_resid = xlen;
		auio.uio_rw = UIO_READ;
		UIO_SETUP_SYSSPACE(&auio);
		error = uvm_io(&vm->vm_map, &auio);
		if (error)
			goto bad;

		for (i = 0; i < xlen && count != 0; i++) {
			if (arg[i] == '\0')
				count--;	/* one full string */
		}

		if (len + i > uio->uio_offset) {
			/* Have data in this page, copy it out */
			error = uiomove(arg + uio->uio_offset - len,
			    i + len - uio->uio_offset, uio);
			if (error || uio->uio_resid <= 0)
				break;
		}
	}

 bad:
	/*
	 * Release the process.
	 */
	uvmspace_free(vm);

	free(arg, M_TEMP);
	return (error);
}