Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/kern_jail.c
Show First 20 Lines • Show All 3,754 Lines • ▼ Show 20 Lines | |||||
SYSCTL_JAIL_PARAM(_allow, reserved_ports, CTLTYPE_INT | CTLFLAG_RW, | SYSCTL_JAIL_PARAM(_allow, reserved_ports, CTLTYPE_INT | CTLFLAG_RW, | ||||
"B", "Jail may bind sockets to reserved ports"); | "B", "Jail may bind sockets to reserved ports"); | ||||
SYSCTL_JAIL_PARAM_SUBNODE(allow, mount, "Jail mount/unmount permission flags"); | SYSCTL_JAIL_PARAM_SUBNODE(allow, mount, "Jail mount/unmount permission flags"); | ||||
SYSCTL_JAIL_PARAM(_allow_mount, , CTLTYPE_INT | CTLFLAG_RW, | SYSCTL_JAIL_PARAM(_allow_mount, , CTLTYPE_INT | CTLFLAG_RW, | ||||
"B", "Jail may mount/unmount jail-friendly file systems in general"); | "B", "Jail may mount/unmount jail-friendly file systems in general"); | ||||
/* | /* | ||||
* The VFS system will register jail-aware filesystems here. They each get | * Add a dynamic parameter allow.<name>, or allow.<prefix>.<name>. Return | ||||
* a parameter allow.mount.xxxfs and a flag to check when a jailed user | * its associated bit in the pr_allow bitmask, or zero if the parameter was | ||||
* attempts to mount. | * not created. | ||||
*/ | */ | ||||
void | unsigned | ||||
prison_add_vfs(struct vfsconf *vfsp) | prison_add_allow(const char *prefix, const char *name, const char *prefix_descr, | ||||
const char *descr) | |||||
{ | { | ||||
char *allow_name, *allow_noname, *mount_allowed; | |||||
struct bool_flags *bf; | struct bool_flags *bf; | ||||
struct sysctl_oid *parent; | |||||
char *allow_name, *allow_noname, *allowed; | |||||
#ifndef NO_SYSCTL_DESCR | #ifndef NO_SYSCTL_DESCR | ||||
char *descr; | char *descr_deprecated; | ||||
#endif | #endif | ||||
unsigned allow_flag; | unsigned allow_flag; | ||||
if (asprintf(&allow_name, M_PRISON, "allow.mount.%s", vfsp->vfc_name) < | if (prefix | ||||
0 || asprintf(&allow_noname, M_PRISON, "allow.mount.no%s", | ? asprintf(&allow_name, M_PRISON, "allow.%s.%s", prefix, name) | ||||
vfsp->vfc_name) < 0) { | < 0 || | ||||
asprintf(&allow_noname, M_PRISON, "allow.%s.no%s", prefix, name) | |||||
< 0 | |||||
: asprintf(&allow_name, M_PRISON, "allow.%s", name) < 0 || | |||||
asprintf(&allow_noname, M_PRISON, "allow.no%s", name) < 0) { | |||||
free(allow_name, M_PRISON); | free(allow_name, M_PRISON); | ||||
return; | return 0; | ||||
} | } | ||||
/* | /* | ||||
* See if this parameter has already beed added, i.e. if the filesystem | * See if this parameter has already beed added, i.e. a module was | ||||
* was previously loaded/unloaded. | * previously loaded/unloaded. | ||||
*/ | */ | ||||
mtx_lock(&prison0.pr_mtx); | mtx_lock(&prison0.pr_mtx); | ||||
for (bf = pr_flag_allow; | for (bf = pr_flag_allow; | ||||
bf < pr_flag_allow + nitems(pr_flag_allow) && bf->flag != 0; | bf < pr_flag_allow + nitems(pr_flag_allow) && bf->flag != 0; | ||||
bf++) { | bf++) { | ||||
if (strcmp(bf->name, allow_name) == 0) { | if (strcmp(bf->name, allow_name) == 0) { | ||||
vfsp->vfc_prison_flag = bf->flag; | allow_flag = bf->flag; | ||||
goto no_add; | goto no_add; | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Find a free bit in prison0's pr_allow, failing if there are none | * Find a free bit in prison0's pr_allow, failing if there are none | ||||
* (which shouldn't happen as long as we keep track of how many | * (which shouldn't happen as long as we keep track of how many | ||||
* filesystems are jail-aware). | * potential dynamic flags exist). | ||||
*/ | */ | ||||
for (allow_flag = 1;; allow_flag <<= 1) { | for (allow_flag = 1;; allow_flag <<= 1) { | ||||
if (allow_flag == 0) | if (allow_flag == 0) | ||||
goto no_add; | goto no_add; | ||||
if ((prison0.pr_allow & allow_flag) == 0) | if ((prison0.pr_allow & allow_flag) == 0) | ||||
break; | break; | ||||
} | } | ||||
/* | /* | ||||
* Note the parameter in the next open slot in pr_flag_allow. | * Note the parameter in the next open slot in pr_flag_allow. | ||||
* Set the flag last so code that checks pr_flag_allow can do so | * Set the flag last so code that checks pr_flag_allow can do so | ||||
* without locking. | * without locking. | ||||
*/ | */ | ||||
for (bf = pr_flag_allow; bf->flag != 0; bf++) | for (bf = pr_flag_allow; bf->flag != 0; bf++) | ||||
if (bf == pr_flag_allow + nitems(pr_flag_allow)) { | if (bf == pr_flag_allow + nitems(pr_flag_allow)) { | ||||
/* This should never happen, but is not fatal. */ | /* This should never happen, but is not fatal. */ | ||||
allow_flag = 0; | |||||
goto no_add; | goto no_add; | ||||
} | } | ||||
prison0.pr_allow |= allow_flag; | prison0.pr_allow |= allow_flag; | ||||
bf->name = allow_name; | bf->name = allow_name; | ||||
bf->noname = allow_noname; | bf->noname = allow_noname; | ||||
bf->flag = allow_flag; | bf->flag = allow_flag; | ||||
vfsp->vfc_prison_flag = allow_flag; | |||||
mtx_unlock(&prison0.pr_mtx); | mtx_unlock(&prison0.pr_mtx); | ||||
/* | /* | ||||
* Create sysctls for the paramter, and the back-compat global | * Create sysctls for the paramter, and the back-compat global | ||||
* permission. | * permission. | ||||
*/ | */ | ||||
#ifndef NO_SYSCTL_DESCR | parent = prefix | ||||
(void)asprintf(&descr, M_TEMP, "Jail may mount the %s file system", | ? SYSCTL_ADD_NODE(NULL, | ||||
vfsp->vfc_name); | SYSCTL_CHILDREN(&sysctl___security_jail_param_allow), | ||||
#endif | OID_AUTO, prefix, 0, 0, prefix_descr) | ||||
(void)SYSCTL_ADD_PROC(NULL, | : &sysctl___security_jail_param_allow; | ||||
SYSCTL_CHILDREN(&sysctl___security_jail_param_allow_mount), | (void)SYSCTL_ADD_PROC(NULL, SYSCTL_CHILDREN(parent), OID_AUTO, | ||||
OID_AUTO, vfsp->vfc_name, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, | name, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, | ||||
NULL, 0, sysctl_jail_param, "B", descr); | NULL, 0, sysctl_jail_param, "B", descr); | ||||
if ((prefix | |||||
? asprintf(&allowed, M_TEMP, "%s_%s_allowed", prefix, name) | |||||
: asprintf(&allowed, M_TEMP, "%s_allowed", name)) >= 0) { | |||||
#ifndef NO_SYSCTL_DESCR | #ifndef NO_SYSCTL_DESCR | ||||
free(descr, M_TEMP); | (void)asprintf(&descr_deprecated, M_TEMP, "%s (deprecated)", | ||||
descr); | |||||
#endif | #endif | ||||
if (asprintf(&mount_allowed, M_TEMP, "mount_%s_allowed", | |||||
vfsp->vfc_name) >= 0) { | |||||
#ifndef NO_SYSCTL_DESCR | |||||
(void)asprintf(&descr, M_TEMP, | |||||
"Processes in jail can mount the %s file system (deprecated)", | |||||
vfsp->vfc_name); | |||||
#endif | |||||
(void)SYSCTL_ADD_PROC(NULL, | (void)SYSCTL_ADD_PROC(NULL, | ||||
SYSCTL_CHILDREN(&sysctl___security_jail), OID_AUTO, | SYSCTL_CHILDREN(&sysctl___security_jail), OID_AUTO, allowed, | ||||
mount_allowed, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, allow_flag, | ||||
NULL, allow_flag, sysctl_jail_default_allow, "I", descr); | sysctl_jail_default_allow, "I", descr_deprecated); | ||||
#ifndef NO_SYSCTL_DESCR | #ifndef NO_SYSCTL_DESCR | ||||
free(descr, M_TEMP); | free(descr_deprecated, M_TEMP); | ||||
#endif | #endif | ||||
free(mount_allowed, M_TEMP); | free(allowed, M_TEMP); | ||||
} | } | ||||
return; | return allow_flag; | ||||
no_add: | no_add: | ||||
mtx_unlock(&prison0.pr_mtx); | mtx_unlock(&prison0.pr_mtx); | ||||
free(allow_name, M_PRISON); | free(allow_name, M_PRISON); | ||||
free(allow_noname, M_PRISON); | free(allow_noname, M_PRISON); | ||||
return allow_flag; | |||||
} | |||||
/* | |||||
* The VFS system will register jail-aware filesystems here. They each get | |||||
* a parameter allow.mount.xxxfs and a flag to check when a jailed user | |||||
* attempts to mount. | |||||
*/ | |||||
void | |||||
prison_add_vfs(struct vfsconf *vfsp) | |||||
{ | |||||
#ifdef NO_SYSCTL_DESCR | |||||
vfsp->vfc_prison_flag = prison_add_allow("mount", vfsp->vfc_name, | |||||
NULL, NULL); | |||||
#else | |||||
char *descr; | |||||
(void)asprintf(&descr, M_TEMP, "Jail may mount the %s file system", | |||||
vfsp->vfc_name); | |||||
vfsp->vfc_prison_flag = prison_add_allow("mount", vfsp->vfc_name, | |||||
NULL, descr); | |||||
free(descr, M_TEMP); | |||||
#endif | |||||
} | } | ||||
#ifdef RACCT | #ifdef RACCT | ||||
void | void | ||||
prison_racct_foreach(void (*callback)(struct racct *racct, | prison_racct_foreach(void (*callback)(struct racct *racct, | ||||
void *arg2, void *arg3), void (*pre)(void), void (*post)(void), | void *arg2, void *arg3), void (*pre)(void), void (*post)(void), | ||||
void *arg2, void *arg3) | void *arg2, void *arg3) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 296 Lines • Show Last 20 Lines |