Clean up some errors that were reported by textproc/igor:

- Bad tag indents
- Wrap long lines
- Two spaces at sentence start
This commit is contained in:
Benedict Reuschling 2018-08-26 15:56:45 +00:00
parent 892468b17f
commit 93632dc9d5
Notes: svn2git 2020-12-08 03:00:23 +00:00
svn path=/head/; revision=52176

View file

@ -4,53 +4,68 @@
$FreeBSD$ $FreeBSD$
--> -->
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="jail"> <chapter xmlns="http://docbook.org/ns/docbook"
<info><title>The Jail Subsystem</title> xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0"
<author><personname><firstname>Evan</firstname><surname>Sarmiento</surname></personname><affiliation> xml:id="jail">
<address><email>evms@cs.bu.edu</email></address> <info>
</affiliation></author> <title>The Jail Subsystem</title>
<author>
<personname>
<firstname>Evan</firstname>
<surname>Sarmiento</surname>
</personname>
<affiliation>
<address>
<email>evms@cs.bu.edu</email>
</address>
</affiliation>
</author>
<copyright> <copyright>
<year>2001</year> <year>2001</year>
<holder role="mailto:evms@cs.bu.edu">Evan Sarmiento</holder> <holder role="mailto:evms@cs.bu.edu">Evan Sarmiento</holder>
</copyright> </copyright>
</info> </info>
<indexterm><primary>security</primary></indexterm> <indexterm><primary>security</primary></indexterm>
<indexterm><primary>Jail</primary></indexterm> <indexterm><primary>Jail</primary></indexterm>
<indexterm><primary>root</primary></indexterm> <indexterm><primary>root</primary></indexterm>
<para>On most &unix; systems, <literal>root</literal> has omnipotent power. <para>On most &unix; systems, <literal>root</literal> has omnipotent
This promotes insecurity. If an attacker gained <literal>root</literal> power. This promotes insecurity. If an attacker gained
on a system, he would have every function at his fingertips. In FreeBSD <literal>root</literal> on a system, he would have every function
there are sysctls which dilute the power of <literal>root</literal>, in at his fingertips. In FreeBSD there are sysctls which dilute the
order to minimize the damage caused by an attacker. Specifically, one of power of <literal>root</literal>, in order to minimize the damage
these functions is called <literal>secure levels</literal>. Similarly, caused by an attacker. Specifically, one of these functions is
another function which is present from FreeBSD 4.0 and onward, is a utility called <literal>secure levels</literal>. Similarly, another
called &man.jail.8;. <application>Jail</application> chroots an environment function which is present from FreeBSD 4.0 and onward, is a
and sets certain restrictions on processes which are forked within utility called &man.jail.8;. <application>Jail</application>
the <application>jail</application>. For example, a jailed process chroots an environment and sets certain restrictions on processes
cannot affect processes outside the <application>jail</application>, which are forked within the <application>jail</application>. For
utilize certain system calls, or inflict any damage on the host example, a jailed process cannot affect processes outside the
environment.</para> <application>jail</application>, utilize certain system calls, or
inflict any damage on the host environment.</para>
<para><application>Jail</application> is becoming the new security <para><application>Jail</application> is becoming the new security
model. People are running potentially vulnerable servers such as model. People are running potentially vulnerable servers such as
<application>Apache</application>, <application>BIND</application>, and <application>Apache</application>,
<application>sendmail</application> within jails, so that if an attacker <application>BIND</application>, and
gains <literal>root</literal> within the <application>jail</application>, <application>sendmail</application> within jails, so that if an
it is only an annoyance, and not a devastation. This article mainly attacker gains <literal>root</literal> within the
focuses on the internals (source code) of <application>jail</application>. <application>jail</application>, it is only an annoyance, and not
For information on how to set up a jail see the <link xlink:href="&url.books.handbook;/jails.html">handbook entry on jails</link>.</para> a devastation. This article mainly focuses on the internals
(source code) of <application>jail</application>. For information
on how to set up a jail see the <link
xlink:href="&url.books.handbook;/jails.html">handbook entry on
jails</link>.</para>
<sect1 xml:id="jail-arch"> <sect1 xml:id="jail-arch">
<title>Architecture</title> <title>Architecture</title>
<para> <para><application>Jail</application> consists of two realms: the
<application>Jail</application> consists of two realms: the
userland program, &man.jail.8;, and the code implemented within userland program, &man.jail.8;, and the code implemented within
the kernel: the &man.jail.2; system call and associated the kernel: the &man.jail.2; system call and associated
restrictions. I will be discussing the userland program and restrictions. I will be discussing the userland program and
then how <application>jail</application> is implemented within then how <application>jail</application> is implemented within
the kernel.</para> the kernel.</para>
@ -60,24 +75,25 @@
<indexterm><primary>Jail</primary> <indexterm><primary>Jail</primary>
<secondary>Userland Program</secondary></indexterm> <secondary>Userland Program</secondary></indexterm>
<para>The source for the userland <application>jail</application> <para>The source for the userland
is located in <filename>/usr/src/usr.sbin/jail</filename>, <application>jail</application> is located in
consisting of one file, <filename>jail.c</filename>. The program <filename>/usr/src/usr.sbin/jail</filename>, consisting of one
takes these arguments: the path of the <application>jail</application>, file, <filename>jail.c</filename>. The program takes these
hostname, IP address, and the command to be executed.</para> arguments: the path of the <application>jail</application>,
hostname, IP address, and the command to be executed.</para>
<sect3> <sect3>
<title>Data Structures</title> <title>Data Structures</title>
<para>In <filename>jail.c</filename>, the first thing I would <para>In <filename>jail.c</filename>, the first thing I would
note is the declaration of an important structure note is the declaration of an important structure
<literal>struct jail j;</literal> which was included from <literal>struct jail j;</literal> which was included from
<filename>/usr/include/sys/jail.h</filename>.</para> <filename>/usr/include/sys/jail.h</filename>.</para>
<para>The definition of the <literal>jail</literal> structure is: <para>The definition of the <literal>jail</literal> structure
</para> is:</para>
<programlisting><filename>/usr/include/sys/jail.h</filename>: <programlisting><filename>/usr/include/sys/jail.h</filename>:
struct jail { struct jail {
u_int32_t version; u_int32_t version;
@ -86,11 +102,11 @@ struct jail {
u_int32_t ip_number; u_int32_t ip_number;
};</programlisting> };</programlisting>
<para>As you can see, there is an entry for each of the <para>As you can see, there is an entry for each of the
arguments passed to the &man.jail.8; program, and indeed, arguments passed to the &man.jail.8; program, and indeed,
they are set during its execution.</para> they are set during its execution.</para>
<programlisting><filename>/usr/src/usr.sbin/jail/jail.c</filename> <programlisting><filename>/usr/src/usr.sbin/jail/jail.c</filename>
char path[PATH_MAX]; char path[PATH_MAX];
... ...
if (realpath(argv[0], path) == NULL) if (realpath(argv[0], path) == NULL)
@ -101,54 +117,55 @@ memset(&amp;j, 0, sizeof(j));
j.version = 0; j.version = 0;
j.path = path; j.path = path;
j.hostname = argv[1];</programlisting> j.hostname = argv[1];</programlisting>
</sect3> </sect3>
<sect3> <sect3>
<title>Networking</title> <title>Networking</title>
<para>One of the arguments passed to the &man.jail.8; program is <para>One of the arguments passed to the &man.jail.8; program
an IP address with which the <application>jail</application> is an IP address with which the
can be accessed over the network. &man.jail.8; translates the <application>jail</application> can be accessed over the
IP address given into host byte order and then stores it in network. &man.jail.8; translates the IP address given into
<literal>j</literal> (the <literal>jail</literal> structure).</para> host byte order and then stores it in <literal>j</literal>
(the <literal>jail</literal> structure).</para>
<programlisting><filename>/usr/src/usr.sbin/jail/jail.c</filename>: <programlisting><filename>/usr/src/usr.sbin/jail/jail.c</filename>:
struct in_addr in; struct in_addr in;
... ...
if (inet_aton(argv[2], &amp;in) == 0) if (inet_aton(argv[2], &amp;in) == 0)
errx(1, "Could not make sense of ip-number: %s", argv[2]); errx(1, "Could not make sense of ip-number: %s", argv[2]);
j.ip_number = ntohl(in.s_addr);</programlisting> j.ip_number = ntohl(in.s_addr);</programlisting>
<para>The &man.inet.aton.3; function "interprets the specified <para>The &man.inet.aton.3; function "interprets the specified
character string as an Internet address, placing the address character string as an Internet address, placing the address
into the structure provided." The <literal>ip_number</literal> into the structure provided." The
member in the <literal>jail</literal> structure is set only <literal>ip_number</literal> member in the
when the IP address placed onto the <literal>in</literal> <literal>jail</literal> structure is set only when the IP
structure by &man.inet.aton.3; is translated into host byte address placed onto the <literal>in</literal> structure by
order by &man.ntohl.3;.</para> &man.inet.aton.3; is translated into host byte order by
&man.ntohl.3;.</para>
</sect3> </sect3>
<sect3> <sect3>
<title>Jailing the Process</title> <title>Jailing the Process</title>
<para>Finally, the userland program jails the process. <para>Finally, the userland program jails the process.
<application>Jail</application> now becomes an imprisoned <application>Jail</application> now becomes an imprisoned
process itself and then executes the command given using process itself and then executes the command given using
&man.execv.3;.</para> &man.execv.3;.</para>
<programlisting><filename>/usr/src/usr.sbin/jail/jail.c</filename>
<programlisting><filename>/usr/src/usr.sbin/jail/jail.c</filename>
i = jail(&amp;j); i = jail(&amp;j);
... ...
if (execv(argv[3], argv + 3) != 0) if (execv(argv[3], argv + 3) != 0)
err(1, "execv: %s", argv[3]);</programlisting> err(1, "execv: %s", argv[3]);</programlisting>
<para>As you can see, the <literal>jail()</literal> function is <para>As you can see, the <literal>jail()</literal> function
called, and its argument is the <literal>jail</literal> structure is called, and its argument is the <literal>jail</literal>
which has been filled with the arguments given to the program. structure which has been filled with the arguments given to
Finally, the program you specify is executed. I will now discuss the program. Finally, the program you specify is executed.
how <application>jail</application> is implemented within the I will now discuss how <application>jail</application> is
kernel.</para> implemented within the kernel.</para>
</sect3> </sect3>
</sect2> </sect2>
@ -159,20 +176,19 @@ if (execv(argv[3], argv + 3) != 0)
<secondary>Kernel Architecture</secondary></indexterm> <secondary>Kernel Architecture</secondary></indexterm>
<para>We will now be looking at the file <para>We will now be looking at the file
<filename>/usr/src/sys/kern/kern_jail.c</filename>. This is <filename>/usr/src/sys/kern/kern_jail.c</filename>. This is
the file where the &man.jail.2; system call, appropriate sysctls, the file where the &man.jail.2; system call, appropriate
and networking functions are defined.</para> sysctls, and networking functions are defined.</para>
<sect3> <sect3>
<title>sysctls</title> <title>Sysctls</title>
<indexterm><primary>sysctl</primary></indexterm> <indexterm><primary>sysctl</primary></indexterm>
<para>In <filename>kern_jail.c</filename>, the following <para>In <filename>kern_jail.c</filename>, the following
sysctls are defined:</para> sysctls are defined:</para>
<programlisting><filename>/usr/src/sys/kern/kern_jail.c:</filename>
<programlisting><filename>/usr/src/sys/kern/kern_jail.c:</filename>
int jail_set_hostname_allowed = 1; int jail_set_hostname_allowed = 1;
SYSCTL_INT(_security_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW, SYSCTL_INT(_security_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,
&amp;jail_set_hostname_allowed, 0, &amp;jail_set_hostname_allowed, 0,
@ -208,29 +224,30 @@ SYSCTL_INT(_security_jail, OID_AUTO, mount_allowed, CTLFLAG_RW,
&amp;jail_mount_allowed, 0, &amp;jail_mount_allowed, 0,
"Processes in jail can mount/unmount jail-friendly file systems");</programlisting> "Processes in jail can mount/unmount jail-friendly file systems");</programlisting>
<para>Each of these sysctls can be accessed by the user <para>Each of these sysctls can be accessed by the user
through the &man.sysctl.8; program. Throughout the kernel, these through the &man.sysctl.8; program. Throughout the kernel,
specific sysctls are recognized by their name. For example, these specific sysctls are recognized by their name. For
the name of the first sysctl is example, the name of the first sysctl is
<literal>security.jail.set_hostname_allowed</literal>.</para> <literal>security.jail.set_hostname_allowed</literal>.</para>
</sect3> </sect3>
<sect3> <sect3>
<title>&man.jail.2; System Call</title> <title>&man.jail.2; System Call</title>
<para>Like all system calls, the &man.jail.2; system call takes <para>Like all system calls, the &man.jail.2; system call
two arguments, <literal>struct thread *td</literal> and takes two arguments, <literal>struct thread *td</literal>
<literal>struct jail_args *uap</literal>. and <literal>struct jail_args *uap</literal>.
<literal>td</literal> is a pointer to the <literal>thread</literal> <literal>td</literal> is a pointer to the
structure which describes the calling thread. In this <literal>thread</literal> structure which describes the
context, <literal>uap</literal> is a pointer to the structure calling thread. In this context, <literal>uap</literal> is
in which a pointer to the <literal>jail</literal> structure a pointer to the structure in which a pointer to the
passed by the userland <filename>jail.c</filename> is contained. <literal>jail</literal> structure passed by the userland
When I described the userland program before, you saw that the <filename>jail.c</filename> is contained. When I described
&man.jail.2; system call was given a <literal>jail</literal> the userland program before, you saw that the &man.jail.2;
structure as its own argument.</para> system call was given a <literal>jail</literal> structure as
its own argument.</para>
<programlisting><filename>/usr/src/sys/kern/kern_jail.c:</filename> <programlisting><filename>/usr/src/sys/kern/kern_jail.c:</filename>
/* /*
* struct jail_args { * struct jail_args {
* struct jail *jail; * struct jail *jail;
@ -239,29 +256,30 @@ SYSCTL_INT(_security_jail, OID_AUTO, mount_allowed, CTLFLAG_RW,
int int
jail(struct thread *td, struct jail_args *uap)</programlisting> jail(struct thread *td, struct jail_args *uap)</programlisting>
<para>Therefore, <literal>uap-&gt;jail</literal> can be used to <para>Therefore, <literal>uap-&gt;jail</literal> can be used
access the <literal>jail</literal> structure which was passed to access the <literal>jail</literal> structure which was
to the system call. Next, the system call copies the passed to the system call. Next, the system call copies the
<literal>jail</literal> structure into kernel space using <literal>jail</literal> structure into kernel space using
the &man.copyin.9; function. &man.copyin.9; takes three arguments: the &man.copyin.9; function. &man.copyin.9; takes three
the address of the data which is to be copied into kernel space, arguments: the address of the data which is to be copied
<literal>uap-&gt;jail</literal>, where to store it, into kernel space, <literal>uap-&gt;jail</literal>, where to
<literal>j</literal> and the size of the storage. The store it, <literal>j</literal> and the size of the storage.
<literal>jail</literal> structure pointed by The <literal>jail</literal> structure pointed by
<literal>uap-&gt;jail</literal> is copied into kernel space and <literal>uap-&gt;jail</literal> is copied into kernel space
is stored in another <literal>jail</literal> structure, and is stored in another <literal>jail</literal> structure,
<literal>j</literal>.</para> <literal>j</literal>.</para>
<programlisting><filename>/usr/src/sys/kern/kern_jail.c: </filename> <programlisting><filename>/usr/src/sys/kern/kern_jail.c:</filename>
error = copyin(uap-&gt;jail, &amp;j, sizeof(j));</programlisting> error = copyin(uap-&gt;jail, &amp;j, sizeof(j));</programlisting>
<para>There is another important structure defined in <para>There is another important structure defined in
<filename>jail.h</filename>. It is the <literal>prison</literal> <filename>jail.h</filename>. It is the
structure. The <literal>prison</literal> structure is used <literal>prison</literal> structure. The
exclusively within kernel space. Here is the definition of the <literal>prison</literal> structure is used exclusively
<literal>prison</literal> structure.</para> within kernel space. Here is the definition of the
<literal>prison</literal> structure.</para>
<programlisting><filename>/usr/include/sys/jail.h</filename>: <programlisting><filename>/usr/include/sys/jail.h</filename>:
struct prison { struct prison {
LIST_ENTRY(prison) pr_list; /* (a) all prisons */ LIST_ENTRY(prison) pr_list; /* (a) all prisons */
int pr_id; /* (c) prison id */ int pr_id; /* (c) prison id */
@ -277,12 +295,12 @@ struct prison {
void **pr_slots; /* (p) additional data */ void **pr_slots; /* (p) additional data */
};</programlisting> };</programlisting>
<para>The &man.jail.2; system call then allocates memory for <para>The &man.jail.2; system call then allocates memory for a
a <literal>prison</literal> structure and copies data between <literal>prison</literal> structure and copies data between
the <literal>jail</literal> and <literal>prison</literal> the <literal>jail</literal> and <literal>prison</literal>
structure.</para> structure.</para>
<programlisting><filename>/usr/src/sys/kern/kern_jail.c</filename>: <programlisting><filename>/usr/src/sys/kern/kern_jail.c</filename>:
MALLOC(pr, struct prison *, sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO); MALLOC(pr, struct prison *, sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO);
... ...
error = copyinstr(j.path, &amp;pr-&gt;pr_path, sizeof(pr-&gt;pr_path), 0); error = copyinstr(j.path, &amp;pr-&gt;pr_path, sizeof(pr-&gt;pr_path), 0);
@ -293,10 +311,12 @@ error = copyinstr(j.hostname, &amp;pr-&gt;pr_host, sizeof(pr-&gt;pr_host), 0);
if (error) if (error)
goto e_dropvnref; goto e_dropvnref;
pr-&gt;pr_ip = j.ip_number;</programlisting> pr-&gt;pr_ip = j.ip_number;</programlisting>
<para>Next, we will discuss another important system call
&man.jail.attach.2;, which implements the function to put <para>Next, we will discuss another important system call
a process into the <application>jail</application>.</para> &man.jail.attach.2;, which implements the function to put a
<programlisting><filename>/usr/src/sys/kern/kern_jail.c</filename>: process into the <application>jail</application>.</para>
<programlisting><filename>/usr/src/sys/kern/kern_jail.c</filename>:
/* /*
* struct jail_attach_args { * struct jail_attach_args {
* int jid; * int jid;
@ -304,34 +324,37 @@ pr-&gt;pr_ip = j.ip_number;</programlisting>
*/ */
int int
jail_attach(struct thread *td, struct jail_attach_args *uap)</programlisting> jail_attach(struct thread *td, struct jail_attach_args *uap)</programlisting>
<para>This system call makes the changes that can distinguish
a jailed process from those unjailed ones.
To understand what &man.jail.attach.2; does for us, certain
background information is needed.</para>
<para>
On FreeBSD, each kernel visible thread is identified by its
<literal>thread</literal> structure, while the processes are
described by their <literal>proc</literal> structures. You can
find the definitions of the <literal>thread</literal> and
<literal>proc</literal> structure in
<filename>/usr/include/sys/proc.h</filename>.
For example, the <literal>td</literal> argument in any system
call is actually a pointer to the calling thread's
<literal>thread</literal> structure, as stated before.
The <literal>td_proc</literal> member in the
<literal>thread</literal> structure pointed by <literal>td</literal>
is a pointer to the <literal>proc</literal> structure which
represents the process that contains the thread represented by
<literal>td</literal>. The <literal>proc</literal> structure
contains members which can describe the owner's
identity(<literal>p_ucred</literal>), the process resource
limits(<literal>p_limit</literal>), and so on. In the
<literal>ucred</literal> structure pointed by
<literal>p_ucred</literal> member in the <literal>proc</literal>
structure, there is a pointer to the <literal>prison</literal>
structure(<literal>cr_prison</literal>).</para>
<programlisting><filename>/usr/include/sys/proc.h: </filename> <para>This system call makes the changes that can distinguish
a jailed process from those unjailed ones. To understand
what &man.jail.attach.2; does for us, certain background
information is needed.</para>
<para>On FreeBSD, each kernel visible thread is identified by
its <literal>thread</literal> structure, while the processes
are described by their <literal>proc</literal> structures.
You can find the definitions of the
<literal>thread</literal> and <literal>proc</literal>
structure in <filename>/usr/include/sys/proc.h</filename>.
For example, the <literal>td</literal> argument in any
system call is actually a pointer to the calling thread's
<literal>thread</literal> structure, as stated before. The
<literal>td_proc</literal> member in the
<literal>thread</literal> structure pointed by
<literal>td</literal> is a pointer to the
<literal>proc</literal> structure which represents the
process that contains the thread represented by
<literal>td</literal>. The <literal>proc</literal>
structure contains members which can describe the owner's
identity(<literal>p_ucred</literal>), the process resource
limits(<literal>p_limit</literal>), and so on. In the
<literal>ucred</literal> structure pointed by
<literal>p_ucred</literal> member in the
<literal>proc</literal> structure, there is a pointer to the
<literal>prison</literal>
structure(<literal>cr_prison</literal>).</para>
<programlisting><filename>/usr/include/sys/proc.h:</filename>
struct thread { struct thread {
... ...
struct proc *td_proc; struct proc *td_proc;
@ -349,29 +372,33 @@ struct ucred {
... ...
};</programlisting> };</programlisting>
<para>In <filename>kern_jail.c</filename>, the function <para>In <filename>kern_jail.c</filename>, the function
<literal>jail()</literal> then calls function <literal>jail()</literal> then calls function
<literal>jail_attach()</literal> with a given <literal>jid</literal>. <literal>jail_attach()</literal> with a given
And <literal>jail_attach()</literal> calls function <literal>jid</literal>. And
<literal>change_root()</literal> to change the root directory of the <literal>jail_attach()</literal> calls function
calling process. The <literal>jail_attach()</literal> then creates <literal>change_root()</literal> to change the root
a new <literal>ucred</literal> structure, and attaches the newly directory of the calling process. The
created <literal>ucred</literal> structure to the calling process <literal>jail_attach()</literal> then creates a new
after it has successfully attached the <literal>prison</literal> <literal>ucred</literal> structure, and attaches the newly
structure to the <literal>ucred</literal> structure. From then on, created <literal>ucred</literal> structure to the calling
the calling process is recognized as jailed. When the kernel routine process after it has successfully attached the
<literal>jailed()</literal> is called in the kernel with the newly <literal>prison</literal> structure to the
created <literal>ucred</literal> structure as its argument, it <literal>ucred</literal> structure. From then on, the
returns 1 to tell that the credential is connected calling process is recognized as jailed. When the kernel
with a <application>jail</application>. The public ancestor process routine <literal>jailed()</literal> is called in the kernel
of all the process forked within the <application>jail</application>, with the newly created <literal>ucred</literal> structure as
is the process which runs &man.jail.8;, as it calls the its argument, it returns 1 to tell that the credential is
&man.jail.2; system call. When a program is executed through connected with a <application>jail</application>. The
&man.execve.2;, it inherits the jailed property of its parent's public ancestor process of all the process forked within the
<literal>ucred</literal> structure, therefore it has a jailed <application>jail</application>, is the process which runs
<literal>ucred</literal> structure.</para> &man.jail.8;, as it calls the &man.jail.2; system call.
When a program is executed through &man.execve.2;, it
inherits the jailed property of its parent's
<literal>ucred</literal> structure, therefore it has a
jailed <literal>ucred</literal> structure.</para>
<programlisting><filename>/usr/src/sys/kern/kern_jail.c</filename> <programlisting><filename>/usr/src/sys/kern/kern_jail.c</filename>
int int
jail(struct thread *td, struct jail_args *uap) jail(struct thread *td, struct jail_args *uap)
{ {
@ -401,17 +428,18 @@ jail_attach(struct thread *td, struct jail_attach_args *uap)
p-&gt;p_ucred = newcred; p-&gt;p_ucred = newcred;
... ...
}</programlisting> }</programlisting>
<para>When a process is forked from its parent process, the
&man.fork.2; system call uses <literal>crhold()</literal> to
maintain the credential for the newly forked process. It inherently
keep the newly forked child's credential consistent with its parent,
so the child process is also jailed.</para>
<programlisting><filename>/usr/src/sys/kern/kern_fork.c</filename>: <para>When a process is forked from its parent process, the
&man.fork.2; system call uses <literal>crhold()</literal> to
maintain the credential for the newly forked process. It
inherently keep the newly forked child's credential
consistent with its parent, so the child process is also
jailed.</para>
<programlisting><filename>/usr/src/sys/kern/kern_fork.c</filename>:
p2-&gt;p_ucred = crhold(td-&gt;td_ucred); p2-&gt;p_ucred = crhold(td-&gt;td_ucred);
... ...
td2-&gt;td_ucred = crhold(p2-&gt;p_ucred);</programlisting> td2-&gt;td_ucred = crhold(p2-&gt;p_ucred);</programlisting>
</sect3> </sect3>
</sect2> </sect2>
</sect1> </sect1>
@ -420,12 +448,11 @@ td2-&gt;td_ucred = crhold(p2-&gt;p_ucred);</programlisting>
<title>Restrictions</title> <title>Restrictions</title>
<para>Throughout the kernel there are access restrictions relating <para>Throughout the kernel there are access restrictions relating
to jailed processes. Usually, these restrictions only check whether to jailed processes. Usually, these restrictions only check
the process is jailed, and if so, returns an error. For whether the process is jailed, and if so, returns an error. For
example:</para> example:</para>
<programlisting> <programlisting>if (jailed(td-&gt;td_ucred))
if (jailed(td-&gt;td_ucred))
return (EPERM);</programlisting> return (EPERM);</programlisting>
<sect2> <sect2>
@ -433,112 +460,128 @@ if (jailed(td-&gt;td_ucred))
<indexterm><primary>System V IPC</primary></indexterm> <indexterm><primary>System V IPC</primary></indexterm>
<para>System V IPC is based on messages. Processes can send each <para>System V IPC is based on messages. Processes can send
other these messages which tell them how to act. The functions each other these messages which tell them how to act. The
which deal with messages are: functions which deal with messages are: &man.msgctl.3;,
&man.msgctl.3;, &man.msgget.3;, &man.msgsnd.3; and &man.msgrcv.3;. &man.msgget.3;, &man.msgsnd.3; and &man.msgrcv.3;. Earlier, I
Earlier, I mentioned that there were certain sysctls you could mentioned that there were certain sysctls you could turn on or
turn on or off in order to affect the behavior of off in order to affect the behavior of
<application>jail</application>. One of these sysctls was <application>jail</application>. One of these sysctls was
<literal>security.jail.sysvipc_allowed</literal>. By default, <literal>security.jail.sysvipc_allowed</literal>. By default,
this sysctl is set to 0. If it were set to 1, it would defeat the this sysctl is set to 0. If it were set to 1, it would defeat
whole purpose of having a <application>jail</application>; privileged the whole purpose of having a <application>jail</application>;
users from the <application>jail</application> would be able to privileged users from the <application>jail</application>
affect processes outside the jailed environment. The difference would be able to affect processes outside the jailed
between a message and a signal is that the message only consists environment. The difference between a message and a signal is
of the signal number.</para> that the message only consists of the signal number.</para>
<para><filename>/usr/src/sys/kern/sysv_msg.c</filename>:</para> <para><filename>/usr/src/sys/kern/sysv_msg.c</filename>:</para>
<itemizedlist> <itemizedlist>
<listitem> <para><literal>msgget(key, msgflg)</literal>: <listitem>
<literal>msgget</literal> returns (and possibly creates) a message <para><literal>msgget(key, msgflg)</literal>:
descriptor that designates a message queue for use in other <literal>msgget</literal> returns (and possibly creates) a
functions.</para></listitem> message descriptor that designates a message queue for use
in other functions.</para>
</listitem>
<listitem> <para><literal>msgctl(msgid, cmd, buf)</literal>: <listitem>
Using this function, a process can query the status of a message <para><literal>msgctl(msgid, cmd, buf)</literal>: Using this
descriptor.</para></listitem> function, a process can query the status of a message
descriptor.</para>
</listitem>
<listitem> <para><literal>msgsnd(msgid, msgp, msgsz, msgflg)</literal>: <listitem>
<literal>msgsnd</literal> sends a message to a <para><literal>msgsnd(msgid, msgp, msgsz, msgflg)</literal>:
process.</para></listitem> <literal>msgsnd</literal> sends a message to a
process.</para>
<listitem> <para><literal>msgrcv(msgid, msgp, msgsz, msgtyp, </listitem>
msgflg)</literal>: a process receives messages using
this function</para></listitem>
<listitem>
<para><literal>msgrcv(msgid, msgp, msgsz, msgtyp,
msgflg)</literal>: a process receives messages using
this function</para>
</listitem>
</itemizedlist> </itemizedlist>
<para>In each of the system calls corresponding to these functions, <para>In each of the system calls corresponding to these
there is this conditional:</para> functions, there is this conditional:</para>
<programlisting><filename>/usr/src/sys/kern/sysv_msg.c</filename>: <programlisting><filename>/usr/src/sys/kern/sysv_msg.c</filename>:
if (!jail_sysvipc_allowed &amp;&amp; jailed(td-&gt;td_ucred)) if (!jail_sysvipc_allowed &amp;&amp; jailed(td-&gt;td_ucred))
return (ENOSYS);</programlisting> return (ENOSYS);</programlisting>
<indexterm><primary>semaphores</primary></indexterm> <indexterm><primary>semaphores</primary></indexterm>
<para>Semaphore system calls allow processes to synchronize <para>Semaphore system calls allow processes to synchronize
execution by doing a set of operations atomically on a set of execution by doing a set of operations atomically on a set of
semaphores. Basically semaphores provide another way for semaphores. Basically semaphores provide another way for
processes lock resources. However, process waiting on a processes lock resources. However, process waiting on a
semaphore, that is being used, will sleep until the resources semaphore, that is being used, will sleep until the resources
are relinquished. The following semaphore system calls are are relinquished. The following semaphore system calls are
blocked inside a <application>jail</application>: &man.semget.2;, blocked inside a <application>jail</application>:
&man.semctl.2; and &man.semop.2;.</para> &man.semget.2;, &man.semctl.2; and &man.semop.2;.</para>
<para><filename>/usr/src/sys/kern/sysv_sem.c</filename>:</para> <para><filename>/usr/src/sys/kern/sysv_sem.c</filename>:</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para><literal>semctl(semid, semnum, cmd, ...)</literal>: <para><literal>semctl(semid, semnum, cmd, ...)</literal>:
<literal>semctl</literal> does the specified <literal>cmd</literal> <literal>semctl</literal> does the specified
on the semaphore queue indicated by <literal>cmd</literal> on the semaphore queue indicated by
<literal>semid</literal>.</para></listitem> <literal>semid</literal>.</para></listitem>
<listitem> <listitem>
<para><literal>semget(key, nsems, flag)</literal>: <para><literal>semget(key, nsems, flag)</literal>:
<literal>semget</literal> creates an array of semaphores, <literal>semget</literal> creates an array of semaphores,
corresponding to <literal>key</literal>.</para> corresponding to <literal>key</literal>.</para>
<para><literal>key and flag take on the same meaning as they <para><literal>key and flag take on the same meaning as they
do in msgget.</literal></para></listitem> do in msgget.</literal></para>
</listitem>
<listitem><para><literal>semop(semid, array, nops)</literal>: <listitem><para><literal>semop(semid, array, nops)</literal>:
<literal>semop</literal> performs a group of operations indicated <literal>semop</literal> performs a group of operations
by <literal>array</literal>, to the set of semaphores identified by indicated by <literal>array</literal>, to the set of
<literal>semid</literal>.</para></listitem> semaphores identified by
<literal>semid</literal>.</para></listitem>
</itemizedlist> </itemizedlist>
<indexterm><primary>shared memory</primary></indexterm> <indexterm><primary>shared memory</primary></indexterm>
<para>System V IPC allows for processes to share
memory. Processes can communicate directly with each other by <para>System V IPC allows for processes to share memory.
sharing parts of their virtual address space and then reading Processes can communicate directly with each other by sharing
and writing data stored in the shared memory. These system parts of their virtual address space and then reading and
calls are blocked within a jailed environment: &man.shmdt.2;, writing data stored in the shared memory. These system calls
&man.shmat.2;, &man.shmctl.2; and &man.shmget.2;.</para> are blocked within a jailed environment: &man.shmdt.2;,
&man.shmat.2;, &man.shmctl.2; and &man.shmget.2;.</para>
<para><filename>/usr/src/sys/kern/sysv_shm.c</filename>:</para> <para><filename>/usr/src/sys/kern/sysv_shm.c</filename>:</para>
<itemizedlist> <itemizedlist>
<listitem><para><literal>shmctl(shmid, cmd, buf)</literal>: <listitem><para><literal>shmctl(shmid, cmd, buf)</literal>:
<literal>shmctl</literal> does various control operations on the <literal>shmctl</literal> does various control operations
shared memory region identified by on the shared memory region identified by
<literal>shmid</literal>.</para></listitem> <literal>shmid</literal>.</para>
</listitem>
<listitem><para><literal>shmget(key, size, flag)</literal>: <listitem><para><literal>shmget(key, size, flag)</literal>:
<literal>shmget</literal> accesses or creates a shared memory <literal>shmget</literal> accesses or creates a shared
region of <literal>size</literal> bytes.</para></listitem> memory region of <literal>size</literal>
bytes.</para>
</listitem>
<listitem><para><literal>shmat(shmid, addr, flag)</literal>: <listitem><para><literal>shmat(shmid, addr, flag)</literal>:
<literal>shmat</literal> attaches a shared memory region identified <literal>shmat</literal> attaches a shared memory region
by <literal>shmid</literal> to the address space of a identified by <literal>shmid</literal> to the address
process.</para></listitem> space of a process.</para>
</listitem>
<listitem><para><literal>shmdt(addr)</literal>:
<literal>shmdt</literal> detaches the shared memory region
previously attached at <literal>addr</literal>.</para></listitem>
<listitem><para><literal>shmdt(addr)</literal>:
<literal>shmdt</literal> detaches the shared memory region
previously attached at
<literal>addr</literal>.</para>
</listitem>
</itemizedlist> </itemizedlist>
</sect2> </sect2>
@ -546,16 +589,17 @@ if (!jail_sysvipc_allowed &amp;&amp; jailed(td-&gt;td_ucred))
<title>Sockets</title> <title>Sockets</title>
<indexterm><primary>sockets</primary></indexterm> <indexterm><primary>sockets</primary></indexterm>
<para><application>Jail</application> treats the &man.socket.2; system
call and related lower-level socket functions in a special manner. <para><application>Jail</application> treats the &man.socket.2;
In order to determine whether a certain socket is allowed to be system call and related lower-level socket functions in a
created, it first checks to see if the sysctl special manner. In order to determine whether a certain
<literal>security.jail.socket_unixiproute_only</literal> is set. If socket is allowed to be created, it first checks to see if the
set, sockets are only allowed to be created if the family sysctl
specified is either <literal>PF_LOCAL</literal>, <literal>security.jail.socket_unixiproute_only</literal> is
<literal>PF_INET</literal> or set. If set, sockets are only allowed to be created if the
<literal>PF_ROUTE</literal>. Otherwise, it returns an family specified is either <literal>PF_LOCAL</literal>,
error.</para> <literal>PF_INET</literal> or <literal>PF_ROUTE</literal>.
Otherwise, it returns an error.</para>
<programlisting><filename>/usr/src/sys/kern/uipc_socket.c</filename>: <programlisting><filename>/usr/src/sys/kern/uipc_socket.c</filename>:
int int
@ -572,7 +616,6 @@ socreate(int dom, struct socket **aso, int type, int proto,
} }
... ...
}</programlisting> }</programlisting>
</sect2> </sect2>
<sect2> <sect2>
@ -581,10 +624,11 @@ socreate(int dom, struct socket **aso, int type, int proto,
<indexterm><primary>Berkeley Packet Filter</primary></indexterm> <indexterm><primary>Berkeley Packet Filter</primary></indexterm>
<indexterm><primary>data link layer</primary></indexterm> <indexterm><primary>data link layer</primary></indexterm>
<para>The <application>Berkeley Packet Filter</application> provides <para>The <application>Berkeley Packet Filter</application>
a raw interface to data link layers in a protocol independent provides a raw interface to data link layers in a protocol
fashion. <application>BPF</application> is now controlled by the independent fashion. <application>BPF</application> is now
&man.devfs.8; whether it can be used in a jailed environment.</para> controlled by the &man.devfs.8; whether it can be used in a
jailed environment.</para>
</sect2> </sect2>
@ -594,23 +638,25 @@ socreate(int dom, struct socket **aso, int type, int proto,
<indexterm><primary>protocols</primary></indexterm> <indexterm><primary>protocols</primary></indexterm>
<para>There are certain protocols which are very common, such as <para>There are certain protocols which are very common, such as
TCP, UDP, IP and ICMP. IP and ICMP are on the same level: the TCP, UDP, IP and ICMP. IP and ICMP are on the same level: the
network layer 2. There are certain precautions which are network layer 2. There are certain precautions which are
taken in order to prevent a jailed process from binding a taken in order to prevent a jailed process from binding a
protocol to a certain address only if the <literal>nam</literal> protocol to a certain address only if the
parameter is set. <literal>nam</literal> is a pointer to a <literal>nam</literal> parameter is set.
<literal>sockaddr</literal> structure, <literal>nam</literal> is a pointer to a
which describes the address on which to bind the service. A <literal>sockaddr</literal> structure, which describes the
more exact definition is that <literal>sockaddr</literal> "may be address on which to bind the service. A more exact definition
used as a template for referring to the identifying tag and length of is that <literal>sockaddr</literal> "may be used as a template
each address". In the function for referring to the identifying tag and length of each
<literal>in_pcbbind_setup()</literal>, <literal>sin</literal> is a address". In the function
pointer to a <literal>sockaddr_in</literal> structure, which <literal>in_pcbbind_setup()</literal>, <literal>sin</literal>
contains the port, address, length and domain family of the socket is a pointer to a <literal>sockaddr_in</literal> structure,
which is to be bound. Basically, this disallows any processes from which contains the port, address, length and domain family of
<application>jail</application> to be able to specify the address the socket which is to be bound. Basically, this disallows
that does not belong to the <application>jail</application> in which any processes from <application>jail</application> to be able
the calling process exists.</para> to specify the address that does not belong to the
<application>jail</application> in which the calling process
exists.</para>
<programlisting><filename>/usr/src/sys/netinet/in_pcb.c</filename>: <programlisting><filename>/usr/src/sys/netinet/in_pcb.c</filename>:
int int
@ -648,14 +694,15 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
}</programlisting> }</programlisting>
<para>You might be wondering what function <para>You might be wondering what function
<literal>prison_ip()</literal> does. <literal>prison_ip()</literal> <literal>prison_ip()</literal> does.
is given three arguments, a pointer to the credential(represented by <literal>prison_ip()</literal> is given three arguments, a
<literal>cred</literal>), any flags, and an IP address. It pointer to the credential(represented by
returns 1 if the IP address does NOT belong to the <literal>cred</literal>), any flags, and an IP address. It
<application>jail</application> or 0 otherwise. As you can see returns 1 if the IP address does NOT belong to the
from the code, if it is indeed an IP address not belonging to the <application>jail</application> or 0 otherwise. As you can
<application>jail</application>, the protocol is not allowed to bind see from the code, if it is indeed an IP address not belonging
to that address.</para> to the <application>jail</application>, the protocol is not
allowed to bind to that address.</para>
<programlisting><filename>/usr/src/sys/kern/kern_jail.c:</filename> <programlisting><filename>/usr/src/sys/kern/kern_jail.c:</filename>
int int
@ -693,10 +740,12 @@ prison_ip(struct ucred *cred, int flag, u_int32_t *ip)
<title>Filesystem</title> <title>Filesystem</title>
<indexterm><primary>filesystem</primary></indexterm> <indexterm><primary>filesystem</primary></indexterm>
<para>Even <literal>root</literal> users within the <para>Even <literal>root</literal> users within the
<application>jail</application> are not allowed to unset or modify <application>jail</application> are not allowed to unset or
any file flags, such as immutable, append-only, and undeleteable modify any file flags, such as immutable, append-only, and
flags, if the securelevel is greater than 0.</para> undeleteable flags, if the securelevel is greater than
0.</para>
<programlisting><filename>/usr/src/sys/ufs/ufs/ufs_vnops.c:</filename> <programlisting><filename>/usr/src/sys/ufs/ufs/ufs_vnops.c:</filename>
static int static int
@ -741,7 +790,5 @@ prison_priv_check(struct ucred *cred, int priv)
... ...
}</programlisting> }</programlisting>
</sect2> </sect2>
</sect1> </sect1>
</chapter> </chapter>