kern_jail.c revision 72786
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 72786 2001-02-21 06:39:57Z rwatson $
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
4746155Sphkint
4846155Sphkjail(p, uap)
4972786Srwatson	struct proc *p;
5072786Srwatson	struct jail_args /* {
5172786Srwatson		syscallarg(struct jail *) jail;
5272786Srwatson	} */ *uap;
5346155Sphk{
5446155Sphk	int error;
5546155Sphk	struct prison *pr;
5646155Sphk	struct jail j;
5746155Sphk	struct chroot_args ca;
5846155Sphk
5972786Srwatson	/* Implicitly fail if already in jail.  */
6046155Sphk	error = suser(p);
6146155Sphk	if (error)
6246155Sphk		return (error);
6346155Sphk	error = copyin(uap->jail, &j, sizeof j);
6446155Sphk	if (error)
6546155Sphk		return (error);
6651398Sphk	if (j.version != 0)
6751398Sphk		return (EINVAL);
6869781Sdwmalone	MALLOC(pr, struct prison *, sizeof *pr , M_PRISON, M_WAITOK | M_ZERO);
6946155Sphk	error = copyinstr(j.hostname, &pr->pr_host, sizeof pr->pr_host, 0);
7046155Sphk	if (error)
7146155Sphk		goto bail;
7246155Sphk	pr->pr_ip = j.ip_number;
7346155Sphk
7446155Sphk	ca.path = j.path;
7546155Sphk	error = chroot(p, &ca);
7646155Sphk	if (error)
7746155Sphk		goto bail;
7846155Sphk
7972786Srwatson	p->p_ucred = crcopy(p->p_ucred);
8072786Srwatson	p->p_ucred->cr_prison = pr;
8172786Srwatson	pr->pr_ref = 1;
8246155Sphk	return (0);
8346155Sphk
8446155Sphkbail:
8546155Sphk	FREE(pr, M_PRISON);
8646155Sphk	return (error);
8746155Sphk}
8846155Sphk
8972786Srwatsonvoid
9072786Srwatsonprison_free(struct prison *pr)
9172786Srwatson{
9272786Srwatson
9372786Srwatson	pr->pr_ref--;
9472786Srwatson	if (pr->pr_ref == 0) {
9572786Srwatson		if (pr->pr_linux != NULL)
9672786Srwatson			FREE(pr->pr_linux, M_PRISON);
9772786Srwatson		FREE(pr, M_PRISON);
9872786Srwatson	}
9972786Srwatson}
10072786Srwatson
10172786Srwatsonvoid
10272786Srwatsonprison_hold(struct prison *pr)
10372786Srwatson{
10472786Srwatson
10572786Srwatson	pr->pr_ref++;
10672786Srwatson}
10772786Srwatson
10846155Sphkint
10972786Srwatsonprison_ip(struct ucred *cred, int flag, u_int32_t *ip)
11046155Sphk{
11146155Sphk	u_int32_t tmp;
11246155Sphk
11372786Srwatson	if (!jailed(cred))
11446155Sphk		return (0);
11546155Sphk	if (flag)
11646155Sphk		tmp = *ip;
11746155Sphk	else
11846155Sphk		tmp = ntohl(*ip);
11946155Sphk	if (tmp == INADDR_ANY) {
12046155Sphk		if (flag)
12172786Srwatson			*ip = cred->cr_prison->pr_ip;
12246155Sphk		else
12372786Srwatson			*ip = htonl(cred->cr_prison->pr_ip);
12446155Sphk		return (0);
12546155Sphk	}
12672786Srwatson	if (cred->cr_prison->pr_ip != tmp)
12746155Sphk		return (1);
12846155Sphk	return (0);
12946155Sphk}
13046155Sphk
13146155Sphkvoid
13272786Srwatsonprison_remote_ip(struct ucred *cred, int flag, u_int32_t *ip)
13346155Sphk{
13446155Sphk	u_int32_t tmp;
13546155Sphk
13672786Srwatson	if (!jailed(cred))
13746155Sphk		return;
13846155Sphk	if (flag)
13946155Sphk		tmp = *ip;
14046155Sphk	else
14146155Sphk		tmp = ntohl(*ip);
14246155Sphk	if (tmp == 0x7f000001) {
14346155Sphk		if (flag)
14472786Srwatson			*ip = cred->cr_prison->pr_ip;
14546155Sphk		else
14672786Srwatson			*ip = htonl(cred->cr_prison->pr_ip);
14746155Sphk		return;
14846155Sphk	}
14946155Sphk	return;
15046155Sphk}
15146155Sphk
15246155Sphkint
15372786Srwatsonprison_if(struct ucred *cred, struct sockaddr *sa)
15446155Sphk{
15546155Sphk	struct sockaddr_in *sai = (struct sockaddr_in*) sa;
15646155Sphk	int ok;
15746155Sphk
15861235Srwatson	if ((sai->sin_family != AF_INET) && jail_socket_unixiproute_only)
15961235Srwatson		ok = 1;
16061235Srwatson	else if (sai->sin_family != AF_INET)
16146155Sphk		ok = 0;
16272786Srwatson	else if (cred->cr_prison->pr_ip != ntohl(sai->sin_addr.s_addr))
16346155Sphk		ok = 1;
16446155Sphk	else
16546155Sphk		ok = 0;
16646155Sphk	return (ok);
16746155Sphk}
16872786Srwatson
16972786Srwatson/*
17072786Srwatson * Return 0 if jails permit p1 to frob p2, otherwise ESRCH.
17172786Srwatson */
17272786Srwatsonint
17372786Srwatsonprison_check(cred1, cred2)
17472786Srwatson	struct ucred *cred1, *cred2;
17572786Srwatson{
17672786Srwatson
17772786Srwatson	if (jailed(cred1)) {
17872786Srwatson		if (!jailed(cred2))
17972786Srwatson			return (ESRCH);
18072786Srwatson		if (cred2->cr_prison != cred1->cr_prison)
18172786Srwatson			return (ESRCH);
18272786Srwatson	}
18372786Srwatson
18472786Srwatson	return (0);
18572786Srwatson}
18672786Srwatson
18772786Srwatson/*
18872786Srwatson * Return 1 if the passed credential is in a jail, otherwise 0.
18972786Srwatson */
19072786Srwatsonint
19172786Srwatsonjailed(cred)
19272786Srwatson	struct ucred *cred;
19372786Srwatson{
19472786Srwatson
19572786Srwatson	return (cred->cr_prison != NULL);
19672786Srwatson}
197