kern_jail.c revision 82710
146197Sphk/*
246197Sphk * ----------------------------------------------------------------------------
346197Sphk * "THE BEER-WARE LICENSE" (Revision 42):
446197Sphk * <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
546197Sphk * can do whatever you want with this stuff. If we meet some day, and you think
646197Sphk * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
746197Sphk * ----------------------------------------------------------------------------
846197Sphk *
950477Speter * $FreeBSD: head/sys/kern/kern_jail.c 82710 2001-09-01 03:04:31Z dillon $
1046197Sphk *
1146197Sphk */
1246155Sphk
1346155Sphk#include <sys/param.h>
1446155Sphk#include <sys/types.h>
1546155Sphk#include <sys/kernel.h>
1646155Sphk#include <sys/systm.h>
1746155Sphk#include <sys/errno.h>
1846155Sphk#include <sys/sysproto.h>
1946155Sphk#include <sys/malloc.h>
2046155Sphk#include <sys/proc.h>
2146155Sphk#include <sys/jail.h>
2246155Sphk#include <sys/socket.h>
2357163Srwatson#include <sys/sysctl.h>
2446155Sphk#include <net/if.h>
2546155Sphk#include <netinet/in.h>
2646155Sphk
2746155SphkMALLOC_DEFINE(M_PRISON, "prison", "Prison structures");
2846155Sphk
2957163SrwatsonSYSCTL_NODE(, OID_AUTO, jail, CTLFLAG_RW, 0,
3057163Srwatson    "Jail rules");
3157163Srwatson
3257163Srwatsonint	jail_set_hostname_allowed = 1;
3357163SrwatsonSYSCTL_INT(_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,
3457163Srwatson    &jail_set_hostname_allowed, 0,
3557163Srwatson    "Processes in jail can set their hostnames");
3657163Srwatson
3761235Srwatsonint	jail_socket_unixiproute_only = 1;
3861235SrwatsonSYSCTL_INT(_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW,
3961235Srwatson    &jail_socket_unixiproute_only, 0,
4061235Srwatson    "Processes in jail are limited to creating UNIX/IPv4/route sockets only");
4161235Srwatson
4268024Srwatsonint	jail_sysvipc_allowed = 0;
4368024SrwatsonSYSCTL_INT(_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
4468024Srwatson    &jail_sysvipc_allowed, 0,
4568024Srwatson    "Processes in jail can use System V IPC primitives");
4668024Srwatson
4782710Sdillon/*
4882710Sdillon * MPSAFE
4982710Sdillon */
5046155Sphkint
5146155Sphkjail(p, uap)
5272786Srwatson	struct proc *p;
5372786Srwatson	struct jail_args /* {
5472786Srwatson		syscallarg(struct jail *) jail;
5572786Srwatson	} */ *uap;
5646155Sphk{
5746155Sphk	int error;
5846155Sphk	struct prison *pr;
5946155Sphk	struct jail j;
6046155Sphk	struct chroot_args ca;
6146155Sphk
6282710Sdillon	mtx_lock(&Giant);
6382710Sdillon
6472786Srwatson	/* Implicitly fail if already in jail.  */
6546155Sphk	error = suser(p);
6646155Sphk	if (error)
6782710Sdillon		goto done2;
6846155Sphk	error = copyin(uap->jail, &j, sizeof j);
6946155Sphk	if (error)
7082710Sdillon		goto done2;
7182710Sdillon	if (j.version != 0) {
7282710Sdillon		error = EINVAL;
7382710Sdillon		goto done2;
7482710Sdillon	}
7569781Sdwmalone	MALLOC(pr, struct prison *, sizeof *pr , M_PRISON, M_WAITOK | M_ZERO);
7646155Sphk	error = copyinstr(j.hostname, &pr->pr_host, sizeof pr->pr_host, 0);
7746155Sphk	if (error)
7846155Sphk		goto bail;
7946155Sphk	pr->pr_ip = j.ip_number;
8046155Sphk
8146155Sphk	ca.path = j.path;
8246155Sphk	error = chroot(p, &ca);
8346155Sphk	if (error)
8446155Sphk		goto bail;
8546155Sphk
8672786Srwatson	p->p_ucred = crcopy(p->p_ucred);
8772786Srwatson	p->p_ucred->cr_prison = pr;
8872786Srwatson	pr->pr_ref = 1;
8982710Sdillon	mtx_unlock(&Giant);
9046155Sphk	return (0);
9146155Sphk
9246155Sphkbail:
9346155Sphk	FREE(pr, M_PRISON);
9482710Sdillondone2:
9582710Sdillon	mtx_unlock(&Giant);
9646155Sphk	return (error);
9746155Sphk}
9846155Sphk
9972786Srwatsonvoid
10072786Srwatsonprison_free(struct prison *pr)
10172786Srwatson{
10272786Srwatson
10372786Srwatson	pr->pr_ref--;
10472786Srwatson	if (pr->pr_ref == 0) {
10572786Srwatson		if (pr->pr_linux != NULL)
10672786Srwatson			FREE(pr->pr_linux, M_PRISON);
10772786Srwatson		FREE(pr, M_PRISON);
10872786Srwatson	}
10972786Srwatson}
11072786Srwatson
11172786Srwatsonvoid
11272786Srwatsonprison_hold(struct prison *pr)
11372786Srwatson{
11472786Srwatson
11572786Srwatson	pr->pr_ref++;
11672786Srwatson}
11772786Srwatson
11846155Sphkint
11972786Srwatsonprison_ip(struct ucred *cred, int flag, u_int32_t *ip)
12046155Sphk{
12146155Sphk	u_int32_t tmp;
12246155Sphk
12372786Srwatson	if (!jailed(cred))
12446155Sphk		return (0);
12546155Sphk	if (flag)
12646155Sphk		tmp = *ip;
12746155Sphk	else
12846155Sphk		tmp = ntohl(*ip);
12946155Sphk	if (tmp == INADDR_ANY) {
13046155Sphk		if (flag)
13172786Srwatson			*ip = cred->cr_prison->pr_ip;
13246155Sphk		else
13372786Srwatson			*ip = htonl(cred->cr_prison->pr_ip);
13446155Sphk		return (0);
13546155Sphk	}
13681114Srwatson	if (tmp == INADDR_LOOPBACK) {
13781114Srwatson		if (flag)
13881114Srwatson			*ip = cred->cr_prison->pr_ip;
13981114Srwatson		else
14081114Srwatson			*ip = htonl(cred->cr_prison->pr_ip);
14181114Srwatson		return (0);
14281114Srwatson	}
14372786Srwatson	if (cred->cr_prison->pr_ip != tmp)
14446155Sphk		return (1);
14546155Sphk	return (0);
14646155Sphk}
14746155Sphk
14846155Sphkvoid
14972786Srwatsonprison_remote_ip(struct ucred *cred, int flag, u_int32_t *ip)
15046155Sphk{
15146155Sphk	u_int32_t tmp;
15246155Sphk
15372786Srwatson	if (!jailed(cred))
15446155Sphk		return;
15546155Sphk	if (flag)
15646155Sphk		tmp = *ip;
15746155Sphk	else
15846155Sphk		tmp = ntohl(*ip);
15981114Srwatson	if (tmp == INADDR_LOOPBACK) {
16046155Sphk		if (flag)
16172786Srwatson			*ip = cred->cr_prison->pr_ip;
16246155Sphk		else
16372786Srwatson			*ip = htonl(cred->cr_prison->pr_ip);
16446155Sphk		return;
16546155Sphk	}
16646155Sphk	return;
16746155Sphk}
16846155Sphk
16946155Sphkint
17072786Srwatsonprison_if(struct ucred *cred, struct sockaddr *sa)
17146155Sphk{
17246155Sphk	struct sockaddr_in *sai = (struct sockaddr_in*) sa;
17346155Sphk	int ok;
17446155Sphk
17561235Srwatson	if ((sai->sin_family != AF_INET) && jail_socket_unixiproute_only)
17661235Srwatson		ok = 1;
17761235Srwatson	else if (sai->sin_family != AF_INET)
17846155Sphk		ok = 0;
17972786Srwatson	else if (cred->cr_prison->pr_ip != ntohl(sai->sin_addr.s_addr))
18046155Sphk		ok = 1;
18146155Sphk	else
18246155Sphk		ok = 0;
18346155Sphk	return (ok);
18446155Sphk}
18572786Srwatson
18672786Srwatson/*
18772786Srwatson * Return 0 if jails permit p1 to frob p2, otherwise ESRCH.
18872786Srwatson */
18972786Srwatsonint
19072786Srwatsonprison_check(cred1, cred2)
19172786Srwatson	struct ucred *cred1, *cred2;
19272786Srwatson{
19372786Srwatson
19472786Srwatson	if (jailed(cred1)) {
19572786Srwatson		if (!jailed(cred2))
19672786Srwatson			return (ESRCH);
19772786Srwatson		if (cred2->cr_prison != cred1->cr_prison)
19872786Srwatson			return (ESRCH);
19972786Srwatson	}
20072786Srwatson
20172786Srwatson	return (0);
20272786Srwatson}
20372786Srwatson
20472786Srwatson/*
20572786Srwatson * Return 1 if the passed credential is in a jail, otherwise 0.
20672786Srwatson */
20772786Srwatsonint
20872786Srwatsonjailed(cred)
20972786Srwatson	struct ucred *cred;
21072786Srwatson{
21172786Srwatson
21272786Srwatson	return (cred->cr_prison != NULL);
21372786Srwatson}
214