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