kern_jail.c revision 84828
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 84828 2001-10-11 23:39:43Z jhb $ 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 3284828Sjhbmp_fixme("these variables need a lock") 3384828Sjhb 3457163Srwatsonint jail_set_hostname_allowed = 1; 3557163SrwatsonSYSCTL_INT(_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW, 3657163Srwatson &jail_set_hostname_allowed, 0, 3757163Srwatson "Processes in jail can set their hostnames"); 3857163Srwatson 3961235Srwatsonint jail_socket_unixiproute_only = 1; 4061235SrwatsonSYSCTL_INT(_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW, 4161235Srwatson &jail_socket_unixiproute_only, 0, 4261235Srwatson "Processes in jail are limited to creating UNIX/IPv4/route sockets only"); 4361235Srwatson 4468024Srwatsonint jail_sysvipc_allowed = 0; 4568024SrwatsonSYSCTL_INT(_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW, 4668024Srwatson &jail_sysvipc_allowed, 0, 4768024Srwatson "Processes in jail can use System V IPC primitives"); 4868024Srwatson 4982710Sdillon/* 5082710Sdillon * MPSAFE 5182710Sdillon */ 5246155Sphkint 5383366Sjulianjail(td, uap) 5483366Sjulian struct thread *td; 5572786Srwatson struct jail_args /* { 5672786Srwatson syscallarg(struct jail *) jail; 5772786Srwatson } */ *uap; 5846155Sphk{ 5983366Sjulian struct proc *p = td->td_proc; 6046155Sphk int error; 6146155Sphk struct prison *pr; 6246155Sphk struct jail j; 6346155Sphk struct chroot_args ca; 6484828Sjhb struct ucred *newcred = NULL, *oldcred; 6546155Sphk 6646155Sphk error = copyin(uap->jail, &j, sizeof j); 6746155Sphk if (error) 6884828Sjhb return (error); 6984828Sjhb if (j.version != 0) 7084828Sjhb return (EINVAL); 7184828Sjhb 7284828Sjhb mtx_lock(&Giant); 7369781Sdwmalone MALLOC(pr, struct prison *, sizeof *pr , M_PRISON, M_WAITOK | M_ZERO); 7483989Srwatson pr->pr_securelevel = securelevel; 7546155Sphk error = copyinstr(j.hostname, &pr->pr_host, sizeof pr->pr_host, 0); 7684828Sjhb if (error) 7746155Sphk goto bail; 7846155Sphk ca.path = j.path; 7983366Sjulian error = chroot(td, &ca); 8046155Sphk if (error) 8146155Sphk goto bail; 8284828Sjhb newcred = crget(); 8384828Sjhb pr->pr_ip = j.ip_number; 8484828Sjhb PROC_LOCK(p); 8584828Sjhb /* Implicitly fail if already in jail. */ 8684828Sjhb error = suser(p); 8784828Sjhb if (error) 8884828Sjhb goto badcred; 8984828Sjhb oldcred = p->p_ucred; 9084828Sjhb crcopy(newcred, oldcred); 9184828Sjhb p->p_ucred = newcred; 9272786Srwatson p->p_ucred->cr_prison = pr; 9372786Srwatson pr->pr_ref = 1; 9484828Sjhb PROC_UNLOCK(p); 9584828Sjhb crfree(oldcred); 9682710Sdillon mtx_unlock(&Giant); 9746155Sphk return (0); 9884828Sjhbbadcred: 9984828Sjhb PROC_UNLOCK(p); 10084828Sjhb crfree(newcred); 10146155Sphkbail: 10246155Sphk FREE(pr, M_PRISON); 10382710Sdillon mtx_unlock(&Giant); 10446155Sphk return (error); 10546155Sphk} 10646155Sphk 10772786Srwatsonvoid 10872786Srwatsonprison_free(struct prison *pr) 10972786Srwatson{ 11072786Srwatson 11172786Srwatson pr->pr_ref--; 11272786Srwatson if (pr->pr_ref == 0) { 11372786Srwatson if (pr->pr_linux != NULL) 11472786Srwatson FREE(pr->pr_linux, M_PRISON); 11572786Srwatson FREE(pr, M_PRISON); 11672786Srwatson } 11772786Srwatson} 11872786Srwatson 11972786Srwatsonvoid 12072786Srwatsonprison_hold(struct prison *pr) 12172786Srwatson{ 12272786Srwatson 12372786Srwatson pr->pr_ref++; 12472786Srwatson} 12572786Srwatson 12646155Sphkint 12772786Srwatsonprison_ip(struct ucred *cred, int flag, u_int32_t *ip) 12846155Sphk{ 12946155Sphk u_int32_t tmp; 13046155Sphk 13172786Srwatson if (!jailed(cred)) 13246155Sphk return (0); 13346155Sphk if (flag) 13446155Sphk tmp = *ip; 13546155Sphk else 13646155Sphk tmp = ntohl(*ip); 13746155Sphk if (tmp == INADDR_ANY) { 13846155Sphk if (flag) 13972786Srwatson *ip = cred->cr_prison->pr_ip; 14046155Sphk else 14172786Srwatson *ip = htonl(cred->cr_prison->pr_ip); 14246155Sphk return (0); 14346155Sphk } 14481114Srwatson if (tmp == INADDR_LOOPBACK) { 14581114Srwatson if (flag) 14681114Srwatson *ip = cred->cr_prison->pr_ip; 14781114Srwatson else 14881114Srwatson *ip = htonl(cred->cr_prison->pr_ip); 14981114Srwatson return (0); 15081114Srwatson } 15172786Srwatson if (cred->cr_prison->pr_ip != tmp) 15246155Sphk return (1); 15346155Sphk return (0); 15446155Sphk} 15546155Sphk 15646155Sphkvoid 15772786Srwatsonprison_remote_ip(struct ucred *cred, int flag, u_int32_t *ip) 15846155Sphk{ 15946155Sphk u_int32_t tmp; 16046155Sphk 16172786Srwatson if (!jailed(cred)) 16246155Sphk return; 16346155Sphk if (flag) 16446155Sphk tmp = *ip; 16546155Sphk else 16646155Sphk tmp = ntohl(*ip); 16781114Srwatson if (tmp == INADDR_LOOPBACK) { 16846155Sphk if (flag) 16972786Srwatson *ip = cred->cr_prison->pr_ip; 17046155Sphk else 17172786Srwatson *ip = htonl(cred->cr_prison->pr_ip); 17246155Sphk return; 17346155Sphk } 17446155Sphk return; 17546155Sphk} 17646155Sphk 17746155Sphkint 17872786Srwatsonprison_if(struct ucred *cred, struct sockaddr *sa) 17946155Sphk{ 18046155Sphk struct sockaddr_in *sai = (struct sockaddr_in*) sa; 18146155Sphk int ok; 18246155Sphk 18361235Srwatson if ((sai->sin_family != AF_INET) && jail_socket_unixiproute_only) 18461235Srwatson ok = 1; 18561235Srwatson else if (sai->sin_family != AF_INET) 18646155Sphk ok = 0; 18772786Srwatson else if (cred->cr_prison->pr_ip != ntohl(sai->sin_addr.s_addr)) 18846155Sphk ok = 1; 18946155Sphk else 19046155Sphk ok = 0; 19146155Sphk return (ok); 19246155Sphk} 19372786Srwatson 19472786Srwatson/* 19572786Srwatson * Return 0 if jails permit p1 to frob p2, otherwise ESRCH. 19672786Srwatson */ 19772786Srwatsonint 19872786Srwatsonprison_check(cred1, cred2) 19972786Srwatson struct ucred *cred1, *cred2; 20072786Srwatson{ 20172786Srwatson 20272786Srwatson if (jailed(cred1)) { 20372786Srwatson if (!jailed(cred2)) 20472786Srwatson return (ESRCH); 20572786Srwatson if (cred2->cr_prison != cred1->cr_prison) 20672786Srwatson return (ESRCH); 20772786Srwatson } 20872786Srwatson 20972786Srwatson return (0); 21072786Srwatson} 21172786Srwatson 21272786Srwatson/* 21372786Srwatson * Return 1 if the passed credential is in a jail, otherwise 0. 21472786Srwatson */ 21572786Srwatsonint 21672786Srwatsonjailed(cred) 21772786Srwatson struct ucred *cred; 21872786Srwatson{ 21972786Srwatson 22072786Srwatson return (cred->cr_prison != NULL); 22172786Srwatson} 222