* struct jail_attach_args { * int jid; * }; */
| 2419 | * }; |
| 2420 | */ |
| 2421 | int |
| 2422 | sys_jail_attach(struct thread *td, struct jail_attach_args *uap) |
| 2423 | { |
| 2424 | struct prison *pr; |
| 2425 | int error; |
| 2426 | |
| 2427 | error = priv_check(td, PRIV_JAIL_ATTACH); |
| 2428 | if (error) |
| 2429 | return (error); |
| 2430 | |
| 2431 | /* |
| 2432 | * Start with exclusive hold on allprison_lock to ensure that a possible |
| 2433 | * PR_METHOD_REMOVE call isn't concurrent with jail_set or jail_remove. |
| 2434 | * But then immediately downgrade it since we don't need to stop |
| 2435 | * readers. |
| 2436 | */ |
| 2437 | sx_xlock(&allprison_lock); |
| 2438 | sx_downgrade(&allprison_lock); |
| 2439 | pr = prison_find_child(td->td_ucred->cr_prison, uap->jid); |
| 2440 | if (pr == NULL) { |
| 2441 | sx_sunlock(&allprison_lock); |
| 2442 | return (EINVAL); |
| 2443 | } |
| 2444 | |
| 2445 | /* Do not allow a process to attach to a prison that is not alive. */ |
| 2446 | if (!prison_isalive(pr)) { |
| 2447 | mtx_unlock(&pr->pr_mtx); |
| 2448 | sx_sunlock(&allprison_lock); |
| 2449 | return (EINVAL); |
| 2450 | } |
| 2451 | |
| 2452 | return (do_jail_attach(td, pr)); |
| 2453 | } |
| 2454 | |
| 2455 | static int |
| 2456 | do_jail_attach(struct thread *td, struct prison *pr) |
nothing calls this directly
no test coverage detected