Deleted Added
sdiff udiff text old ( 168399 ) new ( 168401 )
full compact
1/*-
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 * ----------------------------------------------------------------------------
8 */
9
10#include <sys/cdefs.h>
11__FBSDID("$FreeBSD: head/sys/kern/kern_jail.c 168399 2007-04-05 21:34:54Z pjd $");
12
13#include "opt_mac.h"
14
15#include <sys/param.h>
16#include <sys/types.h>
17#include <sys/kernel.h>
18#include <sys/systm.h>
19#include <sys/errno.h>
20#include <sys/sysproto.h>
21#include <sys/malloc.h>
22#include <sys/priv.h>
23#include <sys/proc.h>
24#include <sys/taskqueue.h>
25#include <sys/jail.h>
26#include <sys/lock.h>
27#include <sys/mutex.h>
28#include <sys/namei.h>
29#include <sys/mount.h>
30#include <sys/queue.h>
31#include <sys/socket.h>
32#include <sys/syscallsubr.h>
33#include <sys/sysctl.h>
34#include <sys/vnode.h>
35#include <net/if.h>

--- 36 unchanged lines hidden (view full) ---

72 &jail_chflags_allowed, 0,
73 "Processes in jail can alter system file flags");
74
75int jail_mount_allowed = 0;
76SYSCTL_INT(_security_jail, OID_AUTO, mount_allowed, CTLFLAG_RW,
77 &jail_mount_allowed, 0,
78 "Processes in jail can mount/unmount jail-friendly file systems");
79
80/* allprison, lastprid, and prisoncount are protected by allprison_mtx. */
81struct prisonlist allprison;
82struct mtx allprison_mtx;
83int lastprid = 0;
84int prisoncount = 0;
85
86static void init_prison(void *);
87static void prison_complete(void *context, int pending);
88static int sysctl_jail_list(SYSCTL_HANDLER_ARGS);
89
90static void
91init_prison(void *data __unused)
92{
93
94 mtx_init(&allprison_mtx, "allprison", NULL, MTX_DEF);
95 LIST_INIT(&allprison);
96}
97
98SYSINIT(prison, SI_SUB_INTRINSIC, SI_ORDER_ANY, init_prison, NULL);
99
100/*
101 * struct jail_args {
102 * struct jail *jail;
103 * };
104 */
105int
106jail(struct thread *td, struct jail_args *uap)
107{
108 struct nameidata nd;
109 struct prison *pr, *tpr;
110 struct jail j;
111 struct jail_attach_args jaa;
112 int vfslocked, error, tryprid;
113
114 error = copyin(uap->jail, &j, sizeof(j));
115 if (error)
116 return (error);
117 if (j.version != 0)

--- 16 unchanged lines hidden (view full) ---

134 NDFREE(&nd, NDF_ONLY_PNBUF);
135 VFS_UNLOCK_GIANT(vfslocked);
136 error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0);
137 if (error)
138 goto e_dropvnref;
139 pr->pr_ip = j.ip_number;
140 pr->pr_linux = NULL;
141 pr->pr_securelevel = securelevel;
142
143 /* Determine next pr_id and add prison to allprison list. */
144 mtx_lock(&allprison_mtx);
145 tryprid = lastprid + 1;
146 if (tryprid == JAIL_MAX)
147 tryprid = 1;
148next:
149 LIST_FOREACH(tpr, &allprison, pr_list) {
150 if (tpr->pr_id == tryprid) {
151 tryprid++;
152 if (tryprid == JAIL_MAX) {
153 mtx_unlock(&allprison_mtx);
154 error = EAGAIN;
155 goto e_dropvnref;
156 }
157 goto next;
158 }
159 }
160 pr->pr_id = jaa.jid = lastprid = tryprid;
161 LIST_INSERT_HEAD(&allprison, pr, pr_list);
162 prisoncount++;
163 mtx_unlock(&allprison_mtx);
164
165 error = jail_attach(td, &jaa);
166 if (error)
167 goto e_dropprref;
168 mtx_lock(&pr->pr_mtx);
169 pr->pr_ref--;
170 mtx_unlock(&pr->pr_mtx);
171 td->td_retval[0] = jaa.jid;
172 return (0);
173e_dropprref:
174 mtx_lock(&allprison_mtx);
175 LIST_REMOVE(pr, pr_list);
176 prisoncount--;
177 mtx_unlock(&allprison_mtx);
178e_dropvnref:
179 vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount);
180 vrele(pr->pr_root);
181 VFS_UNLOCK_GIANT(vfslocked);
182e_killmtx:
183 mtx_destroy(&pr->pr_mtx);
184 FREE(pr, M_PRISON);
185 return (error);

--- 20 unchanged lines hidden (view full) ---

206 * a process root from one prison, but attached to the jail
207 * of another.
208 */
209 error = priv_check(td, PRIV_JAIL_ATTACH);
210 if (error)
211 return (error);
212
213 p = td->td_proc;
214 mtx_lock(&allprison_mtx);
215 pr = prison_find(uap->jid);
216 if (pr == NULL) {
217 mtx_unlock(&allprison_mtx);
218 return (EINVAL);
219 }
220 pr->pr_ref++;
221 mtx_unlock(&pr->pr_mtx);
222 mtx_unlock(&allprison_mtx);
223
224 vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount);
225 vn_lock(pr->pr_root, LK_EXCLUSIVE | LK_RETRY, td);
226 if ((error = change_dir(pr->pr_root, td)) != 0)
227 goto e_unlock;
228#ifdef MAC
229 if ((error = mac_check_vnode_chroot(td->td_ucred, pr->pr_root)))
230 goto e_unlock;

--- 24 unchanged lines hidden (view full) ---

255/*
256 * Returns a locked prison instance, or NULL on failure.
257 */
258struct prison *
259prison_find(int prid)
260{
261 struct prison *pr;
262
263 mtx_assert(&allprison_mtx, MA_OWNED);
264 LIST_FOREACH(pr, &allprison, pr_list) {
265 if (pr->pr_id == prid) {
266 mtx_lock(&pr->pr_mtx);
267 return (pr);
268 }
269 }
270 return (NULL);
271}
272
273void
274prison_free(struct prison *pr)
275{
276
277 mtx_lock(&allprison_mtx);
278 mtx_lock(&pr->pr_mtx);
279 pr->pr_ref--;
280 if (pr->pr_ref == 0) {
281 LIST_REMOVE(pr, pr_list);
282 mtx_unlock(&pr->pr_mtx);
283 prisoncount--;
284 mtx_unlock(&allprison_mtx);
285
286 TASK_INIT(&pr->pr_task, 0, prison_complete, pr);
287 taskqueue_enqueue(taskqueue_thread, &pr->pr_task);
288 return;
289 }
290 mtx_unlock(&pr->pr_mtx);
291 mtx_unlock(&allprison_mtx);
292}
293
294static void
295prison_complete(void *context, int pending)
296{
297 struct prison *pr;
298 int vfslocked;
299

--- 395 unchanged lines hidden (view full) ---

695 * In all remaining cases, deny the privilege request. This
696 * includes almost all network privileges, many system
697 * configuration privileges.
698 */
699 return (EPERM);
700 }
701}
702
703static int
704sysctl_jail_list(SYSCTL_HANDLER_ARGS)
705{
706 struct xprison *xp, *sxp;
707 struct prison *pr;
708 int count, error;
709
710 if (jailed(req->td->td_ucred))
711 return (0);
712retry:
713 mtx_lock(&allprison_mtx);
714 count = prisoncount;
715 mtx_unlock(&allprison_mtx);
716
717 if (count == 0)
718 return (0);
719
720 sxp = xp = malloc(sizeof(*xp) * count, M_TEMP, M_WAITOK | M_ZERO);
721 mtx_lock(&allprison_mtx);
722 if (count != prisoncount) {
723 mtx_unlock(&allprison_mtx);
724 free(sxp, M_TEMP);
725 goto retry;
726 }
727
728 LIST_FOREACH(pr, &allprison, pr_list) {
729 mtx_lock(&pr->pr_mtx);
730 xp->pr_version = XPRISON_VERSION;
731 xp->pr_id = pr->pr_id;
732 strlcpy(xp->pr_path, pr->pr_path, sizeof(xp->pr_path));
733 strlcpy(xp->pr_host, pr->pr_host, sizeof(xp->pr_host));
734 xp->pr_ip = pr->pr_ip;
735 mtx_unlock(&pr->pr_mtx);
736 xp++;
737 }
738 mtx_unlock(&allprison_mtx);
739
740 error = SYSCTL_OUT(req, sxp, sizeof(*sxp) * count);
741 free(sxp, M_TEMP);
742 return (error);
743}
744
745SYSCTL_OID(_security_jail, OID_AUTO, list, CTLTYPE_STRUCT | CTLFLAG_RD,
746 NULL, 0, sysctl_jail_list, "S", "List of active jails");

--- 13 unchanged lines hidden ---