kern_jail.c (168399) | kern_jail.c (168401) |
---|---|
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 10#include <sys/cdefs.h> | 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 10#include <sys/cdefs.h> |
11__FBSDID("$FreeBSD: head/sys/kern/kern_jail.c 168399 2007-04-05 21:34:54Z pjd $"); | 11__FBSDID("$FreeBSD: head/sys/kern/kern_jail.c 168401 2007-04-05 23:19:13Z pjd $"); |
12 13#include "opt_mac.h" 14 15#include <sys/param.h> 16#include <sys/types.h> 17#include <sys/kernel.h> 18#include <sys/systm.h> 19#include <sys/errno.h> 20#include <sys/sysproto.h> 21#include <sys/malloc.h> 22#include <sys/priv.h> 23#include <sys/proc.h> 24#include <sys/taskqueue.h> 25#include <sys/jail.h> 26#include <sys/lock.h> 27#include <sys/mutex.h> | 12 13#include "opt_mac.h" 14 15#include <sys/param.h> 16#include <sys/types.h> 17#include <sys/kernel.h> 18#include <sys/systm.h> 19#include <sys/errno.h> 20#include <sys/sysproto.h> 21#include <sys/malloc.h> 22#include <sys/priv.h> 23#include <sys/proc.h> 24#include <sys/taskqueue.h> 25#include <sys/jail.h> 26#include <sys/lock.h> 27#include <sys/mutex.h> |
28#include <sys/sx.h> |
|
28#include <sys/namei.h> 29#include <sys/mount.h> 30#include <sys/queue.h> 31#include <sys/socket.h> 32#include <sys/syscallsubr.h> 33#include <sys/sysctl.h> 34#include <sys/vnode.h> 35#include <net/if.h> --- 36 unchanged lines hidden (view full) --- 72 &jail_chflags_allowed, 0, 73 "Processes in jail can alter system file flags"); 74 75int jail_mount_allowed = 0; 76SYSCTL_INT(_security_jail, OID_AUTO, mount_allowed, CTLFLAG_RW, 77 &jail_mount_allowed, 0, 78 "Processes in jail can mount/unmount jail-friendly file systems"); 79 | 29#include <sys/namei.h> 30#include <sys/mount.h> 31#include <sys/queue.h> 32#include <sys/socket.h> 33#include <sys/syscallsubr.h> 34#include <sys/sysctl.h> 35#include <sys/vnode.h> 36#include <net/if.h> --- 36 unchanged lines hidden (view full) --- 73 &jail_chflags_allowed, 0, 74 "Processes in jail can alter system file flags"); 75 76int jail_mount_allowed = 0; 77SYSCTL_INT(_security_jail, OID_AUTO, mount_allowed, CTLFLAG_RW, 78 &jail_mount_allowed, 0, 79 "Processes in jail can mount/unmount jail-friendly file systems"); 80 |
80/* allprison, lastprid, and prisoncount are protected by allprison_mtx. */ | 81/* allprison, lastprid, and prisoncount are protected by allprison_lock. */ |
81struct prisonlist allprison; | 82struct prisonlist allprison; |
82struct mtx allprison_mtx; | 83struct sx allprison_lock; |
83int lastprid = 0; 84int prisoncount = 0; 85 | 84int lastprid = 0; 85int prisoncount = 0; 86 |
87/* 88 * List of jail services. Protected by allprison_lock. 89 */ 90TAILQ_HEAD(prison_services_head, prison_service); 91static struct prison_services_head prison_services = 92 TAILQ_HEAD_INITIALIZER(prison_services); 93static int prison_service_slots = 0; 94 95struct prison_service { 96 prison_create_t ps_create; 97 prison_destroy_t ps_destroy; 98 int ps_slotno; 99 TAILQ_ENTRY(prison_service) ps_next; 100 char ps_name[0]; 101}; 102 |
|
86static void init_prison(void *); 87static void prison_complete(void *context, int pending); 88static int sysctl_jail_list(SYSCTL_HANDLER_ARGS); 89 90static void 91init_prison(void *data __unused) 92{ 93 | 103static void init_prison(void *); 104static void prison_complete(void *context, int pending); 105static int sysctl_jail_list(SYSCTL_HANDLER_ARGS); 106 107static void 108init_prison(void *data __unused) 109{ 110 |
94 mtx_init(&allprison_mtx, "allprison", NULL, MTX_DEF); | 111 sx_init(&allprison_lock, "allprison"); |
95 LIST_INIT(&allprison); 96} 97 98SYSINIT(prison, SI_SUB_INTRINSIC, SI_ORDER_ANY, init_prison, NULL); 99 100/* 101 * struct jail_args { 102 * struct jail *jail; 103 * }; 104 */ 105int 106jail(struct thread *td, struct jail_args *uap) 107{ 108 struct nameidata nd; 109 struct prison *pr, *tpr; | 112 LIST_INIT(&allprison); 113} 114 115SYSINIT(prison, SI_SUB_INTRINSIC, SI_ORDER_ANY, init_prison, NULL); 116 117/* 118 * struct jail_args { 119 * struct jail *jail; 120 * }; 121 */ 122int 123jail(struct thread *td, struct jail_args *uap) 124{ 125 struct nameidata nd; 126 struct prison *pr, *tpr; |
127 struct prison_service *psrv; |
|
110 struct jail j; 111 struct jail_attach_args jaa; 112 int vfslocked, error, tryprid; 113 114 error = copyin(uap->jail, &j, sizeof(j)); 115 if (error) 116 return (error); 117 if (j.version != 0) --- 16 unchanged lines hidden (view full) --- 134 NDFREE(&nd, NDF_ONLY_PNBUF); 135 VFS_UNLOCK_GIANT(vfslocked); 136 error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0); 137 if (error) 138 goto e_dropvnref; 139 pr->pr_ip = j.ip_number; 140 pr->pr_linux = NULL; 141 pr->pr_securelevel = securelevel; | 128 struct jail j; 129 struct jail_attach_args jaa; 130 int vfslocked, error, tryprid; 131 132 error = copyin(uap->jail, &j, sizeof(j)); 133 if (error) 134 return (error); 135 if (j.version != 0) --- 16 unchanged lines hidden (view full) --- 152 NDFREE(&nd, NDF_ONLY_PNBUF); 153 VFS_UNLOCK_GIANT(vfslocked); 154 error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0); 155 if (error) 156 goto e_dropvnref; 157 pr->pr_ip = j.ip_number; 158 pr->pr_linux = NULL; 159 pr->pr_securelevel = securelevel; |
160 if (prison_service_slots == 0) 161 pr->pr_slots = NULL; 162 else { 163 pr->pr_slots = malloc(sizeof(*pr->pr_slots) * prison_service_slots, 164 M_PRISON, M_ZERO | M_WAITOK); 165 } |
|
142 143 /* Determine next pr_id and add prison to allprison list. */ | 166 167 /* Determine next pr_id and add prison to allprison list. */ |
144 mtx_lock(&allprison_mtx); | 168 sx_xlock(&allprison_lock); |
145 tryprid = lastprid + 1; 146 if (tryprid == JAIL_MAX) 147 tryprid = 1; 148next: 149 LIST_FOREACH(tpr, &allprison, pr_list) { 150 if (tpr->pr_id == tryprid) { 151 tryprid++; 152 if (tryprid == JAIL_MAX) { | 169 tryprid = lastprid + 1; 170 if (tryprid == JAIL_MAX) 171 tryprid = 1; 172next: 173 LIST_FOREACH(tpr, &allprison, pr_list) { 174 if (tpr->pr_id == tryprid) { 175 tryprid++; 176 if (tryprid == JAIL_MAX) { |
153 mtx_unlock(&allprison_mtx); | 177 sx_xunlock(&allprison_lock); |
154 error = EAGAIN; 155 goto e_dropvnref; 156 } 157 goto next; 158 } 159 } 160 pr->pr_id = jaa.jid = lastprid = tryprid; 161 LIST_INSERT_HEAD(&allprison, pr, pr_list); 162 prisoncount++; | 178 error = EAGAIN; 179 goto e_dropvnref; 180 } 181 goto next; 182 } 183 } 184 pr->pr_id = jaa.jid = lastprid = tryprid; 185 LIST_INSERT_HEAD(&allprison, pr, pr_list); 186 prisoncount++; |
163 mtx_unlock(&allprison_mtx); | 187 sx_downgrade(&allprison_lock); 188 TAILQ_FOREACH(psrv, &prison_services, ps_next) { 189 psrv->ps_create(psrv, pr); 190 } 191 sx_sunlock(&allprison_lock); |
164 165 error = jail_attach(td, &jaa); 166 if (error) 167 goto e_dropprref; 168 mtx_lock(&pr->pr_mtx); 169 pr->pr_ref--; 170 mtx_unlock(&pr->pr_mtx); 171 td->td_retval[0] = jaa.jid; 172 return (0); 173e_dropprref: | 192 193 error = jail_attach(td, &jaa); 194 if (error) 195 goto e_dropprref; 196 mtx_lock(&pr->pr_mtx); 197 pr->pr_ref--; 198 mtx_unlock(&pr->pr_mtx); 199 td->td_retval[0] = jaa.jid; 200 return (0); 201e_dropprref: |
174 mtx_lock(&allprison_mtx); | 202 sx_xlock(&allprison_lock); |
175 LIST_REMOVE(pr, pr_list); 176 prisoncount--; | 203 LIST_REMOVE(pr, pr_list); 204 prisoncount--; |
177 mtx_unlock(&allprison_mtx); | 205 sx_downgrade(&allprison_lock); 206 TAILQ_FOREACH(psrv, &prison_services, ps_next) { 207 psrv->ps_destroy(psrv, pr); 208 } 209 sx_sunlock(&allprison_lock); |
178e_dropvnref: 179 vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount); 180 vrele(pr->pr_root); 181 VFS_UNLOCK_GIANT(vfslocked); 182e_killmtx: 183 mtx_destroy(&pr->pr_mtx); 184 FREE(pr, M_PRISON); 185 return (error); --- 20 unchanged lines hidden (view full) --- 206 * a process root from one prison, but attached to the jail 207 * of another. 208 */ 209 error = priv_check(td, PRIV_JAIL_ATTACH); 210 if (error) 211 return (error); 212 213 p = td->td_proc; | 210e_dropvnref: 211 vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount); 212 vrele(pr->pr_root); 213 VFS_UNLOCK_GIANT(vfslocked); 214e_killmtx: 215 mtx_destroy(&pr->pr_mtx); 216 FREE(pr, M_PRISON); 217 return (error); --- 20 unchanged lines hidden (view full) --- 238 * a process root from one prison, but attached to the jail 239 * of another. 240 */ 241 error = priv_check(td, PRIV_JAIL_ATTACH); 242 if (error) 243 return (error); 244 245 p = td->td_proc; |
214 mtx_lock(&allprison_mtx); | 246 sx_slock(&allprison_lock); |
215 pr = prison_find(uap->jid); 216 if (pr == NULL) { | 247 pr = prison_find(uap->jid); 248 if (pr == NULL) { |
217 mtx_unlock(&allprison_mtx); | 249 sx_sunlock(&allprison_lock); |
218 return (EINVAL); 219 } 220 pr->pr_ref++; 221 mtx_unlock(&pr->pr_mtx); | 250 return (EINVAL); 251 } 252 pr->pr_ref++; 253 mtx_unlock(&pr->pr_mtx); |
222 mtx_unlock(&allprison_mtx); | 254 sx_sunlock(&allprison_lock); |
223 224 vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount); 225 vn_lock(pr->pr_root, LK_EXCLUSIVE | LK_RETRY, td); 226 if ((error = change_dir(pr->pr_root, td)) != 0) 227 goto e_unlock; 228#ifdef MAC 229 if ((error = mac_check_vnode_chroot(td->td_ucred, pr->pr_root))) 230 goto e_unlock; --- 24 unchanged lines hidden (view full) --- 255/* 256 * Returns a locked prison instance, or NULL on failure. 257 */ 258struct prison * 259prison_find(int prid) 260{ 261 struct prison *pr; 262 | 255 256 vfslocked = VFS_LOCK_GIANT(pr->pr_root->v_mount); 257 vn_lock(pr->pr_root, LK_EXCLUSIVE | LK_RETRY, td); 258 if ((error = change_dir(pr->pr_root, td)) != 0) 259 goto e_unlock; 260#ifdef MAC 261 if ((error = mac_check_vnode_chroot(td->td_ucred, pr->pr_root))) 262 goto e_unlock; --- 24 unchanged lines hidden (view full) --- 287/* 288 * Returns a locked prison instance, or NULL on failure. 289 */ 290struct prison * 291prison_find(int prid) 292{ 293 struct prison *pr; 294 |
263 mtx_assert(&allprison_mtx, MA_OWNED); | 295 sx_assert(&allprison_lock, SX_LOCKED); |
264 LIST_FOREACH(pr, &allprison, pr_list) { 265 if (pr->pr_id == prid) { 266 mtx_lock(&pr->pr_mtx); 267 return (pr); 268 } 269 } 270 return (NULL); 271} 272 273void 274prison_free(struct prison *pr) 275{ | 296 LIST_FOREACH(pr, &allprison, pr_list) { 297 if (pr->pr_id == prid) { 298 mtx_lock(&pr->pr_mtx); 299 return (pr); 300 } 301 } 302 return (NULL); 303} 304 305void 306prison_free(struct prison *pr) 307{ |
308 struct prison_service *psrv; |
|
276 | 309 |
277 mtx_lock(&allprison_mtx); | 310 sx_xlock(&allprison_lock); |
278 mtx_lock(&pr->pr_mtx); 279 pr->pr_ref--; 280 if (pr->pr_ref == 0) { 281 LIST_REMOVE(pr, pr_list); 282 mtx_unlock(&pr->pr_mtx); 283 prisoncount--; | 311 mtx_lock(&pr->pr_mtx); 312 pr->pr_ref--; 313 if (pr->pr_ref == 0) { 314 LIST_REMOVE(pr, pr_list); 315 mtx_unlock(&pr->pr_mtx); 316 prisoncount--; |
284 mtx_unlock(&allprison_mtx); | 317 sx_downgrade(&allprison_lock); 318 TAILQ_FOREACH(psrv, &prison_services, ps_next) { 319 psrv->ps_destroy(psrv, pr); 320 } 321 sx_sunlock(&allprison_lock); |
285 286 TASK_INIT(&pr->pr_task, 0, prison_complete, pr); 287 taskqueue_enqueue(taskqueue_thread, &pr->pr_task); 288 return; 289 } 290 mtx_unlock(&pr->pr_mtx); | 322 323 TASK_INIT(&pr->pr_task, 0, prison_complete, pr); 324 taskqueue_enqueue(taskqueue_thread, &pr->pr_task); 325 return; 326 } 327 mtx_unlock(&pr->pr_mtx); |
291 mtx_unlock(&allprison_mtx); | 328 sx_xunlock(&allprison_lock); |
292} 293 294static void 295prison_complete(void *context, int pending) 296{ 297 struct prison *pr; 298 int vfslocked; 299 --- 395 unchanged lines hidden (view full) --- 695 * In all remaining cases, deny the privilege request. This 696 * includes almost all network privileges, many system 697 * configuration privileges. 698 */ 699 return (EPERM); 700 } 701} 702 | 329} 330 331static void 332prison_complete(void *context, int pending) 333{ 334 struct prison *pr; 335 int vfslocked; 336 --- 395 unchanged lines hidden (view full) --- 732 * In all remaining cases, deny the privilege request. This 733 * includes almost all network privileges, many system 734 * configuration privileges. 735 */ 736 return (EPERM); 737 } 738} 739 |
740/* 741 * Register jail service. Provides 'create' and 'destroy' methods. 742 * 'create' method will be called for every existing jail and all 743 * jails in the future as they beeing created. 744 * 'destroy' method will be called for every jail going away and 745 * for all existing jails at the time of service deregistration. 746 */ 747struct prison_service * 748prison_service_register(const char *name, prison_create_t create, 749 prison_destroy_t destroy) 750{ 751 struct prison_service *psrv, *psrv2; 752 struct prison *pr; 753 int reallocate = 1, slotno = 0; 754 void **slots, **oldslots; 755 756 psrv = malloc(sizeof(*psrv) + strlen(name) + 1, M_PRISON, 757 M_WAITOK | M_ZERO); 758 psrv->ps_create = create; 759 psrv->ps_destroy = destroy; 760 strcpy(psrv->ps_name, name); 761 /* 762 * Grab the allprison_lock here, so we won't miss any jail 763 * creation/destruction. 764 */ 765 sx_xlock(&allprison_lock); 766#ifdef INVARIANTS 767 /* 768 * Verify if service is not already registered. 769 */ 770 TAILQ_FOREACH(psrv2, &prison_services, ps_next) { 771 KASSERT(strcmp(psrv2->ps_name, name) != 0, 772 ("jail service %s already registered", name)); 773 } 774#endif 775 /* 776 * Find free slot. When there is no existing free slot available, 777 * allocate one at the end. 778 */ 779 TAILQ_FOREACH(psrv2, &prison_services, ps_next) { 780 if (psrv2->ps_slotno != slotno) { 781 KASSERT(slotno < psrv2->ps_slotno, 782 ("Invalid slotno (slotno=%d >= ps_slotno=%d", 783 slotno, psrv2->ps_slotno)); 784 /* We found free slot. */ 785 reallocate = 0; 786 break; 787 } 788 slotno++; 789 } 790 psrv->ps_slotno = slotno; 791 /* 792 * Keep the list sorted by slot number. 793 */ 794 if (psrv2 != NULL) { 795 KASSERT(reallocate == 0, ("psrv2 != NULL && reallocate != 0")); 796 TAILQ_INSERT_BEFORE(psrv2, psrv, ps_next); 797 } else { 798 KASSERT(reallocate == 1, ("psrv2 == NULL && reallocate == 0")); 799 TAILQ_INSERT_TAIL(&prison_services, psrv, ps_next); 800 } 801 prison_service_slots++; 802 sx_downgrade(&allprison_lock); 803 /* 804 * Allocate memory for new slot if we didn't found empty one. 805 * Do not use realloc(9), because pr_slots is protected with a mutex, 806 * so we can't sleep. 807 */ 808 LIST_FOREACH(pr, &allprison, pr_list) { 809 if (reallocate) { 810 /* First allocate memory with M_WAITOK. */ 811 slots = malloc(sizeof(*slots) * prison_service_slots, 812 M_PRISON, M_WAITOK); 813 /* Now grab the mutex and replace pr_slots. */ 814 mtx_lock(&pr->pr_mtx); 815 oldslots = pr->pr_slots; 816 if (psrv->ps_slotno > 0) { 817 bcopy(oldslots, slots, 818 sizeof(*slots) * (prison_service_slots - 1)); 819 } 820 slots[psrv->ps_slotno] = NULL; 821 pr->pr_slots = slots; 822 mtx_unlock(&pr->pr_mtx); 823 if (oldslots != NULL) 824 free(oldslots, M_PRISON); 825 } 826 /* 827 * Call 'create' method for each existing jail. 828 */ 829 psrv->ps_create(psrv, pr); 830 } 831 sx_sunlock(&allprison_lock); 832 833 return (psrv); 834} 835 836void 837prison_service_deregister(struct prison_service *psrv) 838{ 839 struct prison *pr; 840 void **slots, **oldslots; 841 int last = 0; 842 843 sx_xlock(&allprison_lock); 844 if (TAILQ_LAST(&prison_services, prison_services_head) == psrv) 845 last = 1; 846 TAILQ_REMOVE(&prison_services, psrv, ps_next); 847 prison_service_slots--; 848 sx_downgrade(&allprison_lock); 849 LIST_FOREACH(pr, &allprison, pr_list) { 850 /* 851 * Call 'destroy' method for every currently existing jail. 852 */ 853 psrv->ps_destroy(psrv, pr); 854 /* 855 * If this is the last slot, free the memory allocated for it. 856 */ 857 if (last) { 858 if (prison_service_slots == 0) 859 slots = NULL; 860 else { 861 slots = malloc(sizeof(*slots) * prison_service_slots, 862 M_PRISON, M_WAITOK); 863 } 864 mtx_lock(&pr->pr_mtx); 865 oldslots = pr->pr_slots; 866 /* 867 * We require setting slot to NULL after freeing it, 868 * this way we can check for memory leaks here. 869 */ 870 KASSERT(oldslots[psrv->ps_slotno] == NULL, 871 ("Slot %d (service %s, jailid=%d) still contains data?", 872 psrv->ps_slotno, psrv->ps_name, pr->pr_id)); 873 if (psrv->ps_slotno > 0) { 874 bcopy(oldslots, slots, 875 sizeof(*slots) * prison_service_slots); 876 } 877 pr->pr_slots = slots; 878 mtx_unlock(&pr->pr_mtx); 879 KASSERT(oldslots != NULL, ("oldslots == NULL")); 880 free(oldslots, M_PRISON); 881 } 882 } 883 sx_sunlock(&allprison_lock); 884 free(psrv, M_PRISON); 885} 886 887/* 888 * Function sets data for the given jail in slot assigned for the given 889 * jail service. 890 */ 891void 892prison_service_data_set(struct prison_service *psrv, struct prison *pr, 893 void *data) 894{ 895 896 mtx_assert(&pr->pr_mtx, MA_OWNED); 897 pr->pr_slots[psrv->ps_slotno] = data; 898} 899 900/* 901 * Function clears slots assigned for the given jail service in the given 902 * prison structure and returns current slot data. 903 */ 904void * 905prison_service_data_del(struct prison_service *psrv, struct prison *pr) 906{ 907 void *data; 908 909 mtx_assert(&pr->pr_mtx, MA_OWNED); 910 data = pr->pr_slots[psrv->ps_slotno]; 911 pr->pr_slots[psrv->ps_slotno] = NULL; 912 return (data); 913} 914 915/* 916 * Function returns current data from the slot assigned to the given jail 917 * service for the given jail. 918 */ 919void * 920prison_service_data_get(struct prison_service *psrv, struct prison *pr) 921{ 922 923 mtx_assert(&pr->pr_mtx, MA_OWNED); 924 return (pr->pr_slots[psrv->ps_slotno]); 925} 926 |
|
703static int 704sysctl_jail_list(SYSCTL_HANDLER_ARGS) 705{ 706 struct xprison *xp, *sxp; 707 struct prison *pr; 708 int count, error; 709 710 if (jailed(req->td->td_ucred)) 711 return (0); | 927static int 928sysctl_jail_list(SYSCTL_HANDLER_ARGS) 929{ 930 struct xprison *xp, *sxp; 931 struct prison *pr; 932 int count, error; 933 934 if (jailed(req->td->td_ucred)) 935 return (0); |
712retry: 713 mtx_lock(&allprison_mtx); 714 count = prisoncount; 715 mtx_unlock(&allprison_mtx); | |
716 | 936 |
717 if (count == 0) | 937 sx_slock(&allprison_lock); 938 if ((count = prisoncount) == 0) { 939 sx_sunlock(&allprison_lock); |
718 return (0); | 940 return (0); |
941 } |
|
719 720 sxp = xp = malloc(sizeof(*xp) * count, M_TEMP, M_WAITOK | M_ZERO); | 942 943 sxp = xp = malloc(sizeof(*xp) * count, M_TEMP, M_WAITOK | M_ZERO); |
721 mtx_lock(&allprison_mtx); 722 if (count != prisoncount) { 723 mtx_unlock(&allprison_mtx); 724 free(sxp, M_TEMP); 725 goto retry; 726 } | |
727 728 LIST_FOREACH(pr, &allprison, pr_list) { 729 mtx_lock(&pr->pr_mtx); 730 xp->pr_version = XPRISON_VERSION; 731 xp->pr_id = pr->pr_id; 732 strlcpy(xp->pr_path, pr->pr_path, sizeof(xp->pr_path)); 733 strlcpy(xp->pr_host, pr->pr_host, sizeof(xp->pr_host)); 734 xp->pr_ip = pr->pr_ip; 735 mtx_unlock(&pr->pr_mtx); 736 xp++; 737 } | 944 945 LIST_FOREACH(pr, &allprison, pr_list) { 946 mtx_lock(&pr->pr_mtx); 947 xp->pr_version = XPRISON_VERSION; 948 xp->pr_id = pr->pr_id; 949 strlcpy(xp->pr_path, pr->pr_path, sizeof(xp->pr_path)); 950 strlcpy(xp->pr_host, pr->pr_host, sizeof(xp->pr_host)); 951 xp->pr_ip = pr->pr_ip; 952 mtx_unlock(&pr->pr_mtx); 953 xp++; 954 } |
738 mtx_unlock(&allprison_mtx); | 955 sx_sunlock(&allprison_lock); |
739 740 error = SYSCTL_OUT(req, sxp, sizeof(*sxp) * count); 741 free(sxp, M_TEMP); 742 return (error); 743} 744 745SYSCTL_OID(_security_jail, OID_AUTO, list, CTLTYPE_STRUCT | CTLFLAG_RD, 746 NULL, 0, sysctl_jail_list, "S", "List of active jails"); --- 13 unchanged lines hidden --- | 956 957 error = SYSCTL_OUT(req, sxp, sizeof(*sxp) * count); 958 free(sxp, M_TEMP); 959 return (error); 960} 961 962SYSCTL_OID(_security_jail, OID_AUTO, list, CTLTYPE_STRUCT | CTLFLAG_RD, 963 NULL, 0, sysctl_jail_list, "S", "List of active jails"); --- 13 unchanged lines hidden --- |