kern_proc.c revision 70317
1/*
2 * Copyright (c) 1982, 1986, 1989, 1991, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 *	@(#)kern_proc.c	8.7 (Berkeley) 2/14/95
34 * $FreeBSD: head/sys/kern/kern_proc.c 70317 2000-12-23 19:43:10Z jake $
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/kernel.h>
40#include <sys/sysctl.h>
41#include <sys/malloc.h>
42#include <sys/proc.h>
43#include <sys/filedesc.h>
44#include <sys/tty.h>
45#include <sys/signalvar.h>
46#include <vm/vm.h>
47#include <sys/lock.h>
48#include <vm/pmap.h>
49#include <vm/vm_map.h>
50#include <sys/user.h>
51#include <vm/vm_zone.h>
52
53static MALLOC_DEFINE(M_PGRP, "pgrp", "process group header");
54MALLOC_DEFINE(M_SESSION, "session", "session header");
55static MALLOC_DEFINE(M_PROC, "proc", "Proc structures");
56MALLOC_DEFINE(M_SUBPROC, "subproc", "Proc sub-structures");
57
58int ps_showallprocs = 1;
59SYSCTL_INT(_kern, OID_AUTO, ps_showallprocs, CTLFLAG_RW,
60    &ps_showallprocs, 0, "");
61
62static void pgdelete	__P((struct pgrp *));
63
64static void	orphanpg __P((struct pgrp *pg));
65
66/*
67 * Other process lists
68 */
69struct pidhashhead *pidhashtbl;
70u_long pidhash;
71struct pgrphashhead *pgrphashtbl;
72u_long pgrphash;
73struct proclist allproc;
74struct proclist zombproc;
75struct lock allproc_lock;
76struct lock proctree_lock;
77vm_zone_t proc_zone;
78vm_zone_t ithread_zone;
79
80/*
81 * Initialize global process hashing structures.
82 */
83void
84procinit()
85{
86
87	lockinit(&allproc_lock, PZERO, "allproc", 0, 0);
88	lockinit(&proctree_lock, PZERO, "proctree", 0, 0);
89	LIST_INIT(&allproc);
90	LIST_INIT(&zombproc);
91	pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash);
92	pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash);
93	proc_zone = zinit("PROC", sizeof (struct proc), 0, 0, 5);
94	uihashinit();
95	/*
96	 * This should really be a compile time warning, but I do
97	 * not know of any way to do that...
98	 */
99	if (sizeof(struct kinfo_proc) != KINFO_PROC_SIZE)
100		printf("WARNING: size of kinfo_proc (%d) should be %d!!!\n",
101			sizeof(struct kinfo_proc), KINFO_PROC_SIZE);
102}
103
104/*
105 * Is p an inferior of the current process?
106 */
107int
108inferior(p)
109	register struct proc *p;
110{
111	int rval = 1;
112
113	PROCTREE_LOCK(PT_SHARED);
114	for (; p != curproc; p = p->p_pptr)
115		if (p->p_pid == 0) {
116			rval = 0;
117			break;
118		}
119	PROCTREE_LOCK(PT_RELEASE);
120	return (rval);
121}
122
123/*
124 * Locate a process by number
125 */
126struct proc *
127pfind(pid)
128	register pid_t pid;
129{
130	register struct proc *p;
131
132	ALLPROC_LOCK(AP_SHARED);
133	LIST_FOREACH(p, PIDHASH(pid), p_hash)
134		if (p->p_pid == pid)
135			break;
136	ALLPROC_LOCK(AP_RELEASE);
137	return (p);
138}
139
140/*
141 * Locate a process group by number
142 */
143struct pgrp *
144pgfind(pgid)
145	register pid_t pgid;
146{
147	register struct pgrp *pgrp;
148
149	LIST_FOREACH(pgrp, PGRPHASH(pgid), pg_hash)
150		if (pgrp->pg_id == pgid)
151			return (pgrp);
152	return (NULL);
153}
154
155/*
156 * Move p to a new or existing process group (and session)
157 */
158int
159enterpgrp(p, pgid, mksess)
160	register struct proc *p;
161	pid_t pgid;
162	int mksess;
163{
164	register struct pgrp *pgrp = pgfind(pgid);
165
166	KASSERT(pgrp == NULL || !mksess,
167	    ("enterpgrp: setsid into non-empty pgrp"));
168	KASSERT(!SESS_LEADER(p),
169	    ("enterpgrp: session leader attempted setpgrp"));
170
171	if (pgrp == NULL) {
172		pid_t savepid = p->p_pid;
173		struct proc *np;
174		/*
175		 * new process group
176		 */
177		KASSERT(p->p_pid == pgid,
178		    ("enterpgrp: new pgrp and pid != pgid"));
179		MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
180		    M_WAITOK);
181		if ((np = pfind(savepid)) == NULL || np != p)
182			return (ESRCH);
183		if (mksess) {
184			register struct session *sess;
185
186			/*
187			 * new session
188			 */
189			MALLOC(sess, struct session *, sizeof(struct session),
190			    M_SESSION, M_WAITOK);
191			sess->s_leader = p;
192			sess->s_sid = p->p_pid;
193			sess->s_count = 1;
194			sess->s_ttyvp = NULL;
195			sess->s_ttyp = NULL;
196			bcopy(p->p_session->s_login, sess->s_login,
197			    sizeof(sess->s_login));
198			p->p_flag &= ~P_CONTROLT;
199			pgrp->pg_session = sess;
200			KASSERT(p == curproc,
201			    ("enterpgrp: mksession and p != curproc"));
202		} else {
203			pgrp->pg_session = p->p_session;
204			pgrp->pg_session->s_count++;
205		}
206		pgrp->pg_id = pgid;
207		LIST_INIT(&pgrp->pg_members);
208		LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash);
209		pgrp->pg_jobc = 0;
210		SLIST_INIT(&pgrp->pg_sigiolst);
211	} else if (pgrp == p->p_pgrp)
212		return (0);
213
214	/*
215	 * Adjust eligibility of affected pgrps to participate in job control.
216	 * Increment eligibility counts before decrementing, otherwise we
217	 * could reach 0 spuriously during the first call.
218	 */
219	fixjobc(p, pgrp, 1);
220	fixjobc(p, p->p_pgrp, 0);
221
222	LIST_REMOVE(p, p_pglist);
223	if (LIST_EMPTY(&p->p_pgrp->pg_members))
224		pgdelete(p->p_pgrp);
225	p->p_pgrp = pgrp;
226	LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist);
227	return (0);
228}
229
230/*
231 * remove process from process group
232 */
233int
234leavepgrp(p)
235	register struct proc *p;
236{
237
238	LIST_REMOVE(p, p_pglist);
239	if (LIST_EMPTY(&p->p_pgrp->pg_members))
240		pgdelete(p->p_pgrp);
241	p->p_pgrp = 0;
242	return (0);
243}
244
245/*
246 * delete a process group
247 */
248static void
249pgdelete(pgrp)
250	register struct pgrp *pgrp;
251{
252
253	/*
254	 * Reset any sigio structures pointing to us as a result of
255	 * F_SETOWN with our pgid.
256	 */
257	funsetownlst(&pgrp->pg_sigiolst);
258
259	if (pgrp->pg_session->s_ttyp != NULL &&
260	    pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
261		pgrp->pg_session->s_ttyp->t_pgrp = NULL;
262	LIST_REMOVE(pgrp, pg_hash);
263	if (--pgrp->pg_session->s_count == 0)
264		FREE(pgrp->pg_session, M_SESSION);
265	FREE(pgrp, M_PGRP);
266}
267
268/*
269 * Adjust pgrp jobc counters when specified process changes process group.
270 * We count the number of processes in each process group that "qualify"
271 * the group for terminal job control (those with a parent in a different
272 * process group of the same session).  If that count reaches zero, the
273 * process group becomes orphaned.  Check both the specified process'
274 * process group and that of its children.
275 * entering == 0 => p is leaving specified group.
276 * entering == 1 => p is entering specified group.
277 */
278void
279fixjobc(p, pgrp, entering)
280	register struct proc *p;
281	register struct pgrp *pgrp;
282	int entering;
283{
284	register struct pgrp *hispgrp;
285	register struct session *mysession = pgrp->pg_session;
286
287	/*
288	 * Check p's parent to see whether p qualifies its own process
289	 * group; if so, adjust count for p's process group.
290	 */
291	PROCTREE_LOCK(PT_SHARED);
292	if ((hispgrp = p->p_pptr->p_pgrp) != pgrp &&
293	    hispgrp->pg_session == mysession) {
294		if (entering)
295			pgrp->pg_jobc++;
296		else if (--pgrp->pg_jobc == 0)
297			orphanpg(pgrp);
298	}
299
300	/*
301	 * Check this process' children to see whether they qualify
302	 * their process groups; if so, adjust counts for children's
303	 * process groups.
304	 */
305	LIST_FOREACH(p, &p->p_children, p_sibling)
306		if ((hispgrp = p->p_pgrp) != pgrp &&
307		    hispgrp->pg_session == mysession &&
308		    p->p_stat != SZOMB) {
309			if (entering)
310				hispgrp->pg_jobc++;
311			else if (--hispgrp->pg_jobc == 0)
312				orphanpg(hispgrp);
313		}
314	PROCTREE_LOCK(PT_RELEASE);
315}
316
317/*
318 * A process group has become orphaned;
319 * if there are any stopped processes in the group,
320 * hang-up all process in that group.
321 */
322static void
323orphanpg(pg)
324	struct pgrp *pg;
325{
326	register struct proc *p;
327
328	LIST_FOREACH(p, &pg->pg_members, p_pglist) {
329		if (p->p_stat == SSTOP) {
330			LIST_FOREACH(p, &pg->pg_members, p_pglist) {
331				psignal(p, SIGHUP);
332				psignal(p, SIGCONT);
333			}
334			return;
335		}
336	}
337}
338
339#include "opt_ddb.h"
340#ifdef DDB
341#include <ddb/ddb.h>
342
343DB_SHOW_COMMAND(pgrpdump, pgrpdump)
344{
345	register struct pgrp *pgrp;
346	register struct proc *p;
347	register int i;
348
349	for (i = 0; i <= pgrphash; i++) {
350		if (!LIST_EMPTY(&pgrphashtbl[i])) {
351			printf("\tindx %d\n", i);
352			LIST_FOREACH(pgrp, &pgrphashtbl[i], pg_hash) {
353				printf(
354			"\tpgrp %p, pgid %ld, sess %p, sesscnt %d, mem %p\n",
355				    (void *)pgrp, (long)pgrp->pg_id,
356				    (void *)pgrp->pg_session,
357				    pgrp->pg_session->s_count,
358				    (void *)LIST_FIRST(&pgrp->pg_members));
359				LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
360					printf("\t\tpid %ld addr %p pgrp %p\n",
361					    (long)p->p_pid, (void *)p,
362					    (void *)p->p_pgrp);
363				}
364			}
365		}
366	}
367}
368#endif /* DDB */
369
370/*
371 * Fill in an kinfo_proc structure for the specified process.
372 */
373void
374fill_kinfo_proc(p, kp)
375	struct proc *p;
376	struct kinfo_proc *kp;
377{
378	struct tty *tp;
379	struct session *sp;
380
381	bzero(kp, sizeof(*kp));
382
383	kp->ki_structsize = sizeof(*kp);
384	kp->ki_paddr = p;
385	kp->ki_addr = p->p_addr;
386	kp->ki_args = p->p_args;
387	kp->ki_tracep = p->p_tracep;
388	kp->ki_textvp = p->p_textvp;
389	kp->ki_fd = p->p_fd;
390	kp->ki_vmspace = p->p_vmspace;
391	if (p->p_cred) {
392		kp->ki_uid = p->p_cred->pc_ucred->cr_uid;
393		kp->ki_ruid = p->p_cred->p_ruid;
394		kp->ki_svuid = p->p_cred->p_svuid;
395		kp->ki_ngroups = p->p_cred->pc_ucred->cr_ngroups;
396		bcopy(p->p_cred->pc_ucred->cr_groups, kp->ki_groups,
397		    NGROUPS * sizeof(gid_t));
398		kp->ki_rgid = p->p_cred->p_rgid;
399		kp->ki_svgid = p->p_cred->p_svgid;
400	}
401	if (p->p_procsig) {
402		kp->ki_sigignore = p->p_procsig->ps_sigignore;
403		kp->ki_sigcatch = p->p_procsig->ps_sigcatch;
404	}
405	if (p->p_stat != SIDL && p->p_stat != SZOMB && p->p_vmspace != NULL) {
406		struct vmspace *vm = p->p_vmspace;
407
408		kp->ki_size = vm->vm_map.size;
409		kp->ki_rssize = vmspace_resident_count(vm); /*XXX*/
410		kp->ki_swrss = vm->vm_swrss;
411		kp->ki_tsize = vm->vm_tsize;
412		kp->ki_dsize = vm->vm_dsize;
413		kp->ki_ssize = vm->vm_ssize;
414	}
415	if ((p->p_flag & P_INMEM) && p->p_stats) {
416		kp->ki_start = p->p_stats->p_start;
417		kp->ki_rusage = p->p_stats->p_ru;
418		kp->ki_childtime.tv_sec = p->p_stats->p_cru.ru_utime.tv_sec +
419		    p->p_stats->p_cru.ru_stime.tv_sec;
420		kp->ki_childtime.tv_usec = p->p_stats->p_cru.ru_utime.tv_usec +
421		    p->p_stats->p_cru.ru_stime.tv_usec;
422	}
423	kp->ki_rtprio = p->p_rtprio;
424	kp->ki_runtime = p->p_runtime;
425	kp->ki_pid = p->p_pid;
426	PROCTREE_LOCK(PT_SHARED);
427	if (p->p_pptr)
428		kp->ki_ppid = p->p_pptr->p_pid;
429	PROCTREE_LOCK(PT_RELEASE);
430	sp = NULL;
431	if (p->p_pgrp) {
432		kp->ki_pgid = p->p_pgrp->pg_id;
433		kp->ki_jobc = p->p_pgrp->pg_jobc;
434		sp = p->p_pgrp->pg_session;
435
436		if (sp != NULL) {
437			kp->ki_sid = sp->s_sid;
438			bcopy(sp->s_login, kp->ki_login, sizeof(kp->ki_login));
439			if (sp->s_ttyvp)
440				kp->ki_kiflag = KI_CTTY;
441			if (SESS_LEADER(p))
442				kp->ki_kiflag |= KI_SLEADER;
443		}
444	}
445	if ((p->p_flag & P_CONTROLT) && sp && ((tp = sp->s_ttyp) != NULL)) {
446		kp->ki_tdev = dev2udev(tp->t_dev);
447		kp->ki_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
448		if (tp->t_session)
449			kp->ki_tsid = tp->t_session->s_sid;
450	} else
451		kp->ki_tdev = NOUDEV;
452	if (p->p_wmesg) {
453		strncpy(kp->ki_wmesg, p->p_wmesg, WMESGLEN);
454		kp->ki_wmesg[WMESGLEN] = 0;
455	}
456	if (p->p_comm[0] != 0) {
457		strncpy(kp->ki_comm, p->p_comm, MAXCOMLEN);
458		kp->ki_comm[MAXCOMLEN] = 0;
459	}
460	if (p->p_blocked != 0) {
461		kp->ki_kiflag |= KI_MTXBLOCK;
462		strncpy(kp->ki_mtxname, p->p_mtxname, MTXNAMELEN);
463		kp->ki_wmesg[MTXNAMELEN] = 0;
464	}
465	kp->ki_siglist = p->p_siglist;
466	kp->ki_sigmask = p->p_sigmask;
467	kp->ki_xstat = p->p_xstat;
468	kp->ki_acflag = p->p_acflag;
469	kp->ki_pctcpu = p->p_pctcpu;
470	kp->ki_estcpu = p->p_estcpu;
471	kp->ki_slptime = p->p_slptime;
472	kp->ki_swtime = p->p_swtime;
473	kp->ki_flag = p->p_flag;
474	kp->ki_wchan = p->p_wchan;
475	kp->ki_traceflag = p->p_traceflag;
476	kp->ki_priority = p->p_priority;
477	kp->ki_usrpri = p->p_usrpri;
478	kp->ki_nativepri = p->p_nativepri;
479	kp->ki_stat = p->p_stat;
480	kp->ki_nice = p->p_nice;
481	kp->ki_lock = p->p_lock;
482	kp->ki_rqindex = p->p_rqindex;
483	kp->ki_oncpu = p->p_oncpu;
484	kp->ki_lastcpu = p->p_lastcpu;
485}
486
487static struct proc *
488zpfind(pid_t pid)
489{
490	struct proc *p;
491
492	ALLPROC_LOCK(AP_SHARED);
493	LIST_FOREACH(p, &zombproc, p_list)
494		if (p->p_pid == pid)
495			break;
496	ALLPROC_LOCK(AP_RELEASE);
497	return (p);
498}
499
500
501static int
502sysctl_out_proc(struct proc *p, struct sysctl_req *req, int doingzomb)
503{
504	struct kinfo_proc kinfo_proc;
505	int error;
506	pid_t pid = p->p_pid;
507
508	fill_kinfo_proc(p, &kinfo_proc);
509	error = SYSCTL_OUT(req, (caddr_t)&kinfo_proc, sizeof(kinfo_proc));
510	if (error)
511		return (error);
512	if (!doingzomb && pid && (pfind(pid) != p))
513		return EAGAIN;
514	if (doingzomb && zpfind(pid) != p)
515		return EAGAIN;
516	return (0);
517}
518
519static int
520sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
521{
522	int *name = (int*) arg1;
523	u_int namelen = arg2;
524	struct proc *p;
525	int doingzomb;
526	int error = 0;
527
528	if (oidp->oid_number == KERN_PROC_PID) {
529		if (namelen != 1)
530			return (EINVAL);
531		p = pfind((pid_t)name[0]);
532		if (!p)
533			return (0);
534		if (p_can(curproc, p, P_CAN_SEE, NULL))
535			return (0);
536		error = sysctl_out_proc(p, req, 0);
537		return (error);
538	}
539	if (oidp->oid_number == KERN_PROC_ALL && !namelen)
540		;
541	else if (oidp->oid_number != KERN_PROC_ALL && namelen == 1)
542		;
543	else
544		return (EINVAL);
545
546	if (!req->oldptr) {
547		/* overestimate by 5 procs */
548		error = SYSCTL_OUT(req, 0, sizeof (struct kinfo_proc) * 5);
549		if (error)
550			return (error);
551	}
552	ALLPROC_LOCK(AP_SHARED);
553	for (doingzomb=0 ; doingzomb < 2 ; doingzomb++) {
554		if (!doingzomb)
555			p = LIST_FIRST(&allproc);
556		else
557			p = LIST_FIRST(&zombproc);
558		for (; p != 0; p = LIST_NEXT(p, p_list)) {
559			/*
560			 * Show a user only appropriate processes.
561			 */
562			if (p_can(curproc, p, P_CAN_SEE, NULL))
563				continue;
564			/*
565			 * Skip embryonic processes.
566			 */
567			if (p->p_stat == SIDL)
568				continue;
569			/*
570			 * TODO - make more efficient (see notes below).
571			 * do by session.
572			 */
573			switch (oidp->oid_number) {
574
575			case KERN_PROC_PGRP:
576				/* could do this by traversing pgrp */
577				if (p->p_pgrp == NULL ||
578				    p->p_pgrp->pg_id != (pid_t)name[0])
579					continue;
580				break;
581
582			case KERN_PROC_TTY:
583				if ((p->p_flag & P_CONTROLT) == 0 ||
584				    p->p_session == NULL ||
585				    p->p_session->s_ttyp == NULL ||
586				    dev2udev(p->p_session->s_ttyp->t_dev) !=
587					(udev_t)name[0])
588					continue;
589				break;
590
591			case KERN_PROC_UID:
592				if (p->p_ucred == NULL ||
593				    p->p_ucred->cr_uid != (uid_t)name[0])
594					continue;
595				break;
596
597			case KERN_PROC_RUID:
598				if (p->p_ucred == NULL ||
599				    p->p_cred->p_ruid != (uid_t)name[0])
600					continue;
601				break;
602			}
603
604			if (p_can(curproc, p, P_CAN_SEE, NULL))
605				continue;
606
607			error = sysctl_out_proc(p, req, doingzomb);
608			if (error) {
609				ALLPROC_LOCK(AP_RELEASE);
610				return (error);
611			}
612		}
613	}
614	ALLPROC_LOCK(AP_RELEASE);
615	return (0);
616}
617
618/*
619 * This sysctl allows a process to retrieve the argument list or process
620 * title for another process without groping around in the address space
621 * of the other process.  It also allow a process to set its own "process
622 * title to a string of its own choice.
623 */
624static int
625sysctl_kern_proc_args(SYSCTL_HANDLER_ARGS)
626{
627	int *name = (int*) arg1;
628	u_int namelen = arg2;
629	struct proc *p;
630	struct pargs *pa;
631	int error = 0;
632
633	if (namelen != 1)
634		return (EINVAL);
635
636	p = pfind((pid_t)name[0]);
637	if (!p)
638		return (0);
639
640	if ((!ps_argsopen) && p_can(curproc, p, P_CAN_SEE, NULL))
641		return (0);
642
643	if (req->newptr && curproc != p)
644		return (EPERM);
645
646	if (req->oldptr && p->p_args != NULL)
647		error = SYSCTL_OUT(req, p->p_args->ar_args, p->p_args->ar_length);
648	if (req->newptr == NULL)
649		return (error);
650
651	if (p->p_args && --p->p_args->ar_ref == 0)
652		FREE(p->p_args, M_PARGS);
653	p->p_args = NULL;
654
655	if (req->newlen + sizeof(struct pargs) > ps_arg_cache_limit)
656		return (error);
657
658	MALLOC(pa, struct pargs *, sizeof(struct pargs) + req->newlen,
659	    M_PARGS, M_WAITOK);
660	pa->ar_ref = 1;
661	pa->ar_length = req->newlen;
662	error = SYSCTL_IN(req, pa->ar_args, req->newlen);
663	if (!error)
664		p->p_args = pa;
665	else
666		FREE(pa, M_PARGS);
667	return (error);
668}
669
670SYSCTL_NODE(_kern, KERN_PROC, proc, CTLFLAG_RD,  0, "Process table");
671
672SYSCTL_PROC(_kern_proc, KERN_PROC_ALL, all, CTLFLAG_RD|CTLTYPE_STRUCT,
673	0, 0, sysctl_kern_proc, "S,proc", "Return entire process table");
674
675SYSCTL_NODE(_kern_proc, KERN_PROC_PGRP, pgrp, CTLFLAG_RD,
676	sysctl_kern_proc, "Process table");
677
678SYSCTL_NODE(_kern_proc, KERN_PROC_TTY, tty, CTLFLAG_RD,
679	sysctl_kern_proc, "Process table");
680
681SYSCTL_NODE(_kern_proc, KERN_PROC_UID, uid, CTLFLAG_RD,
682	sysctl_kern_proc, "Process table");
683
684SYSCTL_NODE(_kern_proc, KERN_PROC_RUID, ruid, CTLFLAG_RD,
685	sysctl_kern_proc, "Process table");
686
687SYSCTL_NODE(_kern_proc, KERN_PROC_PID, pid, CTLFLAG_RD,
688	sysctl_kern_proc, "Process table");
689
690SYSCTL_NODE(_kern_proc, KERN_PROC_ARGS, args, CTLFLAG_RW | CTLFLAG_ANYBODY,
691	sysctl_kern_proc_args, "Process argument list");
692