1 /* 2 * ---------------------------------------------------------------------------- 3 * "THE BEER-WARE LICENSE" (Revision 42): 4 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you 5 * can do whatever you want with this stuff. If we meet some day, and you think 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7 * ---------------------------------------------------------------------------- 8 * 9 * $FreeBSD: src/sys/kern/kern_jail.c,v 1.6.2.3 2001/08/17 01:00:26 rwatson Exp $ 10 * $DragonFly: src/sys/kern/kern_jail.c,v 1.6 2005/01/14 02:25:08 joerg Exp $ 11 * 12 */ 13 14 #include <sys/param.h> 15 #include <sys/types.h> 16 #include <sys/kernel.h> 17 #include <sys/systm.h> 18 #include <sys/errno.h> 19 #include <sys/sysproto.h> 20 #include <sys/malloc.h> 21 #include <sys/proc.h> 22 #include <sys/jail.h> 23 #include <sys/socket.h> 24 #include <sys/sysctl.h> 25 #include <net/if.h> 26 #include <netinet/in.h> 27 28 MALLOC_DEFINE(M_PRISON, "prison", "Prison structures"); 29 30 SYSCTL_NODE(, OID_AUTO, jail, CTLFLAG_RW, 0, 31 "Jail rules"); 32 33 int jail_set_hostname_allowed = 1; 34 SYSCTL_INT(_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW, 35 &jail_set_hostname_allowed, 0, 36 "Processes in jail can set their hostnames"); 37 38 int jail_socket_unixiproute_only = 1; 39 SYSCTL_INT(_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW, 40 &jail_socket_unixiproute_only, 0, 41 "Processes in jail are limited to creating UNIX/IPv4/route sockets only"); 42 43 int jail_sysvipc_allowed = 0; 44 SYSCTL_INT(_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW, 45 &jail_sysvipc_allowed, 0, 46 "Processes in jail can use System V IPC primitives"); 47 48 /* 49 * jail() 50 * 51 * jail_args(syscallarg(struct jail *) jail) 52 */ 53 int 54 jail(struct jail_args *uap) 55 { 56 int error; 57 struct prison *pr; 58 struct jail j; 59 struct chroot_args ca; 60 struct thread *td = curthread; 61 struct proc *p = td->td_proc; 62 63 error = suser(td); 64 if (error) 65 return (error); 66 error = copyin(uap->jail, &j, sizeof j); 67 if (error) 68 return (error); 69 if (j.version != 0) 70 return (EINVAL); 71 MALLOC(pr, struct prison *, sizeof *pr , M_PRISON, M_WAITOK); 72 bzero((caddr_t)pr, sizeof *pr); 73 error = copyinstr(j.hostname, &pr->pr_host, sizeof pr->pr_host, 0); 74 if (error) 75 goto bail; 76 pr->pr_ip = j.ip_number; 77 varsymset_init(&pr->pr_varsymset, NULL); 78 79 ca.path = j.path; 80 error = chroot(&ca); 81 if (error) 82 goto bail; 83 84 pr->pr_ref++; 85 cratom(&p->p_ucred); 86 p->p_ucred->cr_prison = pr; 87 p->p_flag |= P_JAILED; 88 return (0); 89 90 bail: 91 FREE(pr, M_PRISON); 92 return (error); 93 } 94 95 int 96 prison_ip(struct thread *td, int flag, u_int32_t *ip) 97 { 98 u_int32_t tmp; 99 struct prison *pr; 100 101 if (td->td_proc == NULL) 102 return (0); 103 if ((pr = td->td_proc->p_ucred->cr_prison) == NULL) 104 return (0); 105 if (flag) 106 tmp = *ip; 107 else 108 tmp = ntohl(*ip); 109 if (tmp == INADDR_ANY) { 110 if (flag) 111 *ip = pr->pr_ip; 112 else 113 *ip = htonl(pr->pr_ip); 114 return (0); 115 } 116 if (tmp == INADDR_LOOPBACK) { 117 if (flag) 118 *ip = pr->pr_ip; 119 else 120 *ip = htonl(pr->pr_ip); 121 return (0); 122 } 123 if (pr->pr_ip != tmp) 124 return (1); 125 return (0); 126 } 127 128 void 129 prison_remote_ip(struct thread *td, int flag, u_int32_t *ip) 130 { 131 u_int32_t tmp; 132 struct prison *pr; 133 134 if (td == NULL || td->td_proc == NULL) 135 return; 136 if ((pr = td->td_proc->p_ucred->cr_prison) == NULL) 137 return; 138 if (flag) 139 tmp = *ip; 140 else 141 tmp = ntohl(*ip); 142 if (tmp == INADDR_LOOPBACK) { 143 if (flag) 144 *ip = pr->pr_ip; 145 else 146 *ip = htonl(pr->pr_ip); 147 } 148 return; 149 } 150 151 int 152 prison_if(struct thread *td, struct sockaddr *sa) 153 { 154 struct prison *pr; 155 struct sockaddr_in *sai = (struct sockaddr_in*) sa; 156 int ok; 157 158 if (td->td_proc == NULL) 159 return(0); 160 pr = td->td_proc->p_ucred->cr_prison; 161 162 if ((sai->sin_family != AF_INET) && jail_socket_unixiproute_only) 163 ok = 1; 164 else if (sai->sin_family != AF_INET) 165 ok = 0; 166 else if (pr->pr_ip != ntohl(sai->sin_addr.s_addr)) 167 ok = 1; 168 else 169 ok = 0; 170 return (ok); 171 } 172