| 2362 | } |
| 2363 | |
| 2364 | static void |
| 2365 | prison_remove_one(struct prison *pr) |
| 2366 | { |
| 2367 | struct proc *p; |
| 2368 | int drflags; |
| 2369 | |
| 2370 | drflags = PD_DEREF | PD_LOCKED | PD_LIST_XLOCKED; |
| 2371 | |
| 2372 | /* |
| 2373 | * Mark the prison as doomed, so it doesn't accidentally come back |
| 2374 | * to life. It may still be explicitly brought back by jail_set(2). |
| 2375 | */ |
| 2376 | pr->pr_flags |= PR_REMOVE; |
| 2377 | |
| 2378 | /* If the prison was persistent, it is not anymore. */ |
| 2379 | if (pr->pr_flags & PR_PERSIST) { |
| 2380 | refcount_release(&pr->pr_ref); |
| 2381 | drflags |= PD_DEUREF; |
| 2382 | pr->pr_flags &= ~PR_PERSIST; |
| 2383 | } |
| 2384 | |
| 2385 | /* |
| 2386 | * jail_remove added a reference. If that's the only one, remove |
| 2387 | * the prison now. refcount(9) doesn't guarantee the cache coherence |
| 2388 | * of non-zero counters, so force it here. |
| 2389 | */ |
| 2390 | KASSERT(refcount_load(&pr->pr_ref) > 0, |
| 2391 | ("prison_remove_one removing a dead prison (jid=%d)", pr->pr_id)); |
| 2392 | if (atomic_load_acq_int(&pr->pr_ref) == 1) { |
| 2393 | prison_deref(pr, drflags); |
| 2394 | return; |
| 2395 | } |
| 2396 | |
| 2397 | mtx_unlock(&pr->pr_mtx); |
| 2398 | sx_xunlock(&allprison_lock); |
| 2399 | drflags &= ~(PD_LOCKED | PD_LIST_XLOCKED); |
| 2400 | /* |
| 2401 | * Kill all processes unfortunate enough to be attached to this prison. |
| 2402 | */ |
| 2403 | sx_slock(&allproc_lock); |
| 2404 | FOREACH_PROC_IN_SYSTEM(p) { |
| 2405 | PROC_LOCK(p); |
| 2406 | if (p->p_state != PRS_NEW && p->p_ucred && |
| 2407 | p->p_ucred->cr_prison == pr) |
| 2408 | kern_psignal(p, SIGKILL); |
| 2409 | PROC_UNLOCK(p); |
| 2410 | } |
| 2411 | sx_sunlock(&allproc_lock); |
| 2412 | /* Remove the temporary reference added by jail_remove. */ |
| 2413 | prison_deref(pr, drflags); |
| 2414 | } |
| 2415 | |
| 2416 | /* |
| 2417 | * struct jail_attach_args { |
no test coverage detected