|
Lines 1-7
Link Here
|
| 1 |
<!-- |
1 |
<!-- |
| 2 |
The FreeBSD Documentation Project |
2 |
The FreeBSD Documentation Project |
| 3 |
|
3 |
|
| 4 |
$FreeBSD: doc/en_US.ISO8859-1/books/arch-handbook/jail/chapter.sgml,v 1.19 2007/01/31 14:22:22 delphij Exp $ |
4 |
$FreeBSD: /repoman/r/dcvs/doc/en_US.ISO8859-1/books/arch-handbook/jail/chapter.sgml,v 1.19 2007/01/31 14:22:22 delphij Exp $ |
| 5 |
--> |
5 |
--> |
| 6 |
|
6 |
|
| 7 |
<chapter id="jail"> |
7 |
<chapter id="jail"> |
|
Lines 55-61
Link Here
|
| 55 |
<para> |
55 |
<para> |
| 56 |
<application>Jail</application> consists of two realms: the |
56 |
<application>Jail</application> consists of two realms: the |
| 57 |
user-space program, jail, and the code implemented within the |
57 |
user-space program, jail, and the code implemented within the |
| 58 |
kernel: the <literal>jail()</literal> system call and associated |
58 |
kernel: the <literal>jail</literal> system call and associated |
| 59 |
restrictions. I will be discussing the user-space program and |
59 |
restrictions. I will be discussing the user-space program and |
| 60 |
then how jail is implemented within the kernel.</para> |
60 |
then how jail is implemented within the kernel.</para> |
| 61 |
|
61 |
|
|
Lines 94-103
Link Here
|
| 94 |
arguments passed to the jail program, and indeed, they are |
94 |
arguments passed to the jail program, and indeed, they are |
| 95 |
set during its execution.</para> |
95 |
set during its execution.</para> |
| 96 |
|
96 |
|
| 97 |
<programlisting><filename>/usr/src/usr.sbin/jail.c</filename> |
97 |
<programlisting><filename>/usr/src/usr.sbin/jail/jail.c</filename> |
| 98 |
j.version = 0; |
98 |
char path[PATH_MAX]; |
| 99 |
j.path = argv[1]; |
99 |
... |
| 100 |
j.hostname = argv[2];</programlisting> |
100 |
if (realpath(argv[0], path) == NULL) |
|
|
101 |
err(1, "realpath: %s", argv[0]); |
| 102 |
if (chdir(path) != 0) |
| 103 |
err(1, "chdir: %s", path); |
| 104 |
memset(&j, 0, sizeof(j)); |
| 105 |
j.version = 0; |
| 106 |
j.path = path; |
| 107 |
j.hostname = argv[1];</programlisting> |
| 101 |
|
108 |
|
| 102 |
</sect3> |
109 |
</sect3> |
| 103 |
|
110 |
|
|
Lines 106-128
Link Here
|
| 106 |
|
113 |
|
| 107 |
<para>One of the arguments passed to the Jail program is an IP |
114 |
<para>One of the arguments passed to the Jail program is an IP |
| 108 |
address with which the jail can be accessed over the |
115 |
address with which the jail can be accessed over the |
| 109 |
network. Jail translates the ip address given into network |
116 |
network. Jail translates the ip address given into host |
| 110 |
byte order and then stores it in j (the jail structure).</para> |
117 |
byte order and then stores it in j (the jail structure).</para> |
| 111 |
|
118 |
|
| 112 |
<programlisting><filename>/usr/src/usr.sbin/jail/jail.c</filename>: |
119 |
<programlisting><filename>/usr/src/usr.sbin/jail/jail.c</filename>: |
| 113 |
struct in.addr in; |
120 |
struct in_addr in; |
| 114 |
... |
|
|
| 115 |
i = inet_aton(argv[3], <![CDATA[&in]]>); |
| 116 |
... |
121 |
... |
| 117 |
j.ip_number = ntohl(in.s.addr);</programlisting> |
122 |
if (inet_aton(argv[2], &in) == 0) |
|
|
123 |
errx(1, "Could not make sense of ip-number: %s", argv[2]); |
| 124 |
j.ip_number = ntohl(in.s_addr);</programlisting> |
| 118 |
|
125 |
|
| 119 |
<para>The |
126 |
<para>The |
| 120 |
<citerefentry><refentrytitle>inet_aton</refentrytitle><manvolnum>3</manvolnum></citerefentry> |
127 |
<citerefentry><refentrytitle>inet_aton</refentrytitle> |
|
|
128 |
<manvolnum>3</manvolnum></citerefentry> |
| 121 |
function "interprets the specified character string as an |
129 |
function "interprets the specified character string as an |
| 122 |
Internet address, placing the address into the structure |
130 |
Internet address, placing the address into the structure |
| 123 |
provided." The ip number node in the jail structure is set |
131 |
provided." The ip number node in the jail structure is set |
| 124 |
only when the ip address placed onto the in structure by |
132 |
only when the ip address placed onto the in structure by |
| 125 |
inet aton is translated into network byte order by |
133 |
inet_aton is translated into host byte order by |
| 126 |
<function>ntohl()</function>.</para> |
134 |
<function>ntohl()</function>.</para> |
| 127 |
|
135 |
|
| 128 |
</sect3> |
136 |
</sect3> |
|
Lines 132-144
Link Here
|
| 132 |
|
140 |
|
| 133 |
<para>Finally, the userland program jails the process, and |
141 |
<para>Finally, the userland program jails the process, and |
| 134 |
executes the command specified. Jail now becomes an |
142 |
executes the command specified. Jail now becomes an |
| 135 |
imprisoned process itself and forks a child process which |
143 |
imprisoned process itself and then executes the command |
| 136 |
then executes the command given using &man.execv.3;</para> |
144 |
given using &man.execv.3;</para> |
| 137 |
|
145 |
|
| 138 |
<programlisting><filename>/usr/src/sys/usr.sbin/jail/jail.c</filename> |
146 |
<programlisting><filename>/usr/src/sys/usr.sbin/jail/jail.c</filename> |
| 139 |
i = jail(<![CDATA[&j]]>); |
147 |
i = jail(&j); |
| 140 |
... |
148 |
... |
| 141 |
i = execv(argv[4], argv + 4);</programlisting> |
149 |
if (execv(argv[3], argv + 3) != 0) |
|
|
150 |
err(1, "execv: %s", argv[3]);</programlisting> |
| 142 |
|
151 |
|
| 143 |
<para>As you can see, the jail function is being called, and |
152 |
<para>As you can see, the jail function is being called, and |
| 144 |
its argument is the jail structure which has been filled |
153 |
its argument is the jail structure which has been filled |
|
Lines 171-203
Link Here
|
| 171 |
|
180 |
|
| 172 |
int jail_set_hostname_allowed = 1; |
181 |
int jail_set_hostname_allowed = 1; |
| 173 |
SYSCTL_INT(_security_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW, |
182 |
SYSCTL_INT(_security_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW, |
| 174 |
<![CDATA[&jail]]>_set_hostname_allowed, 0, |
183 |
&jail_set_hostname_allowed, 0, |
| 175 |
"Processes in jail can set their hostnames"); |
184 |
"Processes in jail can set their hostnames"); |
| 176 |
|
185 |
|
| 177 |
int jail_socket_unixiproute_only = 1; |
186 |
int jail_socket_unixiproute_only = 1; |
| 178 |
SYSCTL_INT(_security_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW, |
187 |
SYSCTL_INT(_security_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW, |
| 179 |
<![CDATA[&jail]]>_socket_unixiproute_only, 0, |
188 |
&jail_socket_unixiproute_only, 0, |
| 180 |
"Processes in jail are limited to creating &unix;/IPv4/route sockets only |
189 |
"Processes in jail are limited to creating &unix;/IPv4/route sockets only"); |
| 181 |
"); |
|
|
| 182 |
|
190 |
|
| 183 |
int jail_sysvipc_allowed = 0; |
191 |
int jail_sysvipc_allowed = 0; |
| 184 |
SYSCTL_INT(_security_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW, |
192 |
SYSCTL_INT(_security_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW, |
| 185 |
<![CDATA[&jail]]>_sysvipc_allowed, 0, |
193 |
&jail_sysvipc_allowed, 0, |
| 186 |
"Processes in jail can use System V IPC primitives"); |
194 |
"Processes in jail can use System V IPC primitives"); |
| 187 |
|
195 |
|
| 188 |
static int jail_enforce_statfs = 2; |
196 |
static int jail_enforce_statfs = 2; |
| 189 |
SYSCTL_INT(_security_jail, OID_AUTO, enforce_statfs, CTLFLAG_RW, |
197 |
SYSCTL_INT(_security_jail, OID_AUTO, enforce_statfs, CTLFLAG_RW, |
| 190 |
<![CDATA[&jail]]>_enforce_statfs, 0, |
198 |
&jail_enforce_statfs, 0, |
| 191 |
"Processes in jail cannot see all mounted file systems"); |
199 |
"Processes in jail cannot see all mounted file systems"); |
| 192 |
|
200 |
|
| 193 |
int jail_allow_raw_sockets = 0; |
201 |
int jail_allow_raw_sockets = 0; |
| 194 |
SYSCTL_INT(_security_jail, OID_AUTO, allow_raw_sockets, CTLFLAG_RW, |
202 |
SYSCTL_INT(_security_jail, OID_AUTO, allow_raw_sockets, CTLFLAG_RW, |
| 195 |
<![CDATA[&jail]]>_allow_raw_sockets, 0, |
203 |
&jail_allow_raw_sockets, 0, |
| 196 |
"Prison root can create raw sockets"); |
204 |
"Prison root can create raw sockets"); |
| 197 |
|
205 |
|
| 198 |
int jail_chflags_allowed = 0; |
206 |
int jail_chflags_allowed = 0; |
| 199 |
SYSCTL_INT(_security_jail, OID_AUTO, chflags_allowed, CTLFLAG_RW, |
207 |
SYSCTL_INT(_security_jail, OID_AUTO, chflags_allowed, CTLFLAG_RW, |
| 200 |
<![CDATA[&jail]]>_chflags_allowed, 0, |
208 |
&jail_chflags_allowed, 0, |
| 201 |
"Processes in jail can alter system file flags");</programlisting> |
209 |
"Processes in jail can alter system file flags");</programlisting> |
| 202 |
|
210 |
|
| 203 |
<para>Each of these sysctls can be accessed by the user |
211 |
<para>Each of these sysctls can be accessed by the user |
|
Lines 211-233
Link Here
|
| 211 |
<title>&man.jail.2; system call</title> |
219 |
<title>&man.jail.2; system call</title> |
| 212 |
|
220 |
|
| 213 |
<para>Like all system calls, the &man.jail.2; system call takes |
221 |
<para>Like all system calls, the &man.jail.2; system call takes |
| 214 |
two arguments, <literal>struct proc *p</literal> and |
222 |
two arguments, <literal>struct thread *td</literal> and |
| 215 |
<literal>struct jail_args |
223 |
<literal>struct jail_args *uap</literal>. |
| 216 |
*uap</literal>. <literal>p</literal> is a pointer to a proc |
224 |
<literal>td</literal> is a pointer to the thread |
| 217 |
structure which describes the calling process. In this |
225 |
structure which describes the calling thread. In this |
| 218 |
context, uap is a pointer to a structure which specifies the |
226 |
context, uap is a pointer to the structure which specifies the |
| 219 |
arguments given to &man.jail.2; from the userland program |
227 |
arguments given to &man.jail.2; from the userland program |
| 220 |
<filename>jail.c</filename>. When I described the userland |
228 |
<filename>jail.c</filename>. When I described the userland |
| 221 |
program before, you saw that the &man.jail.2; system call was |
229 |
program before, you saw that the &man.jail.2; system call was |
| 222 |
given a jail structure as its own argument.</para> |
230 |
given a jail structure as its own argument.</para> |
| 223 |
|
231 |
|
| 224 |
<programlisting><filename>/usr/src/sys/kern/kern_jail.c:</filename> |
232 |
<programlisting><filename>/usr/src/sys/kern/kern_jail.c:</filename> |
| 225 |
int |
233 |
/* |
| 226 |
jail(p, uap) |
234 |
* MPSAFE |
| 227 |
struct proc *p; |
235 |
* |
| 228 |
struct jail_args /* { |
236 |
* struct jail_args { |
| 229 |
syscallarg(struct jail *) jail; |
237 |
* struct jail *jail; |
| 230 |
} */ *uap;</programlisting> |
238 |
* }; |
|
|
239 |
*/ |
| 240 |
int |
| 241 |
jail(struct thread *td, struct jail_args *uap)</programlisting> |
| 231 |
|
242 |
|
| 232 |
<para>Therefore, <literal>uap->jail</literal> would access the |
243 |
<para>Therefore, <literal>uap->jail</literal> would access the |
| 233 |
jail structure which was passed to the system call. Next, |
244 |
jail structure which was passed to the system call. Next, |
|
Lines 242-248
Link Here
|
| 242 |
<literal>j</literal>.</para> |
253 |
<literal>j</literal>.</para> |
| 243 |
|
254 |
|
| 244 |
<programlisting><filename>/usr/src/sys/kern/kern_jail.c: </filename> |
255 |
<programlisting><filename>/usr/src/sys/kern/kern_jail.c: </filename> |
| 245 |
error = copyin(uap->jail, <![CDATA[&j]]>, sizeof j);</programlisting> |
256 |
error = copyin(uap->jail, &j, sizeof(j));</programlisting> |
| 246 |
|
257 |
|
| 247 |
<para>There is another important structure defined in |
258 |
<para>There is another important structure defined in |
| 248 |
jail.h. It is the prison structure |
259 |
jail.h. It is the prison structure |
|
Lines 253-262
Link Here
|
| 253 |
|
264 |
|
| 254 |
<programlisting><filename>/usr/include/sys/jail.h</filename>: |
265 |
<programlisting><filename>/usr/include/sys/jail.h</filename>: |
| 255 |
struct prison { |
266 |
struct prison { |
| 256 |
int pr_ref; |
267 |
LIST_ENTRY(prison) pr_list; /* (a) all prisons */ |
| 257 |
char pr_host[MAXHOSTNAMELEN]; |
268 |
int pr_id; /* (c) prison id */ |
| 258 |
u_int32_t pr_ip; |
269 |
int pr_ref; /* (p) refcount */ |
| 259 |
void *pr_linux; |
270 |
char pr_path[MAXPATHLEN]; /* (c) chroot path */ |
|
|
271 |
struct vnode *pr_root; /* (c) vnode to rdir */ |
| 272 |
char pr_host[MAXHOSTNAMELEN]; /* (p) jail hostname */ |
| 273 |
u_int32_t pr_ip; /* (c) ip addr host */ |
| 274 |
void *pr_linux; /* (p) linux abi */ |
| 275 |
int pr_securelevel; /* (p) securelevel */ |
| 276 |
struct task pr_task; /* (d) destroy task */ |
| 277 |
struct mtx pr_mtx; |
| 260 |
};</programlisting> |
278 |
};</programlisting> |
| 261 |
|
279 |
|
| 262 |
<para>The jail() system call then allocates memory for a |
280 |
<para>The jail() system call then allocates memory for a |
|
Lines 264-346
Link Here
|
| 264 |
structures.</para> |
282 |
structures.</para> |
| 265 |
|
283 |
|
| 266 |
<programlisting><filename>/usr/src/sys/kern/kern_jail.c</filename>: |
284 |
<programlisting><filename>/usr/src/sys/kern/kern_jail.c</filename>: |
| 267 |
MALLOC(pr, struct prison *, sizeof *pr , M_PRISON, M_WAITOK); |
285 |
MALLOC(pr, struct prison *, sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO); |
| 268 |
bzero((caddr_t)pr, sizeof *pr); |
286 |
... |
| 269 |
error = copyinstr(j.hostname, <![CDATA[&pr->pr_host]]>, sizeof pr->pr_host, 0); |
287 |
error = copyinstr(j.path, &pr->pr_path, sizeof(pr->pr_path), 0); |
| 270 |
if (error) |
288 |
if (error) |
| 271 |
goto bail;</programlisting> |
289 |
goto e_killmtx; |
| 272 |
|
290 |
... |
| 273 |
<indexterm><primary>chroot</primary></indexterm> |
291 |
error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0); |
| 274 |
|
292 |
if (error) |
| 275 |
<para>Finally, the jail system call chroots the path |
293 |
goto e_dropvnref;</programlisting> |
| 276 |
specified. The chroot function is given two arguments. The |
|
|
| 277 |
first is p, which represents the calling process, the second |
| 278 |
is a pointer to the structure chroot args. The structure |
| 279 |
chroot args contains the path which is to be chrooted. As |
| 280 |
you can see, the path specified in the jail structure is |
| 281 |
copied to the chroot args structure and used.</para> |
| 282 |
|
| 283 |
<programlisting><filename>/usr/src/sys/kern/kern_jail.c</filename>: |
| 284 |
ca.path = j.path; |
| 285 |
error = chroot(p, <![CDATA[&ca]]>);</programlisting> |
| 286 |
|
| 287 |
<para>These next three lines in the source are very important, |
294 |
<para>These next three lines in the source are very important, |
| 288 |
as they specify how the kernel recognizes a process as |
295 |
as they specify how the kernel recognizes a process as |
| 289 |
jailed. Each process on a &unix; system is described by its |
296 |
jailed. Each process on a &unix; system is described by its |
| 290 |
own proc structure. You can see the whole proc structure in |
297 |
own proc structure. You can see the whole proc structure in |
| 291 |
<filename>/usr/include/sys/proc.h</filename>. For example, |
298 |
<filename>/usr/include/sys/proc.h</filename>. For example, |
| 292 |
the p argument in any system call is actually a pointer to |
299 |
the td argument in any system call is actually a pointer to |
| 293 |
that process' proc structure, as stated before. The proc |
300 |
that calling thread's thread structure, as stated before. The |
| 294 |
structure contains nodes which can describe the owner's |
301 |
td->td_proc is a pointer to the calling process' process |
| 295 |
identity (<literal>p_cred</literal>), the process resource |
302 |
structure. The proc structure contains nodes which can describe |
| 296 |
limits (<literal>p_limit</literal>), and so on. In the |
303 |
the owner's identity (<literal>p_ucred</literal>), the process |
| 297 |
definition of the process structure, there is a pointer to a |
304 |
resource limits (<literal>p_limit</literal>), and so on. In the |
| 298 |
prison structure. (<literal>p_prison</literal>).</para> |
305 |
definition of the ucred structure, there is a pointer to a |
|
|
306 |
prison structure. (<literal>cr_prison</literal>).</para> |
| 299 |
|
307 |
|
| 300 |
<programlisting><filename>/usr/include/sys/proc.h: </filename> |
308 |
<programlisting><filename>/usr/include/sys/proc.h: </filename> |
| 301 |
struct proc { |
309 |
struct proc { |
| 302 |
... |
310 |
... |
| 303 |
struct prison *p_prison; |
311 |
struct ucred *p_ucred; |
|
|
312 |
... |
| 313 |
}; |
| 314 |
<filename>/usr/include/sys/ucred.h</filename> |
| 315 |
struct ucred { |
| 316 |
... |
| 317 |
struct prison *cr_prison; |
| 304 |
... |
318 |
... |
| 305 |
};</programlisting> |
319 |
};</programlisting> |
| 306 |
|
320 |
|
| 307 |
<para>In <filename>kern_jail.c</filename>, the function then |
321 |
<para>In <filename>kern_jail.c</filename>, the function then |
| 308 |
copies the pr structure, which is filled with all the |
322 |
calls function jail_attach with a given jid. And the jail_attach |
| 309 |
information from the original jail structure, over to the |
323 |
calls function change_root to change the root directory of the |
| 310 |
<literal>p->p_prison</literal> structure. It then does a |
324 |
calling process. The jail_attach function then creates a new ucred |
| 311 |
bitwise OR of <literal>p->p_flag</literal> with the constant |
325 |
structure, and attaches the newly created ucred structure to the |
| 312 |
<literal>P_JAILED</literal>, meaning that the calling |
326 |
calling process after it has successfully attaches the prison on the |
| 313 |
process is now recognized as jailed. The parent process of |
327 |
cred structure. From then on, the calling process is recognized as |
| 314 |
each process, forked within the jail, is the program jail |
328 |
jailed. When calls function jailed with the newly created ucred |
| 315 |
itself, as it calls the &man.jail.2; system call. When the |
329 |
structure as the argument, it returns 1 to tell that the credential |
| 316 |
program is executed through execve, it inherits the |
330 |
is in a jail. The parent process of each process, forked within |
| 317 |
properties of its parents proc structure, therefore it has |
331 |
the jail, is the program jail itself, as it calls the &man.jail.2; |
| 318 |
the <literal>p->p_flag</literal> set, and the |
332 |
system call. When the program is executed through execve, it |
| 319 |
<literal>p->p_prison</literal> structure is filled.</para> |
333 |
inherits the properties of its parent's ucred structure, therefore it |
|
|
334 |
has the jailed ucred structure.</para> |
| 320 |
|
335 |
|
| 321 |
<programlisting><filename>/usr/src/sys/kern/kern_jail.c</filename> |
336 |
<programlisting><filename>/usr/src/sys/kern/kern_jail.c</filename> |
| 322 |
p->p.prison = pr; |
337 |
int |
| 323 |
p->p.flag |= P.JAILED;</programlisting> |
338 |
jail(struct thread *td, struct jail_args *uap) |
|
|
339 |
{ |
| 340 |
... |
| 341 |
struct jail_attach_args jaa; |
| 342 |
... |
| 343 |
error = jail_attach(td, &jaa); |
| 344 |
if (error) |
| 345 |
goto e_dropprref; |
| 346 |
... |
| 347 |
} |
| 324 |
|
348 |
|
|
|
349 |
int |
| 350 |
jail_attach(struct thread *td, struct jail_attach_args *uap) |
| 351 |
{ |
| 352 |
struct proc *p; |
| 353 |
struct ucred *newcred, *oldcred; |
| 354 |
struct prison *pr; |
| 355 |
... |
| 356 |
p = td->td_proc; |
| 357 |
... |
| 358 |
pr = prison_find(uap->jid); |
| 359 |
... |
| 360 |
change_root(pr->pr_root, td); |
| 361 |
... |
| 362 |
newcred->cr_prison = pr; |
| 363 |
p->p_ucred = newcred; |
| 364 |
... |
| 365 |
}</programlisting> |
| 325 |
<para>When a process is forked from a parent process, the |
366 |
<para>When a process is forked from a parent process, the |
| 326 |
&man.fork.2; system call deals differently with imprisoned |
367 |
&man.fork.2; system call uses crhold to maintain the credential |
| 327 |
processes. In the fork system call, there are two pointers |
368 |
for the newly forked process. It inherently keep the newly forked |
| 328 |
to a <literal>proc</literal> structure <literal>p1</literal> |
369 |
child's credential consistent with its parent, so the child process |
| 329 |
and <literal>p2</literal>. <literal>p1</literal> points to |
370 |
is also jailed.</para> |
| 330 |
the parent's <literal>proc</literal> structure and p2 points |
|
|
| 331 |
to the child's unfilled <literal>proc</literal> |
| 332 |
structure. After copying all relevant data between the |
| 333 |
structures, &man.fork.2; checks if the structure |
| 334 |
<literal>p->p_prison</literal> is filled on |
| 335 |
<literal>p2</literal>. If it is, it increments the |
| 336 |
<literal>pr.ref</literal> by one, and sets the |
| 337 |
<literal>p_flag</literal> to one on the child process.</para> |
| 338 |
|
371 |
|
| 339 |
<programlisting><filename>/usr/src/sys/kern/kern_fork.c</filename>: |
372 |
<programlisting><filename>/usr/src/sys/kern/kern_fork.c</filename>: |
| 340 |
if (p2->p_prison) { |
373 |
p2->p_ucred = crhold(td->td_ucred); |
| 341 |
p2->p_prison->pr_ref++; |
374 |
td2->td_ucred = crhold(p2->p_ucred);</programlisting> |
| 342 |
p2->p_flag |= P_JAILED; |
|
|
| 343 |
}</programlisting> |
| 344 |
|
375 |
|
| 345 |
</sect3> |
376 |
</sect3> |
| 346 |
</sect2> |
377 |
</sect2> |
|
Lines 354-361
Link Here
|
| 354 |
the process is jailed, and if so, returns an error. For |
385 |
the process is jailed, and if so, returns an error. For |
| 355 |
example:</para> |
386 |
example:</para> |
| 356 |
|
387 |
|
| 357 |
<programlisting>if (p->p_prison) |
388 |
<programlisting>if (jailed(td->td_ucred)) |
| 358 |
return EPERM;</programlisting> |
389 |
return (EPERM);</programlisting> |
| 359 |
|
390 |
|
| 360 |
<sect2> |
391 |
<sect2> |
| 361 |
<title>SysV IPC</title> |
392 |
<title>SysV IPC</title> |
|
Lines 369-377
Link Here
|
| 369 |
<literal>msgsend</literal> and <literal>msgrcv</literal>. |
400 |
<literal>msgsend</literal> and <literal>msgrcv</literal>. |
| 370 |
Earlier, I mentioned that there were certain sysctls you could |
401 |
Earlier, I mentioned that there were certain sysctls you could |
| 371 |
turn on or off in order to affect the behavior of Jail. One of |
402 |
turn on or off in order to affect the behavior of Jail. One of |
| 372 |
these sysctls was <literal>jail_sysvipc_allowed</literal>. On |
403 |
these sysctls was <literal>security.jail.sysvipc_allowed</literal>. |
| 373 |
most systems, this sysctl is set to 0. If it were set to 1, it |
404 |
On most systems, this sysctl is set to 0. If it were set to 1, |
| 374 |
would defeat the whole purpose of having a jail; privileged |
405 |
it would defeat the whole purpose of having a jail; privileged |
| 375 |
users from within the jail would be able to affect processes |
406 |
users from within the jail would be able to affect processes |
| 376 |
outside of the environment. The difference between a message |
407 |
outside of the environment. The difference between a message |
| 377 |
and a signal is that the message only consists of the signal |
408 |
and a signal is that the message only consists of the signal |
|
Lines 399-407
Link Here
|
| 399 |
<para>In each of these system calls, there is this |
430 |
<para>In each of these system calls, there is this |
| 400 |
conditional:</para> |
431 |
conditional:</para> |
| 401 |
|
432 |
|
| 402 |
<programlisting><filename>/usr/src/sys/kern/sysv msg.c</filename>: |
433 |
<programlisting><filename>/usr/src/sys/kern/sysv_msg.c</filename>: |
| 403 |
if (!jail.sysvipc.allowed && p->p_prison != NULL) |
434 |
if (!jail_sysvipc_allowed && jailed(td->td_ucred) |
| 404 |
return (ENOSYS);</programlisting> |
435 |
return (ENOSYS);</programlisting> |
| 405 |
|
436 |
|
| 406 |
<indexterm><primary>semaphores</primary></indexterm> |
437 |
<indexterm><primary>semaphores</primary></indexterm> |
| 407 |
<para>Semaphore system calls allow processes to synchronize |
438 |
<para>Semaphore system calls allow processes to synchronize |
|
Lines 430-436
Link Here
|
| 430 |
<para><literal>Key and flag take on the same meaning as they |
461 |
<para><literal>Key and flag take on the same meaning as they |
| 431 |
do in msgget.</literal></para></listitem> |
462 |
do in msgget.</literal></para></listitem> |
| 432 |
|
463 |
|
| 433 |
<listitem><para>&man.semop.2;<literal>(id, ops, num)</literal>: |
464 |
<listitem><para>&man.semop.2;<literal>(semid, sops, nsops)</literal>: |
| 434 |
Semop does the set of semaphore operations in the array of |
465 |
Semop does the set of semaphore operations in the array of |
| 435 |
structures ops, to the set of semaphores identified by |
466 |
structures ops, to the set of semaphores identified by |
| 436 |
id.</para></listitem> |
467 |
id.</para></listitem> |
|
Lines 445-466
Link Here
|
| 445 |
shmat, oshmctl, shmctl, shmget</literal>, and |
476 |
shmat, oshmctl, shmctl, shmget</literal>, and |
| 446 |
<literal>shmsys</literal>.</para> |
477 |
<literal>shmsys</literal>.</para> |
| 447 |
|
478 |
|
| 448 |
<para><filename>/usr/src/sys/kern/sysv shm.c</filename>:</para> |
479 |
<para><filename>/usr/src/sys/kern/sysv_shm.c</filename>:</para> |
| 449 |
|
480 |
|
| 450 |
<itemizedlist> |
481 |
<itemizedlist> |
| 451 |
<listitem><para>&man.shmctl.2;<literal>(id, cmd, buf)</literal>: |
482 |
<listitem><para>&man.shmctl.2;<literal>(shmid, cmd, buf)</literal>: |
| 452 |
shmctl does various control operations on the shared memory |
483 |
shmctl does various control operations on the shared memory |
| 453 |
region identified by id.</para></listitem> |
484 |
region identified by id.</para></listitem> |
| 454 |
|
485 |
|
| 455 |
<listitem><para>&man.shmget.2;<literal>(key, size, |
486 |
<listitem><para>&man.shmget.2;<literal>(key, size, |
| 456 |
flag)</literal>: shmget accesses or creates a shared memory |
487 |
shmflg)</literal>: shmget accesses or creates a shared memory |
| 457 |
region of size bytes.</para></listitem> |
488 |
region of size bytes.</para></listitem> |
| 458 |
|
489 |
|
| 459 |
<listitem><para>&man.shmat.2;<literal>(id, addr, flag)</literal>: |
490 |
<listitem><para>&man.shmat.2;<literal>(shmid, shmaddr, shmflg)</literal>: |
| 460 |
shmat attaches a shared memory region identified by id to the |
491 |
shmat attaches a shared memory region identified by id to the |
| 461 |
address space of a process.</para></listitem> |
492 |
address space of a process.</para></listitem> |
| 462 |
|
493 |
|
| 463 |
<listitem><para>&man.shmdt.2;<literal>(addr)</literal>: shmdt |
494 |
<listitem><para>&man.shmdt.2;<literal>(shmaddr)</literal>: shmdt |
| 464 |
detaches the shared memory region previously attached at |
495 |
detaches the shared memory region previously attached at |
| 465 |
addr.</para></listitem> |
496 |
addr.</para></listitem> |
| 466 |
|
497 |
|
|
Lines 475-481
Link Here
|
| 475 |
lower-level socket functions in a special manner. In order to |
506 |
lower-level socket functions in a special manner. In order to |
| 476 |
determine whether a certain socket is allowed to be created, |
507 |
determine whether a certain socket is allowed to be created, |
| 477 |
it first checks to see if the sysctl |
508 |
it first checks to see if the sysctl |
| 478 |
<literal>jail.socket.unixiproute.only</literal> is set. If |
509 |
<literal>security.jail.socket_unixiproute_only</literal> is set. If |
| 479 |
set, sockets are only allowed to be created if the family |
510 |
set, sockets are only allowed to be created if the family |
| 480 |
specified is either <literal>PF_LOCAL</literal>, |
511 |
specified is either <literal>PF_LOCAL</literal>, |
| 481 |
<literal>PF_INET</literal> or |
512 |
<literal>PF_INET</literal> or |
|
Lines 483-497
Link Here
|
| 483 |
error.</para> |
514 |
error.</para> |
| 484 |
|
515 |
|
| 485 |
<programlisting><filename>/usr/src/sys/kern/uipc_socket.c</filename>: |
516 |
<programlisting><filename>/usr/src/sys/kern/uipc_socket.c</filename>: |
| 486 |
int socreate(dom, aso, type, proto, p) |
517 |
int |
| 487 |
... |
518 |
socreate(dom, aso, type, proto, cred, td) |
| 488 |
register struct protosw *prp; |
519 |
... |
| 489 |
... |
|
|
| 490 |
{ |
520 |
{ |
| 491 |
if (p->p_prison && jail_socket_unixiproute_only && |
521 |
struct protosw *prp; |
| 492 |
prp->pr_domain->dom_family != PR_LOCAL && prp->pr_domain->dom_family != PF_INET |
522 |
... |
| 493 |
&& prp->pr_domain->dom_family != PF_ROUTE) |
523 |
if (jailed(cred) && jail_socket_unixiproute_only && |
| 494 |
return (EPROTONOSUPPORT); |
524 |
prp->pr_domain->dom_family != PF_LOCAL && |
|
|
525 |
prp->pr_domain->dom_family != PF_INET && |
| 526 |
prp->pr_domain->dom_family != PF_ROUTE) { |
| 527 |
return (EPROTONOSUPPORT); |
| 528 |
} |
| 495 |
... |
529 |
... |
| 496 |
}</programlisting> |
530 |
}</programlisting> |
| 497 |
|
531 |
|
|
Lines 506-522
Link Here
|
| 506 |
<para>The Berkeley Packet Filter provides a raw interface to |
540 |
<para>The Berkeley Packet Filter provides a raw interface to |
| 507 |
data link layers in a protocol independent fashion. The |
541 |
data link layers in a protocol independent fashion. The |
| 508 |
function <literal>bpfopen()</literal> opens an Ethernet |
542 |
function <literal>bpfopen()</literal> opens an Ethernet |
| 509 |
device. There is a conditional which disallows any jailed |
543 |
device. It's now controlled by the devfs whether can be used |
| 510 |
processes from accessing this function.</para> |
544 |
in the jail. |
| 511 |
|
|
|
| 512 |
<programlisting><filename>/usr/src/sys/net/bpf.c</filename>: |
| 513 |
static int bpfopen(dev, flags, fmt, p) |
| 514 |
... |
| 515 |
{ |
| 516 |
if (p->p_prison) |
| 517 |
return (EPERM); |
| 518 |
... |
| 519 |
}</programlisting> |
| 520 |
|
545 |
|
| 521 |
</sect2> |
546 |
</sect2> |
| 522 |
|
547 |
|
|
Lines 534-611
Link Here
|
| 534 |
which describes the address on which to bind the service. A |
559 |
which describes the address on which to bind the service. A |
| 535 |
more exact definition is that sockaddr "may be used as a |
560 |
more exact definition is that sockaddr "may be used as a |
| 536 |
template for referring to the identifying tag and length of |
561 |
template for referring to the identifying tag and length of |
| 537 |
each address"[2]. In the function in |
562 |
each address"[2]. In the function |
| 538 |
<literal>pcbbind</literal>, <literal>sin</literal> is a |
563 |
<literal>in_pcbbind_setup</literal>, <literal>sin</literal> is a |
| 539 |
pointer to a sockaddr.in structure, which contains the port, |
564 |
pointer to a sockaddr_in structure, which contains the port, |
| 540 |
address, length and domain family of the socket which is to be |
565 |
address, length and domain family of the socket which is to be |
| 541 |
bound. Basically, this disallows any processes from jail to be |
566 |
bound. Basically, this disallows any processes from jail to be |
| 542 |
able to specify the domain family.</para> |
567 |
able to specify the domain family.</para> |
| 543 |
|
568 |
|
| 544 |
<programlisting><filename>/usr/src/sys/kern/netinet/in_pcb.c</filename>: |
569 |
<programlisting><filename>/usr/src/sys/netinet/in_pcb.c</filename>: |
| 545 |
int in.pcbbind(int, nam, p) |
570 |
int |
| 546 |
... |
571 |
in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp, |
| 547 |
struct sockaddr *nam; |
572 |
u_short *lportp, struct ucred *cred) |
| 548 |
struct proc *p; |
|
|
| 549 |
{ |
573 |
{ |
| 550 |
... |
574 |
... |
| 551 |
struct sockaddr.in *sin; |
575 |
struct sockaddr_in *sin; |
| 552 |
... |
576 |
... |
| 553 |
if (nam) { |
577 |
if (nam) { |
| 554 |
sin = (struct sockaddr.in *)nam; |
578 |
sin = (struct sockaddr_in *)nam; |
| 555 |
... |
579 |
... |
| 556 |
if (sin->sin_addr.s_addr != INADDR_ANY) |
580 |
#ifdef notdef |
| 557 |
if (prison.ip(p, 0, <![CDATA[&sin]]>->sin.addr.s_addr)) |
581 |
/* |
| 558 |
return (EINVAL); |
582 |
* We should check the family, but old programs |
| 559 |
.... |
583 |
* incorrectly fail to initialize it. |
| 560 |
} |
584 |
*/ |
|
|
585 |
if (sin->sin_family != AF_INET) |
| 586 |
return (EAFNOSUPPORT); |
| 587 |
#endif |
| 588 |
if (sin->sin_addr.s_addr != INADDR_ANY) |
| 589 |
if (prison_ip(cred, 0, &sin->sin_addr.s_addr)) |
| 590 |
return(EINVAL); |
| 591 |
... |
| 592 |
} |
| 561 |
... |
593 |
... |
| 562 |
}</programlisting> |
594 |
}</programlisting> |
| 563 |
|
595 |
|
| 564 |
<para>You might be wondering what function |
596 |
<para>You might be wondering what function |
| 565 |
<literal>prison_ip()</literal> does. prison.ip is given three |
597 |
<literal>prison_ip()</literal> does. prison_ip is given three |
| 566 |
arguments, the current process (represented by |
598 |
arguments, a pointer to the credential(represented by |
| 567 |
<literal>p</literal>), any flags, and an ip address. It |
599 |
<literal>cred</literal>), any flags, and an ip address. It |
| 568 |
returns 1 if the ip address belongs to a jail or 0 if it does |
600 |
returns 1 if the ip address does NOT belong to the jail or |
| 569 |
not. As you can see from the code, if it is indeed an ip |
601 |
0 otherwise. As you can see from the code, if it is indeed |
| 570 |
address belonging to a jail, the protcol is not allowed to |
602 |
an ip address not belonging to the jail, the protcol is |
| 571 |
bind to a certain port.</para> |
603 |
not allowed to bind to a certain port.</para> |
| 572 |
|
604 |
|
| 573 |
<programlisting><filename>/usr/src/sys/kern/kern_jail.c:</filename> |
605 |
<programlisting><filename>/usr/src/sys/kern/kern_jail.c:</filename> |
| 574 |
int prison_ip(struct proc *p, int flag, u_int32_t *ip) { |
606 |
int |
| 575 |
u_int32_t tmp; |
607 |
prison_ip(struct ucred *cred, int flag, u_int32_t *ip) |
| 576 |
|
608 |
{ |
| 577 |
if (!p->p_prison) |
609 |
u_int32_t tmp; |
| 578 |
return (0); |
|
|
| 579 |
if (flag) |
| 580 |
tmp = *ip; |
| 581 |
else tmp = ntohl (*ip); |
| 582 |
|
| 583 |
if (tmp == INADDR_ANY) { |
| 584 |
if (flag) |
| 585 |
*ip = p->p_prison->pr_ip; |
| 586 |
else *ip = htonl(p->p_prison->pr_ip); |
| 587 |
return (0); |
| 588 |
} |
| 589 |
|
610 |
|
| 590 |
if (p->p_prison->pr_ip != tmp) |
611 |
if (!jailed(cred)) |
| 591 |
return (1); |
612 |
return (0); |
| 592 |
return (0); |
613 |
if (flag) |
|
|
614 |
tmp = *ip; |
| 615 |
else |
| 616 |
tmp = ntohl(*ip); |
| 617 |
if (tmp == INADDR_ANY) { |
| 618 |
if (flag) |
| 619 |
*ip = cred->cr_prison->pr_ip; |
| 620 |
else |
| 621 |
*ip = htonl(cred->cr_prison->pr_ip); |
| 622 |
return (0); |
| 623 |
} |
| 624 |
if (tmp == INADDR_LOOPBACK) { |
| 625 |
if (flag) |
| 626 |
*ip = cred->cr_prison->pr_ip; |
| 627 |
else |
| 628 |
*ip = htonl(cred->cr_prison->pr_ip); |
| 629 |
return (0); |
| 630 |
} |
| 631 |
if (cred->cr_prison->pr_ip != tmp) |
| 632 |
return (1); |
| 633 |
return (0); |
| 593 |
}</programlisting> |
634 |
}</programlisting> |
| 594 |
|
635 |
|
| 595 |
<para>Jailed users are not allowed to bind services to an ip |
636 |
<para>Jailed users are not allowed to bind services to an ip |
| 596 |
which does not belong to the jail. The restriction is also |
637 |
which does not belong to the jail. The restriction is also |
| 597 |
written within the function <literal>in_pcbbind</literal>:</para> |
638 |
written within the function <literal>in_pcbbind_setup</literal>:</para> |
| 598 |
|
639 |
|
| 599 |
<programlisting><filename>/usr/src/sys/net inet/in_pcb.c</filename> |
640 |
<programlisting><filename>/usr/src/sys/netinet/in_pcb.c</filename> |
| 600 |
if (nam) { |
641 |
if (nam) { |
| 601 |
... |
642 |
... |
| 602 |
lport = sin->sin.port; |
643 |
lport = sin->sin.port; |
| 603 |
... if (lport) { |
644 |
... if (lport) { |
| 604 |
... |
645 |
... |
| 605 |
if (p && p->p_prison) |
646 |
if (jailed(cred)) |
| 606 |
prison = 1; |
647 |
prison = 1; |
|
|
648 |
... |
| 607 |
if (prison && |
649 |
if (prison && |
| 608 |
prison_ip(p, 0, <![CDATA[&sin]]>->sin_addr.s_addr)) |
650 |
prison_ip(cred, 0, &sin->sin_addr.s_addr)) |
| 609 |
return (EADDRNOTAVAIL);</programlisting> |
651 |
return (EADDRNOTAVAIL);</programlisting> |
| 610 |
|
652 |
|
| 611 |
</sect2> |
653 |
</sect2> |
|
Lines 619-632
Link Here
|
| 619 |
the securelevel is greater than 0.</para> |
661 |
the securelevel is greater than 0.</para> |
| 620 |
|
662 |
|
| 621 |
<programlisting>/usr/src/sys/ufs/ufs/ufs_vnops.c: |
663 |
<programlisting>/usr/src/sys/ufs/ufs/ufs_vnops.c: |
| 622 |
int ufs.setattr(ap) |
664 |
static int |
| 623 |
... |
665 |
ufs_setattr(ap) |
|
|
666 |
... |
| 624 |
{ |
667 |
{ |
| 625 |
if ((cred->cr.uid == 0) && (p->prison == NULL)) { |
668 |
... |
| 626 |
if ((ip->i_flags |
669 |
if (!suser_cred(cred, |
| 627 |
& (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) && |
670 |
jail_chflags_allowed ? SUSER_ALLOWJAIL : 0)) { |
| 628 |
securelevel > 0) |
671 |
if (ip->i_flags |
| 629 |
return (EPERM); |
672 |
& (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) { |
|
|
673 |
error = securelevel_gt(cred, 0); |
| 674 |
if (error) |
| 675 |
return (error); |
| 676 |
} |
| 677 |
... |
| 630 |
}</programlisting> |
678 |
}</programlisting> |
| 631 |
|
679 |
|
| 632 |
</sect2> |
680 |
</sect2> |