1 /*- 2 * Copyright (c) 2014 John Baldwin 3 * Copyright (c) 2014, 2016 The FreeBSD Foundation 4 * 5 * Portions of this software were developed by Konstantin Belousov 6 * under sponsorship from the FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/capsicum.h> 36 #include <sys/lock.h> 37 #include <sys/mutex.h> 38 #include <sys/priv.h> 39 #include <sys/proc.h> 40 #include <sys/procctl.h> 41 #include <sys/sx.h> 42 #include <sys/syscallsubr.h> 43 #include <sys/sysproto.h> 44 #include <sys/wait.h> 45 46 #include <vm/vm.h> 47 #include <vm/pmap.h> 48 #include <vm/vm_map.h> 49 #include <vm/vm_extern.h> 50 51 static int 52 protect_setchild(struct thread *td, struct proc *p, int flags) 53 { 54 55 PROC_LOCK_ASSERT(p, MA_OWNED); 56 if (p->p_flag & P_SYSTEM || p_cansched(td, p) != 0) 57 return (0); 58 if (flags & PPROT_SET) { 59 p->p_flag |= P_PROTECTED; 60 if (flags & PPROT_INHERIT) 61 p->p_flag2 |= P2_INHERIT_PROTECTED; 62 } else { 63 p->p_flag &= ~P_PROTECTED; 64 p->p_flag2 &= ~P2_INHERIT_PROTECTED; 65 } 66 return (1); 67 } 68 69 static int 70 protect_setchildren(struct thread *td, struct proc *top, int flags) 71 { 72 struct proc *p; 73 int ret; 74 75 p = top; 76 ret = 0; 77 sx_assert(&proctree_lock, SX_LOCKED); 78 for (;;) { 79 ret |= protect_setchild(td, p, flags); 80 PROC_UNLOCK(p); 81 /* 82 * If this process has children, descend to them next, 83 * otherwise do any siblings, and if done with this level, 84 * follow back up the tree (but not past top). 85 */ 86 if (!LIST_EMPTY(&p->p_children)) 87 p = LIST_FIRST(&p->p_children); 88 else for (;;) { 89 if (p == top) { 90 PROC_LOCK(p); 91 return (ret); 92 } 93 if (LIST_NEXT(p, p_sibling)) { 94 p = LIST_NEXT(p, p_sibling); 95 break; 96 } 97 p = p->p_pptr; 98 } 99 PROC_LOCK(p); 100 } 101 } 102 103 static int 104 protect_set(struct thread *td, struct proc *p, int flags) 105 { 106 int error, ret; 107 108 switch (PPROT_OP(flags)) { 109 case PPROT_SET: 110 case PPROT_CLEAR: 111 break; 112 default: 113 return (EINVAL); 114 } 115 116 if ((PPROT_FLAGS(flags) & ~(PPROT_DESCEND | PPROT_INHERIT)) != 0) 117 return (EINVAL); 118 119 error = priv_check(td, PRIV_VM_MADV_PROTECT); 120 if (error) 121 return (error); 122 123 if (flags & PPROT_DESCEND) 124 ret = protect_setchildren(td, p, flags); 125 else 126 ret = protect_setchild(td, p, flags); 127 if (ret == 0) 128 return (EPERM); 129 return (0); 130 } 131 132 static int 133 reap_acquire(struct thread *td, struct proc *p) 134 { 135 136 sx_assert(&proctree_lock, SX_XLOCKED); 137 if (p != curproc) 138 return (EPERM); 139 if ((p->p_treeflag & P_TREE_REAPER) != 0) 140 return (EBUSY); 141 p->p_treeflag |= P_TREE_REAPER; 142 /* 143 * We do not reattach existing children and the whole tree 144 * under them to us, since p->p_reaper already seen them. 145 */ 146 return (0); 147 } 148 149 static int 150 reap_release(struct thread *td, struct proc *p) 151 { 152 153 sx_assert(&proctree_lock, SX_XLOCKED); 154 if (p != curproc) 155 return (EPERM); 156 if (p == initproc) 157 return (EINVAL); 158 if ((p->p_treeflag & P_TREE_REAPER) == 0) 159 return (EINVAL); 160 reaper_abandon_children(p, false); 161 return (0); 162 } 163 164 static int 165 reap_status(struct thread *td, struct proc *p, 166 struct procctl_reaper_status *rs) 167 { 168 struct proc *reap, *p2, *first_p; 169 170 sx_assert(&proctree_lock, SX_LOCKED); 171 bzero(rs, sizeof(*rs)); 172 if ((p->p_treeflag & P_TREE_REAPER) == 0) { 173 reap = p->p_reaper; 174 } else { 175 reap = p; 176 rs->rs_flags |= REAPER_STATUS_OWNED; 177 } 178 if (reap == initproc) 179 rs->rs_flags |= REAPER_STATUS_REALINIT; 180 rs->rs_reaper = reap->p_pid; 181 rs->rs_descendants = 0; 182 rs->rs_children = 0; 183 if (!LIST_EMPTY(&reap->p_reaplist)) { 184 first_p = LIST_FIRST(&reap->p_children); 185 if (first_p == NULL) 186 first_p = LIST_FIRST(&reap->p_reaplist); 187 rs->rs_pid = first_p->p_pid; 188 LIST_FOREACH(p2, &reap->p_reaplist, p_reapsibling) { 189 if (proc_realparent(p2) == reap) 190 rs->rs_children++; 191 rs->rs_descendants++; 192 } 193 } else { 194 rs->rs_pid = -1; 195 } 196 return (0); 197 } 198 199 static int 200 reap_getpids(struct thread *td, struct proc *p, struct procctl_reaper_pids *rp) 201 { 202 struct proc *reap, *p2; 203 struct procctl_reaper_pidinfo *pi, *pip; 204 u_int i, n; 205 int error; 206 207 sx_assert(&proctree_lock, SX_LOCKED); 208 PROC_UNLOCK(p); 209 reap = (p->p_treeflag & P_TREE_REAPER) == 0 ? p->p_reaper : p; 210 n = i = 0; 211 error = 0; 212 LIST_FOREACH(p2, &reap->p_reaplist, p_reapsibling) 213 n++; 214 sx_unlock(&proctree_lock); 215 if (rp->rp_count < n) 216 n = rp->rp_count; 217 pi = malloc(n * sizeof(*pi), M_TEMP, M_WAITOK); 218 sx_slock(&proctree_lock); 219 LIST_FOREACH(p2, &reap->p_reaplist, p_reapsibling) { 220 if (i == n) 221 break; 222 pip = &pi[i]; 223 bzero(pip, sizeof(*pip)); 224 pip->pi_pid = p2->p_pid; 225 pip->pi_subtree = p2->p_reapsubtree; 226 pip->pi_flags = REAPER_PIDINFO_VALID; 227 if (proc_realparent(p2) == reap) 228 pip->pi_flags |= REAPER_PIDINFO_CHILD; 229 if ((p2->p_treeflag & P_TREE_REAPER) != 0) 230 pip->pi_flags |= REAPER_PIDINFO_REAPER; 231 i++; 232 } 233 sx_sunlock(&proctree_lock); 234 error = copyout(pi, rp->rp_pids, i * sizeof(*pi)); 235 free(pi, M_TEMP); 236 sx_slock(&proctree_lock); 237 PROC_LOCK(p); 238 return (error); 239 } 240 241 static void 242 reap_kill_proc(struct thread *td, struct proc *p2, ksiginfo_t *ksi, 243 struct procctl_reaper_kill *rk, int *error) 244 { 245 int error1; 246 247 PROC_LOCK(p2); 248 error1 = p_cansignal(td, p2, rk->rk_sig); 249 if (error1 == 0) { 250 pksignal(p2, rk->rk_sig, ksi); 251 rk->rk_killed++; 252 *error = error1; 253 } else if (*error == ESRCH) { 254 rk->rk_fpid = p2->p_pid; 255 *error = error1; 256 } 257 PROC_UNLOCK(p2); 258 } 259 260 struct reap_kill_tracker { 261 struct proc *parent; 262 TAILQ_ENTRY(reap_kill_tracker) link; 263 }; 264 265 TAILQ_HEAD(reap_kill_tracker_head, reap_kill_tracker); 266 267 static void 268 reap_kill_sched(struct reap_kill_tracker_head *tracker, struct proc *p2) 269 { 270 struct reap_kill_tracker *t; 271 272 t = malloc(sizeof(struct reap_kill_tracker), M_TEMP, M_WAITOK); 273 t->parent = p2; 274 TAILQ_INSERT_TAIL(tracker, t, link); 275 } 276 277 static int 278 reap_kill(struct thread *td, struct proc *p, struct procctl_reaper_kill *rk) 279 { 280 struct proc *reap, *p2; 281 ksiginfo_t ksi; 282 struct reap_kill_tracker_head tracker; 283 struct reap_kill_tracker *t; 284 int error; 285 286 sx_assert(&proctree_lock, SX_LOCKED); 287 if (IN_CAPABILITY_MODE(td)) 288 return (ECAPMODE); 289 if (rk->rk_sig <= 0 || rk->rk_sig > _SIG_MAXSIG || 290 (rk->rk_flags & ~(REAPER_KILL_CHILDREN | 291 REAPER_KILL_SUBTREE)) != 0 || (rk->rk_flags & 292 (REAPER_KILL_CHILDREN | REAPER_KILL_SUBTREE)) == 293 (REAPER_KILL_CHILDREN | REAPER_KILL_SUBTREE)) 294 return (EINVAL); 295 PROC_UNLOCK(p); 296 reap = (p->p_treeflag & P_TREE_REAPER) == 0 ? p->p_reaper : p; 297 ksiginfo_init(&ksi); 298 ksi.ksi_signo = rk->rk_sig; 299 ksi.ksi_code = SI_USER; 300 ksi.ksi_pid = td->td_proc->p_pid; 301 ksi.ksi_uid = td->td_ucred->cr_ruid; 302 error = ESRCH; 303 rk->rk_killed = 0; 304 rk->rk_fpid = -1; 305 if ((rk->rk_flags & REAPER_KILL_CHILDREN) != 0) { 306 for (p2 = LIST_FIRST(&reap->p_children); p2 != NULL; 307 p2 = LIST_NEXT(p2, p_sibling)) { 308 reap_kill_proc(td, p2, &ksi, rk, &error); 309 /* 310 * Do not end the loop on error, signal 311 * everything we can. 312 */ 313 } 314 } else { 315 TAILQ_INIT(&tracker); 316 reap_kill_sched(&tracker, reap); 317 while ((t = TAILQ_FIRST(&tracker)) != NULL) { 318 MPASS((t->parent->p_treeflag & P_TREE_REAPER) != 0); 319 TAILQ_REMOVE(&tracker, t, link); 320 for (p2 = LIST_FIRST(&t->parent->p_reaplist); p2 != NULL; 321 p2 = LIST_NEXT(p2, p_reapsibling)) { 322 if (t->parent == reap && 323 (rk->rk_flags & REAPER_KILL_SUBTREE) != 0 && 324 p2->p_reapsubtree != rk->rk_subtree) 325 continue; 326 if ((p2->p_treeflag & P_TREE_REAPER) != 0) 327 reap_kill_sched(&tracker, p2); 328 reap_kill_proc(td, p2, &ksi, rk, &error); 329 } 330 free(t, M_TEMP); 331 } 332 } 333 PROC_LOCK(p); 334 return (error); 335 } 336 337 static int 338 trace_ctl(struct thread *td, struct proc *p, int state) 339 { 340 341 PROC_LOCK_ASSERT(p, MA_OWNED); 342 343 /* 344 * Ktrace changes p_traceflag from or to zero under the 345 * process lock, so the test does not need to acquire ktrace 346 * mutex. 347 */ 348 if ((p->p_flag & P_TRACED) != 0 || p->p_traceflag != 0) 349 return (EBUSY); 350 351 switch (state) { 352 case PROC_TRACE_CTL_ENABLE: 353 if (td->td_proc != p) 354 return (EPERM); 355 p->p_flag2 &= ~(P2_NOTRACE | P2_NOTRACE_EXEC); 356 break; 357 case PROC_TRACE_CTL_DISABLE_EXEC: 358 p->p_flag2 |= P2_NOTRACE_EXEC | P2_NOTRACE; 359 break; 360 case PROC_TRACE_CTL_DISABLE: 361 if ((p->p_flag2 & P2_NOTRACE_EXEC) != 0) { 362 KASSERT((p->p_flag2 & P2_NOTRACE) != 0, 363 ("dandling P2_NOTRACE_EXEC")); 364 if (td->td_proc != p) 365 return (EPERM); 366 p->p_flag2 &= ~P2_NOTRACE_EXEC; 367 } else { 368 p->p_flag2 |= P2_NOTRACE; 369 } 370 break; 371 default: 372 return (EINVAL); 373 } 374 return (0); 375 } 376 377 static int 378 trace_status(struct thread *td, struct proc *p, int *data) 379 { 380 381 if ((p->p_flag2 & P2_NOTRACE) != 0) { 382 KASSERT((p->p_flag & P_TRACED) == 0, 383 ("%d traced but tracing disabled", p->p_pid)); 384 *data = -1; 385 } else if ((p->p_flag & P_TRACED) != 0) { 386 *data = p->p_pptr->p_pid; 387 } else { 388 *data = 0; 389 } 390 return (0); 391 } 392 393 static int 394 trapcap_ctl(struct thread *td, struct proc *p, int state) 395 { 396 397 PROC_LOCK_ASSERT(p, MA_OWNED); 398 399 switch (state) { 400 case PROC_TRAPCAP_CTL_ENABLE: 401 p->p_flag2 |= P2_TRAPCAP; 402 break; 403 case PROC_TRAPCAP_CTL_DISABLE: 404 p->p_flag2 &= ~P2_TRAPCAP; 405 break; 406 default: 407 return (EINVAL); 408 } 409 return (0); 410 } 411 412 static int 413 trapcap_status(struct thread *td, struct proc *p, int *data) 414 { 415 416 *data = (p->p_flag2 & P2_TRAPCAP) != 0 ? PROC_TRAPCAP_CTL_ENABLE : 417 PROC_TRAPCAP_CTL_DISABLE; 418 return (0); 419 } 420 421 static int 422 aslr_ctl(struct thread *td, struct proc *p, int state) 423 { 424 425 PROC_LOCK_ASSERT(p, MA_OWNED); 426 427 switch (state) { 428 case PROC_ASLR_FORCE_ENABLE: 429 p->p_flag2 &= ~P2_ASLR_DISABLE; 430 p->p_flag2 |= P2_ASLR_ENABLE; 431 break; 432 case PROC_ASLR_FORCE_DISABLE: 433 p->p_flag2 |= P2_ASLR_DISABLE; 434 p->p_flag2 &= ~P2_ASLR_ENABLE; 435 break; 436 case PROC_ASLR_NOFORCE: 437 p->p_flag2 &= ~(P2_ASLR_ENABLE | P2_ASLR_DISABLE); 438 break; 439 default: 440 return (EINVAL); 441 } 442 return (0); 443 } 444 445 static int 446 aslr_status(struct thread *td, struct proc *p, int *data) 447 { 448 struct vmspace *vm; 449 int d; 450 451 switch (p->p_flag2 & (P2_ASLR_ENABLE | P2_ASLR_DISABLE)) { 452 case 0: 453 d = PROC_ASLR_NOFORCE; 454 break; 455 case P2_ASLR_ENABLE: 456 d = PROC_ASLR_FORCE_ENABLE; 457 break; 458 case P2_ASLR_DISABLE: 459 d = PROC_ASLR_FORCE_DISABLE; 460 break; 461 } 462 if ((p->p_flag & P_WEXIT) == 0) { 463 _PHOLD(p); 464 PROC_UNLOCK(p); 465 vm = vmspace_acquire_ref(p); 466 if (vm != NULL && (vm->vm_map.flags & MAP_ASLR) != 0) { 467 d |= PROC_ASLR_ACTIVE; 468 vmspace_free(vm); 469 } 470 PROC_LOCK(p); 471 _PRELE(p); 472 } 473 *data = d; 474 return (0); 475 } 476 477 #ifndef _SYS_SYSPROTO_H_ 478 struct procctl_args { 479 idtype_t idtype; 480 id_t id; 481 int com; 482 void *data; 483 }; 484 #endif 485 /* ARGSUSED */ 486 int 487 sys_procctl(struct thread *td, struct procctl_args *uap) 488 { 489 void *data; 490 union { 491 struct procctl_reaper_status rs; 492 struct procctl_reaper_pids rp; 493 struct procctl_reaper_kill rk; 494 } x; 495 int error, error1, flags, signum; 496 497 switch (uap->com) { 498 case PROC_ASLR_CTL: 499 case PROC_SPROTECT: 500 case PROC_TRACE_CTL: 501 case PROC_TRAPCAP_CTL: 502 error = copyin(uap->data, &flags, sizeof(flags)); 503 if (error != 0) 504 return (error); 505 data = &flags; 506 break; 507 case PROC_REAP_ACQUIRE: 508 case PROC_REAP_RELEASE: 509 if (uap->data != NULL) 510 return (EINVAL); 511 data = NULL; 512 break; 513 case PROC_REAP_STATUS: 514 data = &x.rs; 515 break; 516 case PROC_REAP_GETPIDS: 517 error = copyin(uap->data, &x.rp, sizeof(x.rp)); 518 if (error != 0) 519 return (error); 520 data = &x.rp; 521 break; 522 case PROC_REAP_KILL: 523 error = copyin(uap->data, &x.rk, sizeof(x.rk)); 524 if (error != 0) 525 return (error); 526 data = &x.rk; 527 break; 528 case PROC_ASLR_STATUS: 529 case PROC_TRACE_STATUS: 530 case PROC_TRAPCAP_STATUS: 531 data = &flags; 532 break; 533 case PROC_PDEATHSIG_CTL: 534 error = copyin(uap->data, &signum, sizeof(signum)); 535 if (error != 0) 536 return (error); 537 data = &signum; 538 break; 539 case PROC_PDEATHSIG_STATUS: 540 data = &signum; 541 break; 542 default: 543 return (EINVAL); 544 } 545 error = kern_procctl(td, uap->idtype, uap->id, uap->com, data); 546 switch (uap->com) { 547 case PROC_REAP_STATUS: 548 if (error == 0) 549 error = copyout(&x.rs, uap->data, sizeof(x.rs)); 550 break; 551 case PROC_REAP_KILL: 552 error1 = copyout(&x.rk, uap->data, sizeof(x.rk)); 553 if (error == 0) 554 error = error1; 555 break; 556 case PROC_ASLR_STATUS: 557 case PROC_TRACE_STATUS: 558 case PROC_TRAPCAP_STATUS: 559 if (error == 0) 560 error = copyout(&flags, uap->data, sizeof(flags)); 561 break; 562 case PROC_PDEATHSIG_STATUS: 563 if (error == 0) 564 error = copyout(&signum, uap->data, sizeof(signum)); 565 break; 566 } 567 return (error); 568 } 569 570 static int 571 kern_procctl_single(struct thread *td, struct proc *p, int com, void *data) 572 { 573 574 PROC_LOCK_ASSERT(p, MA_OWNED); 575 switch (com) { 576 case PROC_ASLR_CTL: 577 return (aslr_ctl(td, p, *(int *)data)); 578 case PROC_ASLR_STATUS: 579 return (aslr_status(td, p, data)); 580 case PROC_SPROTECT: 581 return (protect_set(td, p, *(int *)data)); 582 case PROC_REAP_ACQUIRE: 583 return (reap_acquire(td, p)); 584 case PROC_REAP_RELEASE: 585 return (reap_release(td, p)); 586 case PROC_REAP_STATUS: 587 return (reap_status(td, p, data)); 588 case PROC_REAP_GETPIDS: 589 return (reap_getpids(td, p, data)); 590 case PROC_REAP_KILL: 591 return (reap_kill(td, p, data)); 592 case PROC_TRACE_CTL: 593 return (trace_ctl(td, p, *(int *)data)); 594 case PROC_TRACE_STATUS: 595 return (trace_status(td, p, data)); 596 case PROC_TRAPCAP_CTL: 597 return (trapcap_ctl(td, p, *(int *)data)); 598 case PROC_TRAPCAP_STATUS: 599 return (trapcap_status(td, p, data)); 600 default: 601 return (EINVAL); 602 } 603 } 604 605 int 606 kern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data) 607 { 608 struct pgrp *pg; 609 struct proc *p; 610 int error, first_error, ok; 611 int signum; 612 bool tree_locked; 613 614 switch (com) { 615 case PROC_ASLR_CTL: 616 case PROC_ASLR_STATUS: 617 case PROC_REAP_ACQUIRE: 618 case PROC_REAP_RELEASE: 619 case PROC_REAP_STATUS: 620 case PROC_REAP_GETPIDS: 621 case PROC_REAP_KILL: 622 case PROC_TRACE_STATUS: 623 case PROC_TRAPCAP_STATUS: 624 case PROC_PDEATHSIG_CTL: 625 case PROC_PDEATHSIG_STATUS: 626 if (idtype != P_PID) 627 return (EINVAL); 628 } 629 630 switch (com) { 631 case PROC_PDEATHSIG_CTL: 632 signum = *(int *)data; 633 p = td->td_proc; 634 if ((id != 0 && id != p->p_pid) || 635 (signum != 0 && !_SIG_VALID(signum))) 636 return (EINVAL); 637 PROC_LOCK(p); 638 p->p_pdeathsig = signum; 639 PROC_UNLOCK(p); 640 return (0); 641 case PROC_PDEATHSIG_STATUS: 642 p = td->td_proc; 643 if (id != 0 && id != p->p_pid) 644 return (EINVAL); 645 PROC_LOCK(p); 646 *(int *)data = p->p_pdeathsig; 647 PROC_UNLOCK(p); 648 return (0); 649 } 650 651 switch (com) { 652 case PROC_SPROTECT: 653 case PROC_REAP_STATUS: 654 case PROC_REAP_GETPIDS: 655 case PROC_REAP_KILL: 656 case PROC_TRACE_CTL: 657 case PROC_TRAPCAP_CTL: 658 sx_slock(&proctree_lock); 659 tree_locked = true; 660 break; 661 case PROC_REAP_ACQUIRE: 662 case PROC_REAP_RELEASE: 663 sx_xlock(&proctree_lock); 664 tree_locked = true; 665 break; 666 case PROC_ASLR_CTL: 667 case PROC_ASLR_STATUS: 668 case PROC_TRACE_STATUS: 669 case PROC_TRAPCAP_STATUS: 670 tree_locked = false; 671 break; 672 default: 673 return (EINVAL); 674 } 675 676 switch (idtype) { 677 case P_PID: 678 p = pfind(id); 679 if (p == NULL) { 680 error = ESRCH; 681 break; 682 } 683 error = p_cansee(td, p); 684 if (error == 0) 685 error = kern_procctl_single(td, p, com, data); 686 PROC_UNLOCK(p); 687 break; 688 case P_PGID: 689 /* 690 * Attempt to apply the operation to all members of the 691 * group. Ignore processes in the group that can't be 692 * seen. Ignore errors so long as at least one process is 693 * able to complete the request successfully. 694 */ 695 pg = pgfind(id); 696 if (pg == NULL) { 697 error = ESRCH; 698 break; 699 } 700 PGRP_UNLOCK(pg); 701 ok = 0; 702 first_error = 0; 703 LIST_FOREACH(p, &pg->pg_members, p_pglist) { 704 PROC_LOCK(p); 705 if (p->p_state == PRS_NEW || p_cansee(td, p) != 0) { 706 PROC_UNLOCK(p); 707 continue; 708 } 709 error = kern_procctl_single(td, p, com, data); 710 PROC_UNLOCK(p); 711 if (error == 0) 712 ok = 1; 713 else if (first_error == 0) 714 first_error = error; 715 } 716 if (ok) 717 error = 0; 718 else if (first_error != 0) 719 error = first_error; 720 else 721 /* 722 * Was not able to see any processes in the 723 * process group. 724 */ 725 error = ESRCH; 726 break; 727 default: 728 error = EINVAL; 729 break; 730 } 731 if (tree_locked) 732 sx_unlock(&proctree_lock); 733 return (error); 734 } 735