mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-26 16:18:31 +00:00
Implement functionality I called 'jail services'.
It may be used for external modules to attach some data to jail's in-kernel structure. - Change allprison_mtx mutex to allprison_sx sx(9) lock. We will need to call external functions while holding this lock, which may want to allocate memory. Make use of the fact that this is shared-exclusive lock and use shared version when possible. - Implement the following functions: prison_service_register() - registers a service that wants to be noticed when a jail is created and destroyed prison_service_deregister() - deregisters service prison_service_data_add() - adds service-specific data to the jail structure prison_service_data_get() - takes service-specific data from the jail structure prison_service_data_del() - removes service-specific data from the jail structure Reviewed by: rwatson
This commit is contained in:
parent
616db5f04c
commit
dc68a63332
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=168401
@ -25,6 +25,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#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/sx.h>
|
||||||
#include <sys/namei.h>
|
#include <sys/namei.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
@ -77,12 +78,28 @@ SYSCTL_INT(_security_jail, OID_AUTO, mount_allowed, CTLFLAG_RW,
|
|||||||
&jail_mount_allowed, 0,
|
&jail_mount_allowed, 0,
|
||||||
"Processes in jail can mount/unmount jail-friendly file systems");
|
"Processes in jail can mount/unmount jail-friendly file systems");
|
||||||
|
|
||||||
/* allprison, lastprid, and prisoncount are protected by allprison_mtx. */
|
/* allprison, lastprid, and prisoncount are protected by allprison_lock. */
|
||||||
struct prisonlist allprison;
|
struct prisonlist allprison;
|
||||||
struct mtx allprison_mtx;
|
struct sx allprison_lock;
|
||||||
int lastprid = 0;
|
int lastprid = 0;
|
||||||
int prisoncount = 0;
|
int prisoncount = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List of jail services. Protected by allprison_lock.
|
||||||
|
*/
|
||||||
|
TAILQ_HEAD(prison_services_head, prison_service);
|
||||||
|
static struct prison_services_head prison_services =
|
||||||
|
TAILQ_HEAD_INITIALIZER(prison_services);
|
||||||
|
static int prison_service_slots = 0;
|
||||||
|
|
||||||
|
struct prison_service {
|
||||||
|
prison_create_t ps_create;
|
||||||
|
prison_destroy_t ps_destroy;
|
||||||
|
int ps_slotno;
|
||||||
|
TAILQ_ENTRY(prison_service) ps_next;
|
||||||
|
char ps_name[0];
|
||||||
|
};
|
||||||
|
|
||||||
static void init_prison(void *);
|
static void init_prison(void *);
|
||||||
static void prison_complete(void *context, int pending);
|
static void prison_complete(void *context, int pending);
|
||||||
static int sysctl_jail_list(SYSCTL_HANDLER_ARGS);
|
static int sysctl_jail_list(SYSCTL_HANDLER_ARGS);
|
||||||
@ -91,7 +108,7 @@ static void
|
|||||||
init_prison(void *data __unused)
|
init_prison(void *data __unused)
|
||||||
{
|
{
|
||||||
|
|
||||||
mtx_init(&allprison_mtx, "allprison", NULL, MTX_DEF);
|
sx_init(&allprison_lock, "allprison");
|
||||||
LIST_INIT(&allprison);
|
LIST_INIT(&allprison);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,6 +124,7 @@ jail(struct thread *td, struct jail_args *uap)
|
|||||||
{
|
{
|
||||||
struct nameidata nd;
|
struct nameidata nd;
|
||||||
struct prison *pr, *tpr;
|
struct prison *pr, *tpr;
|
||||||
|
struct prison_service *psrv;
|
||||||
struct jail j;
|
struct jail j;
|
||||||
struct jail_attach_args jaa;
|
struct jail_attach_args jaa;
|
||||||
int vfslocked, error, tryprid;
|
int vfslocked, error, tryprid;
|
||||||
@ -139,9 +157,15 @@ jail(struct thread *td, struct jail_args *uap)
|
|||||||
pr->pr_ip = j.ip_number;
|
pr->pr_ip = j.ip_number;
|
||||||
pr->pr_linux = NULL;
|
pr->pr_linux = NULL;
|
||||||
pr->pr_securelevel = securelevel;
|
pr->pr_securelevel = securelevel;
|
||||||
|
if (prison_service_slots == 0)
|
||||||
|
pr->pr_slots = NULL;
|
||||||
|
else {
|
||||||
|
pr->pr_slots = malloc(sizeof(*pr->pr_slots) * prison_service_slots,
|
||||||
|
M_PRISON, M_ZERO | M_WAITOK);
|
||||||
|
}
|
||||||
|
|
||||||
/* Determine next pr_id and add prison to allprison list. */
|
/* Determine next pr_id and add prison to allprison list. */
|
||||||
mtx_lock(&allprison_mtx);
|
sx_xlock(&allprison_lock);
|
||||||
tryprid = lastprid + 1;
|
tryprid = lastprid + 1;
|
||||||
if (tryprid == JAIL_MAX)
|
if (tryprid == JAIL_MAX)
|
||||||
tryprid = 1;
|
tryprid = 1;
|
||||||
@ -150,7 +174,7 @@ jail(struct thread *td, struct jail_args *uap)
|
|||||||
if (tpr->pr_id == tryprid) {
|
if (tpr->pr_id == tryprid) {
|
||||||
tryprid++;
|
tryprid++;
|
||||||
if (tryprid == JAIL_MAX) {
|
if (tryprid == JAIL_MAX) {
|
||||||
mtx_unlock(&allprison_mtx);
|
sx_xunlock(&allprison_lock);
|
||||||
error = EAGAIN;
|
error = EAGAIN;
|
||||||
goto e_dropvnref;
|
goto e_dropvnref;
|
||||||
}
|
}
|
||||||
@ -160,7 +184,11 @@ jail(struct thread *td, struct jail_args *uap)
|
|||||||
pr->pr_id = jaa.jid = lastprid = tryprid;
|
pr->pr_id = jaa.jid = lastprid = tryprid;
|
||||||
LIST_INSERT_HEAD(&allprison, pr, pr_list);
|
LIST_INSERT_HEAD(&allprison, pr, pr_list);
|
||||||
prisoncount++;
|
prisoncount++;
|
||||||
mtx_unlock(&allprison_mtx);
|
sx_downgrade(&allprison_lock);
|
||||||
|
TAILQ_FOREACH(psrv, &prison_services, ps_next) {
|
||||||
|
psrv->ps_create(psrv, pr);
|
||||||
|
}
|
||||||
|
sx_sunlock(&allprison_lock);
|
||||||
|
|
||||||
error = jail_attach(td, &jaa);
|
error = jail_attach(td, &jaa);
|
||||||
if (error)
|
if (error)
|
||||||
@ -171,10 +199,14 @@ jail(struct thread *td, struct jail_args *uap)
|
|||||||
td->td_retval[0] = jaa.jid;
|
td->td_retval[0] = jaa.jid;
|
||||||
return (0);
|
return (0);
|
||||||
e_dropprref:
|
e_dropprref:
|
||||||
mtx_lock(&allprison_mtx);
|
sx_xlock(&allprison_lock);
|
||||||
LIST_REMOVE(pr, pr_list);
|
LIST_REMOVE(pr, pr_list);
|
||||||
prisoncount--;
|
prisoncount--;
|
||||||
mtx_unlock(&allprison_mtx);
|
sx_downgrade(&allprison_lock);
|
||||||
|
TAILQ_FOREACH(psrv, &prison_services, ps_next) {
|
||||||
|
psrv->ps_destroy(psrv, pr);
|
||||||
|
}
|
||||||
|
sx_sunlock(&allprison_lock);
|
||||||
e_dropvnref:
|
e_dropvnref:
|
||||||
vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount);
|
vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount);
|
||||||
vrele(pr->pr_root);
|
vrele(pr->pr_root);
|
||||||
@ -211,15 +243,15 @@ jail_attach(struct thread *td, struct jail_attach_args *uap)
|
|||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
p = td->td_proc;
|
p = td->td_proc;
|
||||||
mtx_lock(&allprison_mtx);
|
sx_slock(&allprison_lock);
|
||||||
pr = prison_find(uap->jid);
|
pr = prison_find(uap->jid);
|
||||||
if (pr == NULL) {
|
if (pr == NULL) {
|
||||||
mtx_unlock(&allprison_mtx);
|
sx_sunlock(&allprison_lock);
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
}
|
}
|
||||||
pr->pr_ref++;
|
pr->pr_ref++;
|
||||||
mtx_unlock(&pr->pr_mtx);
|
mtx_unlock(&pr->pr_mtx);
|
||||||
mtx_unlock(&allprison_mtx);
|
sx_sunlock(&allprison_lock);
|
||||||
|
|
||||||
vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount);
|
vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount);
|
||||||
vn_lock(pr->pr_root, LK_EXCLUSIVE | LK_RETRY, td);
|
vn_lock(pr->pr_root, LK_EXCLUSIVE | LK_RETRY, td);
|
||||||
@ -260,7 +292,7 @@ prison_find(int prid)
|
|||||||
{
|
{
|
||||||
struct prison *pr;
|
struct prison *pr;
|
||||||
|
|
||||||
mtx_assert(&allprison_mtx, MA_OWNED);
|
sx_assert(&allprison_lock, SX_LOCKED);
|
||||||
LIST_FOREACH(pr, &allprison, pr_list) {
|
LIST_FOREACH(pr, &allprison, pr_list) {
|
||||||
if (pr->pr_id == prid) {
|
if (pr->pr_id == prid) {
|
||||||
mtx_lock(&pr->pr_mtx);
|
mtx_lock(&pr->pr_mtx);
|
||||||
@ -273,22 +305,27 @@ prison_find(int prid)
|
|||||||
void
|
void
|
||||||
prison_free(struct prison *pr)
|
prison_free(struct prison *pr)
|
||||||
{
|
{
|
||||||
|
struct prison_service *psrv;
|
||||||
|
|
||||||
mtx_lock(&allprison_mtx);
|
sx_xlock(&allprison_lock);
|
||||||
mtx_lock(&pr->pr_mtx);
|
mtx_lock(&pr->pr_mtx);
|
||||||
pr->pr_ref--;
|
pr->pr_ref--;
|
||||||
if (pr->pr_ref == 0) {
|
if (pr->pr_ref == 0) {
|
||||||
LIST_REMOVE(pr, pr_list);
|
LIST_REMOVE(pr, pr_list);
|
||||||
mtx_unlock(&pr->pr_mtx);
|
mtx_unlock(&pr->pr_mtx);
|
||||||
prisoncount--;
|
prisoncount--;
|
||||||
mtx_unlock(&allprison_mtx);
|
sx_downgrade(&allprison_lock);
|
||||||
|
TAILQ_FOREACH(psrv, &prison_services, ps_next) {
|
||||||
|
psrv->ps_destroy(psrv, pr);
|
||||||
|
}
|
||||||
|
sx_sunlock(&allprison_lock);
|
||||||
|
|
||||||
TASK_INIT(&pr->pr_task, 0, prison_complete, pr);
|
TASK_INIT(&pr->pr_task, 0, prison_complete, pr);
|
||||||
taskqueue_enqueue(taskqueue_thread, &pr->pr_task);
|
taskqueue_enqueue(taskqueue_thread, &pr->pr_task);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mtx_unlock(&pr->pr_mtx);
|
mtx_unlock(&pr->pr_mtx);
|
||||||
mtx_unlock(&allprison_mtx);
|
sx_xunlock(&allprison_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -700,6 +737,193 @@ prison_priv_check(struct ucred *cred, int priv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register jail service. Provides 'create' and 'destroy' methods.
|
||||||
|
* 'create' method will be called for every existing jail and all
|
||||||
|
* jails in the future as they beeing created.
|
||||||
|
* 'destroy' method will be called for every jail going away and
|
||||||
|
* for all existing jails at the time of service deregistration.
|
||||||
|
*/
|
||||||
|
struct prison_service *
|
||||||
|
prison_service_register(const char *name, prison_create_t create,
|
||||||
|
prison_destroy_t destroy)
|
||||||
|
{
|
||||||
|
struct prison_service *psrv, *psrv2;
|
||||||
|
struct prison *pr;
|
||||||
|
int reallocate = 1, slotno = 0;
|
||||||
|
void **slots, **oldslots;
|
||||||
|
|
||||||
|
psrv = malloc(sizeof(*psrv) + strlen(name) + 1, M_PRISON,
|
||||||
|
M_WAITOK | M_ZERO);
|
||||||
|
psrv->ps_create = create;
|
||||||
|
psrv->ps_destroy = destroy;
|
||||||
|
strcpy(psrv->ps_name, name);
|
||||||
|
/*
|
||||||
|
* Grab the allprison_lock here, so we won't miss any jail
|
||||||
|
* creation/destruction.
|
||||||
|
*/
|
||||||
|
sx_xlock(&allprison_lock);
|
||||||
|
#ifdef INVARIANTS
|
||||||
|
/*
|
||||||
|
* Verify if service is not already registered.
|
||||||
|
*/
|
||||||
|
TAILQ_FOREACH(psrv2, &prison_services, ps_next) {
|
||||||
|
KASSERT(strcmp(psrv2->ps_name, name) != 0,
|
||||||
|
("jail service %s already registered", name));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Find free slot. When there is no existing free slot available,
|
||||||
|
* allocate one at the end.
|
||||||
|
*/
|
||||||
|
TAILQ_FOREACH(psrv2, &prison_services, ps_next) {
|
||||||
|
if (psrv2->ps_slotno != slotno) {
|
||||||
|
KASSERT(slotno < psrv2->ps_slotno,
|
||||||
|
("Invalid slotno (slotno=%d >= ps_slotno=%d",
|
||||||
|
slotno, psrv2->ps_slotno));
|
||||||
|
/* We found free slot. */
|
||||||
|
reallocate = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
slotno++;
|
||||||
|
}
|
||||||
|
psrv->ps_slotno = slotno;
|
||||||
|
/*
|
||||||
|
* Keep the list sorted by slot number.
|
||||||
|
*/
|
||||||
|
if (psrv2 != NULL) {
|
||||||
|
KASSERT(reallocate == 0, ("psrv2 != NULL && reallocate != 0"));
|
||||||
|
TAILQ_INSERT_BEFORE(psrv2, psrv, ps_next);
|
||||||
|
} else {
|
||||||
|
KASSERT(reallocate == 1, ("psrv2 == NULL && reallocate == 0"));
|
||||||
|
TAILQ_INSERT_TAIL(&prison_services, psrv, ps_next);
|
||||||
|
}
|
||||||
|
prison_service_slots++;
|
||||||
|
sx_downgrade(&allprison_lock);
|
||||||
|
/*
|
||||||
|
* Allocate memory for new slot if we didn't found empty one.
|
||||||
|
* Do not use realloc(9), because pr_slots is protected with a mutex,
|
||||||
|
* so we can't sleep.
|
||||||
|
*/
|
||||||
|
LIST_FOREACH(pr, &allprison, pr_list) {
|
||||||
|
if (reallocate) {
|
||||||
|
/* First allocate memory with M_WAITOK. */
|
||||||
|
slots = malloc(sizeof(*slots) * prison_service_slots,
|
||||||
|
M_PRISON, M_WAITOK);
|
||||||
|
/* Now grab the mutex and replace pr_slots. */
|
||||||
|
mtx_lock(&pr->pr_mtx);
|
||||||
|
oldslots = pr->pr_slots;
|
||||||
|
if (psrv->ps_slotno > 0) {
|
||||||
|
bcopy(oldslots, slots,
|
||||||
|
sizeof(*slots) * (prison_service_slots - 1));
|
||||||
|
}
|
||||||
|
slots[psrv->ps_slotno] = NULL;
|
||||||
|
pr->pr_slots = slots;
|
||||||
|
mtx_unlock(&pr->pr_mtx);
|
||||||
|
if (oldslots != NULL)
|
||||||
|
free(oldslots, M_PRISON);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Call 'create' method for each existing jail.
|
||||||
|
*/
|
||||||
|
psrv->ps_create(psrv, pr);
|
||||||
|
}
|
||||||
|
sx_sunlock(&allprison_lock);
|
||||||
|
|
||||||
|
return (psrv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
prison_service_deregister(struct prison_service *psrv)
|
||||||
|
{
|
||||||
|
struct prison *pr;
|
||||||
|
void **slots, **oldslots;
|
||||||
|
int last = 0;
|
||||||
|
|
||||||
|
sx_xlock(&allprison_lock);
|
||||||
|
if (TAILQ_LAST(&prison_services, prison_services_head) == psrv)
|
||||||
|
last = 1;
|
||||||
|
TAILQ_REMOVE(&prison_services, psrv, ps_next);
|
||||||
|
prison_service_slots--;
|
||||||
|
sx_downgrade(&allprison_lock);
|
||||||
|
LIST_FOREACH(pr, &allprison, pr_list) {
|
||||||
|
/*
|
||||||
|
* Call 'destroy' method for every currently existing jail.
|
||||||
|
*/
|
||||||
|
psrv->ps_destroy(psrv, pr);
|
||||||
|
/*
|
||||||
|
* If this is the last slot, free the memory allocated for it.
|
||||||
|
*/
|
||||||
|
if (last) {
|
||||||
|
if (prison_service_slots == 0)
|
||||||
|
slots = NULL;
|
||||||
|
else {
|
||||||
|
slots = malloc(sizeof(*slots) * prison_service_slots,
|
||||||
|
M_PRISON, M_WAITOK);
|
||||||
|
}
|
||||||
|
mtx_lock(&pr->pr_mtx);
|
||||||
|
oldslots = pr->pr_slots;
|
||||||
|
/*
|
||||||
|
* We require setting slot to NULL after freeing it,
|
||||||
|
* this way we can check for memory leaks here.
|
||||||
|
*/
|
||||||
|
KASSERT(oldslots[psrv->ps_slotno] == NULL,
|
||||||
|
("Slot %d (service %s, jailid=%d) still contains data?",
|
||||||
|
psrv->ps_slotno, psrv->ps_name, pr->pr_id));
|
||||||
|
if (psrv->ps_slotno > 0) {
|
||||||
|
bcopy(oldslots, slots,
|
||||||
|
sizeof(*slots) * prison_service_slots);
|
||||||
|
}
|
||||||
|
pr->pr_slots = slots;
|
||||||
|
mtx_unlock(&pr->pr_mtx);
|
||||||
|
KASSERT(oldslots != NULL, ("oldslots == NULL"));
|
||||||
|
free(oldslots, M_PRISON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sx_sunlock(&allprison_lock);
|
||||||
|
free(psrv, M_PRISON);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function sets data for the given jail in slot assigned for the given
|
||||||
|
* jail service.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
prison_service_data_set(struct prison_service *psrv, struct prison *pr,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
|
||||||
|
mtx_assert(&pr->pr_mtx, MA_OWNED);
|
||||||
|
pr->pr_slots[psrv->ps_slotno] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function clears slots assigned for the given jail service in the given
|
||||||
|
* prison structure and returns current slot data.
|
||||||
|
*/
|
||||||
|
void *
|
||||||
|
prison_service_data_del(struct prison_service *psrv, struct prison *pr)
|
||||||
|
{
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
mtx_assert(&pr->pr_mtx, MA_OWNED);
|
||||||
|
data = pr->pr_slots[psrv->ps_slotno];
|
||||||
|
pr->pr_slots[psrv->ps_slotno] = NULL;
|
||||||
|
return (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function returns current data from the slot assigned to the given jail
|
||||||
|
* service for the given jail.
|
||||||
|
*/
|
||||||
|
void *
|
||||||
|
prison_service_data_get(struct prison_service *psrv, struct prison *pr)
|
||||||
|
{
|
||||||
|
|
||||||
|
mtx_assert(&pr->pr_mtx, MA_OWNED);
|
||||||
|
return (pr->pr_slots[psrv->ps_slotno]);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sysctl_jail_list(SYSCTL_HANDLER_ARGS)
|
sysctl_jail_list(SYSCTL_HANDLER_ARGS)
|
||||||
{
|
{
|
||||||
@ -709,21 +933,14 @@ sysctl_jail_list(SYSCTL_HANDLER_ARGS)
|
|||||||
|
|
||||||
if (jailed(req->td->td_ucred))
|
if (jailed(req->td->td_ucred))
|
||||||
return (0);
|
return (0);
|
||||||
retry:
|
|
||||||
mtx_lock(&allprison_mtx);
|
|
||||||
count = prisoncount;
|
|
||||||
mtx_unlock(&allprison_mtx);
|
|
||||||
|
|
||||||
if (count == 0)
|
sx_slock(&allprison_lock);
|
||||||
|
if ((count = prisoncount) == 0) {
|
||||||
|
sx_sunlock(&allprison_lock);
|
||||||
return (0);
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
sxp = xp = malloc(sizeof(*xp) * count, M_TEMP, M_WAITOK | M_ZERO);
|
sxp = xp = malloc(sizeof(*xp) * count, M_TEMP, M_WAITOK | M_ZERO);
|
||||||
mtx_lock(&allprison_mtx);
|
|
||||||
if (count != prisoncount) {
|
|
||||||
mtx_unlock(&allprison_mtx);
|
|
||||||
free(sxp, M_TEMP);
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
LIST_FOREACH(pr, &allprison, pr_list) {
|
LIST_FOREACH(pr, &allprison, pr_list) {
|
||||||
mtx_lock(&pr->pr_mtx);
|
mtx_lock(&pr->pr_mtx);
|
||||||
@ -735,7 +952,7 @@ sysctl_jail_list(SYSCTL_HANDLER_ARGS)
|
|||||||
mtx_unlock(&pr->pr_mtx);
|
mtx_unlock(&pr->pr_mtx);
|
||||||
xp++;
|
xp++;
|
||||||
}
|
}
|
||||||
mtx_unlock(&allprison_mtx);
|
sx_sunlock(&allprison_lock);
|
||||||
|
|
||||||
error = SYSCTL_OUT(req, sxp, sizeof(*sxp) * count);
|
error = SYSCTL_OUT(req, sxp, sizeof(*sxp) * count);
|
||||||
free(sxp, M_TEMP);
|
free(sxp, M_TEMP);
|
||||||
|
@ -54,7 +54,7 @@ MALLOC_DECLARE(M_PRISON);
|
|||||||
* delete the struture when the last inmate is dead.
|
* delete the struture when the last inmate is dead.
|
||||||
*
|
*
|
||||||
* Lock key:
|
* Lock key:
|
||||||
* (a) allprison_mtx
|
* (a) allprison_lock
|
||||||
* (p) locked by pr_mtx
|
* (p) locked by pr_mtx
|
||||||
* (c) set only during creation before the structure is shared, no mutex
|
* (c) set only during creation before the structure is shared, no mutex
|
||||||
* required to read
|
* required to read
|
||||||
@ -73,6 +73,7 @@ struct prison {
|
|||||||
int pr_securelevel; /* (p) securelevel */
|
int pr_securelevel; /* (p) securelevel */
|
||||||
struct task pr_task; /* (d) destroy task */
|
struct task pr_task; /* (d) destroy task */
|
||||||
struct mtx pr_mtx;
|
struct mtx pr_mtx;
|
||||||
|
void **pr_slots; /* (p) additional data */
|
||||||
};
|
};
|
||||||
#endif /* _KERNEL || _WANT_PRISON */
|
#endif /* _KERNEL || _WANT_PRISON */
|
||||||
|
|
||||||
@ -91,6 +92,7 @@ extern int jail_chflags_allowed;
|
|||||||
|
|
||||||
LIST_HEAD(prisonlist, prison);
|
LIST_HEAD(prisonlist, prison);
|
||||||
extern struct prisonlist allprison;
|
extern struct prisonlist allprison;
|
||||||
|
extern struct sx allprison_lock;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kernel support functions for jail().
|
* Kernel support functions for jail().
|
||||||
@ -114,5 +116,21 @@ int prison_ip(struct ucred *cred, int flag, u_int32_t *ip);
|
|||||||
int prison_priv_check(struct ucred *cred, int priv);
|
int prison_priv_check(struct ucred *cred, int priv);
|
||||||
void prison_remote_ip(struct ucred *cred, int flags, u_int32_t *ip);
|
void prison_remote_ip(struct ucred *cred, int flags, u_int32_t *ip);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Kernel jail services.
|
||||||
|
*/
|
||||||
|
struct prison_service;
|
||||||
|
typedef int (*prison_create_t)(struct prison_service *psrv, struct prison *pr);
|
||||||
|
typedef int (*prison_destroy_t)(struct prison_service *psrv, struct prison *pr);
|
||||||
|
|
||||||
|
struct prison_service *prison_service_register(const char *name,
|
||||||
|
prison_create_t create, prison_destroy_t destroy);
|
||||||
|
void prison_service_deregister(struct prison_service *psrv);
|
||||||
|
|
||||||
|
void prison_service_data_set(struct prison_service *psrv, struct prison *pr,
|
||||||
|
void *data);
|
||||||
|
void *prison_service_data_get(struct prison_service *psrv, struct prison *pr);
|
||||||
|
void *prison_service_data_del(struct prison_service *psrv, struct prison *pr);
|
||||||
|
|
||||||
#endif /* _KERNEL */
|
#endif /* _KERNEL */
|
||||||
#endif /* !_SYS_JAIL_H_ */
|
#endif /* !_SYS_JAIL_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user