Changeset View
Standalone View
kern/kern_jail.c
Context not available. | |||||
.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, | ||||
.pr_allow_mount = 0, | |||||
}; | }; | ||||
MTX_SYSINIT(prison0, &prison0.pr_mtx, "jail mutex", MTX_DEF); | MTX_SYSINIT(prison0, &prison0.pr_mtx, "jail mutex", MTX_DEF); | ||||
jhb: Any reason to not let the compiler autocompute the size still? 'NBBY * NBPW' doesn't seem to… | |||||
Not Done Inline ActionsThe array needs to reflect the full 32 permission bits which could be dynamically set. If I don't go the dynamic pr_allow route this wouldn't be necessary, but see my comment on that. jamie: The array needs to reflect the full 32 permission bits which could be dynamically set. If I… | |||||
Context not available. | |||||
"allow.mount", | "allow.mount", | ||||
"allow.quotas", | "allow.quotas", | ||||
"allow.socket_af", | "allow.socket_af", | ||||
"allow.mount.devfs", | [15] = "allow.reserved_ports", | ||||
"allow.mount.nullfs", | |||||
"allow.mount.zfs", | |||||
"allow.mount.procfs", | |||||
"allow.mount.tmpfs", | |||||
"allow.mount.fdescfs", | |||||
"allow.mount.linprocfs", | |||||
"allow.mount.linsysfs", | |||||
"allow.reserved_ports", | |||||
}; | }; | ||||
const size_t pr_allow_names_size = sizeof(pr_allow_names); | const size_t pr_allow_names_size = sizeof(pr_allow_names); | ||||
Context not available. | |||||
"allow.nomount", | "allow.nomount", | ||||
"allow.noquotas", | "allow.noquotas", | ||||
"allow.nosocket_af", | "allow.nosocket_af", | ||||
Not Done Inline ActionsThis is weird. I must admit. kib: This is weird. I must admit. | |||||
Not Done Inline ActionsYes, there's this gap now before PR_ALLOW_RESERVED_PORTS that requires this. Since I had to bump __FreeBSD_version anyway, I might as well close that gap (change the to defines past the mount points). I'm not really happy with the way these arrays are presented anyway. I may fix them up in a separate commit. jamie: Yes, there's this gap now before PR_ALLOW_RESERVED_PORTS that requires this. Since I had to… | |||||
"allow.mount.nodevfs", | [15] = "allow.noreserved_ports", | ||||
"allow.mount.nonullfs", | |||||
"allow.mount.nozfs", | |||||
"allow.mount.noprocfs", | |||||
"allow.mount.notmpfs", | |||||
"allow.mount.nofdescfs", | |||||
"allow.mount.nolinprocfs", | |||||
"allow.mount.nolinsysfs", | |||||
"allow.noreserved_ports", | |||||
}; | }; | ||||
const size_t pr_allow_nonames_size = sizeof(pr_allow_nonames); | const size_t pr_allow_nonames_size = sizeof(pr_allow_nonames); | ||||
static char *pr_allow_mount_names[NBBY * NBPW]; | |||||
static char *pr_allow_mount_nonames[NBBY * NBPW]; | |||||
static const struct vfsconf *pr_allow_mount_vfc[NBBY * NBPW]; | |||||
#define JAIL_DEFAULT_ALLOW (PR_ALLOW_SET_HOSTNAME | PR_ALLOW_RESERVED_PORTS) | #define JAIL_DEFAULT_ALLOW (PR_ALLOW_SET_HOSTNAME | PR_ALLOW_RESERVED_PORTS) | ||||
#define JAIL_DEFAULT_ENFORCE_STATFS 2 | #define JAIL_DEFAULT_ENFORCE_STATFS 2 | ||||
#define JAIL_DEFAULT_DEVFS_RSNUM 0 | #define JAIL_DEFAULT_DEVFS_RSNUM 0 | ||||
static unsigned jail_default_allow = JAIL_DEFAULT_ALLOW; | static unsigned jail_default_allow = JAIL_DEFAULT_ALLOW; | ||||
static unsigned jail_default_allow_mount = 0; | |||||
static int jail_default_enforce_statfs = JAIL_DEFAULT_ENFORCE_STATFS; | static int jail_default_enforce_statfs = JAIL_DEFAULT_ENFORCE_STATFS; | ||||
static int jail_default_devfs_rsnum = JAIL_DEFAULT_DEVFS_RSNUM; | static int jail_default_devfs_rsnum = JAIL_DEFAULT_DEVFS_RSNUM; | ||||
#if defined(INET) || defined(INET6) | #if defined(INET) || defined(INET6) | ||||
Context not available. | |||||
int | int | ||||
kern_jail(struct thread *td, struct jail *j) | kern_jail(struct thread *td, struct jail *j) | ||||
{ | { | ||||
struct iovec optiov[2 * (4 + nitems(pr_allow_names) | struct iovec optiov[2 * (4 + nitems(pr_allow_names) + | ||||
nitems(pr_allow_mount_names) | |||||
#ifdef INET | #ifdef INET | ||||
+ 1 | + 1 | ||||
#endif | #endif | ||||
Context not available. | |||||
/* Set permissions for top-level jails from sysctls. */ | /* Set permissions for top-level jails from sysctls. */ | ||||
if (!jailed(td->td_ucred)) { | if (!jailed(td->td_ucred)) { | ||||
for (fi = 0; fi < nitems(pr_allow_names); fi++) { | for (fi = 0; fi < nitems(pr_allow_names); fi++) { | ||||
if (pr_allow_names[fi] == NULL) | |||||
continue; | |||||
optiov[opt.uio_iovcnt].iov_base = | optiov[opt.uio_iovcnt].iov_base = | ||||
(jail_default_allow & (1 << fi)) | (jail_default_allow & (1 << fi)) | ||||
? pr_allow_names[fi] : pr_allow_nonames[fi]; | ? pr_allow_names[fi] : pr_allow_nonames[fi]; | ||||
Context not available. | |||||
strlen(optiov[opt.uio_iovcnt].iov_base) + 1; | strlen(optiov[opt.uio_iovcnt].iov_base) + 1; | ||||
opt.uio_iovcnt += 2; | opt.uio_iovcnt += 2; | ||||
} | } | ||||
for (fi = 0; fi < nitems(pr_allow_mount_names); fi++) { | |||||
if (pr_allow_mount_names[fi] == NULL) | |||||
continue; | |||||
optiov[opt.uio_iovcnt].iov_base = | |||||
(jail_default_allow_mount & (1 << fi)) | |||||
? pr_allow_mount_names[fi] | |||||
: pr_allow_mount_nonames[fi]; | |||||
optiov[opt.uio_iovcnt].iov_len = | |||||
strlen(optiov[opt.uio_iovcnt].iov_base) + 1; | |||||
opt.uio_iovcnt += 2; | |||||
} | |||||
optiov[opt.uio_iovcnt].iov_base = "enforce_statfs"; | optiov[opt.uio_iovcnt].iov_base = "enforce_statfs"; | ||||
optiov[opt.uio_iovcnt].iov_len = sizeof("enforce_statfs"); | optiov[opt.uio_iovcnt].iov_len = sizeof("enforce_statfs"); | ||||
opt.uio_iovcnt++; | opt.uio_iovcnt++; | ||||
Context not available. | |||||
#ifdef INET6 | #ifdef INET6 | ||||
int ip6s, redo_ip6; | int ip6s, redo_ip6; | ||||
#endif | #endif | ||||
uint64_t pr_allow, ch_allow, pr_flags, ch_flags; | uint64_t pr_allow, ch_allow, pr_allow_mount, ch_allow_mount; | ||||
uint64_t pr_flags, ch_flags; | |||||
unsigned tallow; | unsigned tallow; | ||||
char numbuf[12]; | char numbuf[12]; | ||||
Context not available. | |||||
pr_allow = ch_allow = 0; | pr_allow = ch_allow = 0; | ||||
for (fi = 0; fi < nitems(pr_allow_names); fi++) { | for (fi = 0; fi < nitems(pr_allow_names); fi++) { | ||||
if (pr_allow_names[fi] == NULL) | |||||
continue; | |||||
vfs_flagopt(opts, pr_allow_names[fi], &pr_allow, 1 << fi); | vfs_flagopt(opts, pr_allow_names[fi], &pr_allow, 1 << fi); | ||||
vfs_flagopt(opts, pr_allow_nonames[fi], &ch_allow, 1 << fi); | vfs_flagopt(opts, pr_allow_nonames[fi], &ch_allow, 1 << fi); | ||||
} | } | ||||
ch_allow |= pr_allow; | ch_allow |= pr_allow; | ||||
pr_allow_mount = ch_allow_mount = 0; | |||||
for (fi = 0; fi < nitems(pr_allow_mount_names); fi++) { | |||||
if (pr_allow_mount_names[fi] == NULL) | |||||
continue; | |||||
vfs_flagopt(opts, pr_allow_mount_names[fi], &pr_allow_mount, | |||||
1 << fi); | |||||
vfs_flagopt(opts, pr_allow_mount_nonames[fi], &ch_allow_mount, | |||||
1 << fi); | |||||
} | |||||
ch_allow_mount |= pr_allow_mount; | |||||
error = vfs_getopt(opts, "name", (void **)&name, &len); | error = vfs_getopt(opts, "name", (void **)&name, &len); | ||||
if (error == ENOENT) | if (error == ENOENT) | ||||
Context not available. | |||||
} | } | ||||
} | } | ||||
} | } | ||||
if (pr_allow & ~ppr->pr_allow) { | if ((pr_allow & ~ppr->pr_allow) || | ||||
(pr_allow_mount & ~ppr->pr_allow_mount)) { | |||||
error = EPERM; | error = EPERM; | ||||
goto done_deref_locked; | goto done_deref_locked; | ||||
} | } | ||||
Context not available. | |||||
tpr->pr_allow &= ~tallow; | tpr->pr_allow &= ~tallow; | ||||
} | } | ||||
pr->pr_allow = (pr->pr_allow & ~ch_allow) | pr_allow; | pr->pr_allow = (pr->pr_allow & ~ch_allow) | pr_allow; | ||||
if ((tallow = ch_allow_mount & ~pr_allow_mount)) { | |||||
FOREACH_PRISON_DESCENDANT_LOCKED(pr, tpr, descend) | |||||
tpr->pr_allow_mount &= ~tallow; | |||||
} | |||||
pr->pr_allow_mount = | |||||
(pr->pr_allow_mount & ~ch_allow_mount) | pr_allow_mount; | |||||
/* | /* | ||||
* Persistent prisons get an extra reference, and prisons losing their | * Persistent prisons get an extra reference, and prisons losing their | ||||
* persist flag lose that reference. Only do this for existing prisons | * persist flag lose that reference. Only do this for existing prisons | ||||
Context not available. | |||||
if (error != 0 && error != ENOENT) | if (error != 0 && error != ENOENT) | ||||
goto done_deref; | goto done_deref; | ||||
} | } | ||||
for (fi = 0; fi < nitems(pr_allow_mount_names); fi++) { | |||||
if (pr_allow_mount_names[fi] == NULL) | |||||
continue; | |||||
i = (pr->pr_allow_mount & (1 << fi)) ? 1 : 0; | |||||
error = | |||||
vfs_setopt(opts, pr_allow_mount_names[fi], &i, sizeof(i)); | |||||
if (error != 0 && error != ENOENT) | |||||
goto done_deref; | |||||
i = !i; | |||||
error = | |||||
vfs_setopt(opts, pr_allow_mount_nonames[fi], &i, sizeof(i)); | |||||
if (error != 0 && error != ENOENT) | |||||
goto done_deref; | |||||
} | |||||
i = (pr->pr_uref == 0); | i = (pr->pr_uref == 0); | ||||
error = vfs_setopt(opts, "dying", &i, sizeof(i)); | error = vfs_setopt(opts, "dying", &i, sizeof(i)); | ||||
if (error != 0 && error != ENOENT) | if (error != 0 && error != ENOENT) | ||||
Context not available. | |||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, | ||||
NULL, PR_ALLOW_MOUNT, sysctl_jail_default_allow, "I", | NULL, PR_ALLOW_MOUNT, sysctl_jail_default_allow, "I", | ||||
"Processes in jail can mount/unmount jail-friendly file systems (deprecated)"); | "Processes in jail can mount/unmount jail-friendly file systems (deprecated)"); | ||||
SYSCTL_PROC(_security_jail, OID_AUTO, mount_devfs_allowed, | |||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, | |||||
NULL, PR_ALLOW_MOUNT_DEVFS, sysctl_jail_default_allow, "I", | |||||
"Processes in jail can mount the devfs file system (deprecated)"); | |||||
SYSCTL_PROC(_security_jail, OID_AUTO, mount_fdescfs_allowed, | |||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, | |||||
NULL, PR_ALLOW_MOUNT_FDESCFS, sysctl_jail_default_allow, "I", | |||||
"Processes in jail can mount the fdescfs file system (deprecated)"); | |||||
SYSCTL_PROC(_security_jail, OID_AUTO, mount_nullfs_allowed, | |||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, | |||||
NULL, PR_ALLOW_MOUNT_NULLFS, sysctl_jail_default_allow, "I", | |||||
"Processes in jail can mount the nullfs file system (deprecated)"); | |||||
SYSCTL_PROC(_security_jail, OID_AUTO, mount_procfs_allowed, | |||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, | |||||
NULL, PR_ALLOW_MOUNT_PROCFS, sysctl_jail_default_allow, "I", | |||||
"Processes in jail can mount the procfs file system (deprecated)"); | |||||
SYSCTL_PROC(_security_jail, OID_AUTO, mount_linprocfs_allowed, | |||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, | |||||
NULL, PR_ALLOW_MOUNT_LINPROCFS, sysctl_jail_default_allow, "I", | |||||
"Processes in jail can mount the linprocfs file system (deprecated)"); | |||||
SYSCTL_PROC(_security_jail, OID_AUTO, mount_linsysfs_allowed, | |||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, | |||||
NULL, PR_ALLOW_MOUNT_LINSYSFS, sysctl_jail_default_allow, "I", | |||||
"Processes in jail can mount the linsysfs file system (deprecated)"); | |||||
SYSCTL_PROC(_security_jail, OID_AUTO, mount_tmpfs_allowed, | |||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, | |||||
NULL, PR_ALLOW_MOUNT_TMPFS, sysctl_jail_default_allow, "I", | |||||
"Processes in jail can mount the tmpfs file system (deprecated)"); | |||||
SYSCTL_PROC(_security_jail, OID_AUTO, mount_zfs_allowed, | |||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, | |||||
NULL, PR_ALLOW_MOUNT_ZFS, sysctl_jail_default_allow, "I", | |||||
"Processes in jail can mount the zfs file system (deprecated)"); | |||||
static int | static int | ||||
sysctl_jail_default_allow_mount(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
struct prison *pr; | |||||
int allow, error, i; | |||||
pr = req->td->td_ucred->cr_prison; | |||||
allow = (pr == &prison0) | |||||
? jail_default_allow_mount : pr->pr_allow_mount; | |||||
/* Get the current flag value, and convert it to a boolean. */ | |||||
i = (allow & arg2) ? 1 : 0; | |||||
error = sysctl_handle_int(oidp, &i, 0, req); | |||||
if (error || !req->newptr) | |||||
return (error); | |||||
i = i ? arg2 : 0; | |||||
/* | |||||
* The sysctls don't have CTLFLAGS_PRISON, so assume prison0 | |||||
* for writing. | |||||
*/ | |||||
mtx_lock(&prison0.pr_mtx); | |||||
jail_default_allow_mount = (jail_default_allow_mount & ~arg2) | i; | |||||
mtx_unlock(&prison0.pr_mtx); | |||||
return (0); | |||||
} | |||||
static int | |||||
sysctl_jail_default_level(SYSCTL_HANDLER_ARGS) | sysctl_jail_default_level(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct prison *pr; | struct prison *pr; | ||||
Not Done Inline Actions/* should be on the separate line. Also, there should be a blank line before multi-line comment. kib: /* should be on the separate line. Also, there should be a blank line before multi-line… | |||||
Not Done Inline ActionsOops - I let my own coding style slip in when I wasn't paying attention. I'll fix that. jamie: Oops - I let my own coding style slip in when I wasn't paying attention. I'll fix that. | |||||
Not Done Inline ActionsIf NO_SYSCTL_DESCR is defined, the descr variable is not. Then you should get the compilation error. kib: If NO_SYSCTL_DESCR is defined, the descr variable is not. Then you should get the compilation… | |||||
Not Done Inline ActionsThe SYSCTL_ADD_PROC macro disregards descr when NO_SYSCTL_DESCR is defined, so it actually compiles without a problem. jamie: The SYSCTL_ADD_PROC macro disregards descr when NO_SYSCTL_DESCR is defined, so it actually… | |||||
Context not available. | |||||
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"); | ||||
SYSCTL_JAIL_PARAM(_allow_mount, devfs, CTLTYPE_INT | CTLFLAG_RW, | |||||
"B", "Jail may mount the devfs file system"); | |||||
SYSCTL_JAIL_PARAM(_allow_mount, fdescfs, CTLTYPE_INT | CTLFLAG_RW, | |||||
"B", "Jail may mount the fdescfs file system"); | |||||
SYSCTL_JAIL_PARAM(_allow_mount, nullfs, CTLTYPE_INT | CTLFLAG_RW, | |||||
"B", "Jail may mount the nullfs file system"); | |||||
SYSCTL_JAIL_PARAM(_allow_mount, procfs, CTLTYPE_INT | CTLFLAG_RW, | |||||
"B", "Jail may mount the procfs file system"); | |||||
SYSCTL_JAIL_PARAM(_allow_mount, linprocfs, CTLTYPE_INT | CTLFLAG_RW, | |||||
"B", "Jail may mount the linprocfs file system"); | |||||
SYSCTL_JAIL_PARAM(_allow_mount, linsysfs, CTLTYPE_INT | CTLFLAG_RW, | |||||
"B", "Jail may mount the linsysfs file system"); | |||||
SYSCTL_JAIL_PARAM(_allow_mount, tmpfs, CTLTYPE_INT | CTLFLAG_RW, | |||||
"B", "Jail may mount the tmpfs file system"); | |||||
SYSCTL_JAIL_PARAM(_allow_mount, zfs, CTLTYPE_INT | CTLFLAG_RW, | |||||
"B", "Jail may mount the zfs file system"); | |||||
/* | |||||
* The VFS system will register jail-aware filesystems here. They each get | |||||
* a parameter allow.mount.xxxfs that is checked when a jailed user attempts | |||||
* to mount. | |||||
*/ | |||||
void | |||||
prison_add_vfs_param(const struct vfsconf *vfsp) | |||||
{ | |||||
char *allow_name, *allow_noname; | |||||
int fi; | |||||
unsigned flag; | |||||
char allowstr[MFSNAMELEN + 32], global_allowstr[MFSNAMELEN + 58]; | |||||
snprintf(allowstr, sizeof(allowstr), "allow.mount.%s", vfsp->vfc_name); | |||||
allow_name = strdup(allowstr, M_PRISON); | |||||
kibUnsubmitted Not Done Inline ActionsWhy not use asprintf(9) instead of manually reimplement it and calculating the string lengths ? kib: Why not use asprintf(9) instead of manually reimplement it and calculating the string lengths ? | |||||
jamieAuthorUnsubmitted Not Done Inline ActionsFor whatever reason, asprintf uses M_NOWAIT, while strdup uses M_WAITOK. Not that running out of memory for such a small allocation is at all likely, but I would want to handle failure (probably just return, same as no available bit). asprintf may also be the better choice than having these hand-sized allowstr and global_allowstr arrays. jamie: For whatever reason, asprintf uses M_NOWAIT, while strdup uses M_WAITOK. Not that running out… | |||||
snprintf(allowstr, sizeof(allowstr), "allow.mount.no%s", | |||||
vfsp->vfc_name); | |||||
allow_noname = strdup(allowstr, M_PRISON); | |||||
/* | |||||
* See if this parameter has already beed added, i.e. if the filesystem | |||||
* was previously loaded/unloaded. | |||||
*/ | |||||
mtx_lock(&prison0.pr_mtx); | |||||
for (fi = 0; fi < nitems(pr_allow_mount_names); fi++) { | |||||
if (pr_allow_mount_names[fi] != NULL && | |||||
strcmp(pr_allow_mount_names[fi], allow_name) == 0) { | |||||
pr_allow_mount_vfc[fi] = vfsp; | |||||
goto no_add; | |||||
} | |||||
} | |||||
/* | |||||
* Find a free bit in prison0's pr_allow_mount, failing if there are | |||||
* none (which shouldn't happen as long as we keep track of how many | |||||
* filesystems are jail-aware). | |||||
*/ | |||||
for (fi = 0, flag = 1;; fi++, flag <<= 1) { | |||||
if (flag == 0) | |||||
goto no_add; | |||||
if ((prison0.pr_allow_mount & flag) == 0) | |||||
break; | |||||
} | |||||
prison0.pr_allow_mount |= flag; | |||||
pr_allow_mount_nonames[fi] = allow_noname; | |||||
pr_allow_mount_names[fi] = allow_name; | |||||
pr_allow_mount_vfc[fi] = vfsp; | |||||
mtx_unlock(&prison0.pr_mtx); | |||||
/* | |||||
* Create sysctls for the paramter, and the back-compat global | |||||
* permission. | |||||
*/ | |||||
snprintf(allowstr, sizeof(allowstr), | |||||
"Jail may mount the %s file system", vfsp->vfc_name); | |||||
kibUnsubmitted Not Done Inline ActionsThis verbosity should be avoided if NO_SYSCTL_DESCR kernel option is configured. kib: This verbosity should be avoided if NO_SYSCTL_DESCR kernel option is configured. | |||||
jamieAuthorUnsubmitted Not Done Inline ActionsIndeed - I didn't know about that option. I'll put something in. jamie: Indeed - I didn't know about that option. I'll put something in. | |||||
(void)SYSCTL_ADD_PROC(NULL, | |||||
SYSCTL_CHILDREN(&sysctl___security_jail_param_allow_mount), | |||||
OID_AUTO, vfsp->vfc_name, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, | |||||
NULL, 0, sysctl_jail_param, "B", allowstr); | |||||
snprintf(allowstr, sizeof(allowstr), "mount_%s_allowed", | |||||
vfsp->vfc_name); | |||||
snprintf(global_allowstr, sizeof(global_allowstr), | |||||
kibUnsubmitted Not Done Inline ActionsThis one too. kib: This one too. | |||||
"Processes in jail can mount the %s file system (deprecated)", | |||||
vfsp->vfc_name); | |||||
(void)SYSCTL_ADD_PROC(NULL, SYSCTL_CHILDREN(&sysctl___security_jail), | |||||
OID_AUTO, allowstr, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, | |||||
flag, sysctl_jail_default_allow_mount, "I", global_allowstr); | |||||
return; | |||||
no_add: | |||||
mtx_unlock(&prison0.pr_mtx); | |||||
free(allow_name, M_PRISON); | |||||
free(allow_noname, M_PRISON); | |||||
} | |||||
/* | |||||
* See if a process has permission to mount a jail-aware filesystem. | |||||
*/ | |||||
int | |||||
prison_check_vfs(struct ucred *cred, const struct vfsconf *vfsp) | |||||
kibUnsubmitted Not Done Inline ActionsI would just store the bit number or bit mask for the pr_allow_mount in a member of struct vfsconf, allocated on the fs module load (you already do this). Then this function becomes trivial. kib: I would just store the bit number or bit mask for the pr_allow_mount in a member of struct… | |||||
jamieAuthorUnsubmitted Not Done Inline ActionsYeah, jhb preferred it that way too. I could do that (and bump __FreeBSD_version), and the current version becomes the kind of thing that would go into an MFC. jamie: Yeah, jhb preferred it that way too. I could do that (and bump __FreeBSD_version), and the… | |||||
{ | |||||
int fi; | |||||
unsigned flag; | |||||
/* Find the flag bit corresponding to this filesystem. */ | |||||
flag = 0; | |||||
for (fi = 0; fi < nitems(pr_allow_mount_vfc); fi++) { | |||||
if (pr_allow_mount_vfc[fi] == vfsp) { | |||||
flag = 1 << fi; | |||||
break; | |||||
} | |||||
} | |||||
if (cred->cr_prison->pr_allow_mount & flag) | |||||
return (0); | |||||
return (EPERM); | |||||
} | |||||
#ifdef RACCT | #ifdef RACCT | ||||
void | void | ||||
prison_racct_foreach(void (*callback)(struct racct *racct, | prison_racct_foreach(void (*callback)(struct racct *racct, | ||||
Context not available. |
Any reason to not let the compiler autocompute the size still? 'NBBY * NBPW' doesn't seem to make sense for setting the number of pointers in the array either.