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.5 2003/06/26 02:17:45 dillon 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 78 ca.path = j.path; 79 error = chroot(&ca); 80 if (error) 81 goto bail; 82 83 pr->pr_ref++; 84 cratom(&p->p_ucred); 85 p->p_ucred->cr_prison = pr; 86 p->p_flag |= P_JAILED; 87 return (0); 88 89 bail: 90 FREE(pr, M_PRISON); 91 return (error); 92 } 93 94 int 95 prison_ip(struct thread *td, int flag, u_int32_t *ip) 96 { 97 u_int32_t tmp; 98 struct prison *pr; 99 100 if (td->td_proc == NULL) 101 return (0); 102 if ((pr = td->td_proc->p_ucred->cr_prison) == NULL) 103 return (0); 104 if (flag) 105 tmp = *ip; 106 else 107 tmp = ntohl(*ip); 108 if (tmp == INADDR_ANY) { 109 if (flag) 110 *ip = pr->pr_ip; 111 else 112 *ip = htonl(pr->pr_ip); 113 return (0); 114 } 115 if (tmp == INADDR_LOOPBACK) { 116 if (flag) 117 *ip = pr->pr_ip; 118 else 119 *ip = htonl(pr->pr_ip); 120 return (0); 121 } 122 if (pr->pr_ip != tmp) 123 return (1); 124 return (0); 125 } 126 127 void 128 prison_remote_ip(struct thread *td, int flag, u_int32_t *ip) 129 { 130 u_int32_t tmp; 131 struct prison *pr; 132 133 if (td == NULL || td->td_proc == NULL) 134 return; 135 if ((pr = td->td_proc->p_ucred->cr_prison) == NULL) 136 return; 137 if (flag) 138 tmp = *ip; 139 else 140 tmp = ntohl(*ip); 141 if (tmp == INADDR_LOOPBACK) { 142 if (flag) 143 *ip = pr->pr_ip; 144 else 145 *ip = htonl(pr->pr_ip); 146 } 147 return; 148 } 149 150 int 151 prison_if(struct thread *td, struct sockaddr *sa) 152 { 153 struct prison *pr; 154 struct sockaddr_in *sai = (struct sockaddr_in*) sa; 155 int ok; 156 157 if (td->td_proc == NULL) 158 return(0); 159 pr = td->td_proc->p_ucred->cr_prison; 160 161 if ((sai->sin_family != AF_INET) && jail_socket_unixiproute_only) 162 ok = 1; 163 else if (sai->sin_family != AF_INET) 164 ok = 0; 165 else if (pr->pr_ip != ntohl(sai->sin_addr.s_addr)) 166 ok = 1; 167 else 168 ok = 0; 169 return (ok); 170 } 171