Introduce the extensible jail framework, using the same "name=value"
interface as nmount(2). Three new system calls are added: * jail_set, to create jails and change the parameters of existing jails. This replaces jail(2). * jail_get, to read the parameters of existing jails. This replaces the security.jail.list sysctl. * jail_remove to kill off a jail's processes and remove the jail. Most jail parameters may now be changed after creation, and jails may be set to exist without any attached processes. The current jail(2) system call still exists, though it is now a stub to jail_set(2). Approved by: bz (mentor)
This commit is contained in:
parent
32a71137f0
commit
453b86f943
lib/libc/sys
sys
cddl/compat/opensolaris/kern
compat/freebsd32
kern
sys
@ -137,7 +137,10 @@ 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+=jail.2 jail_attach.2 \
|
||||
jail.2 jail_get.2 \
|
||||
jail.2 jail_remove.2 \
|
||||
jail.2 jail_set.2
|
||||
MLINKS+=kldunload.2 kldunloadf.2
|
||||
MLINKS+=kqueue.2 kevent.2
|
||||
MLINKS+=link.2 linkat.2
|
||||
|
@ -344,6 +344,9 @@ FBSD_1.1 {
|
||||
fexecve;
|
||||
fstatat;
|
||||
futimesat;
|
||||
jail_get;
|
||||
jail_set;
|
||||
jail_remove;
|
||||
linkat;
|
||||
mkdirat;
|
||||
mkfifoat;
|
||||
|
@ -1,4 +1,5 @@
|
||||
.\" Copyright (c) 1999 Poul-Henning Kamp.
|
||||
.\" Copyright (c) 2009 James Gritton.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
@ -24,12 +25,16 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd January 6, 2009
|
||||
.Dd April 29, 2009
|
||||
.Dt JAIL 2
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm jail , jail_attach
|
||||
.Nd imprison current process and future descendants
|
||||
.Nm jail ,
|
||||
.Nm jail_get ,
|
||||
.Nm jail_set ,
|
||||
.Nm jail_remove ,
|
||||
.Nm jail_attach
|
||||
.Nd create and manage system jails
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
@ -39,6 +44,13 @@
|
||||
.Fn jail "struct jail *jail"
|
||||
.Ft int
|
||||
.Fn jail_attach "int jid"
|
||||
.Ft int
|
||||
.Fn jail_remove "int jid"
|
||||
.In sys/uio.h
|
||||
.Ft int
|
||||
.Fn jail_get "struct iovec *iov" "u_int niov" "int flags"
|
||||
.Ft int
|
||||
.Fn jail_set "struct iovec *iov" "u_int niov" "int flags"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn jail
|
||||
@ -94,20 +106,147 @@ pointers can be set to an arrays of IPv4 and IPv6 addresses to be assigned to
|
||||
the prison, or NULL if none.
|
||||
IPv4 addresses must be in network byte order.
|
||||
.Pp
|
||||
This is equivalent to the
|
||||
.Fn jail_set
|
||||
system call (see below), with the parameters
|
||||
.Va path ,
|
||||
.Va host.hostname ,
|
||||
.Va name ,
|
||||
.Va ip4.addr ,
|
||||
and
|
||||
.Va ip6.addr ,
|
||||
and with the
|
||||
.Dv JAIL_ATTACH
|
||||
flag.
|
||||
.Pp
|
||||
The
|
||||
.Fn jail_set
|
||||
system call creates a new jail, or modifies an existing one, and optionally
|
||||
locks the current process in it.
|
||||
Jail parameters are passed as an array of name-value pairs in the array
|
||||
.Fa iov ,
|
||||
containing
|
||||
.Fa niov
|
||||
elements.
|
||||
Parameter names are a null-terminated string, and values may be strings,
|
||||
integers, or other arbitrary data.
|
||||
Some parameters are boolean, and do not have a value (their length is zero)
|
||||
but are set by the name alone with or without a
|
||||
.Dq no
|
||||
prefix, e.g.
|
||||
.Va persist
|
||||
or
|
||||
.Va nopersist .
|
||||
Any parameters not set will be given default values, generally based on
|
||||
the current environment.
|
||||
.Pp
|
||||
Jails have a set of core parameters, and modules can add their own jail
|
||||
parameters.
|
||||
The current set of available parameters, and their formats, can be
|
||||
retrieved via the
|
||||
.Va security.jail.param
|
||||
sysctl MIB entry.
|
||||
Notable parameters include those mentioned in the
|
||||
.Fn jail
|
||||
description above, as well as
|
||||
.Va jid
|
||||
and
|
||||
.Va name ,
|
||||
which identify the jail being created or modified.
|
||||
See
|
||||
.Xr jail 8
|
||||
for more information on the core jail parameters.
|
||||
.Pp
|
||||
The
|
||||
.Fa flags
|
||||
arguments consists of one or more of the following flags:
|
||||
.Bl -tag -width indent
|
||||
.It Dv JAIL_CREATE
|
||||
Create a new jail.
|
||||
If a
|
||||
.Va jid
|
||||
or
|
||||
.Va name
|
||||
parameters exists, they must not refer to an existing jail.
|
||||
.It Dv JAIL_UPDATE
|
||||
Modify an existing jail.
|
||||
One of the
|
||||
.Va jid
|
||||
or
|
||||
.Va name
|
||||
parameters must exist, and must refer to an existing jail.
|
||||
If both
|
||||
.Dv JAIL_CREATE
|
||||
and
|
||||
.Dv JAIL_UPDATE
|
||||
are set, a jail will be created if it does not yet exist, and modified if it
|
||||
does exist.
|
||||
.It Dv JAIL_ATTACH
|
||||
In addition to creating or modifying the jail, attach the current process to
|
||||
it, as with the
|
||||
.Fn jail_attach
|
||||
system call.
|
||||
.It Dv JAIL_DYING
|
||||
Allow setting a jail that is in the process of being removed.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn jail_get
|
||||
system call retrieves jail parameters, using the same name-value list as
|
||||
.Fn jail_set
|
||||
in the
|
||||
.Fa iov
|
||||
and
|
||||
.Fa niov
|
||||
arguments.
|
||||
The jail to read can be specified by either
|
||||
.Va jid
|
||||
or
|
||||
.Va name
|
||||
by including those parameters in the list.
|
||||
If they are included but are not intended to be the search key, they
|
||||
should be cleared (zero and the empty string respectively).
|
||||
.Pp
|
||||
The special parameter
|
||||
.Va lastjid
|
||||
can be used to retrieve a list of all jails.
|
||||
It will fetch the jail with the jid above and closest to the passed value.
|
||||
The first jail (usually but not always jid 1) can be found by passing a
|
||||
.Va lastjid
|
||||
of zero.
|
||||
.Pp
|
||||
The
|
||||
.Fa flags
|
||||
arguments consists of one or more following flags:
|
||||
.Bl -tag -width indent
|
||||
.It Dv JAIL_DYING
|
||||
Allow getting a jail that is in the process of being removed.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn jail_attach
|
||||
system call attaches the current process to an existing jail,
|
||||
identified by
|
||||
.Fa jid .
|
||||
.Pp
|
||||
The
|
||||
.Fn jail_remove
|
||||
system call removes the jail identified by
|
||||
.Fa jid .
|
||||
It will kill all processes belonging to the jail, and remove any children
|
||||
of that jail.
|
||||
.Sh RETURN VALUES
|
||||
If successful,
|
||||
.Fn jail
|
||||
returns a non-negative integer, termed the jail identifier (JID).
|
||||
It returns \-1 on failure, and sets
|
||||
.Fn jail ,
|
||||
.Fn jail_set ,
|
||||
and
|
||||
.Fn jail_get
|
||||
return a non-negative integer, termed the jail identifier (JID).
|
||||
They return \-1 on failure, and set
|
||||
.Va errno
|
||||
to indicate the error.
|
||||
.Pp
|
||||
.Rv -std jail_attach
|
||||
.Rv -std jail_attach jail_remove
|
||||
.Sh PRISON?
|
||||
Once a process has been put in a prison, it and its descendants cannot escape
|
||||
the prison.
|
||||
@ -152,15 +291,111 @@ The
|
||||
system call
|
||||
will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EPERM
|
||||
This process is not allowed to create a jail.
|
||||
.It Bq Er EFAULT
|
||||
.Fa jail
|
||||
points to an address outside the allocated address space of the process.
|
||||
.It Bq Er EINVAL
|
||||
The version number of the argument is not correct.
|
||||
.It Bq Er EAGAIN
|
||||
No free JID could be found.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn jail_set
|
||||
system call
|
||||
will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EPERM
|
||||
This process is not allowed to create a jail.
|
||||
.It Bq Er EPERM
|
||||
A jail parameter was set to a less restrictive value then the current
|
||||
environment.
|
||||
.It Bq Er EFAULT
|
||||
.Fa Iov ,
|
||||
or one of the addresses contained within it,
|
||||
points to an address outside the allocated address space of the process.
|
||||
.It Bq Er ENOENT
|
||||
The jail referred to by a
|
||||
.Va jid
|
||||
or
|
||||
.Va name
|
||||
parameter does not exist, and the
|
||||
.Dv JAIL_CREATE
|
||||
flag is not set.
|
||||
.It Bq Er EEXIST
|
||||
The jail referred to by a
|
||||
.Va jid
|
||||
or
|
||||
.Va name
|
||||
parameter exists, and the
|
||||
.Dv JAIL_UPDATE
|
||||
flag is not set.
|
||||
.It Bq Er EINVAL
|
||||
A supplied parameter is the wrong size.
|
||||
.It Bq Er EINVAL
|
||||
A supplied parameter is out of range.
|
||||
.It Bq Er EINVAL
|
||||
A supplied string parameter is not null-terminated.
|
||||
.It Bq Er EINVAL
|
||||
A supplied parameter name does not match any known parameters.
|
||||
.It Bq Er EINVAL
|
||||
One of the
|
||||
.Dv JAIL_CREATE
|
||||
or
|
||||
.Dv JAIL_UPDATE
|
||||
flags is not set.
|
||||
.It Bq Er ENAMETOOLONG
|
||||
A supplied string parameter is longer than allowed.
|
||||
.It Bq Er EAGAIN
|
||||
There are no jail IDs left.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn jail_get
|
||||
system call
|
||||
will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EFAULT
|
||||
.Fa Iov ,
|
||||
or one of the addresses contained within it,
|
||||
points to an address outside the allocated address space of the process.
|
||||
.It Bq Er ENOENT
|
||||
The jail referred to by a
|
||||
.Va jid
|
||||
or
|
||||
.Va name
|
||||
parameter does not exist.
|
||||
.It Bq Er ENOENT
|
||||
The
|
||||
.Va lastjid
|
||||
parameter is greater than the highest current jail ID.
|
||||
.It Bq Er EINVAL
|
||||
A supplied parameter is the wrong size.
|
||||
.It Bq Er EINVAL
|
||||
A supplied parameter name does not match any known parameters.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn jail_attach
|
||||
and
|
||||
.Fn jail_remove
|
||||
system calls
|
||||
will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EINVAL
|
||||
The jail specified by
|
||||
.Fa jid
|
||||
does not exist.
|
||||
.El
|
||||
.Pp
|
||||
Further
|
||||
.Fn jail
|
||||
calls
|
||||
.Fn jail ,
|
||||
.Fn jail_set ,
|
||||
and
|
||||
.Fn jail_attach
|
||||
call
|
||||
.Xr chroot 2
|
||||
internally, so it can fail for all the same reasons.
|
||||
Please consult the
|
||||
@ -168,7 +403,8 @@ Please consult the
|
||||
manual page for details.
|
||||
.Sh SEE ALSO
|
||||
.Xr chdir 2 ,
|
||||
.Xr chroot 2
|
||||
.Xr chroot 2 ,
|
||||
.Xr jail 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Fn jail
|
||||
@ -178,6 +414,13 @@ The
|
||||
.Fn jail_attach
|
||||
system call appeared in
|
||||
.Fx 5.1 .
|
||||
The
|
||||
.Fn jail_set ,
|
||||
.Fn jail_get ,
|
||||
and
|
||||
.Fn jail_remove
|
||||
system calls appeared in
|
||||
.Fx 8.0 .
|
||||
.Sh AUTHORS
|
||||
The jail feature was written by
|
||||
.An Poul-Henning Kamp
|
||||
@ -185,3 +428,5 @@ for R&D Associates
|
||||
.Dq Li http://www.rndassociates.com/
|
||||
who contributed it to
|
||||
.Fx .
|
||||
.An James Gritton
|
||||
added the extensible jail parameters.
|
||||
|
@ -233,7 +233,7 @@ static void
|
||||
zone_sysinit(void *arg __unused)
|
||||
{
|
||||
|
||||
zone_slot = osd_jail_register(zone_destroy);
|
||||
zone_slot = osd_jail_register(zone_destroy, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -28,6 +28,8 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_compat.h"
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
@ -76,6 +78,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/sem.h>
|
||||
#include <sys/shm.h>
|
||||
|
||||
#ifdef INET
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_param.h>
|
||||
@ -106,6 +112,8 @@ CTASSERT(sizeof(struct msghdr32) == 28);
|
||||
CTASSERT(sizeof(struct stat32) == 96);
|
||||
CTASSERT(sizeof(struct sigaction32) == 24);
|
||||
|
||||
extern int jail_max_af_ips;
|
||||
|
||||
static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
|
||||
static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
|
||||
|
||||
@ -2036,9 +2044,17 @@ freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
|
||||
int
|
||||
freebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap)
|
||||
{
|
||||
struct iovec optiov[10];
|
||||
struct uio opt;
|
||||
char *u_path, *u_hostname, *u_name;
|
||||
#ifdef INET
|
||||
struct in_addr *u_ip4;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
struct in6_addr *u_ip6;
|
||||
#endif
|
||||
uint32_t version;
|
||||
int error;
|
||||
struct jail j;
|
||||
|
||||
error = copyin(uap->jail, &version, sizeof(uint32_t));
|
||||
if (error)
|
||||
@ -2050,14 +2066,45 @@ freebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap)
|
||||
/* FreeBSD single IPv4 jails. */
|
||||
struct jail32_v0 j32_v0;
|
||||
|
||||
bzero(&j, sizeof(struct jail));
|
||||
error = copyin(uap->jail, &j32_v0, sizeof(struct jail32_v0));
|
||||
if (error)
|
||||
return (error);
|
||||
CP(j32_v0, j, version);
|
||||
PTRIN_CP(j32_v0, j, path);
|
||||
PTRIN_CP(j32_v0, j, hostname);
|
||||
j.ip4s = j32_v0.ip_number;
|
||||
u_path = malloc(MAXPATHLEN + MAXHOSTNAMELEN, M_TEMP, M_WAITOK);
|
||||
u_hostname = u_path + MAXPATHLEN;
|
||||
opt.uio_iov = optiov;
|
||||
opt.uio_iovcnt = 4;
|
||||
opt.uio_offset = -1;
|
||||
opt.uio_resid = -1;
|
||||
opt.uio_segflg = UIO_SYSSPACE;
|
||||
opt.uio_rw = UIO_READ;
|
||||
opt.uio_td = td;
|
||||
optiov[0].iov_base = "path";
|
||||
optiov[0].iov_len = sizeof("path");
|
||||
optiov[1].iov_base = u_path;
|
||||
error = copyinstr(PTRIN(j32_v0.path), u_path, MAXPATHLEN,
|
||||
&optiov[1].iov_len);
|
||||
if (error) {
|
||||
free(u_path, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
optiov[2].iov_base = "host.hostname";
|
||||
optiov[2].iov_len = sizeof("host.hostname");
|
||||
optiov[3].iov_base = u_hostname;
|
||||
error = copyinstr(PTRIN(j32_v0.hostname), u_hostname,
|
||||
MAXHOSTNAMELEN, &optiov[3].iov_len);
|
||||
if (error) {
|
||||
free(u_path, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
#ifdef INET
|
||||
optiov[opt.uio_iovcnt].iov_base = "ip4.addr";
|
||||
optiov[opt.uio_iovcnt].iov_len = sizeof("ip4.addr");
|
||||
opt.uio_iovcnt++;
|
||||
optiov[opt.uio_iovcnt].iov_base = &j32_v0.ip_number;
|
||||
j32_v0.ip_number = htonl(j32_v0.ip_number);
|
||||
optiov[opt.uio_iovcnt].iov_len = sizeof(j32_v0.ip_number);
|
||||
opt.uio_iovcnt++;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2072,18 +2119,109 @@ freebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap)
|
||||
{
|
||||
/* FreeBSD multi-IPv4/IPv6,noIP jails. */
|
||||
struct jail32 j32;
|
||||
size_t tmplen;
|
||||
|
||||
error = copyin(uap->jail, &j32, sizeof(struct jail32));
|
||||
if (error)
|
||||
return (error);
|
||||
CP(j32, j, version);
|
||||
PTRIN_CP(j32, j, path);
|
||||
PTRIN_CP(j32, j, hostname);
|
||||
PTRIN_CP(j32, j, jailname);
|
||||
CP(j32, j, ip4s);
|
||||
CP(j32, j, ip6s);
|
||||
PTRIN_CP(j32, j, ip4);
|
||||
PTRIN_CP(j32, j, ip6);
|
||||
tmplen = MAXPATHLEN + MAXHOSTNAMELEN + MAXHOSTNAMELEN;
|
||||
#ifdef INET
|
||||
if (j32.ip4s > jail_max_af_ips)
|
||||
return (EINVAL);
|
||||
tmplen += j32.ip4s * sizeof(struct in_addr);
|
||||
#else
|
||||
if (j32.ip4s > 0)
|
||||
return (EINVAL);
|
||||
#endif
|
||||
#ifdef INET6
|
||||
if (j32.ip6s > jail_max_af_ips)
|
||||
return (EINVAL);
|
||||
tmplen += j32.ip6s * sizeof(struct in6_addr);
|
||||
#else
|
||||
if (j32.ip6s > 0)
|
||||
return (EINVAL);
|
||||
#endif
|
||||
u_path = malloc(tmplen, M_TEMP, M_WAITOK);
|
||||
u_hostname = u_path + MAXPATHLEN;
|
||||
u_name = u_hostname + MAXHOSTNAMELEN;
|
||||
#ifdef INET
|
||||
u_ip4 = (struct in_addr *)(u_name + MAXHOSTNAMELEN);
|
||||
#endif
|
||||
#ifdef INET6
|
||||
#ifdef INET
|
||||
u_ip6 = (struct in6_addr *)(u_ip4 + j32.ip4s);
|
||||
#else
|
||||
u_ip6 = (struct in6_addr *)(u_name + MAXHOSTNAMELEN);
|
||||
#endif
|
||||
#endif
|
||||
opt.uio_iov = optiov;
|
||||
opt.uio_iovcnt = 4;
|
||||
opt.uio_offset = -1;
|
||||
opt.uio_resid = -1;
|
||||
opt.uio_segflg = UIO_SYSSPACE;
|
||||
opt.uio_rw = UIO_READ;
|
||||
opt.uio_td = td;
|
||||
optiov[0].iov_base = "path";
|
||||
optiov[0].iov_len = sizeof("path");
|
||||
optiov[1].iov_base = u_path;
|
||||
error = copyinstr(PTRIN(j32.path), u_path, MAXPATHLEN,
|
||||
&optiov[1].iov_len);
|
||||
if (error) {
|
||||
free(u_path, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
optiov[2].iov_base = "host.hostname";
|
||||
optiov[2].iov_len = sizeof("host.hostname");
|
||||
optiov[3].iov_base = u_hostname;
|
||||
error = copyinstr(PTRIN(j32.hostname), u_hostname,
|
||||
MAXHOSTNAMELEN, &optiov[3].iov_len);
|
||||
if (error) {
|
||||
free(u_path, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
if (PTRIN(j32.jailname) != NULL) {
|
||||
optiov[opt.uio_iovcnt].iov_base = "name";
|
||||
optiov[opt.uio_iovcnt].iov_len = sizeof("name");
|
||||
opt.uio_iovcnt++;
|
||||
optiov[opt.uio_iovcnt].iov_base = u_name;
|
||||
error = copyinstr(PTRIN(j32.jailname), u_name,
|
||||
MAXHOSTNAMELEN, &optiov[opt.uio_iovcnt].iov_len);
|
||||
if (error) {
|
||||
free(u_path, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
opt.uio_iovcnt++;
|
||||
}
|
||||
#ifdef INET
|
||||
optiov[opt.uio_iovcnt].iov_base = "ip4.addr";
|
||||
optiov[opt.uio_iovcnt].iov_len = sizeof("ip4.addr");
|
||||
opt.uio_iovcnt++;
|
||||
optiov[opt.uio_iovcnt].iov_base = u_ip4;
|
||||
optiov[opt.uio_iovcnt].iov_len =
|
||||
j32.ip4s * sizeof(struct in_addr);
|
||||
error = copyin(PTRIN(j32.ip4), u_ip4,
|
||||
optiov[opt.uio_iovcnt].iov_len);
|
||||
if (error) {
|
||||
free(u_path, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
opt.uio_iovcnt++;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
optiov[opt.uio_iovcnt].iov_base = "ip6.addr";
|
||||
optiov[opt.uio_iovcnt].iov_len = sizeof("ip6.addr");
|
||||
opt.uio_iovcnt++;
|
||||
optiov[opt.uio_iovcnt].iov_base = u_ip6;
|
||||
optiov[opt.uio_iovcnt].iov_len =
|
||||
j32.ip6s * sizeof(struct in6_addr);
|
||||
error = copyin(PTRIN(j32.ip6), u_ip6,
|
||||
optiov[opt.uio_iovcnt].iov_len);
|
||||
if (error) {
|
||||
free(u_path, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
opt.uio_iovcnt++;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2091,7 +2229,54 @@ freebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap)
|
||||
/* Sci-Fi jails are not supported, sorry. */
|
||||
return (EINVAL);
|
||||
}
|
||||
return (kern_jail(td, &j));
|
||||
error = kern_jail_set(td, &opt, JAIL_CREATE | JAIL_ATTACH);
|
||||
free(u_path, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
freebsd32_jail_set(struct thread *td, struct freebsd32_jail_set_args *uap)
|
||||
{
|
||||
struct uio *auio;
|
||||
int error;
|
||||
|
||||
/* Check that we have an even number of iovecs. */
|
||||
if (uap->iovcnt & 1)
|
||||
return (EINVAL);
|
||||
|
||||
error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
|
||||
if (error)
|
||||
return (error);
|
||||
error = kern_jail_set(td, auio, uap->flags);
|
||||
free(auio, M_IOV);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
freebsd32_jail_get(struct thread *td, struct freebsd32_jail_get_args *uap)
|
||||
{
|
||||
struct iovec32 iov32;
|
||||
struct uio *auio;
|
||||
int error, i;
|
||||
|
||||
/* Check that we have an even number of iovecs. */
|
||||
if (uap->iovcnt & 1)
|
||||
return (EINVAL);
|
||||
|
||||
error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
|
||||
if (error)
|
||||
return (error);
|
||||
error = kern_jail_get(td, auio, uap->flags);
|
||||
if (error == 0)
|
||||
for (i = 0; i < uap->iovcnt; i++) {
|
||||
PTROUT_CP(auio->uio_iov[i], iov32, iov_base);
|
||||
CP(auio->uio_iov[i], iov32, iov_len);
|
||||
error = copyout(&iov32, uap->iovp + i, sizeof(iov32));
|
||||
if (error != 0)
|
||||
break;
|
||||
}
|
||||
free(auio, M_IOV);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -870,3 +870,8 @@
|
||||
504 AUE_POSIX_OPENPT NOPROTO { int posix_openpt(int flags); }
|
||||
; 505 is initialised by the kgssapi code, if present.
|
||||
505 AUE_NULL UNIMPL gssd_syscall
|
||||
506 AUE_NULL STD { int freebsd32_jail_get(struct iovec32 *iovp, \
|
||||
unsigned int iovcnt, int flags); }
|
||||
507 AUE_NULL STD { int freebsd32_jail_set(struct iovec32 *iovp, \
|
||||
unsigned int iovcnt, int flags); }
|
||||
508 AUE_NULL NOPROTO { int jail_remove(int jid); }
|
||||
|
2113
sys/kern/kern_jail.c
2113
sys/kern/kern_jail.c
File diff suppressed because it is too large
Load Diff
@ -72,7 +72,9 @@ static LIST_HEAD(, osd) osd_list[OSD_LAST + 1]; /* (m) */
|
||||
static osd_method_t *osd_methods[OSD_LAST + 1]; /* (m) */
|
||||
static u_int osd_nslots[OSD_LAST + 1]; /* (m) */
|
||||
static osd_destructor_t *osd_destructors[OSD_LAST + 1]; /* (o) */
|
||||
static const u_int osd_nmethods[OSD_LAST + 1];
|
||||
static const u_int osd_nmethods[OSD_LAST + 1] = {
|
||||
[OSD_JAIL] = 5,
|
||||
};
|
||||
|
||||
static struct sx osd_module_lock[OSD_LAST + 1];
|
||||
static struct rmlock osd_object_lock[OSD_LAST + 1];
|
||||
@ -345,9 +347,9 @@ osd_call(u_int type, u_int method, void *obj, void *data)
|
||||
*/
|
||||
error = 0;
|
||||
sx_slock(&osd_module_lock[type]);
|
||||
for (i = 1; i <= osd_nslots[type]; i++) {
|
||||
for (i = 0; i < osd_nslots[type]; i++) {
|
||||
methodfun =
|
||||
osd_methods[type][(i - 1) * osd_nmethods[type] + method];
|
||||
osd_methods[type][i * osd_nmethods[type] + method];
|
||||
if (methodfun != NULL && (error = methodfun(obj, data)) != 0)
|
||||
break;
|
||||
}
|
||||
|
@ -897,5 +897,10 @@
|
||||
504 AUE_POSIX_OPENPT STD { int posix_openpt(int flags); }
|
||||
; 505 is initialised by the kgssapi code, if present.
|
||||
505 AUE_NULL NOSTD { int gssd_syscall(char *path); }
|
||||
506 AUE_NULL STD { int jail_get(struct iovec *iovp, \
|
||||
unsigned int iovcnt, int flags); }
|
||||
507 AUE_NULL STD { int jail_set(struct iovec *iovp, \
|
||||
unsigned int iovcnt, int flags); }
|
||||
508 AUE_NULL STD { int jail_remove(int jid); }
|
||||
; Please copy any additions and changes to the following compatability tables:
|
||||
; sys/compat/freebsd32/syscalls.master
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1999 Poul-Henning Kamp.
|
||||
* Copyright (c) 2009 James Gritton.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -97,15 +98,30 @@ static const struct prison_state {
|
||||
{ PRISON_STATE_DYING, "DYING" },
|
||||
};
|
||||
|
||||
/*
|
||||
* Flags for jail_set and jail_get.
|
||||
*/
|
||||
#define JAIL_CREATE 0x01 /* Create jail if it doesn't exist */
|
||||
#define JAIL_UPDATE 0x02 /* Update parameters of existing jail */
|
||||
#define JAIL_ATTACH 0x04 /* Attach to jail upon creation */
|
||||
#define JAIL_DYING 0x08 /* Allow getting a dying jail */
|
||||
#define JAIL_SET_MASK 0x0f
|
||||
#define JAIL_GET_MASK 0x08
|
||||
|
||||
#ifndef _KERNEL
|
||||
|
||||
struct iovec;
|
||||
|
||||
int jail(struct jail *);
|
||||
int jail_set(struct iovec *, unsigned int, int);
|
||||
int jail_get(struct iovec *, unsigned int, int);
|
||||
int jail_attach(int);
|
||||
int jail_remove(int);
|
||||
|
||||
#else /* _KERNEL */
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/_lock.h>
|
||||
#include <sys/_mutex.h>
|
||||
#include <sys/_task.h>
|
||||
@ -136,29 +152,44 @@ struct cpuset;
|
||||
* (d) set only during destruction of jail, no mutex needed
|
||||
*/
|
||||
struct prison {
|
||||
LIST_ENTRY(prison) pr_list; /* (a) all prisons */
|
||||
TAILQ_ENTRY(prison) pr_list; /* (a) all prisons */
|
||||
int pr_id; /* (c) prison id */
|
||||
int pr_ref; /* (p) refcount */
|
||||
int pr_state; /* (p) prison state */
|
||||
int pr_nprocs; /* (p) process count */
|
||||
int pr_uref; /* (p) user (alive) refcount */
|
||||
unsigned pr_flags; /* (p) PR_* flags */
|
||||
char pr_path[MAXPATHLEN]; /* (c) chroot path */
|
||||
struct cpuset *pr_cpuset; /* (p) cpuset */
|
||||
struct vnode *pr_root; /* (c) vnode to rdir */
|
||||
char pr_host[MAXHOSTNAMELEN]; /* (p) jail hostname */
|
||||
char pr_name[MAXHOSTNAMELEN]; /* (c) admin jail name */
|
||||
char pr_name[MAXHOSTNAMELEN]; /* (p) admin jail name */
|
||||
void *pr_linux; /* (p) linux abi */
|
||||
int pr_securelevel; /* (p) securelevel */
|
||||
struct task pr_task; /* (d) destroy task */
|
||||
struct mtx pr_mtx;
|
||||
struct osd pr_osd; /* (p) additional data */
|
||||
int pr_ip4s; /* (c) number of v4 IPs */
|
||||
struct in_addr *pr_ip4; /* (c) v4 IPs of jail */
|
||||
int pr_ip6s; /* (c) number of v6 IPs */
|
||||
struct in6_addr *pr_ip6; /* (c) v6 IPs of jail */
|
||||
int pr_ip4s; /* (p) number of v4 IPs */
|
||||
struct in_addr *pr_ip4; /* (p) v4 IPs of jail */
|
||||
int pr_ip6s; /* (p) number of v6 IPs */
|
||||
struct in6_addr *pr_ip6; /* (p) v6 IPs of jail */
|
||||
};
|
||||
#endif /* _KERNEL || _WANT_PRISON */
|
||||
|
||||
#ifdef _KERNEL
|
||||
/*
|
||||
* Flag bits set via options or internally
|
||||
*/
|
||||
#define PR_PERSIST 0x00000001 /* Can exist without processes */
|
||||
#define PR_REMOVE 0x01000000 /* In process of being removed */
|
||||
|
||||
/*
|
||||
* OSD methods
|
||||
*/
|
||||
#define PR_METHOD_CREATE 0
|
||||
#define PR_METHOD_GET 1
|
||||
#define PR_METHOD_SET 2
|
||||
#define PR_METHOD_CHECK 3
|
||||
#define PR_METHOD_ATTACH 4
|
||||
|
||||
/*
|
||||
* Sysctl-set variables that determine global jail policy
|
||||
*
|
||||
@ -171,10 +202,29 @@ extern int jail_getfsstat_jailrootonly;
|
||||
extern int jail_allow_raw_sockets;
|
||||
extern int jail_chflags_allowed;
|
||||
|
||||
LIST_HEAD(prisonlist, prison);
|
||||
TAILQ_HEAD(prisonlist, prison);
|
||||
extern struct prisonlist allprison;
|
||||
extern struct sx allprison_lock;
|
||||
|
||||
/*
|
||||
* Sysctls to describe jail parameters.
|
||||
*/
|
||||
SYSCTL_DECL(_security_jail_param);
|
||||
|
||||
#define SYSCTL_JAIL_PARAM(module, param, type, fmt, descr) \
|
||||
SYSCTL_PROC(_security_jail_param ## module, OID_AUTO, param, \
|
||||
(type) | CTLFLAG_MPSAFE, NULL, 0, sysctl_jail_param, fmt, descr)
|
||||
#define SYSCTL_JAIL_PARAM_STRING(module, param, access, len, descr) \
|
||||
SYSCTL_PROC(_security_jail_param ## module, OID_AUTO, param, \
|
||||
CTLTYPE_STRING | CTLFLAG_MPSAFE | (access), NULL, len, \
|
||||
sysctl_jail_param, "A", descr)
|
||||
#define SYSCTL_JAIL_PARAM_STRUCT(module, param, access, len, fmt, descr)\
|
||||
SYSCTL_PROC(_security_jail_param ## module, OID_AUTO, param, \
|
||||
CTLTYPE_STRUCT | CTLFLAG_MPSAFE | (access), NULL, len, \
|
||||
sysctl_jail_param, fmt, descr)
|
||||
#define SYSCTL_JAIL_PARAM_NODE(module, descr) \
|
||||
SYSCTL_NODE(_security_jail_param, OID_AUTO, module, CTLFLAG_RW, 0, descr)
|
||||
|
||||
/*
|
||||
* Kernel support functions for jail().
|
||||
*/
|
||||
@ -182,8 +232,6 @@ struct ucred;
|
||||
struct mount;
|
||||
struct sockaddr;
|
||||
struct statfs;
|
||||
struct thread;
|
||||
int kern_jail(struct thread *, struct jail *);
|
||||
int jailed(struct ucred *cred);
|
||||
void getcredhostname(struct ucred *cred, char *, size_t);
|
||||
int prison_check(struct ucred *cred1, struct ucred *cred2);
|
||||
@ -191,6 +239,7 @@ int prison_canseemount(struct ucred *cred, struct mount *mp);
|
||||
void prison_enforce_statfs(struct ucred *cred, struct mount *mp,
|
||||
struct statfs *sp);
|
||||
struct prison *prison_find(int prid);
|
||||
struct prison *prison_find_name(const char *name);
|
||||
void prison_free(struct prison *pr);
|
||||
void prison_free_locked(struct prison *pr);
|
||||
void prison_hold(struct prison *pr);
|
||||
@ -210,6 +259,7 @@ int prison_check_ip6(struct ucred *, struct in6_addr *);
|
||||
int prison_check_af(struct ucred *cred, int af);
|
||||
int prison_if(struct ucred *cred, struct sockaddr *sa);
|
||||
int prison_priv_check(struct ucred *cred, int priv);
|
||||
int sysctl_jail_param(struct sysctl_oid *, void *, int , struct sysctl_req *);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
#endif /* !_SYS_JAIL_H_ */
|
||||
|
@ -81,8 +81,8 @@ void osd_exit(u_int type, struct osd *osd);
|
||||
#define osd_thread_exit(td) \
|
||||
osd_exit(OSD_THREAD, &(td)->td_osd)
|
||||
|
||||
#define osd_jail_register(destructor) \
|
||||
osd_register(OSD_JAIL, (destructor), NULL)
|
||||
#define osd_jail_register(destructor, methods) \
|
||||
osd_register(OSD_JAIL, (destructor), (methods))
|
||||
#define osd_jail_deregister(slot) \
|
||||
osd_deregister(OSD_JAIL, (slot))
|
||||
#define osd_jail_set(pr, slot, value) \
|
||||
|
@ -128,6 +128,8 @@
|
||||
* Jail privileges.
|
||||
*/
|
||||
#define PRIV_JAIL_ATTACH 110 /* Attach to a jail. */
|
||||
#define PRIV_JAIL_SET 111 /* Set jail parameters. */
|
||||
#define PRIV_JAIL_REMOVE 112 /* Remove a jail. */
|
||||
|
||||
/*
|
||||
* Kernel environment priveleges.
|
||||
|
@ -105,6 +105,8 @@ int kern_getsockname(struct thread *td, int fd, struct sockaddr **sa,
|
||||
int kern_getsockopt(struct thread *td, int s, int level, int name,
|
||||
void *optval, enum uio_seg valseg, socklen_t *valsize);
|
||||
int kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data);
|
||||
int kern_jail_get(struct thread *td, struct uio *options, int flags);
|
||||
int kern_jail_set(struct thread *td, struct uio *options, int flags);
|
||||
int kern_kevent(struct thread *td, int fd, int nchanges, int nevents,
|
||||
struct kevent_copyops *k_ops, const struct timespec *timeout);
|
||||
int kern_kldload(struct thread *td, const char *file, int *fileid);
|
||||
|
Loading…
x
Reference in New Issue
Block a user