kern_jail.c revision 57163
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 57163 2000-02-12 13:41:56Z 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
3746155Sphkint
3846155Sphkjail(p, uap)
3946155Sphk        struct proc *p;
4046155Sphk        struct jail_args /* {
4146155Sphk                syscallarg(struct jail *) jail;
4246155Sphk        } */ *uap;
4346155Sphk{
4446155Sphk	int error;
4546155Sphk	struct prison *pr;
4646155Sphk	struct jail j;
4746155Sphk	struct chroot_args ca;
4846155Sphk
4946155Sphk	error = suser(p);
5046155Sphk	if (error)
5146155Sphk		return (error);
5246155Sphk	error = copyin(uap->jail, &j, sizeof j);
5346155Sphk	if (error)
5446155Sphk		return (error);
5551398Sphk	if (j.version != 0)
5651398Sphk		return (EINVAL);
5746155Sphk	MALLOC(pr, struct prison *, sizeof *pr , M_PRISON, M_WAITOK);
5846155Sphk	bzero((caddr_t)pr, sizeof *pr);
5946155Sphk	error = copyinstr(j.hostname, &pr->pr_host, sizeof pr->pr_host, 0);
6046155Sphk	if (error)
6146155Sphk		goto bail;
6246155Sphk	pr->pr_ip = j.ip_number;
6346155Sphk
6446155Sphk	ca.path = j.path;
6546155Sphk	error = chroot(p, &ca);
6646155Sphk	if (error)
6746155Sphk		goto bail;
6846155Sphk
6946155Sphk	pr->pr_ref++;
7046155Sphk	p->p_prison = pr;
7146155Sphk	p->p_flag |= P_JAILED;
7246155Sphk	return (0);
7346155Sphk
7446155Sphkbail:
7546155Sphk	FREE(pr, M_PRISON);
7646155Sphk	return (error);
7746155Sphk}
7846155Sphk
7946155Sphkint
8046155Sphkprison_ip(struct proc *p, int flag, u_int32_t *ip)
8146155Sphk{
8246155Sphk	u_int32_t tmp;
8346155Sphk
8446155Sphk	if (!p->p_prison)
8546155Sphk		return (0);
8646155Sphk	if (flag)
8746155Sphk		tmp = *ip;
8846155Sphk	else
8946155Sphk		tmp = ntohl(*ip);
9046155Sphk	if (tmp == INADDR_ANY) {
9146155Sphk		if (flag)
9246155Sphk			*ip = p->p_prison->pr_ip;
9346155Sphk		else
9446155Sphk			*ip = htonl(p->p_prison->pr_ip);
9546155Sphk		return (0);
9646155Sphk	}
9746155Sphk	if (p->p_prison->pr_ip != tmp)
9846155Sphk		return (1);
9946155Sphk	return (0);
10046155Sphk}
10146155Sphk
10246155Sphkvoid
10346155Sphkprison_remote_ip(struct proc *p, int flag, u_int32_t *ip)
10446155Sphk{
10546155Sphk	u_int32_t tmp;
10646155Sphk
10746194Sphk	if (!p || !p->p_prison)
10846155Sphk		return;
10946155Sphk	if (flag)
11046155Sphk		tmp = *ip;
11146155Sphk	else
11246155Sphk		tmp = ntohl(*ip);
11346155Sphk	if (tmp == 0x7f000001) {
11446155Sphk		if (flag)
11546155Sphk			*ip = p->p_prison->pr_ip;
11646155Sphk		else
11746155Sphk			*ip = htonl(p->p_prison->pr_ip);
11846155Sphk		return;
11946155Sphk	}
12046155Sphk	return;
12146155Sphk}
12246155Sphk
12346155Sphkint
12446155Sphkprison_if(struct proc *p, struct sockaddr *sa)
12546155Sphk{
12646155Sphk	struct sockaddr_in *sai = (struct sockaddr_in*) sa;
12746155Sphk	int ok;
12846155Sphk
12946155Sphk	if (sai->sin_family != AF_INET)
13046155Sphk		ok = 0;
13146155Sphk	else if (p->p_prison->pr_ip != ntohl(sai->sin_addr.s_addr))
13246155Sphk		ok = 1;
13346155Sphk	else
13446155Sphk		ok = 0;
13546155Sphk	return (ok);
13646155Sphk}
137