2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
9 * $FreeBSD: src/sys/kern/kern_jail.c,v 1.6.2.3 2001/08/17 01:00:26 rwatson Exp $
10 * $DragonFly: src/sys/kern/kern_jail.c,v 1.7 2005/01/31 22:29:59 joerg Exp $
14 #include <sys/param.h>
15 #include <sys/types.h>
16 #include <sys/kernel.h>
17 #include <sys/kinfo.h>
18 #include <sys/systm.h>
19 #include <sys/errno.h>
20 #include <sys/sysproto.h>
21 #include <sys/malloc.h>
22 #include <sys/nlookup.h>
23 #include <sys/namecache.h>
26 #include <sys/socket.h>
27 #include <sys/sysctl.h>
28 #include <sys/kern_syscall.h>
30 #include <netinet/in.h>
32 static struct prison
*prison_find(int);
34 MALLOC_DEFINE(M_PRISON
, "prison", "Prison structures");
36 SYSCTL_NODE(, OID_AUTO
, jail
, CTLFLAG_RW
, 0,
39 int jail_set_hostname_allowed
= 1;
40 SYSCTL_INT(_jail
, OID_AUTO
, set_hostname_allowed
, CTLFLAG_RW
,
41 &jail_set_hostname_allowed
, 0,
42 "Processes in jail can set their hostnames");
44 int jail_socket_unixiproute_only
= 1;
45 SYSCTL_INT(_jail
, OID_AUTO
, socket_unixiproute_only
, CTLFLAG_RW
,
46 &jail_socket_unixiproute_only
, 0,
47 "Processes in jail are limited to creating UNIX/IPv4/route sockets only");
49 int jail_sysvipc_allowed
= 0;
50 SYSCTL_INT(_jail
, OID_AUTO
, sysvipc_allowed
, CTLFLAG_RW
,
51 &jail_sysvipc_allowed
, 0,
52 "Processes in jail can use System V IPC primitives");
57 LIST_HEAD(prisonlist
, prison
);
58 struct prisonlist allprison
= LIST_HEAD_INITIALIZER(&allprison
);
61 kern_jail_attach(int jid
)
63 struct proc
*p
= curthread
->td_proc
;
67 pr
= prison_find(jid
);
71 error
= kern_chroot(pr
->pr_root
);
77 p
->p_ucred
->cr_prison
= pr
;
78 p
->p_flag
|= P_JAILED
;
86 * jail_args(syscallarg(struct jail *) jail)
89 jail(struct jail_args
*uap
)
91 struct prison
*pr
, *tpr
;
93 struct thread
*td
= curthread
;
95 struct nlookupdata nd
;
100 error
= copyin(uap
->jail
, &j
, sizeof j
);
105 MALLOC(pr
, struct prison
*, sizeof *pr
, M_PRISON
, M_WAITOK
| M_ZERO
);
107 error
= copyinstr(j
.hostname
, &pr
->pr_host
, sizeof pr
->pr_host
, 0);
110 error
= nlookup_init(&nd
, j
.path
, UIO_USERSPACE
, NLC_FOLLOW
);
112 goto nlookup_init_clean
;
113 error
= nlookup(&nd
);
115 goto nlookup_init_clean
;
116 pr
->pr_root
= cache_hold(nd
.nl_ncp
);
118 pr
->pr_ip
= j
.ip_number
;
119 varsymset_init(&pr
->pr_varsymset
, NULL
);
121 tryprid
= lastprid
+ 1;
122 if (tryprid
== JAIL_MAX
)
125 LIST_FOREACH(tpr
, &allprison
, pr_list
) {
126 if (tpr
->pr_id
!= tryprid
)
129 if (tryprid
== JAIL_MAX
) {
135 pr
->pr_id
= lastprid
= tryprid
;
136 LIST_INSERT_HEAD(&allprison
, pr
, pr_list
);
139 error
= kern_jail_attach(pr
->pr_id
);
141 goto jail_attach_clean
;
147 LIST_REMOVE(pr
, pr_list
);
149 varsymset_clean(&pr
->pr_varsymset
);
158 * int jail_attach(int jid);
161 jail_attach(struct jail_attach_args
*uap
)
163 struct thread
*td
= curthread
;
170 return(kern_jail_attach(uap
->jid
));
174 prison_ip(struct thread
*td
, int flag
, u_int32_t
*ip
)
179 if (td
->td_proc
== NULL
)
181 if ((pr
= td
->td_proc
->p_ucred
->cr_prison
) == NULL
)
187 if (tmp
== INADDR_ANY
) {
191 *ip
= htonl(pr
->pr_ip
);
194 if (tmp
== INADDR_LOOPBACK
) {
198 *ip
= htonl(pr
->pr_ip
);
201 if (pr
->pr_ip
!= tmp
)
207 prison_remote_ip(struct thread
*td
, int flag
, u_int32_t
*ip
)
212 if (td
== NULL
|| td
->td_proc
== NULL
)
214 if ((pr
= td
->td_proc
->p_ucred
->cr_prison
) == NULL
)
220 if (tmp
== INADDR_LOOPBACK
) {
224 *ip
= htonl(pr
->pr_ip
);
230 prison_if(struct thread
*td
, struct sockaddr
*sa
)
233 struct sockaddr_in
*sai
= (struct sockaddr_in
*) sa
;
236 if (td
->td_proc
== NULL
)
238 pr
= td
->td_proc
->p_ucred
->cr_prison
;
240 if ((sai
->sin_family
!= AF_INET
) && jail_socket_unixiproute_only
)
242 else if (sai
->sin_family
!= AF_INET
)
244 else if (pr
->pr_ip
!= ntohl(sai
->sin_addr
.s_addr
))
252 * Returns a prison instance, or NULL on failure.
254 static struct prison
*
255 prison_find(int prid
)
259 LIST_FOREACH(pr
, &allprison
, pr_list
) {
260 if (pr
->pr_id
== prid
)
267 sysctl_jail_list(SYSCTL_HANDLER_ARGS
)
270 struct kinfo_prison
*xp
, *sxp
;
274 p
= curthread
->td_proc
;
276 if (jailed(p
->p_ucred
))
284 sxp
= xp
= malloc(sizeof(*xp
) * count
, M_TEMP
, M_WAITOK
| M_ZERO
);
285 if (count
< prisoncount
) {
291 LIST_FOREACH(pr
, &allprison
, pr_list
) {
292 char *fullpath
, *freepath
;
293 xp
->pr_version
= KINFO_PRISON_VERSION
;
294 xp
->pr_id
= pr
->pr_id
;
295 error
= cache_fullpath(p
, pr
->pr_root
, &fullpath
, &freepath
);
297 strlcpy(xp
->pr_path
, fullpath
, sizeof(xp
->pr_path
));
298 free(freepath
, M_TEMP
);
300 bzero(xp
->pr_path
, sizeof(xp
->pr_path
));
302 strlcpy(xp
->pr_host
, pr
->pr_host
, sizeof(xp
->pr_host
));
303 xp
->pr_ip
= pr
->pr_ip
;
307 error
= SYSCTL_OUT(req
, sxp
, sizeof(*sxp
) * count
);
312 SYSCTL_OID(_jail
, OID_AUTO
, list
, CTLTYPE_STRUCT
| CTLFLAG_RD
, NULL
, 0,
313 sysctl_jail_list
, "S", "List of active jails");
316 prison_hold(struct prison
*pr
)
322 prison_free(struct prison
*pr
)
324 KKASSERT(pr
->pr_ref
>= 1);
326 if (--pr
->pr_ref
> 0)
329 LIST_REMOVE(pr
, pr_list
);
332 if (pr
->pr_linux
!= NULL
)
333 free(pr
->pr_linux
, M_PRISON
);
334 varsymset_clean(&pr
->pr_varsymset
);
335 cache_drop(pr
->pr_root
);