xref: /freebsd/sys/kern/kern_jail.c (revision 83f1e257e02a6766b65484799ad21d82c4a5c4da)
107901f22SPoul-Henning Kamp /*
207901f22SPoul-Henning Kamp  * ----------------------------------------------------------------------------
307901f22SPoul-Henning Kamp  * "THE BEER-WARE LICENSE" (Revision 42):
407901f22SPoul-Henning Kamp  * <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
507901f22SPoul-Henning Kamp  * can do whatever you want with this stuff. If we meet some day, and you think
607901f22SPoul-Henning Kamp  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
707901f22SPoul-Henning Kamp  * ----------------------------------------------------------------------------
807901f22SPoul-Henning Kamp  *
9c3aac50fSPeter Wemm  * $FreeBSD$
1007901f22SPoul-Henning Kamp  *
1107901f22SPoul-Henning Kamp  */
1275c13541SPoul-Henning Kamp 
1375c13541SPoul-Henning Kamp #include <sys/param.h>
1475c13541SPoul-Henning Kamp #include <sys/types.h>
1575c13541SPoul-Henning Kamp #include <sys/kernel.h>
1675c13541SPoul-Henning Kamp #include <sys/systm.h>
1775c13541SPoul-Henning Kamp #include <sys/errno.h>
1875c13541SPoul-Henning Kamp #include <sys/sysproto.h>
1975c13541SPoul-Henning Kamp #include <sys/malloc.h>
2075c13541SPoul-Henning Kamp #include <sys/proc.h>
2175c13541SPoul-Henning Kamp #include <sys/jail.h>
2275c13541SPoul-Henning Kamp #include <sys/socket.h>
2383f1e257SRobert Watson #include <sys/sysctl.h>
2475c13541SPoul-Henning Kamp #include <net/if.h>
2575c13541SPoul-Henning Kamp #include <netinet/in.h>
2675c13541SPoul-Henning Kamp 
2775c13541SPoul-Henning Kamp MALLOC_DEFINE(M_PRISON, "prison", "Prison structures");
2875c13541SPoul-Henning Kamp 
2983f1e257SRobert Watson SYSCTL_NODE(, OID_AUTO, jail, CTLFLAG_RW, 0,
3083f1e257SRobert Watson     "Jail rules");
3183f1e257SRobert Watson 
3283f1e257SRobert Watson int	jail_set_hostname_allowed = 1;
3383f1e257SRobert Watson SYSCTL_INT(_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,
3483f1e257SRobert Watson     &jail_set_hostname_allowed, 0,
3583f1e257SRobert Watson     "Processes in jail can set their hostnames");
3683f1e257SRobert Watson 
3775c13541SPoul-Henning Kamp int
3875c13541SPoul-Henning Kamp jail(p, uap)
3975c13541SPoul-Henning Kamp         struct proc *p;
4075c13541SPoul-Henning Kamp         struct jail_args /* {
4175c13541SPoul-Henning Kamp                 syscallarg(struct jail *) jail;
4275c13541SPoul-Henning Kamp         } */ *uap;
4375c13541SPoul-Henning Kamp {
4475c13541SPoul-Henning Kamp 	int error;
4575c13541SPoul-Henning Kamp 	struct prison *pr;
4675c13541SPoul-Henning Kamp 	struct jail j;
4775c13541SPoul-Henning Kamp 	struct chroot_args ca;
4875c13541SPoul-Henning Kamp 
4975c13541SPoul-Henning Kamp 	error = suser(p);
5075c13541SPoul-Henning Kamp 	if (error)
5175c13541SPoul-Henning Kamp 		return (error);
5275c13541SPoul-Henning Kamp 	error = copyin(uap->jail, &j, sizeof j);
5375c13541SPoul-Henning Kamp 	if (error)
5475c13541SPoul-Henning Kamp 		return (error);
55978f8d93SPoul-Henning Kamp 	if (j.version != 0)
56978f8d93SPoul-Henning Kamp 		return (EINVAL);
5775c13541SPoul-Henning Kamp 	MALLOC(pr, struct prison *, sizeof *pr , M_PRISON, M_WAITOK);
5875c13541SPoul-Henning Kamp 	bzero((caddr_t)pr, sizeof *pr);
5975c13541SPoul-Henning Kamp 	error = copyinstr(j.hostname, &pr->pr_host, sizeof pr->pr_host, 0);
6075c13541SPoul-Henning Kamp 	if (error)
6175c13541SPoul-Henning Kamp 		goto bail;
6275c13541SPoul-Henning Kamp 	pr->pr_ip = j.ip_number;
6375c13541SPoul-Henning Kamp 
6475c13541SPoul-Henning Kamp 	ca.path = j.path;
6575c13541SPoul-Henning Kamp 	error = chroot(p, &ca);
6675c13541SPoul-Henning Kamp 	if (error)
6775c13541SPoul-Henning Kamp 		goto bail;
6875c13541SPoul-Henning Kamp 
6975c13541SPoul-Henning Kamp 	pr->pr_ref++;
7075c13541SPoul-Henning Kamp 	p->p_prison = pr;
7175c13541SPoul-Henning Kamp 	p->p_flag |= P_JAILED;
7275c13541SPoul-Henning Kamp 	return (0);
7375c13541SPoul-Henning Kamp 
7475c13541SPoul-Henning Kamp bail:
7575c13541SPoul-Henning Kamp 	FREE(pr, M_PRISON);
7675c13541SPoul-Henning Kamp 	return (error);
7775c13541SPoul-Henning Kamp }
7875c13541SPoul-Henning Kamp 
7975c13541SPoul-Henning Kamp int
8075c13541SPoul-Henning Kamp prison_ip(struct proc *p, int flag, u_int32_t *ip)
8175c13541SPoul-Henning Kamp {
8275c13541SPoul-Henning Kamp 	u_int32_t tmp;
8375c13541SPoul-Henning Kamp 
8475c13541SPoul-Henning Kamp 	if (!p->p_prison)
8575c13541SPoul-Henning Kamp 		return (0);
8675c13541SPoul-Henning Kamp 	if (flag)
8775c13541SPoul-Henning Kamp 		tmp = *ip;
8875c13541SPoul-Henning Kamp 	else
8975c13541SPoul-Henning Kamp 		tmp = ntohl(*ip);
9075c13541SPoul-Henning Kamp 	if (tmp == INADDR_ANY) {
9175c13541SPoul-Henning Kamp 		if (flag)
9275c13541SPoul-Henning Kamp 			*ip = p->p_prison->pr_ip;
9375c13541SPoul-Henning Kamp 		else
9475c13541SPoul-Henning Kamp 			*ip = htonl(p->p_prison->pr_ip);
9575c13541SPoul-Henning Kamp 		return (0);
9675c13541SPoul-Henning Kamp 	}
9775c13541SPoul-Henning Kamp 	if (p->p_prison->pr_ip != tmp)
9875c13541SPoul-Henning Kamp 		return (1);
9975c13541SPoul-Henning Kamp 	return (0);
10075c13541SPoul-Henning Kamp }
10175c13541SPoul-Henning Kamp 
10275c13541SPoul-Henning Kamp void
10375c13541SPoul-Henning Kamp prison_remote_ip(struct proc *p, int flag, u_int32_t *ip)
10475c13541SPoul-Henning Kamp {
10575c13541SPoul-Henning Kamp 	u_int32_t tmp;
10675c13541SPoul-Henning Kamp 
107430210c0SPoul-Henning Kamp 	if (!p || !p->p_prison)
10875c13541SPoul-Henning Kamp 		return;
10975c13541SPoul-Henning Kamp 	if (flag)
11075c13541SPoul-Henning Kamp 		tmp = *ip;
11175c13541SPoul-Henning Kamp 	else
11275c13541SPoul-Henning Kamp 		tmp = ntohl(*ip);
11375c13541SPoul-Henning Kamp 	if (tmp == 0x7f000001) {
11475c13541SPoul-Henning Kamp 		if (flag)
11575c13541SPoul-Henning Kamp 			*ip = p->p_prison->pr_ip;
11675c13541SPoul-Henning Kamp 		else
11775c13541SPoul-Henning Kamp 			*ip = htonl(p->p_prison->pr_ip);
11875c13541SPoul-Henning Kamp 		return;
11975c13541SPoul-Henning Kamp 	}
12075c13541SPoul-Henning Kamp 	return;
12175c13541SPoul-Henning Kamp }
12275c13541SPoul-Henning Kamp 
12375c13541SPoul-Henning Kamp int
12475c13541SPoul-Henning Kamp prison_if(struct proc *p, struct sockaddr *sa)
12575c13541SPoul-Henning Kamp {
12675c13541SPoul-Henning Kamp 	struct sockaddr_in *sai = (struct sockaddr_in*) sa;
12775c13541SPoul-Henning Kamp 	int ok;
12875c13541SPoul-Henning Kamp 
12975c13541SPoul-Henning Kamp 	if (sai->sin_family != AF_INET)
13075c13541SPoul-Henning Kamp 		ok = 0;
13175c13541SPoul-Henning Kamp 	else if (p->p_prison->pr_ip != ntohl(sai->sin_addr.s_addr))
13275c13541SPoul-Henning Kamp 		ok = 1;
13375c13541SPoul-Henning Kamp 	else
13475c13541SPoul-Henning Kamp 		ok = 0;
13575c13541SPoul-Henning Kamp 	return (ok);
13675c13541SPoul-Henning Kamp }
137