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> 2201137630SRobert Watson #include <sys/lock.h> 2301137630SRobert Watson #include <sys/mutex.h> 24fd7a8150SMike Barcroft #include <sys/namei.h> 25fd7a8150SMike Barcroft #include <sys/queue.h> 2675c13541SPoul-Henning Kamp #include <sys/socket.h> 27fd7a8150SMike Barcroft #include <sys/syscallsubr.h> 2883f1e257SRobert Watson #include <sys/sysctl.h> 29fd7a8150SMike Barcroft #include <sys/vnode.h> 3075c13541SPoul-Henning Kamp #include <net/if.h> 3175c13541SPoul-Henning Kamp #include <netinet/in.h> 3275c13541SPoul-Henning Kamp 3375c13541SPoul-Henning Kamp MALLOC_DEFINE(M_PRISON, "prison", "Prison structures"); 3475c13541SPoul-Henning Kamp 35d0615c64SAndrew R. Reiter SYSCTL_DECL(_security); 36d0615c64SAndrew R. Reiter SYSCTL_NODE(_security, OID_AUTO, jail, CTLFLAG_RW, 0, 3783f1e257SRobert Watson "Jail rules"); 3883f1e257SRobert Watson 39a2f2b3afSJohn Baldwin mp_fixme("these variables need a lock") 40a2f2b3afSJohn Baldwin 4183f1e257SRobert Watson int jail_set_hostname_allowed = 1; 42d0615c64SAndrew R. Reiter SYSCTL_INT(_security_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW, 4383f1e257SRobert Watson &jail_set_hostname_allowed, 0, 4483f1e257SRobert Watson "Processes in jail can set their hostnames"); 4583f1e257SRobert Watson 467cadc266SRobert Watson int jail_socket_unixiproute_only = 1; 47d0615c64SAndrew R. Reiter SYSCTL_INT(_security_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW, 487cadc266SRobert Watson &jail_socket_unixiproute_only, 0, 497cadc266SRobert Watson "Processes in jail are limited to creating UNIX/IPv4/route sockets only"); 507cadc266SRobert Watson 51cb1f0db9SRobert Watson int jail_sysvipc_allowed = 0; 52d0615c64SAndrew R. Reiter SYSCTL_INT(_security_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW, 53cb1f0db9SRobert Watson &jail_sysvipc_allowed, 0, 54cb1f0db9SRobert Watson "Processes in jail can use System V IPC primitives"); 55cb1f0db9SRobert Watson 56fd7a8150SMike Barcroft /* allprison, lastprid, and prisoncount are protected by allprison_mtx. */ 57fd7a8150SMike Barcroft struct prisonlist allprison; 58fd7a8150SMike Barcroft struct mtx allprison_mtx; 59fd7a8150SMike Barcroft int lastprid = 0; 60fd7a8150SMike Barcroft int prisoncount = 0; 61fd7a8150SMike Barcroft 62fd7a8150SMike Barcroft static void init_prison(void *); 63fd7a8150SMike Barcroft static struct prison *prison_find(int); 64fd7a8150SMike Barcroft static int sysctl_jail_list(SYSCTL_HANDLER_ARGS); 65fd7a8150SMike Barcroft 66fd7a8150SMike Barcroft static void 67fd7a8150SMike Barcroft init_prison(void *data __unused) 68fd7a8150SMike Barcroft { 69fd7a8150SMike Barcroft 70fd7a8150SMike Barcroft mtx_init(&allprison_mtx, "allprison", NULL, MTX_DEF); 71fd7a8150SMike Barcroft LIST_INIT(&allprison); 72fd7a8150SMike Barcroft } 73fd7a8150SMike Barcroft 74fd7a8150SMike Barcroft SYSINIT(prison, SI_SUB_INTRINSIC, SI_ORDER_ANY, init_prison, NULL); 75fd7a8150SMike Barcroft 76116734c4SMatthew Dillon /* 77116734c4SMatthew Dillon * MPSAFE 789ddb7954SMike Barcroft * 799ddb7954SMike Barcroft * struct jail_args { 809ddb7954SMike Barcroft * struct jail *jail; 819ddb7954SMike Barcroft * }; 82116734c4SMatthew Dillon */ 8375c13541SPoul-Henning Kamp int 849ddb7954SMike Barcroft jail(struct thread *td, struct jail_args *uap) 8575c13541SPoul-Henning Kamp { 86fd7a8150SMike Barcroft struct nameidata nd; 87fd7a8150SMike Barcroft struct prison *pr, *tpr; 8875c13541SPoul-Henning Kamp struct jail j; 89fd7a8150SMike Barcroft struct jail_attach_args jaa; 90fd7a8150SMike Barcroft int error, tryprid; 9175c13541SPoul-Henning Kamp 929ddb7954SMike Barcroft error = copyin(uap->jail, &j, sizeof(j)); 9375c13541SPoul-Henning Kamp if (error) 94a2f2b3afSJohn Baldwin return (error); 95a2f2b3afSJohn Baldwin if (j.version != 0) 96a2f2b3afSJohn Baldwin return (EINVAL); 97a2f2b3afSJohn Baldwin 989ddb7954SMike Barcroft MALLOC(pr, struct prison *, sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO); 996008862bSJohn Baldwin mtx_init(&pr->pr_mtx, "jail mutex", NULL, MTX_DEF); 100fd7a8150SMike Barcroft pr->pr_ref = 1; 1019ddb7954SMike Barcroft error = copyinstr(j.path, &pr->pr_path, sizeof(pr->pr_path), 0); 102fd7a8150SMike Barcroft if (error) 103fd7a8150SMike Barcroft goto e_killmtx; 104fd7a8150SMike Barcroft mtx_lock(&Giant); 105fd7a8150SMike Barcroft NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, pr->pr_path, td); 106fd7a8150SMike Barcroft error = namei(&nd); 107fd7a8150SMike Barcroft if (error) { 108fd7a8150SMike Barcroft mtx_unlock(&Giant); 109fd7a8150SMike Barcroft goto e_killmtx; 110fd7a8150SMike Barcroft } 111fd7a8150SMike Barcroft pr->pr_root = nd.ni_vp; 112fd7a8150SMike Barcroft VOP_UNLOCK(nd.ni_vp, 0, td); 113fd7a8150SMike Barcroft NDFREE(&nd, NDF_ONLY_PNBUF); 114fd7a8150SMike Barcroft mtx_unlock(&Giant); 1159ddb7954SMike Barcroft error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0); 11675c13541SPoul-Henning Kamp if (error) 117fd7a8150SMike Barcroft goto e_dropvnref; 118a2f2b3afSJohn Baldwin pr->pr_ip = j.ip_number; 119fd7a8150SMike Barcroft pr->pr_linux = NULL; 120fd7a8150SMike Barcroft pr->pr_securelevel = securelevel; 121fd7a8150SMike Barcroft 122fd7a8150SMike Barcroft /* Determine next pr_id and add prison to allprison list. */ 123fd7a8150SMike Barcroft mtx_lock(&allprison_mtx); 124fd7a8150SMike Barcroft tryprid = lastprid + 1; 125fd7a8150SMike Barcroft if (tryprid == JAIL_MAX) 126fd7a8150SMike Barcroft tryprid = 1; 127fd7a8150SMike Barcroft next: 128fd7a8150SMike Barcroft LIST_FOREACH(tpr, &allprison, pr_list) { 129fd7a8150SMike Barcroft if (tpr->pr_id == tryprid) { 130fd7a8150SMike Barcroft tryprid++; 131fd7a8150SMike Barcroft if (tryprid == JAIL_MAX) { 132fd7a8150SMike Barcroft mtx_unlock(&allprison_mtx); 133fd7a8150SMike Barcroft error = EAGAIN; 134fd7a8150SMike Barcroft goto e_dropvnref; 135fd7a8150SMike Barcroft } 136fd7a8150SMike Barcroft goto next; 137fd7a8150SMike Barcroft } 138fd7a8150SMike Barcroft } 139fd7a8150SMike Barcroft pr->pr_id = jaa.jid = lastprid = tryprid; 140fd7a8150SMike Barcroft LIST_INSERT_HEAD(&allprison, pr, pr_list); 141fd7a8150SMike Barcroft prisoncount++; 142fd7a8150SMike Barcroft mtx_unlock(&allprison_mtx); 143fd7a8150SMike Barcroft 144fd7a8150SMike Barcroft error = jail_attach(td, &jaa); 145a2f2b3afSJohn Baldwin if (error) 146fd7a8150SMike Barcroft goto e_dropprref; 147fd7a8150SMike Barcroft mtx_lock(&pr->pr_mtx); 148fd7a8150SMike Barcroft pr->pr_ref--; 149fd7a8150SMike Barcroft mtx_unlock(&pr->pr_mtx); 150fd7a8150SMike Barcroft td->td_retval[0] = jaa.jid; 15175c13541SPoul-Henning Kamp return (0); 152fd7a8150SMike Barcroft e_dropprref: 153fd7a8150SMike Barcroft mtx_lock(&allprison_mtx); 154fd7a8150SMike Barcroft LIST_REMOVE(pr, pr_list); 155fd7a8150SMike Barcroft prisoncount--; 156fd7a8150SMike Barcroft mtx_unlock(&allprison_mtx); 157fd7a8150SMike Barcroft e_dropvnref: 158fd7a8150SMike Barcroft mtx_lock(&Giant); 159fd7a8150SMike Barcroft vrele(pr->pr_root); 160fd7a8150SMike Barcroft mtx_unlock(&Giant); 161fd7a8150SMike Barcroft e_killmtx: 162894db7b0SMaxime Henrion mtx_destroy(&pr->pr_mtx); 16375c13541SPoul-Henning Kamp FREE(pr, M_PRISON); 16475c13541SPoul-Henning Kamp return (error); 16575c13541SPoul-Henning Kamp } 16675c13541SPoul-Henning Kamp 167fd7a8150SMike Barcroft /* 168fd7a8150SMike Barcroft * MPSAFE 1699ddb7954SMike Barcroft * 1709ddb7954SMike Barcroft * struct jail_attach_args { 1719ddb7954SMike Barcroft * int jid; 1729ddb7954SMike Barcroft * }; 173fd7a8150SMike Barcroft */ 174fd7a8150SMike Barcroft int 1759ddb7954SMike Barcroft jail_attach(struct thread *td, struct jail_attach_args *uap) 176fd7a8150SMike Barcroft { 177fd7a8150SMike Barcroft struct proc *p; 178fd7a8150SMike Barcroft struct ucred *newcred, *oldcred; 179fd7a8150SMike Barcroft struct prison *pr; 180fd7a8150SMike Barcroft int error; 181fd7a8150SMike Barcroft 182fd7a8150SMike Barcroft p = td->td_proc; 183fd7a8150SMike Barcroft 184fd7a8150SMike Barcroft mtx_lock(&allprison_mtx); 185fd7a8150SMike Barcroft pr = prison_find(uap->jid); 186fd7a8150SMike Barcroft if (pr == NULL) { 187fd7a8150SMike Barcroft mtx_unlock(&allprison_mtx); 188fd7a8150SMike Barcroft return (EINVAL); 189fd7a8150SMike Barcroft } 190fd7a8150SMike Barcroft pr->pr_ref++; 191fd7a8150SMike Barcroft mtx_unlock(&pr->pr_mtx); 192fd7a8150SMike Barcroft mtx_unlock(&allprison_mtx); 193fd7a8150SMike Barcroft 194fd7a8150SMike Barcroft error = suser_cred(td->td_ucred, PRISON_ROOT); 195fd7a8150SMike Barcroft if (error) 196fd7a8150SMike Barcroft goto e_dropref; 197fd7a8150SMike Barcroft mtx_lock(&Giant); 198fd7a8150SMike Barcroft vn_lock(pr->pr_root, LK_EXCLUSIVE | LK_RETRY, td); 199fd7a8150SMike Barcroft if ((error = change_dir(pr->pr_root, td)) != 0) 200fd7a8150SMike Barcroft goto e_unlock; 201fd7a8150SMike Barcroft #ifdef MAC 202fd7a8150SMike Barcroft if ((error = mac_check_vnode_chroot(td->td_ucred, pr->pr_root))) 203fd7a8150SMike Barcroft goto e_unlock; 204fd7a8150SMike Barcroft #endif 205fd7a8150SMike Barcroft VOP_UNLOCK(pr->pr_root, 0, td); 206fd7a8150SMike Barcroft change_root(pr->pr_root, td); 207fd7a8150SMike Barcroft mtx_unlock(&Giant); 208fd7a8150SMike Barcroft 209fd7a8150SMike Barcroft newcred = crget(); 210fd7a8150SMike Barcroft PROC_LOCK(p); 211fd7a8150SMike Barcroft /* Implicitly fail if already in jail. */ 212fd7a8150SMike Barcroft error = suser_cred(p->p_ucred, 0); 213fd7a8150SMike Barcroft if (error) { 214fd7a8150SMike Barcroft PROC_UNLOCK(p); 215fd7a8150SMike Barcroft crfree(newcred); 216fd7a8150SMike Barcroft goto e_dropref; 217fd7a8150SMike Barcroft } 218fd7a8150SMike Barcroft oldcred = p->p_ucred; 219fd7a8150SMike Barcroft setsugid(p); 220fd7a8150SMike Barcroft crcopy(newcred, oldcred); 22169c4ee54SJohn Baldwin newcred->cr_prison = pr; 222fd7a8150SMike Barcroft p->p_ucred = newcred; 223fd7a8150SMike Barcroft PROC_UNLOCK(p); 224fd7a8150SMike Barcroft crfree(oldcred); 225fd7a8150SMike Barcroft return (0); 226fd7a8150SMike Barcroft e_unlock: 227fd7a8150SMike Barcroft VOP_UNLOCK(pr->pr_root, 0, td); 228fd7a8150SMike Barcroft mtx_unlock(&Giant); 229fd7a8150SMike Barcroft e_dropref: 230fd7a8150SMike Barcroft mtx_lock(&pr->pr_mtx); 231fd7a8150SMike Barcroft pr->pr_ref--; 232fd7a8150SMike Barcroft mtx_unlock(&pr->pr_mtx); 233fd7a8150SMike Barcroft return (error); 234fd7a8150SMike Barcroft } 235fd7a8150SMike Barcroft 236fd7a8150SMike Barcroft /* 237fd7a8150SMike Barcroft * Returns a locked prison instance, or NULL on failure. 238fd7a8150SMike Barcroft */ 239fd7a8150SMike Barcroft static struct prison * 240fd7a8150SMike Barcroft prison_find(int prid) 241fd7a8150SMike Barcroft { 242fd7a8150SMike Barcroft struct prison *pr; 243fd7a8150SMike Barcroft 244fd7a8150SMike Barcroft mtx_assert(&allprison_mtx, MA_OWNED); 245fd7a8150SMike Barcroft LIST_FOREACH(pr, &allprison, pr_list) { 246fd7a8150SMike Barcroft if (pr->pr_id == prid) { 247fd7a8150SMike Barcroft mtx_lock(&pr->pr_mtx); 248fd7a8150SMike Barcroft return (pr); 249fd7a8150SMike Barcroft } 250fd7a8150SMike Barcroft } 251fd7a8150SMike Barcroft return (NULL); 252fd7a8150SMike Barcroft } 253fd7a8150SMike Barcroft 25491421ba2SRobert Watson void 25591421ba2SRobert Watson prison_free(struct prison *pr) 25691421ba2SRobert Watson { 25791421ba2SRobert Watson 258fd7a8150SMike Barcroft mtx_assert(&Giant, MA_OWNED); 259fd7a8150SMike Barcroft mtx_lock(&allprison_mtx); 26001137630SRobert Watson mtx_lock(&pr->pr_mtx); 26191421ba2SRobert Watson pr->pr_ref--; 26291421ba2SRobert Watson if (pr->pr_ref == 0) { 263fd7a8150SMike Barcroft LIST_REMOVE(pr, pr_list); 26401137630SRobert Watson mtx_unlock(&pr->pr_mtx); 265fd7a8150SMike Barcroft prisoncount--; 266fd7a8150SMike Barcroft mtx_unlock(&allprison_mtx); 267fd7a8150SMike Barcroft vrele(pr->pr_root); 26801137630SRobert Watson mtx_destroy(&pr->pr_mtx); 26991421ba2SRobert Watson if (pr->pr_linux != NULL) 27091421ba2SRobert Watson FREE(pr->pr_linux, M_PRISON); 27191421ba2SRobert Watson FREE(pr, M_PRISON); 27201137630SRobert Watson return; 27391421ba2SRobert Watson } 27401137630SRobert Watson mtx_unlock(&pr->pr_mtx); 275fd7a8150SMike Barcroft mtx_unlock(&allprison_mtx); 27691421ba2SRobert Watson } 27791421ba2SRobert Watson 27891421ba2SRobert Watson void 27991421ba2SRobert Watson prison_hold(struct prison *pr) 28091421ba2SRobert Watson { 28191421ba2SRobert Watson 28201137630SRobert Watson mtx_lock(&pr->pr_mtx); 28391421ba2SRobert Watson pr->pr_ref++; 28401137630SRobert Watson mtx_unlock(&pr->pr_mtx); 28501137630SRobert Watson } 28601137630SRobert Watson 28701137630SRobert Watson u_int32_t 28801137630SRobert Watson prison_getip(struct ucred *cred) 28901137630SRobert Watson { 29001137630SRobert Watson 29101137630SRobert Watson return (cred->cr_prison->pr_ip); 29291421ba2SRobert Watson } 29391421ba2SRobert Watson 29475c13541SPoul-Henning Kamp int 29591421ba2SRobert Watson prison_ip(struct ucred *cred, int flag, u_int32_t *ip) 29675c13541SPoul-Henning Kamp { 29775c13541SPoul-Henning Kamp u_int32_t tmp; 29875c13541SPoul-Henning Kamp 29991421ba2SRobert Watson if (!jailed(cred)) 30075c13541SPoul-Henning Kamp return (0); 30175c13541SPoul-Henning Kamp if (flag) 30275c13541SPoul-Henning Kamp tmp = *ip; 30375c13541SPoul-Henning Kamp else 30475c13541SPoul-Henning Kamp tmp = ntohl(*ip); 30575c13541SPoul-Henning Kamp if (tmp == INADDR_ANY) { 30675c13541SPoul-Henning Kamp if (flag) 30791421ba2SRobert Watson *ip = cred->cr_prison->pr_ip; 30875c13541SPoul-Henning Kamp else 30991421ba2SRobert Watson *ip = htonl(cred->cr_prison->pr_ip); 31075c13541SPoul-Henning Kamp return (0); 31175c13541SPoul-Henning Kamp } 312fd6aaf7fSRobert Watson if (tmp == INADDR_LOOPBACK) { 313fd6aaf7fSRobert Watson if (flag) 314fd6aaf7fSRobert Watson *ip = cred->cr_prison->pr_ip; 315fd6aaf7fSRobert Watson else 316fd6aaf7fSRobert Watson *ip = htonl(cred->cr_prison->pr_ip); 317fd6aaf7fSRobert Watson return (0); 318fd6aaf7fSRobert Watson } 31991421ba2SRobert Watson if (cred->cr_prison->pr_ip != tmp) 32075c13541SPoul-Henning Kamp return (1); 32175c13541SPoul-Henning Kamp return (0); 32275c13541SPoul-Henning Kamp } 32375c13541SPoul-Henning Kamp 32475c13541SPoul-Henning Kamp void 32591421ba2SRobert Watson prison_remote_ip(struct ucred *cred, int flag, u_int32_t *ip) 32675c13541SPoul-Henning Kamp { 32775c13541SPoul-Henning Kamp u_int32_t tmp; 32875c13541SPoul-Henning Kamp 32991421ba2SRobert Watson if (!jailed(cred)) 33075c13541SPoul-Henning Kamp return; 33175c13541SPoul-Henning Kamp if (flag) 33275c13541SPoul-Henning Kamp tmp = *ip; 33375c13541SPoul-Henning Kamp else 33475c13541SPoul-Henning Kamp tmp = ntohl(*ip); 335fd6aaf7fSRobert Watson if (tmp == INADDR_LOOPBACK) { 33675c13541SPoul-Henning Kamp if (flag) 33791421ba2SRobert Watson *ip = cred->cr_prison->pr_ip; 33875c13541SPoul-Henning Kamp else 33991421ba2SRobert Watson *ip = htonl(cred->cr_prison->pr_ip); 34075c13541SPoul-Henning Kamp return; 34175c13541SPoul-Henning Kamp } 34275c13541SPoul-Henning Kamp return; 34375c13541SPoul-Henning Kamp } 34475c13541SPoul-Henning Kamp 34575c13541SPoul-Henning Kamp int 34691421ba2SRobert Watson prison_if(struct ucred *cred, struct sockaddr *sa) 34775c13541SPoul-Henning Kamp { 3489ddb7954SMike Barcroft struct sockaddr_in *sai; 34975c13541SPoul-Henning Kamp int ok; 35075c13541SPoul-Henning Kamp 3519ddb7954SMike Barcroft sai = (struct sockaddr_in *)sa; 3527cadc266SRobert Watson if ((sai->sin_family != AF_INET) && jail_socket_unixiproute_only) 3537cadc266SRobert Watson ok = 1; 3547cadc266SRobert Watson else if (sai->sin_family != AF_INET) 35575c13541SPoul-Henning Kamp ok = 0; 35691421ba2SRobert Watson else if (cred->cr_prison->pr_ip != ntohl(sai->sin_addr.s_addr)) 35775c13541SPoul-Henning Kamp ok = 1; 35875c13541SPoul-Henning Kamp else 35975c13541SPoul-Henning Kamp ok = 0; 36075c13541SPoul-Henning Kamp return (ok); 36175c13541SPoul-Henning Kamp } 36291421ba2SRobert Watson 36391421ba2SRobert Watson /* 36491421ba2SRobert Watson * Return 0 if jails permit p1 to frob p2, otherwise ESRCH. 36591421ba2SRobert Watson */ 36691421ba2SRobert Watson int 3679ddb7954SMike Barcroft prison_check(struct ucred *cred1, struct ucred *cred2) 36891421ba2SRobert Watson { 36991421ba2SRobert Watson 37091421ba2SRobert Watson if (jailed(cred1)) { 37191421ba2SRobert Watson if (!jailed(cred2)) 37291421ba2SRobert Watson return (ESRCH); 37391421ba2SRobert Watson if (cred2->cr_prison != cred1->cr_prison) 37491421ba2SRobert Watson return (ESRCH); 37591421ba2SRobert Watson } 37691421ba2SRobert Watson 37791421ba2SRobert Watson return (0); 37891421ba2SRobert Watson } 37991421ba2SRobert Watson 38091421ba2SRobert Watson /* 38191421ba2SRobert Watson * Return 1 if the passed credential is in a jail, otherwise 0. 38291421ba2SRobert Watson */ 38391421ba2SRobert Watson int 3849ddb7954SMike Barcroft jailed(struct ucred *cred) 38591421ba2SRobert Watson { 38691421ba2SRobert Watson 38791421ba2SRobert Watson return (cred->cr_prison != NULL); 38891421ba2SRobert Watson } 3899484d0c0SRobert Drehmel 3909484d0c0SRobert Drehmel /* 3919484d0c0SRobert Drehmel * Return the correct hostname for the passed credential. 3929484d0c0SRobert Drehmel */ 393ad1ff099SRobert Drehmel void 3949ddb7954SMike Barcroft getcredhostname(struct ucred *cred, char *buf, size_t size) 3959484d0c0SRobert Drehmel { 3969484d0c0SRobert Drehmel 397ad1ff099SRobert Drehmel if (jailed(cred)) { 398ad1ff099SRobert Drehmel mtx_lock(&cred->cr_prison->pr_mtx); 399e80fb434SRobert Drehmel strlcpy(buf, cred->cr_prison->pr_host, size); 400ad1ff099SRobert Drehmel mtx_unlock(&cred->cr_prison->pr_mtx); 4019ddb7954SMike Barcroft } else 402e80fb434SRobert Drehmel strlcpy(buf, hostname, size); 4039484d0c0SRobert Drehmel } 404fd7a8150SMike Barcroft 405fd7a8150SMike Barcroft static int 406fd7a8150SMike Barcroft sysctl_jail_list(SYSCTL_HANDLER_ARGS) 407fd7a8150SMike Barcroft { 408fd7a8150SMike Barcroft struct xprison *xp, *sxp; 409fd7a8150SMike Barcroft struct prison *pr; 410fd7a8150SMike Barcroft int count, error; 411fd7a8150SMike Barcroft 412fd7a8150SMike Barcroft mtx_assert(&Giant, MA_OWNED); 413fd7a8150SMike Barcroft retry: 414fd7a8150SMike Barcroft mtx_lock(&allprison_mtx); 415fd7a8150SMike Barcroft count = prisoncount; 416fd7a8150SMike Barcroft mtx_unlock(&allprison_mtx); 417fd7a8150SMike Barcroft 418fd7a8150SMike Barcroft if (count == 0) 419fd7a8150SMike Barcroft return (0); 420fd7a8150SMike Barcroft 421fd7a8150SMike Barcroft sxp = xp = malloc(sizeof(*xp) * count, M_TEMP, M_WAITOK | M_ZERO); 422fd7a8150SMike Barcroft mtx_lock(&allprison_mtx); 423fd7a8150SMike Barcroft if (count != prisoncount) { 424fd7a8150SMike Barcroft mtx_unlock(&allprison_mtx); 425fd7a8150SMike Barcroft free(sxp, M_TEMP); 426fd7a8150SMike Barcroft goto retry; 427fd7a8150SMike Barcroft } 428fd7a8150SMike Barcroft 429fd7a8150SMike Barcroft LIST_FOREACH(pr, &allprison, pr_list) { 430fd7a8150SMike Barcroft mtx_lock(&pr->pr_mtx); 431fd7a8150SMike Barcroft xp->pr_version = XPRISON_VERSION; 432fd7a8150SMike Barcroft xp->pr_id = pr->pr_id; 433fd7a8150SMike Barcroft strlcpy(xp->pr_path, pr->pr_path, sizeof(xp->pr_path)); 434fd7a8150SMike Barcroft strlcpy(xp->pr_host, pr->pr_host, sizeof(xp->pr_host)); 435fd7a8150SMike Barcroft xp->pr_ip = pr->pr_ip; 436fd7a8150SMike Barcroft mtx_unlock(&pr->pr_mtx); 437fd7a8150SMike Barcroft xp++; 438fd7a8150SMike Barcroft } 439fd7a8150SMike Barcroft mtx_unlock(&allprison_mtx); 440fd7a8150SMike Barcroft 441fd7a8150SMike Barcroft error = SYSCTL_OUT(req, sxp, sizeof(*sxp) * count); 442fd7a8150SMike Barcroft free(sxp, M_TEMP); 443fd7a8150SMike Barcroft if (error) 444fd7a8150SMike Barcroft return (error); 445fd7a8150SMike Barcroft return (0); 446fd7a8150SMike Barcroft } 447fd7a8150SMike Barcroft 448fd7a8150SMike Barcroft SYSCTL_OID(_security_jail, OID_AUTO, list, CTLTYPE_STRUCT | CTLFLAG_RD, 449fd7a8150SMike Barcroft NULL, 0, sysctl_jail_list, "S", "List of active jails"); 450