1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-15 10:17:20 +00:00

o In struct prison, add an allprison linked list of prisons (protected

by allprison_mtx), a unique prison/jail identifier field, two path
  fields (pr_path for reporting and pr_root vnode instance) to store
  the chroot() point of each jail.
o Add jail_attach(2) to allow a process to bind to an existing jail.
o Add change_root() to perform the chroot operation on a specified
  vnode.
o Generalize change_dir() to accept a vnode, and move namei() calls
  to callers of change_dir().
o Add a new sysctl (security.jail.list) which is a group of
  struct xprison instances that represent a snapshot of active jails.

Reviewed by:	rwatson, tjr
This commit is contained in:
Mike Barcroft 2003-04-09 02:55:18 +00:00
parent db5f2ca8df
commit fd7a8150fb
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=113275
11 changed files with 412 additions and 120 deletions

View File

@ -115,6 +115,7 @@ MLINKS+=getsockopt.2 setsockopt.2
MLINKS+=gettimeofday.2 settimeofday.2
MLINKS+=getuid.2 geteuid.2
MLINKS+=intro.2 errno.2
MLINKS+=jail.2 jail_attach.2
MLINKS+=kqueue.2 kevent.2
MLINKS+=kse.2 kse_create.2 kse.2 kse_exit.2 kse.2 kse_release.2 \
kse.2 kse_wakeup.2 kse.2 kse_thr_interrupt.2

View File

@ -8,7 +8,7 @@
.\"
.\"$FreeBSD$
.\"
.Dd April 28, 1999
.Dd April 8, 2003
.Dt JAIL 2
.Os
.Sh NAME
@ -17,10 +17,12 @@
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In sys/types.h
.In sys/param.h
.In sys/jail.h
.Ft int
.Fn jail "struct jail *jail"
.Ft int
.Fn jail_attach "int jid"
.Sh DESCRIPTION
The
.Fn jail
@ -52,9 +54,29 @@ from the inside of the prison.
The
.Dq Li ip_number
can be set to the IP number assigned to the prison.
.Pp
The
.Fn jail_attach
system call attaches the current process to an existing jail,
identified by
.Va jid .
.Sh RETURN VALUES
If successful,
.Fn jail
returns a non-negative integer, termed the jail identifier (JID).
It returns -1 on failure, and sets
.Va errno
to indicate the error.
.Pp
If successful,
.Fn jail_attach
returns 0.
It returns -1 on failure, and sets
.Va errno
to indicate the error.
.Sh PRISON?
Once a process has been put in a prison, it and its decendants cannot escape
the prison. It is not possible to add a process to a preexisting prison.
the prison.
.Pp
Inside the prison, the concept of "superuser" is very diluted. In general,
it can be assumed that nothing can be mangled from inside a prison which
@ -100,6 +122,10 @@ The
.Fn jail
system call appeared in
.Fx 4.0 .
The
.Fn jail_attach
system call appeared in
.Fx 5.1 .
.Sh AUTHORS
The jail feature was written by
.An Poul-Henning Kamp

View File

@ -607,4 +607,5 @@
433 STD BSD { int thr_kill(thr_id_t id, int sig); }
434 MSTD BSD { int _umtx_lock(struct umtx *umtx); }
435 MSTD BSD { int _umtx_unlock(struct umtx *umtx); }
436 MSTD BSD { int jail_attach(int jid); }

View File

@ -607,4 +607,5 @@
433 STD BSD { int thr_kill(thr_id_t id, int sig); }
434 MSTD BSD { int _umtx_lock(struct umtx *umtx); }
435 MSTD BSD { int _umtx_unlock(struct umtx *umtx); }
436 MSTD BSD { int jail_attach(int jid); }

View File

@ -607,4 +607,5 @@
433 STD BSD { int thr_kill(thr_id_t id, int sig); }
434 MSTD BSD { int _umtx_lock(struct umtx *umtx); }
435 MSTD BSD { int _umtx_unlock(struct umtx *umtx); }
436 MSTD BSD { int jail_attach(int jid); }

View File

@ -21,8 +21,12 @@
#include <sys/jail.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/namei.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <sys/vnode.h>
#include <net/if.h>
#include <netinet/in.h>
@ -49,6 +53,26 @@ SYSCTL_INT(_security_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
&jail_sysvipc_allowed, 0,
"Processes in jail can use System V IPC primitives");
/* allprison, lastprid, and prisoncount are protected by allprison_mtx. */
struct prisonlist allprison;
struct mtx allprison_mtx;
int lastprid = 0;
int prisoncount = 0;
static void init_prison(void *);
static struct prison *prison_find(int);
static int sysctl_jail_list(SYSCTL_HANDLER_ARGS);
static void
init_prison(void *data __unused)
{
mtx_init(&allprison_mtx, "allprison", NULL, MTX_DEF);
LIST_INIT(&allprison);
}
SYSINIT(prison, SI_SUB_INTRINSIC, SI_ORDER_ANY, init_prison, NULL);
/*
* MPSAFE
*/
@ -59,12 +83,11 @@ jail(td, uap)
struct jail *jail;
} */ *uap;
{
struct proc *p = td->td_proc;
int error;
struct prison *pr;
struct nameidata nd;
struct prison *pr, *tpr;
struct jail j;
struct chroot_args ca;
struct ucred *newcred = NULL, *oldcred;
struct jail_attach_args jaa;
int error, tryprid;
error = copyin(uap->jail, &j, sizeof j);
if (error)
@ -74,48 +97,176 @@ jail(td, uap)
MALLOC(pr, struct prison *, sizeof *pr , M_PRISON, M_WAITOK | M_ZERO);
mtx_init(&pr->pr_mtx, "jail mutex", NULL, MTX_DEF);
pr->pr_securelevel = securelevel;
pr->pr_ref = 1;
error = copyinstr(j.path, &pr->pr_path, sizeof pr->pr_path, 0);
if (error)
goto e_killmtx;
mtx_lock(&Giant);
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, pr->pr_path, td);
error = namei(&nd);
if (error) {
mtx_unlock(&Giant);
goto e_killmtx;
}
pr->pr_root = nd.ni_vp;
VOP_UNLOCK(nd.ni_vp, 0, td);
NDFREE(&nd, NDF_ONLY_PNBUF);
mtx_unlock(&Giant);
error = copyinstr(j.hostname, &pr->pr_host, sizeof pr->pr_host, 0);
if (error)
goto bail;
ca.path = j.path;
mtx_lock(&Giant);
error = chroot(td, &ca);
mtx_unlock(&Giant);
if (error)
goto bail;
newcred = crget();
goto e_dropvnref;
pr->pr_ip = j.ip_number;
PROC_LOCK(p);
/* Implicitly fail if already in jail. */
error = suser_cred(p->p_ucred, 0);
pr->pr_linux = NULL;
pr->pr_securelevel = securelevel;
/* Determine next pr_id and add prison to allprison list. */
mtx_lock(&allprison_mtx);
tryprid = lastprid + 1;
if (tryprid == JAIL_MAX)
tryprid = 1;
next:
LIST_FOREACH(tpr, &allprison, pr_list) {
if (tpr->pr_id == tryprid) {
tryprid++;
if (tryprid == JAIL_MAX) {
mtx_unlock(&allprison_mtx);
error = EAGAIN;
goto e_dropvnref;
}
goto next;
}
}
pr->pr_id = jaa.jid = lastprid = tryprid;
LIST_INSERT_HEAD(&allprison, pr, pr_list);
prisoncount++;
mtx_unlock(&allprison_mtx);
error = jail_attach(td, &jaa);
if (error)
goto badcred;
oldcred = p->p_ucred;
crcopy(newcred, oldcred);
p->p_ucred = newcred;
p->p_ucred->cr_prison = pr;
pr->pr_ref = 1;
PROC_UNLOCK(p);
crfree(oldcred);
goto e_dropprref;
mtx_lock(&pr->pr_mtx);
pr->pr_ref--;
mtx_unlock(&pr->pr_mtx);
td->td_retval[0] = jaa.jid;
return (0);
badcred:
PROC_UNLOCK(p);
crfree(newcred);
bail:
e_dropprref:
mtx_lock(&allprison_mtx);
LIST_REMOVE(pr, pr_list);
prisoncount--;
mtx_unlock(&allprison_mtx);
e_dropvnref:
mtx_lock(&Giant);
vrele(pr->pr_root);
mtx_unlock(&Giant);
e_killmtx:
mtx_destroy(&pr->pr_mtx);
FREE(pr, M_PRISON);
return (error);
}
/*
* MPSAFE
*/
int
jail_attach(td, uap)
struct thread *td;
struct jail_attach_args /* {
int jid;
} */ *uap;
{
struct proc *p;
struct ucred *newcred, *oldcred;
struct prison *pr;
int error;
p = td->td_proc;
mtx_lock(&allprison_mtx);
pr = prison_find(uap->jid);
if (pr == NULL) {
mtx_unlock(&allprison_mtx);
return (EINVAL);
}
pr->pr_ref++;
mtx_unlock(&pr->pr_mtx);
mtx_unlock(&allprison_mtx);
error = suser_cred(td->td_ucred, PRISON_ROOT);
if (error)
goto e_dropref;
mtx_lock(&Giant);
vn_lock(pr->pr_root, LK_EXCLUSIVE | LK_RETRY, td);
if ((error = change_dir(pr->pr_root, td)) != 0)
goto e_unlock;
#ifdef MAC
if ((error = mac_check_vnode_chroot(td->td_ucred, pr->pr_root)))
goto e_unlock;
#endif
VOP_UNLOCK(pr->pr_root, 0, td);
change_root(pr->pr_root, td);
mtx_unlock(&Giant);
newcred = crget();
PROC_LOCK(p);
/* Implicitly fail if already in jail. */
error = suser_cred(p->p_ucred, 0);
if (error) {
PROC_UNLOCK(p);
crfree(newcred);
goto e_dropref;
}
oldcred = p->p_ucred;
setsugid(p);
crcopy(newcred, oldcred);
p->p_ucred = newcred;
mtx_lock(&pr->pr_mtx);
p->p_ucred->cr_prison = pr;
mtx_unlock(&pr->pr_mtx);
PROC_UNLOCK(p);
crfree(oldcred);
return (0);
e_unlock:
VOP_UNLOCK(pr->pr_root, 0, td);
mtx_unlock(&Giant);
e_dropref:
mtx_lock(&pr->pr_mtx);
pr->pr_ref--;
mtx_unlock(&pr->pr_mtx);
return (error);
}
/*
* Returns a locked prison instance, or NULL on failure.
*/
static struct prison *
prison_find(int prid)
{
struct prison *pr;
mtx_assert(&allprison_mtx, MA_OWNED);
LIST_FOREACH(pr, &allprison, pr_list) {
if (pr->pr_id == prid) {
mtx_lock(&pr->pr_mtx);
return (pr);
}
}
return (NULL);
}
void
prison_free(struct prison *pr)
{
mtx_assert(&Giant, MA_OWNED);
mtx_lock(&allprison_mtx);
mtx_lock(&pr->pr_mtx);
pr->pr_ref--;
if (pr->pr_ref == 0) {
LIST_REMOVE(pr, pr_list);
mtx_unlock(&pr->pr_mtx);
prisoncount--;
mtx_unlock(&allprison_mtx);
vrele(pr->pr_root);
mtx_destroy(&pr->pr_mtx);
if (pr->pr_linux != NULL)
FREE(pr->pr_linux, M_PRISON);
@ -123,6 +274,7 @@ prison_free(struct prison *pr)
return;
}
mtx_unlock(&pr->pr_mtx);
mtx_unlock(&allprison_mtx);
}
void
@ -256,3 +408,49 @@ getcredhostname(cred, buf, size)
else
strlcpy(buf, hostname, size);
}
static int
sysctl_jail_list(SYSCTL_HANDLER_ARGS)
{
struct xprison *xp, *sxp;
struct prison *pr;
int count, error;
mtx_assert(&Giant, MA_OWNED);
retry:
mtx_lock(&allprison_mtx);
count = prisoncount;
mtx_unlock(&allprison_mtx);
if (count == 0)
return (0);
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) {
mtx_lock(&pr->pr_mtx);
xp->pr_version = XPRISON_VERSION;
xp->pr_id = pr->pr_id;
strlcpy(xp->pr_path, pr->pr_path, sizeof(xp->pr_path));
strlcpy(xp->pr_host, pr->pr_host, sizeof(xp->pr_host));
xp->pr_ip = pr->pr_ip;
mtx_unlock(&pr->pr_mtx);
xp++;
}
mtx_unlock(&allprison_mtx);
error = SYSCTL_OUT(req, sxp, sizeof(*sxp) * count);
free(sxp, M_TEMP);
if (error)
return (error);
return (0);
}
SYSCTL_OID(_security_jail, OID_AUTO, list, CTLTYPE_STRUCT | CTLFLAG_RD,
NULL, 0, sysctl_jail_list, "S", "List of active jails");

View File

@ -266,6 +266,7 @@ static struct witness_order_list_entry order_lists[] = {
{ "session", &lock_class_mtx_sleep },
{ "uidinfo hash", &lock_class_mtx_sleep },
{ "uidinfo struct", &lock_class_mtx_sleep },
{ "allprison", &lock_class_mtx_sleep },
{ NULL, NULL },
/*
* spin locks

View File

@ -630,6 +630,7 @@
433 MSTD BSD { int thr_kill(thr_id_t id, int sig); }
434 MSTD BSD { int _umtx_lock(struct umtx *umtx); }
435 MSTD BSD { int _umtx_unlock(struct umtx *umtx); }
436 MSTD BSD { int jail_attach(int jid); }
; Please copy any additions and changes to the following compatability tables:
; sys/ia64/ia32/syscalls.master (take a best guess)

View File

@ -78,7 +78,6 @@
#include <vm/vm_page.h>
#include <vm/uma.h>
static int change_dir(struct nameidata *ndp, struct thread *td);
static int chroot_refuse_vdir_fds(struct filedesc *fdp);
static int getutimes(const struct timeval *, enum uio_seg, struct timespec *);
static int setfown(struct thread *td, struct vnode *, uid_t, gid_t);
@ -463,8 +462,13 @@ kern_chdir(struct thread *td, char *path, enum uio_seg pathseg)
struct vnode *vp;
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, pathseg, path, td);
if ((error = change_dir(&nd, td)) != 0)
if ((error = namei(&nd)) != 0)
return (error);
if ((error = change_dir(nd.ni_vp, td)) != 0) {
vput(nd.ni_vp);
NDFREE(&nd, NDF_ONLY_PNBUF);
return (error);
}
VOP_UNLOCK(nd.ni_vp, 0, td);
NDFREE(&nd, NDF_ONLY_PNBUF);
FILEDESC_LOCK(fdp);
@ -530,45 +534,31 @@ chroot(td, uap)
char *path;
} */ *uap;
{
register struct filedesc *fdp = td->td_proc->p_fd;
int error;
struct nameidata nd;
struct vnode *vp;
error = suser_cred(td->td_ucred, PRISON_ROOT);
if (error)
return (error);
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, td);
mtx_lock(&Giant);
if ((error = change_dir(&nd, td)) != 0)
error = namei(&nd);
if (error)
goto error;
if ((error = change_dir(nd.ni_vp, td)) != 0)
goto e_vunlock;
#ifdef MAC
if ((error = mac_check_vnode_chroot(td->td_ucred, nd.ni_vp))) {
vput(nd.ni_vp);
goto error;
}
if ((error = mac_check_vnode_chroot(td->td_ucred, nd.ni_vp)))
goto e_vunlock;
#endif
VOP_UNLOCK(nd.ni_vp, 0, td);
FILEDESC_LOCK(fdp);
if (chroot_allow_open_directories == 0 ||
(chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
error = chroot_refuse_vdir_fds(fdp);
if (error)
goto error_unlock;
}
vp = fdp->fd_rdir;
fdp->fd_rdir = nd.ni_vp;
if (!fdp->fd_jdir) {
fdp->fd_jdir = nd.ni_vp;
VREF(fdp->fd_jdir);
}
FILEDESC_UNLOCK(fdp);
error = change_root(nd.ni_vp, td);
vrele(nd.ni_vp);
NDFREE(&nd, NDF_ONLY_PNBUF);
vrele(vp);
mtx_unlock(&Giant);
return (0);
error_unlock:
FILEDESC_UNLOCK(fdp);
return (error);
e_vunlock:
vput(nd.ni_vp);
error:
mtx_unlock(&Giant);
NDFREE(&nd, NDF_ONLY_PNBUF);
@ -576,32 +566,63 @@ chroot(td, uap)
}
/*
* Common routine for chroot and chdir. On success, the directory vnode
* is returned locked, and must be unlocked by the caller.
* Common routine for chroot and chdir. Callers must provide a locked vnode
* instance.
*/
static int
change_dir(ndp, td)
register struct nameidata *ndp;
int
change_dir(vp, td)
struct vnode *vp;
struct thread *td;
{
struct vnode *vp;
int error;
error = namei(ndp);
if (error)
return (error);
vp = ndp->ni_vp;
ASSERT_VOP_LOCKED(vp, "change_dir(): vp not locked");
if (vp->v_type != VDIR)
error = ENOTDIR;
return (ENOTDIR);
#ifdef MAC
if (error == 0)
error = mac_check_vnode_chdir(td->td_ucred, vp);
#endif
if (error == 0)
error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
if (error)
vput(vp);
return (error);
#endif
error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
return (error);
}
/*
* Common routine for kern_chroot() and jail_attach(). The caller is
* responsible for invoking suser() and mac_check_chroot() to authorize this
* operation.
*/
int
change_root(vp, td)
struct vnode *vp;
struct thread *td;
{
struct filedesc *fdp;
struct vnode *oldvp;
int error;
mtx_assert(&Giant, MA_OWNED);
fdp = td->td_proc->p_fd;
FILEDESC_LOCK(fdp);
if (chroot_allow_open_directories == 0 ||
(chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
error = chroot_refuse_vdir_fds(fdp);
if (error) {
FILEDESC_UNLOCK(fdp);
return (error);
}
}
oldvp = fdp->fd_rdir;
fdp->fd_rdir = vp;
VREF(fdp->fd_rdir);
if (!fdp->fd_jdir) {
fdp->fd_jdir = vp;
VREF(fdp->fd_jdir);
}
FILEDESC_UNLOCK(fdp);
vrele(oldvp);
return (0);
}
/*

View File

@ -78,7 +78,6 @@
#include <vm/vm_page.h>
#include <vm/uma.h>
static int change_dir(struct nameidata *ndp, struct thread *td);
static int chroot_refuse_vdir_fds(struct filedesc *fdp);
static int getutimes(const struct timeval *, enum uio_seg, struct timespec *);
static int setfown(struct thread *td, struct vnode *, uid_t, gid_t);
@ -463,8 +462,13 @@ kern_chdir(struct thread *td, char *path, enum uio_seg pathseg)
struct vnode *vp;
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, pathseg, path, td);
if ((error = change_dir(&nd, td)) != 0)
if ((error = namei(&nd)) != 0)
return (error);
if ((error = change_dir(nd.ni_vp, td)) != 0) {
vput(nd.ni_vp);
NDFREE(&nd, NDF_ONLY_PNBUF);
return (error);
}
VOP_UNLOCK(nd.ni_vp, 0, td);
NDFREE(&nd, NDF_ONLY_PNBUF);
FILEDESC_LOCK(fdp);
@ -530,45 +534,31 @@ chroot(td, uap)
char *path;
} */ *uap;
{
register struct filedesc *fdp = td->td_proc->p_fd;
int error;
struct nameidata nd;
struct vnode *vp;
error = suser_cred(td->td_ucred, PRISON_ROOT);
if (error)
return (error);
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->path, td);
mtx_lock(&Giant);
if ((error = change_dir(&nd, td)) != 0)
error = namei(&nd);
if (error)
goto error;
if ((error = change_dir(nd.ni_vp, td)) != 0)
goto e_vunlock;
#ifdef MAC
if ((error = mac_check_vnode_chroot(td->td_ucred, nd.ni_vp))) {
vput(nd.ni_vp);
goto error;
}
if ((error = mac_check_vnode_chroot(td->td_ucred, nd.ni_vp)))
goto e_vunlock;
#endif
VOP_UNLOCK(nd.ni_vp, 0, td);
FILEDESC_LOCK(fdp);
if (chroot_allow_open_directories == 0 ||
(chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
error = chroot_refuse_vdir_fds(fdp);
if (error)
goto error_unlock;
}
vp = fdp->fd_rdir;
fdp->fd_rdir = nd.ni_vp;
if (!fdp->fd_jdir) {
fdp->fd_jdir = nd.ni_vp;
VREF(fdp->fd_jdir);
}
FILEDESC_UNLOCK(fdp);
error = change_root(nd.ni_vp, td);
vrele(nd.ni_vp);
NDFREE(&nd, NDF_ONLY_PNBUF);
vrele(vp);
mtx_unlock(&Giant);
return (0);
error_unlock:
FILEDESC_UNLOCK(fdp);
return (error);
e_vunlock:
vput(nd.ni_vp);
error:
mtx_unlock(&Giant);
NDFREE(&nd, NDF_ONLY_PNBUF);
@ -576,32 +566,63 @@ chroot(td, uap)
}
/*
* Common routine for chroot and chdir. On success, the directory vnode
* is returned locked, and must be unlocked by the caller.
* Common routine for chroot and chdir. Callers must provide a locked vnode
* instance.
*/
static int
change_dir(ndp, td)
register struct nameidata *ndp;
int
change_dir(vp, td)
struct vnode *vp;
struct thread *td;
{
struct vnode *vp;
int error;
error = namei(ndp);
if (error)
return (error);
vp = ndp->ni_vp;
ASSERT_VOP_LOCKED(vp, "change_dir(): vp not locked");
if (vp->v_type != VDIR)
error = ENOTDIR;
return (ENOTDIR);
#ifdef MAC
if (error == 0)
error = mac_check_vnode_chdir(td->td_ucred, vp);
#endif
if (error == 0)
error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
if (error)
vput(vp);
return (error);
#endif
error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
return (error);
}
/*
* Common routine for kern_chroot() and jail_attach(). The caller is
* responsible for invoking suser() and mac_check_chroot() to authorize this
* operation.
*/
int
change_root(vp, td)
struct vnode *vp;
struct thread *td;
{
struct filedesc *fdp;
struct vnode *oldvp;
int error;
mtx_assert(&Giant, MA_OWNED);
fdp = td->td_proc->p_fd;
FILEDESC_LOCK(fdp);
if (chroot_allow_open_directories == 0 ||
(chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
error = chroot_refuse_vdir_fds(fdp);
if (error) {
FILEDESC_UNLOCK(fdp);
return (error);
}
}
oldvp = fdp->fd_rdir;
fdp->fd_rdir = vp;
VREF(fdp->fd_rdir);
if (!fdp->fd_jdir) {
fdp->fd_jdir = vp;
VREF(fdp->fd_jdir);
}
FILEDESC_UNLOCK(fdp);
vrele(oldvp);
return (0);
}
/*

View File

@ -20,9 +20,19 @@ struct jail {
u_int32_t ip_number;
};
struct xprison {
int pr_version;
int pr_id;
char pr_path[MAXPATHLEN];
char pr_host[MAXHOSTNAMELEN];
u_int32_t pr_ip;
};
#define XPRISON_VERSION 1
#ifndef _KERNEL
int jail(struct jail *);
int jail_attach(int);
#else /* _KERNEL */
@ -30,6 +40,8 @@ int jail(struct jail *);
#include <sys/_lock.h>
#include <sys/_mutex.h>
#define JAIL_MAX 999999
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_PRISON);
#endif
@ -40,13 +52,18 @@ MALLOC_DECLARE(M_PRISON);
* delete the struture when the last inmate is dead.
*
* Lock key:
* (a) allprison_mutex
* (p) locked by pr_mutex
* (c) set only during creation before the structure is shared, no mutex
* required to read
*/
struct mtx;
struct prison {
LIST_ENTRY(prison) pr_list; /* (a) all prisons */
int pr_id; /* (c) prison id */
int pr_ref; /* (p) refcount */
char pr_path[MAXPATHLEN]; /* (c) chroot path */
struct vnode *pr_root; /* (c) vnode to rdir */
char pr_host[MAXHOSTNAMELEN]; /* (p) jail hostname */
u_int32_t pr_ip; /* (c) ip addr host */
void *pr_linux; /* (p) linux abi */
@ -63,6 +80,9 @@ extern int jail_set_hostname_allowed;
extern int jail_socket_unixiproute_only;
extern int jail_sysvipc_allowed;
LIST_HEAD(prisonlist, prison);
extern struct prisonlist allprison;
/*
* Kernel support functions for jail().
*/