Changeset View
Standalone View
sys/kern/kern_jail.c
Show All 27 Lines | |||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include "opt_compat.h" | #include "opt_compat.h" | ||||
#include "opt_ddb.h" | #include "opt_ddb.h" | ||||
#include "opt_inet.h" | #include "opt_inet.h" | ||||
#include "opt_inet6.h" | #include "opt_inet6.h" | ||||
#include "opt_pax.h" | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/errno.h> | #include <sys/errno.h> | ||||
#include <sys/sysproto.h> | #include <sys/sysproto.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/osd.h> | #include <sys/osd.h> | ||||
#include <sys/pax.h> | |||||
#include <sys/priv.h> | #include <sys/priv.h> | ||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/taskqueue.h> | #include <sys/taskqueue.h> | ||||
#include <sys/fcntl.h> | #include <sys/fcntl.h> | ||||
#include <sys/jail.h> | #include <sys/jail.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <sys/racct.h> | #include <sys/racct.h> | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | |||||
#else | #else | ||||
.pr_flags = PR_HOST|_PR_IP_SADDRSEL, | .pr_flags = PR_HOST|_PR_IP_SADDRSEL, | ||||
#endif | #endif | ||||
.pr_allow = PR_ALLOW_ALL, | .pr_allow = PR_ALLOW_ALL, | ||||
}; | }; | ||||
MTX_SYSINIT(prison0, &prison0.pr_mtx, "jail mutex", MTX_DEF); | MTX_SYSINIT(prison0, &prison0.pr_mtx, "jail mutex", MTX_DEF); | ||||
/* allprison, allprison_racct and lastprid are protected by allprison_lock. */ | /* allprison, allprison_racct and lastprid are protected by allprison_lock. */ | ||||
struct sx allprison_lock; | struct sx allprison_lock; | ||||
rwatson: I find myself wondering if it's time for a new prison_init_prison0() sysinit that can take care… | |||||
Not Done Inline ActionsIs that a problem a patch implementing ASLR needs to solve? lattera-gmail.com: Is that a problem a patch implementing ASLR needs to solve? | |||||
Not Done Inline ActionsIt's a problem that the ASLR patch introduces: before ASLR, there isn't an issue with multiple independent sysinits for prison0. rwatson: It's a problem that the ASLR patch introduces: before ASLR, there isn't an issue with multiple… | |||||
Not Done Inline ActionsWhy this is a problem? op: Why this is a problem? | |||||
Not Done Inline ActionsIf there is avoidable non-atomicity in initialising kernel data structures, it's nice to do so. In this case, it might be that we are not yet ready to initialise prison0's ASLR state until well after we are ready to initialise its mutex .. on the other hand, it would be nice to think that prison0 state is fully initialised before something would need to use its mutex. This is an inevitable source of difficulty in bootstrapping the system, but maintaining congruence between bootstrap initialisation of special-case structures (e.g., prison0) and later instances of the same structure (e.g., every other prison structure) is a reasonable goal. rwatson: If there is avoidable non-atomicity in initialising kernel data structures, it's nice to do so. | |||||
Not Done Inline ActionsIn older version of pax_init_prison(struct prison *pr) we acquired the prison lock, and because this it's needed after prison0's mtx initializations. Currently we don't acquire the prison lock and I think it's fine, if we move the pax's prison0 initialization before the prison0's mutex initialization in sysinit priority list. op: In older version of pax_init_prison(struct prison *pr) we acquired the prison lock, and because… | |||||
Not Done Inline ActionsI was sort of pondering a new sysinit (very vaguely) along the lines of: static void mtx_init(&prison0) pax_init(&prison0) } The interesting question is what sysinit ordering to give it: I guess a new SI_SUB_PRISON could fall after SI_SUB_PAX such that PAX's internal state is initialised before the first prison structure uses it? rwatson: I was sort of pondering a new sysinit (very vaguely) along the lines of:
static void… | |||||
SX_SYSINIT(allprison_lock, &allprison_lock, "allprison"); | SX_SYSINIT(allprison_lock, &allprison_lock, "allprison"); | ||||
struct prisonlist allprison = TAILQ_HEAD_INITIALIZER(allprison); | struct prisonlist allprison = TAILQ_HEAD_INITIALIZER(allprison); | ||||
LIST_HEAD(, prison_racct) allprison_racct; | LIST_HEAD(, prison_racct) allprison_racct; | ||||
int lastprid = 0; | int lastprid = 0; | ||||
static int do_jail_attach(struct thread *td, struct prison *pr); | static int do_jail_attach(struct thread *td, struct prison *pr); | ||||
static void prison_complete(void *context, int pending); | static void prison_complete(void *context, int pending); | ||||
Not Done Inline ActionsYou define this as a sysinit here and ... imp: You define this as a sysinit here and ... | |||||
static void prison_deref(struct prison *pr, int flags); | static void prison_deref(struct prison *pr, int flags); | ||||
static char *prison_path(struct prison *pr1, struct prison *pr2); | static char *prison_path(struct prison *pr1, struct prison *pr2); | ||||
static void prison_remove_one(struct prison *pr); | static void prison_remove_one(struct prison *pr); | ||||
#ifdef RACCT | #ifdef RACCT | ||||
static void prison_racct_attach(struct prison *pr); | static void prison_racct_attach(struct prison *pr); | ||||
static void prison_racct_modify(struct prison *pr); | static void prison_racct_modify(struct prison *pr); | ||||
static void prison_racct_detach(struct prison *pr); | static void prison_racct_detach(struct prison *pr); | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 108 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
void | void | ||||
prison0_init(void) | prison0_init(void) | ||||
{ | { | ||||
prison0.pr_cpuset = cpuset_ref(thread0.td_cpuset); | prison0.pr_cpuset = cpuset_ref(thread0.td_cpuset); | ||||
prison0.pr_osreldate = osreldate; | prison0.pr_osreldate = osreldate; | ||||
strlcpy(prison0.pr_osrelease, osrelease, sizeof(prison0.pr_osrelease)); | strlcpy(prison0.pr_osrelease, osrelease, sizeof(prison0.pr_osrelease)); | ||||
#ifdef PAX_ASLR | |||||
Not Done Inline ActionsRemove blank line. rwatson: Remove blank line. | |||||
pax_init_prison(&prison0); | |||||
#endif | |||||
} | } | ||||
#ifdef INET | #ifdef INET | ||||
static int | static int | ||||
qcmp_v4(const void *ip1, const void *ip2) | qcmp_v4(const void *ip1, const void *ip2) | ||||
{ | { | ||||
in_addr_t iaa, iab; | in_addr_t iaa, iab; | ||||
▲ Show 20 Lines • Show All 1,050 Lines • ▼ Show 20 Lines | #ifdef INET | ||||
bcopy(ppr->pr_ip4, pr->pr_ip4, | bcopy(ppr->pr_ip4, pr->pr_ip4, | ||||
pr->pr_ip4s * sizeof(*pr->pr_ip4)); | pr->pr_ip4s * sizeof(*pr->pr_ip4)); | ||||
} | } | ||||
} | } | ||||
#endif | #endif | ||||
#ifdef INET6 | #ifdef INET6 | ||||
if (!(ch_flags & PR_IP6_USER)) | if (!(ch_flags & PR_IP6_USER)) | ||||
pr->pr_flags |= PR_IP6 | PR_IP6_USER; | pr->pr_flags |= PR_IP6 | PR_IP6_USER; | ||||
else if (!(pr_flags & PR_IP6_USER)) { | else if (!(pr_flags & PR_IP6_USER)) { | ||||
Not Done Inline Actions... explicitly call it here. Why? imp: ... explicitly call it here. Why? | |||||
Not Done Inline ActionsThe sysinit is for jail 0. This call is for when new (child) jails are spun up. lattera-gmail.com: The sysinit is for jail 0. This call is for when new (child) jails are spun up. | |||||
Not Done Inline ActionsThis is fine. They call it for new prisons and this code does not get executed for prison0. mjg: This is fine. They call it for new prisons and this code does not get executed for prison0. | |||||
pr->pr_flags |= ppr->pr_flags & PR_IP6; | pr->pr_flags |= ppr->pr_flags & PR_IP6; | ||||
if (ppr->pr_ip6 != NULL) { | if (ppr->pr_ip6 != NULL) { | ||||
pr->pr_ip6s = ppr->pr_ip6s; | pr->pr_ip6s = ppr->pr_ip6s; | ||||
pr->pr_ip6 = malloc(pr->pr_ip6s * | pr->pr_ip6 = malloc(pr->pr_ip6s * | ||||
sizeof(struct in6_addr), M_PRISON, | sizeof(struct in6_addr), M_PRISON, | ||||
M_WAITOK); | M_WAITOK); | ||||
bcopy(ppr->pr_ip6, pr->pr_ip6, | bcopy(ppr->pr_ip6, pr->pr_ip6, | ||||
pr->pr_ip6s * sizeof(*pr->pr_ip6)); | pr->pr_ip6s * sizeof(*pr->pr_ip6)); | ||||
Show All 28 Lines | #endif | ||||
* Allocate a dedicated cpuset for each jail. | * Allocate a dedicated cpuset for each jail. | ||||
* Unlike other initial settings, this may return an erorr. | * Unlike other initial settings, this may return an erorr. | ||||
*/ | */ | ||||
error = cpuset_create_root(ppr, &pr->pr_cpuset); | error = cpuset_create_root(ppr, &pr->pr_cpuset); | ||||
if (error) { | if (error) { | ||||
prison_deref(pr, PD_LIST_XLOCKED); | prison_deref(pr, PD_LIST_XLOCKED); | ||||
goto done_releroot; | goto done_releroot; | ||||
} | } | ||||
#ifdef PAX_ASLR | |||||
pax_init_prison(pr); | |||||
#endif | |||||
Not Done Inline ActionsRemove blank line. rwatson: Remove blank line. | |||||
mtx_lock(&pr->pr_mtx); | mtx_lock(&pr->pr_mtx); | ||||
/* | /* | ||||
Not Done Inline ActionsRemove blank line. rwatson: Remove blank line. | |||||
* New prisons do not yet have a reference, because we do not | * New prisons do not yet have a reference, because we do not | ||||
* want other to see the incomplete prison once the | * want other to see the incomplete prison once the | ||||
* allprison_lock is downgraded. | * allprison_lock is downgraded. | ||||
*/ | */ | ||||
} else { | } else { | ||||
created = 0; | created = 0; | ||||
/* | /* | ||||
* Grab a reference for existing prisons, to ensure they | * Grab a reference for existing prisons, to ensure they | ||||
▲ Show 20 Lines • Show All 3,369 Lines • Show Last 20 Lines |
I find myself wondering if it's time for a new prison_init_prison0() sysinit that can take care of mutex initialisation, etc.