Commit | Line | Data |
---|---|---|
984263bc MD |
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: src/sys/kern/kern_proc.c,v 1.63.2.9 2003/05/08 07:47:16 kbyanc Exp $ | |
fa2217dc | 35 | * $DragonFly: src/sys/kern/kern_proc.c,v 1.45 2008/06/12 23:25:02 dillon Exp $ |
984263bc MD |
36 | */ |
37 | ||
38 | #include <sys/param.h> | |
39 | #include <sys/systm.h> | |
40 | #include <sys/kernel.h> | |
41 | #include <sys/sysctl.h> | |
42 | #include <sys/malloc.h> | |
43 | #include <sys/proc.h> | |
56c703bd | 44 | #include <sys/jail.h> |
984263bc MD |
45 | #include <sys/filedesc.h> |
46 | #include <sys/tty.h> | |
47 | #include <sys/signalvar.h> | |
5bf0d9b5 | 48 | #include <sys/spinlock.h> |
984263bc MD |
49 | #include <vm/vm.h> |
50 | #include <sys/lock.h> | |
51 | #include <vm/pmap.h> | |
52 | #include <vm/vm_map.h> | |
53 | #include <sys/user.h> | |
630ccdeb | 54 | #include <machine/smp.h> |
984263bc | 55 | |
5bf0d9b5 MD |
56 | #include <sys/spinlock2.h> |
57 | ||
984263bc MD |
58 | static MALLOC_DEFINE(M_PGRP, "pgrp", "process group header"); |
59 | MALLOC_DEFINE(M_SESSION, "session", "session header"); | |
fb2a331e | 60 | MALLOC_DEFINE(M_PROC, "proc", "Proc structures"); |
f6c36234 | 61 | MALLOC_DEFINE(M_LWP, "lwp", "lwp structures"); |
984263bc MD |
62 | MALLOC_DEFINE(M_SUBPROC, "subproc", "Proc sub-structures"); |
63 | ||
28c57d20 | 64 | int ps_showallprocs = 1; |
73e4f7b9 | 65 | static int ps_showallthreads = 1; |
43a0f7ae MS |
66 | SYSCTL_INT(_security, OID_AUTO, ps_showallprocs, CTLFLAG_RW, |
67 | &ps_showallprocs, 0, | |
68 | "Unprivileged processes can see proccesses with different UID/GID"); | |
69 | SYSCTL_INT(_security, OID_AUTO, ps_showallthreads, CTLFLAG_RW, | |
70 | &ps_showallthreads, 0, | |
71 | "Unprivileged processes can see kernel threads"); | |
984263bc | 72 | |
51e64ff2 MD |
73 | static void pgdelete(struct pgrp *); |
74 | static void orphanpg(struct pgrp *pg); | |
75 | static pid_t proc_getnewpid_locked(int random_offset); | |
984263bc MD |
76 | |
77 | /* | |
78 | * Other process lists | |
79 | */ | |
80 | struct pidhashhead *pidhashtbl; | |
81 | u_long pidhash; | |
82 | struct pgrphashhead *pgrphashtbl; | |
83 | u_long pgrphash; | |
84 | struct proclist allproc; | |
85 | struct proclist zombproc; | |
5bf0d9b5 | 86 | struct spinlock allproc_spin; |
984263bc | 87 | |
51e64ff2 MD |
88 | /* |
89 | * Random component to nextpid generation. We mix in a random factor to make | |
90 | * it a little harder to predict. We sanity check the modulus value to avoid | |
91 | * doing it in critical paths. Don't let it be too small or we pointlessly | |
92 | * waste randomness entropy, and don't let it be impossibly large. Using a | |
93 | * modulus that is too big causes a LOT more process table scans and slows | |
94 | * down fork processing as the pidchecked caching is defeated. | |
95 | */ | |
96 | static int randompid = 0; | |
97 | ||
98 | static int | |
99 | sysctl_kern_randompid(SYSCTL_HANDLER_ARGS) | |
100 | { | |
101 | int error, pid; | |
102 | ||
103 | pid = randompid; | |
104 | error = sysctl_handle_int(oidp, &pid, 0, req); | |
105 | if (error || !req->newptr) | |
106 | return (error); | |
107 | if (pid < 0 || pid > PID_MAX - 100) /* out of range */ | |
108 | pid = PID_MAX - 100; | |
109 | else if (pid < 2) /* NOP */ | |
110 | pid = 0; | |
111 | else if (pid < 100) /* Make it reasonable */ | |
112 | pid = 100; | |
113 | randompid = pid; | |
114 | return (error); | |
115 | } | |
116 | ||
117 | SYSCTL_PROC(_kern, OID_AUTO, randompid, CTLTYPE_INT|CTLFLAG_RW, | |
118 | 0, 0, sysctl_kern_randompid, "I", "Random PID modulus"); | |
119 | ||
984263bc MD |
120 | /* |
121 | * Initialize global process hashing structures. | |
122 | */ | |
123 | void | |
77153250 | 124 | procinit(void) |
984263bc | 125 | { |
984263bc MD |
126 | LIST_INIT(&allproc); |
127 | LIST_INIT(&zombproc); | |
5bf0d9b5 | 128 | spin_init(&allproc_spin); |
40aaf5fc | 129 | lwkt_init(); |
984263bc MD |
130 | pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash); |
131 | pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash); | |
984263bc MD |
132 | uihashinit(); |
133 | } | |
134 | ||
135 | /* | |
136 | * Is p an inferior of the current process? | |
137 | */ | |
138 | int | |
77153250 | 139 | inferior(struct proc *p) |
984263bc | 140 | { |
984263bc MD |
141 | for (; p != curproc; p = p->p_pptr) |
142 | if (p->p_pid == 0) | |
143 | return (0); | |
144 | return (1); | |
145 | } | |
146 | ||
147 | /* | |
148 | * Locate a process by number | |
149 | */ | |
150 | struct proc * | |
77153250 | 151 | pfind(pid_t pid) |
984263bc | 152 | { |
1fd87d54 | 153 | struct proc *p; |
984263bc | 154 | |
5bf0d9b5 | 155 | LIST_FOREACH(p, PIDHASH(pid), p_hash) { |
984263bc MD |
156 | if (p->p_pid == pid) |
157 | return (p); | |
5bf0d9b5 | 158 | } |
984263bc MD |
159 | return (NULL); |
160 | } | |
161 | ||
162 | /* | |
163 | * Locate a process group by number | |
164 | */ | |
165 | struct pgrp * | |
77153250 | 166 | pgfind(pid_t pgid) |
984263bc | 167 | { |
1fd87d54 | 168 | struct pgrp *pgrp; |
984263bc | 169 | |
5bf0d9b5 | 170 | LIST_FOREACH(pgrp, PGRPHASH(pgid), pg_hash) { |
984263bc MD |
171 | if (pgrp->pg_id == pgid) |
172 | return (pgrp); | |
5bf0d9b5 | 173 | } |
984263bc MD |
174 | return (NULL); |
175 | } | |
176 | ||
177 | /* | |
178 | * Move p to a new or existing process group (and session) | |
179 | */ | |
180 | int | |
77153250 | 181 | enterpgrp(struct proc *p, pid_t pgid, int mksess) |
984263bc | 182 | { |
1fd87d54 | 183 | struct pgrp *pgrp = pgfind(pgid); |
984263bc MD |
184 | |
185 | KASSERT(pgrp == NULL || !mksess, | |
186 | ("enterpgrp: setsid into non-empty pgrp")); | |
187 | KASSERT(!SESS_LEADER(p), | |
188 | ("enterpgrp: session leader attempted setpgrp")); | |
189 | ||
190 | if (pgrp == NULL) { | |
191 | pid_t savepid = p->p_pid; | |
192 | struct proc *np; | |
193 | /* | |
194 | * new process group | |
195 | */ | |
196 | KASSERT(p->p_pid == pgid, | |
197 | ("enterpgrp: new pgrp and pid != pgid")); | |
198 | if ((np = pfind(savepid)) == NULL || np != p) | |
199 | return (ESRCH); | |
200 | MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, | |
201 | M_WAITOK); | |
202 | if (mksess) { | |
1fd87d54 | 203 | struct session *sess; |
984263bc MD |
204 | |
205 | /* | |
206 | * new session | |
207 | */ | |
208 | MALLOC(sess, struct session *, sizeof(struct session), | |
209 | M_SESSION, M_WAITOK); | |
210 | sess->s_leader = p; | |
211 | sess->s_sid = p->p_pid; | |
212 | sess->s_count = 1; | |
213 | sess->s_ttyvp = NULL; | |
214 | sess->s_ttyp = NULL; | |
215 | bcopy(p->p_session->s_login, sess->s_login, | |
216 | sizeof(sess->s_login)); | |
217 | p->p_flag &= ~P_CONTROLT; | |
218 | pgrp->pg_session = sess; | |
219 | KASSERT(p == curproc, | |
220 | ("enterpgrp: mksession and p != curproc")); | |
221 | } else { | |
222 | pgrp->pg_session = p->p_session; | |
8b90699b | 223 | sess_hold(pgrp->pg_session); |
984263bc MD |
224 | } |
225 | pgrp->pg_id = pgid; | |
226 | LIST_INIT(&pgrp->pg_members); | |
227 | LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash); | |
228 | pgrp->pg_jobc = 0; | |
229 | SLIST_INIT(&pgrp->pg_sigiolst); | |
167e6ecb | 230 | lockinit(&pgrp->pg_lock, "pgwt", 0, 0); |
984263bc MD |
231 | } else if (pgrp == p->p_pgrp) |
232 | return (0); | |
233 | ||
234 | /* | |
235 | * Adjust eligibility of affected pgrps to participate in job control. | |
236 | * Increment eligibility counts before decrementing, otherwise we | |
237 | * could reach 0 spuriously during the first call. | |
238 | */ | |
239 | fixjobc(p, pgrp, 1); | |
240 | fixjobc(p, p->p_pgrp, 0); | |
241 | ||
242 | LIST_REMOVE(p, p_pglist); | |
243 | if (LIST_EMPTY(&p->p_pgrp->pg_members)) | |
244 | pgdelete(p->p_pgrp); | |
245 | p->p_pgrp = pgrp; | |
246 | LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist); | |
247 | return (0); | |
248 | } | |
249 | ||
250 | /* | |
251 | * remove process from process group | |
252 | */ | |
253 | int | |
77153250 | 254 | leavepgrp(struct proc *p) |
984263bc MD |
255 | { |
256 | ||
257 | LIST_REMOVE(p, p_pglist); | |
258 | if (LIST_EMPTY(&p->p_pgrp->pg_members)) | |
259 | pgdelete(p->p_pgrp); | |
260 | p->p_pgrp = 0; | |
261 | return (0); | |
262 | } | |
263 | ||
264 | /* | |
265 | * delete a process group | |
266 | */ | |
267 | static void | |
77153250 | 268 | pgdelete(struct pgrp *pgrp) |
984263bc MD |
269 | { |
270 | ||
271 | /* | |
272 | * Reset any sigio structures pointing to us as a result of | |
273 | * F_SETOWN with our pgid. | |
274 | */ | |
275 | funsetownlst(&pgrp->pg_sigiolst); | |
276 | ||
277 | if (pgrp->pg_session->s_ttyp != NULL && | |
278 | pgrp->pg_session->s_ttyp->t_pgrp == pgrp) | |
279 | pgrp->pg_session->s_ttyp->t_pgrp = NULL; | |
280 | LIST_REMOVE(pgrp, pg_hash); | |
8b90699b | 281 | sess_rele(pgrp->pg_session); |
efda3bd0 | 282 | kfree(pgrp, M_PGRP); |
8b90699b MD |
283 | } |
284 | ||
285 | /* | |
286 | * Adjust the ref count on a session structure. When the ref count falls to | |
287 | * zero the tty is disassociated from the session and the session structure | |
288 | * is freed. Note that tty assocation is not itself ref-counted. | |
289 | */ | |
290 | void | |
291 | sess_hold(struct session *sp) | |
292 | { | |
293 | ++sp->s_count; | |
294 | } | |
295 | ||
296 | void | |
297 | sess_rele(struct session *sp) | |
298 | { | |
299 | KKASSERT(sp->s_count > 0); | |
300 | if (--sp->s_count == 0) { | |
301 | if (sp->s_ttyp && sp->s_ttyp->t_session) { | |
302 | #ifdef TTY_DO_FULL_CLOSE | |
303 | /* FULL CLOSE, see ttyclearsession() */ | |
304 | KKASSERT(sp->s_ttyp->t_session == sp); | |
305 | sp->s_ttyp->t_session = NULL; | |
306 | #else | |
307 | /* HALF CLOSE, see ttyclearsession() */ | |
308 | if (sp->s_ttyp->t_session == sp) | |
309 | sp->s_ttyp->t_session = NULL; | |
310 | #endif | |
311 | } | |
efda3bd0 | 312 | kfree(sp, M_SESSION); |
8b90699b | 313 | } |
984263bc MD |
314 | } |
315 | ||
316 | /* | |
317 | * Adjust pgrp jobc counters when specified process changes process group. | |
318 | * We count the number of processes in each process group that "qualify" | |
319 | * the group for terminal job control (those with a parent in a different | |
320 | * process group of the same session). If that count reaches zero, the | |
321 | * process group becomes orphaned. Check both the specified process' | |
322 | * process group and that of its children. | |
323 | * entering == 0 => p is leaving specified group. | |
324 | * entering == 1 => p is entering specified group. | |
325 | */ | |
326 | void | |
77153250 | 327 | fixjobc(struct proc *p, struct pgrp *pgrp, int entering) |
984263bc | 328 | { |
1fd87d54 RG |
329 | struct pgrp *hispgrp; |
330 | struct session *mysession = pgrp->pg_session; | |
984263bc MD |
331 | |
332 | /* | |
333 | * Check p's parent to see whether p qualifies its own process | |
334 | * group; if so, adjust count for p's process group. | |
335 | */ | |
336 | if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && | |
337 | hispgrp->pg_session == mysession) { | |
338 | if (entering) | |
339 | pgrp->pg_jobc++; | |
340 | else if (--pgrp->pg_jobc == 0) | |
341 | orphanpg(pgrp); | |
342 | } | |
343 | ||
344 | /* | |
345 | * Check this process' children to see whether they qualify | |
346 | * their process groups; if so, adjust counts for children's | |
347 | * process groups. | |
348 | */ | |
349 | LIST_FOREACH(p, &p->p_children, p_sibling) | |
350 | if ((hispgrp = p->p_pgrp) != pgrp && | |
351 | hispgrp->pg_session == mysession && | |
416d05d7 | 352 | p->p_stat != SZOMB) { |
984263bc MD |
353 | if (entering) |
354 | hispgrp->pg_jobc++; | |
355 | else if (--hispgrp->pg_jobc == 0) | |
356 | orphanpg(hispgrp); | |
357 | } | |
358 | } | |
359 | ||
360 | /* | |
361 | * A process group has become orphaned; | |
362 | * if there are any stopped processes in the group, | |
363 | * hang-up all process in that group. | |
364 | */ | |
365 | static void | |
77153250 | 366 | orphanpg(struct pgrp *pg) |
984263bc | 367 | { |
1fd87d54 | 368 | struct proc *p; |
984263bc MD |
369 | |
370 | LIST_FOREACH(p, &pg->pg_members, p_pglist) { | |
164b8401 | 371 | if (p->p_stat == SSTOP) { |
984263bc | 372 | LIST_FOREACH(p, &pg->pg_members, p_pglist) { |
84204577 MD |
373 | ksignal(p, SIGHUP); |
374 | ksignal(p, SIGCONT); | |
984263bc MD |
375 | } |
376 | return; | |
377 | } | |
378 | } | |
379 | } | |
380 | ||
51e64ff2 MD |
381 | /* |
382 | * Add a new process to the allproc list and the PID hash. This | |
383 | * also assigns a pid to the new process. | |
384 | * | |
0ced1954 | 385 | * MPALMOSTSAFE - acquires mplock for karc4random() call |
51e64ff2 MD |
386 | */ |
387 | void | |
388 | proc_add_allproc(struct proc *p) | |
389 | { | |
390 | int random_offset; | |
391 | ||
392 | if ((random_offset = randompid) != 0) { | |
393 | get_mplock(); | |
0ced1954 | 394 | random_offset = karc4random() % random_offset; |
51e64ff2 MD |
395 | rel_mplock(); |
396 | } | |
397 | ||
398 | spin_lock_wr(&allproc_spin); | |
399 | p->p_pid = proc_getnewpid_locked(random_offset); | |
400 | LIST_INSERT_HEAD(&allproc, p, p_list); | |
401 | LIST_INSERT_HEAD(PIDHASH(p->p_pid), p, p_hash); | |
402 | spin_unlock_wr(&allproc_spin); | |
403 | } | |
404 | ||
405 | /* | |
406 | * Calculate a new process pid. This function is integrated into | |
407 | * proc_add_allproc() to guarentee that the new pid is not reused before | |
408 | * the new process can be added to the allproc list. | |
409 | * | |
410 | * MPSAFE - must be called with allproc_spin held. | |
411 | */ | |
412 | static | |
413 | pid_t | |
414 | proc_getnewpid_locked(int random_offset) | |
415 | { | |
416 | static pid_t nextpid; | |
417 | static pid_t pidchecked; | |
418 | struct proc *p; | |
419 | ||
420 | /* | |
421 | * Find an unused process ID. We remember a range of unused IDs | |
422 | * ready to use (from nextpid+1 through pidchecked-1). | |
423 | */ | |
424 | nextpid = nextpid + 1 + random_offset; | |
425 | retry: | |
426 | /* | |
427 | * If the process ID prototype has wrapped around, | |
428 | * restart somewhat above 0, as the low-numbered procs | |
429 | * tend to include daemons that don't exit. | |
430 | */ | |
431 | if (nextpid >= PID_MAX) { | |
432 | nextpid = nextpid % PID_MAX; | |
433 | if (nextpid < 100) | |
434 | nextpid += 100; | |
435 | pidchecked = 0; | |
436 | } | |
437 | if (nextpid >= pidchecked) { | |
438 | int doingzomb = 0; | |
439 | ||
440 | pidchecked = PID_MAX; | |
441 | /* | |
442 | * Scan the active and zombie procs to check whether this pid | |
443 | * is in use. Remember the lowest pid that's greater | |
444 | * than nextpid, so we can avoid checking for a while. | |
445 | */ | |
446 | p = LIST_FIRST(&allproc); | |
447 | again: | |
448 | for (; p != 0; p = LIST_NEXT(p, p_list)) { | |
449 | while (p->p_pid == nextpid || | |
450 | p->p_pgrp->pg_id == nextpid || | |
451 | p->p_session->s_sid == nextpid) { | |
452 | nextpid++; | |
453 | if (nextpid >= pidchecked) | |
454 | goto retry; | |
455 | } | |
456 | if (p->p_pid > nextpid && pidchecked > p->p_pid) | |
457 | pidchecked = p->p_pid; | |
458 | if (p->p_pgrp->pg_id > nextpid && | |
459 | pidchecked > p->p_pgrp->pg_id) | |
460 | pidchecked = p->p_pgrp->pg_id; | |
461 | if (p->p_session->s_sid > nextpid && | |
462 | pidchecked > p->p_session->s_sid) | |
463 | pidchecked = p->p_session->s_sid; | |
464 | } | |
465 | if (!doingzomb) { | |
466 | doingzomb = 1; | |
467 | p = LIST_FIRST(&zombproc); | |
468 | goto again; | |
469 | } | |
470 | } | |
471 | return(nextpid); | |
472 | } | |
473 | ||
5bf0d9b5 MD |
474 | /* |
475 | * Called from exit1 to remove a process from the allproc | |
476 | * list and move it to the zombie list. | |
477 | * | |
478 | * MPSAFE | |
479 | */ | |
480 | void | |
481 | proc_move_allproc_zombie(struct proc *p) | |
482 | { | |
483 | spin_lock_wr(&allproc_spin); | |
484 | while (p->p_lock) { | |
485 | spin_unlock_wr(&allproc_spin); | |
486 | tsleep(p, 0, "reap1", hz / 10); | |
487 | spin_lock_wr(&allproc_spin); | |
488 | } | |
489 | LIST_REMOVE(p, p_list); | |
490 | LIST_INSERT_HEAD(&zombproc, p, p_list); | |
491 | LIST_REMOVE(p, p_hash); | |
416d05d7 | 492 | p->p_stat = SZOMB; |
5bf0d9b5 MD |
493 | spin_unlock_wr(&allproc_spin); |
494 | } | |
495 | ||
496 | /* | |
497 | * This routine is called from kern_wait() and will remove the process | |
498 | * from the zombie list and the sibling list. This routine will block | |
499 | * if someone has a lock on the proces (p_lock). | |
500 | * | |
501 | * MPSAFE | |
502 | */ | |
503 | void | |
504 | proc_remove_zombie(struct proc *p) | |
505 | { | |
506 | spin_lock_wr(&allproc_spin); | |
507 | while (p->p_lock) { | |
508 | spin_unlock_wr(&allproc_spin); | |
509 | tsleep(p, 0, "reap1", hz / 10); | |
510 | spin_lock_wr(&allproc_spin); | |
511 | } | |
512 | LIST_REMOVE(p, p_list); /* off zombproc */ | |
513 | LIST_REMOVE(p, p_sibling); | |
514 | spin_unlock_wr(&allproc_spin); | |
515 | } | |
516 | ||
517 | /* | |
518 | * Scan all processes on the allproc list. The process is automatically | |
519 | * held for the callback. A return value of -1 terminates the loop. | |
520 | * | |
521 | * MPSAFE | |
522 | */ | |
523 | void | |
524 | allproc_scan(int (*callback)(struct proc *, void *), void *data) | |
525 | { | |
526 | struct proc *p; | |
527 | int r; | |
528 | ||
529 | spin_lock_rd(&allproc_spin); | |
530 | LIST_FOREACH(p, &allproc, p_list) { | |
531 | PHOLD(p); | |
532 | spin_unlock_rd(&allproc_spin); | |
533 | r = callback(p, data); | |
534 | spin_lock_rd(&allproc_spin); | |
535 | PRELE(p); | |
536 | if (r < 0) | |
537 | break; | |
538 | } | |
539 | spin_unlock_rd(&allproc_spin); | |
540 | } | |
541 | ||
c7e98b2f SS |
542 | /* |
543 | * Scan all lwps of processes on the allproc list. The lwp is automatically | |
544 | * held for the callback. A return value of -1 terminates the loop. | |
545 | * | |
546 | * possibly not MPSAFE, needs to access foreingn proc structures | |
547 | */ | |
548 | void | |
549 | alllwp_scan(int (*callback)(struct lwp *, void *), void *data) | |
550 | { | |
551 | struct proc *p; | |
552 | struct lwp *lp; | |
553 | int r = 0; | |
554 | ||
555 | spin_lock_rd(&allproc_spin); | |
556 | LIST_FOREACH(p, &allproc, p_list) { | |
557 | PHOLD(p); | |
558 | spin_unlock_rd(&allproc_spin); | |
559 | FOREACH_LWP_IN_PROC(lp, p) { | |
560 | LWPHOLD(lp); | |
561 | r = callback(lp, data); | |
562 | LWPRELE(lp); | |
563 | } | |
564 | spin_lock_rd(&allproc_spin); | |
565 | PRELE(p); | |
566 | if (r < 0) | |
567 | break; | |
568 | } | |
569 | spin_unlock_rd(&allproc_spin); | |
570 | } | |
571 | ||
5bf0d9b5 MD |
572 | /* |
573 | * Scan all processes on the zombproc list. The process is automatically | |
574 | * held for the callback. A return value of -1 terminates the loop. | |
575 | * | |
576 | * MPSAFE | |
577 | */ | |
578 | void | |
579 | zombproc_scan(int (*callback)(struct proc *, void *), void *data) | |
580 | { | |
581 | struct proc *p; | |
582 | int r; | |
583 | ||
584 | spin_lock_rd(&allproc_spin); | |
585 | LIST_FOREACH(p, &zombproc, p_list) { | |
586 | PHOLD(p); | |
587 | spin_unlock_rd(&allproc_spin); | |
588 | r = callback(p, data); | |
589 | spin_lock_rd(&allproc_spin); | |
590 | PRELE(p); | |
591 | if (r < 0) | |
592 | break; | |
593 | } | |
594 | spin_unlock_rd(&allproc_spin); | |
595 | } | |
596 | ||
984263bc MD |
597 | #include "opt_ddb.h" |
598 | #ifdef DDB | |
599 | #include <ddb/ddb.h> | |
600 | ||
601 | DB_SHOW_COMMAND(pgrpdump, pgrpdump) | |
602 | { | |
1fd87d54 RG |
603 | struct pgrp *pgrp; |
604 | struct proc *p; | |
605 | int i; | |
984263bc MD |
606 | |
607 | for (i = 0; i <= pgrphash; i++) { | |
608 | if (!LIST_EMPTY(&pgrphashtbl[i])) { | |
6ea70f76 | 609 | kprintf("\tindx %d\n", i); |
984263bc | 610 | LIST_FOREACH(pgrp, &pgrphashtbl[i], pg_hash) { |
6ea70f76 | 611 | kprintf( |
984263bc MD |
612 | "\tpgrp %p, pgid %ld, sess %p, sesscnt %d, mem %p\n", |
613 | (void *)pgrp, (long)pgrp->pg_id, | |
614 | (void *)pgrp->pg_session, | |
615 | pgrp->pg_session->s_count, | |
616 | (void *)LIST_FIRST(&pgrp->pg_members)); | |
617 | LIST_FOREACH(p, &pgrp->pg_members, p_pglist) { | |
6ea70f76 | 618 | kprintf("\t\tpid %ld addr %p pgrp %p\n", |
984263bc MD |
619 | (long)p->p_pid, (void *)p, |
620 | (void *)p->p_pgrp); | |
621 | } | |
622 | } | |
623 | } | |
624 | } | |
625 | } | |
626 | #endif /* DDB */ | |
627 | ||
5bf0d9b5 MD |
628 | /* |
629 | * Locate a process on the zombie list. Return a held process or NULL. | |
630 | */ | |
984263bc MD |
631 | struct proc * |
632 | zpfind(pid_t pid) | |
633 | { | |
634 | struct proc *p; | |
635 | ||
636 | LIST_FOREACH(p, &zombproc, p_list) | |
637 | if (p->p_pid == pid) | |
638 | return (p); | |
639 | return (NULL); | |
640 | } | |
641 | ||
984263bc | 642 | static int |
5dfd06ac | 643 | sysctl_out_proc(struct proc *p, struct sysctl_req *req, int flags) |
984263bc | 644 | { |
5dfd06ac SS |
645 | struct kinfo_proc ki; |
646 | struct lwp *lp; | |
fe14f34e | 647 | int skp = 0, had_output = 0; |
984263bc | 648 | int error; |
d9d6cb99 | 649 | |
fa2217dc | 650 | bzero(&ki, sizeof(ki)); |
5dfd06ac SS |
651 | fill_kinfo_proc(p, &ki); |
652 | if ((flags & KERN_PROC_FLAG_LWP) == 0) | |
653 | skp = 1; | |
fa2217dc | 654 | error = 0; |
5dfd06ac | 655 | FOREACH_LWP_IN_PROC(lp, p) { |
fa2217dc | 656 | LWPHOLD(lp); |
5dfd06ac | 657 | fill_kinfo_lwp(lp, &ki.kp_lwp); |
5dfd06ac SS |
658 | had_output = 1; |
659 | error = SYSCTL_OUT(req, &ki, sizeof(ki)); | |
fa2217dc | 660 | LWPRELE(lp); |
5dfd06ac | 661 | if (error) |
fa2217dc | 662 | break; |
5dfd06ac SS |
663 | if (skp) |
664 | break; | |
73e4f7b9 | 665 | } |
5dfd06ac | 666 | /* We need to output at least the proc, even if there is no lwp. */ |
fa2217dc MD |
667 | if (had_output == 0) { |
668 | error = SYSCTL_OUT(req, &ki, sizeof(ki)); | |
669 | } | |
670 | return (error); | |
984263bc MD |
671 | } |
672 | ||
ef02d0e1 TS |
673 | static int |
674 | sysctl_out_proc_kthread(struct thread *td, struct sysctl_req *req, int flags) | |
675 | { | |
676 | struct kinfo_proc ki; | |
677 | int error; | |
678 | ||
679 | fill_kinfo_proc_kthread(td, &ki); | |
680 | error = SYSCTL_OUT(req, &ki, sizeof(ki)); | |
681 | if (error) | |
682 | return error; | |
683 | return(0); | |
684 | } | |
685 | ||
984263bc MD |
686 | static int |
687 | sysctl_kern_proc(SYSCTL_HANDLER_ARGS) | |
688 | { | |
689 | int *name = (int*) arg1; | |
5dfd06ac | 690 | int oid = oidp->oid_number; |
984263bc | 691 | u_int namelen = arg2; |
7cd8fd20 | 692 | struct proc *p; |
5dfd06ac | 693 | struct proclist *plist; |
ef02d0e1 | 694 | struct thread *td; |
5dfd06ac | 695 | int doingzomb, flags = 0; |
984263bc | 696 | int error = 0; |
ef02d0e1 | 697 | int n; |
630ccdeb | 698 | int origcpu; |
41c20dac | 699 | struct ucred *cr1 = curproc->p_ucred; |
984263bc | 700 | |
5dfd06ac SS |
701 | flags = oid & KERN_PROC_FLAGMASK; |
702 | oid &= ~KERN_PROC_FLAGMASK; | |
703 | ||
704 | if ((oid == KERN_PROC_ALL && namelen != 0) || | |
705 | (oid != KERN_PROC_ALL && namelen != 1)) | |
706 | return (EINVAL); | |
707 | ||
708 | if (oid == KERN_PROC_PID) { | |
984263bc MD |
709 | p = pfind((pid_t)name[0]); |
710 | if (!p) | |
711 | return (0); | |
41c20dac | 712 | if (!PRISON_CHECK(cr1, p->p_ucred)) |
984263bc | 713 | return (0); |
e7093b07 | 714 | PHOLD(p); |
5dfd06ac | 715 | error = sysctl_out_proc(p, req, flags); |
e7093b07 | 716 | PRELE(p); |
984263bc MD |
717 | return (error); |
718 | } | |
5dfd06ac | 719 | |
984263bc MD |
720 | if (!req->oldptr) { |
721 | /* overestimate by 5 procs */ | |
722 | error = SYSCTL_OUT(req, 0, sizeof (struct kinfo_proc) * 5); | |
723 | if (error) | |
724 | return (error); | |
725 | } | |
5dfd06ac SS |
726 | for (doingzomb = 0; doingzomb <= 1; doingzomb++) { |
727 | if (doingzomb) | |
728 | plist = &zombproc; | |
984263bc | 729 | else |
5dfd06ac | 730 | plist = &allproc; |
7cd8fd20 | 731 | LIST_FOREACH(p, plist, p_list) { |
984263bc MD |
732 | /* |
733 | * Show a user only their processes. | |
734 | */ | |
41c20dac | 735 | if ((!ps_showallprocs) && p_trespass(cr1, p->p_ucred)) |
984263bc MD |
736 | continue; |
737 | /* | |
738 | * Skip embryonic processes. | |
739 | */ | |
740 | if (p->p_stat == SIDL) | |
741 | continue; | |
742 | /* | |
743 | * TODO - make more efficient (see notes below). | |
744 | * do by session. | |
745 | */ | |
5dfd06ac | 746 | switch (oid) { |
984263bc MD |
747 | case KERN_PROC_PGRP: |
748 | /* could do this by traversing pgrp */ | |
749 | if (p->p_pgrp == NULL || | |
750 | p->p_pgrp->pg_id != (pid_t)name[0]) | |
751 | continue; | |
752 | break; | |
753 | ||
754 | case KERN_PROC_TTY: | |
755 | if ((p->p_flag & P_CONTROLT) == 0 || | |
756 | p->p_session == NULL || | |
757 | p->p_session->s_ttyp == NULL || | |
758 | dev2udev(p->p_session->s_ttyp->t_dev) != | |
759 | (udev_t)name[0]) | |
760 | continue; | |
761 | break; | |
762 | ||
763 | case KERN_PROC_UID: | |
764 | if (p->p_ucred == NULL || | |
765 | p->p_ucred->cr_uid != (uid_t)name[0]) | |
766 | continue; | |
767 | break; | |
768 | ||
769 | case KERN_PROC_RUID: | |
770 | if (p->p_ucred == NULL || | |
41c20dac | 771 | p->p_ucred->cr_ruid != (uid_t)name[0]) |
984263bc MD |
772 | continue; |
773 | break; | |
774 | } | |
775 | ||
41c20dac | 776 | if (!PRISON_CHECK(cr1, p->p_ucred)) |
984263bc | 777 | continue; |
c008d3ad | 778 | PHOLD(p); |
5dfd06ac | 779 | error = sysctl_out_proc(p, req, flags); |
c008d3ad | 780 | PRELE(p); |
984263bc MD |
781 | if (error) |
782 | return (error); | |
783 | } | |
784 | } | |
630ccdeb MD |
785 | |
786 | /* | |
787 | * Iterate over all active cpus and scan their thread list. Start | |
788 | * with the next logical cpu and end with our original cpu. We | |
789 | * migrate our own thread to each target cpu in order to safely scan | |
790 | * its thread list. In the last loop we migrate back to our original | |
791 | * cpu. | |
792 | */ | |
793 | origcpu = mycpu->gd_cpuid; | |
56c703bd JS |
794 | if (!ps_showallthreads || jailed(cr1)) |
795 | goto post_threads; | |
796 | for (n = 1; n <= ncpus; ++n) { | |
630ccdeb MD |
797 | globaldata_t rgd; |
798 | int nid; | |
799 | ||
800 | nid = (origcpu + n) % ncpus; | |
801 | if ((smp_active_mask & (1 << nid)) == 0) | |
802 | continue; | |
803 | rgd = globaldata_find(nid); | |
804 | lwkt_setcpu_self(rgd); | |
630ccdeb | 805 | |
73e4f7b9 MD |
806 | TAILQ_FOREACH(td, &mycpu->gd_tdallq, td_allq) { |
807 | if (td->td_proc) | |
808 | continue; | |
ef02d0e1 | 809 | switch (oid) { |
73e4f7b9 MD |
810 | case KERN_PROC_PGRP: |
811 | case KERN_PROC_TTY: | |
812 | case KERN_PROC_UID: | |
813 | case KERN_PROC_RUID: | |
814 | continue; | |
815 | default: | |
816 | break; | |
817 | } | |
818 | lwkt_hold(td); | |
ef02d0e1 | 819 | error = sysctl_out_proc_kthread(td, req, doingzomb); |
73e4f7b9 MD |
820 | lwkt_rele(td); |
821 | if (error) | |
822 | return (error); | |
823 | } | |
824 | } | |
56c703bd | 825 | post_threads: |
984263bc MD |
826 | return (0); |
827 | } | |
828 | ||
829 | /* | |
830 | * This sysctl allows a process to retrieve the argument list or process | |
831 | * title for another process without groping around in the address space | |
832 | * of the other process. It also allow a process to set its own "process | |
833 | * title to a string of its own choice. | |
834 | */ | |
835 | static int | |
836 | sysctl_kern_proc_args(SYSCTL_HANDLER_ARGS) | |
837 | { | |
838 | int *name = (int*) arg1; | |
839 | u_int namelen = arg2; | |
840 | struct proc *p; | |
841 | struct pargs *pa; | |
842 | int error = 0; | |
41c20dac | 843 | struct ucred *cr1 = curproc->p_ucred; |
984263bc MD |
844 | |
845 | if (namelen != 1) | |
846 | return (EINVAL); | |
847 | ||
848 | p = pfind((pid_t)name[0]); | |
849 | if (!p) | |
850 | return (0); | |
851 | ||
41c20dac | 852 | if ((!ps_argsopen) && p_trespass(cr1, p->p_ucred)) |
984263bc MD |
853 | return (0); |
854 | ||
855 | if (req->newptr && curproc != p) | |
856 | return (EPERM); | |
857 | ||
858 | if (req->oldptr && p->p_args != NULL) | |
859 | error = SYSCTL_OUT(req, p->p_args->ar_args, p->p_args->ar_length); | |
860 | if (req->newptr == NULL) | |
861 | return (error); | |
862 | ||
863 | if (p->p_args && --p->p_args->ar_ref == 0) | |
864 | FREE(p->p_args, M_PARGS); | |
865 | p->p_args = NULL; | |
866 | ||
867 | if (req->newlen + sizeof(struct pargs) > ps_arg_cache_limit) | |
868 | return (error); | |
869 | ||
870 | MALLOC(pa, struct pargs *, sizeof(struct pargs) + req->newlen, | |
871 | M_PARGS, M_WAITOK); | |
872 | pa->ar_ref = 1; | |
873 | pa->ar_length = req->newlen; | |
874 | error = SYSCTL_IN(req, pa->ar_args, req->newlen); | |
875 | if (!error) | |
876 | p->p_args = pa; | |
877 | else | |
878 | FREE(pa, M_PARGS); | |
879 | return (error); | |
880 | } | |
881 | ||
882 | SYSCTL_NODE(_kern, KERN_PROC, proc, CTLFLAG_RD, 0, "Process table"); | |
883 | ||
884 | SYSCTL_PROC(_kern_proc, KERN_PROC_ALL, all, CTLFLAG_RD|CTLTYPE_STRUCT, | |
885 | 0, 0, sysctl_kern_proc, "S,proc", "Return entire process table"); | |
886 | ||
887 | SYSCTL_NODE(_kern_proc, KERN_PROC_PGRP, pgrp, CTLFLAG_RD, | |
888 | sysctl_kern_proc, "Process table"); | |
889 | ||
890 | SYSCTL_NODE(_kern_proc, KERN_PROC_TTY, tty, CTLFLAG_RD, | |
891 | sysctl_kern_proc, "Process table"); | |
892 | ||
893 | SYSCTL_NODE(_kern_proc, KERN_PROC_UID, uid, CTLFLAG_RD, | |
894 | sysctl_kern_proc, "Process table"); | |
895 | ||
896 | SYSCTL_NODE(_kern_proc, KERN_PROC_RUID, ruid, CTLFLAG_RD, | |
897 | sysctl_kern_proc, "Process table"); | |
898 | ||
899 | SYSCTL_NODE(_kern_proc, KERN_PROC_PID, pid, CTLFLAG_RD, | |
900 | sysctl_kern_proc, "Process table"); | |
901 | ||
5dfd06ac SS |
902 | SYSCTL_NODE(_kern_proc, (KERN_PROC_ALL | KERN_PROC_FLAG_LWP), all_lwp, CTLFLAG_RD, |
903 | sysctl_kern_proc, "Process table"); | |
904 | ||
905 | SYSCTL_NODE(_kern_proc, (KERN_PROC_PGRP | KERN_PROC_FLAG_LWP), pgrp_lwp, CTLFLAG_RD, | |
906 | sysctl_kern_proc, "Process table"); | |
907 | ||
908 | SYSCTL_NODE(_kern_proc, (KERN_PROC_TTY | KERN_PROC_FLAG_LWP), tty_lwp, CTLFLAG_RD, | |
909 | sysctl_kern_proc, "Process table"); | |
910 | ||
911 | SYSCTL_NODE(_kern_proc, (KERN_PROC_UID | KERN_PROC_FLAG_LWP), uid_lwp, CTLFLAG_RD, | |
912 | sysctl_kern_proc, "Process table"); | |
913 | ||
914 | SYSCTL_NODE(_kern_proc, (KERN_PROC_RUID | KERN_PROC_FLAG_LWP), ruid_lwp, CTLFLAG_RD, | |
915 | sysctl_kern_proc, "Process table"); | |
916 | ||
917 | SYSCTL_NODE(_kern_proc, (KERN_PROC_PID | KERN_PROC_FLAG_LWP), pid_lwp, CTLFLAG_RD, | |
918 | sysctl_kern_proc, "Process table"); | |
919 | ||
984263bc MD |
920 | SYSCTL_NODE(_kern_proc, KERN_PROC_ARGS, args, CTLFLAG_RW | CTLFLAG_ANYBODY, |
921 | sysctl_kern_proc_args, "Process argument list"); |