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