View | Details | Raw Unified | Return to bug 48471 | Differences between
and this patch

Collapse All | Expand All

(-)b/sys/kern/kern_jail.c (+4 lines)
Lines 60-65 __FBSDID("$FreeBSD$"); Link Here
60
#include <sys/syscallsubr.h>
60
#include <sys/syscallsubr.h>
61
#include <sys/sysctl.h>
61
#include <sys/sysctl.h>
62
#include <sys/vnode.h>
62
#include <sys/vnode.h>
63
#include <sys/ipc.h>
63
64
64
#include <net/if.h>
65
#include <net/if.h>
65
#include <net/vnet.h>
66
#include <net/vnet.h>
Lines 2330-2335 prison_remove_one(struct prison *pr) Link Here
2330
		pr->pr_flags &= ~PR_PERSIST;
2331
		pr->pr_flags &= ~PR_PERSIST;
2331
	}
2332
	}
2332
2333
2334
	/* SysV IPC cleanup for the prison */
2335
	ipc_cleanup_for_prison(pr);
2336
2333
	/*
2337
	/*
2334
	 * jail_remove added a reference.  If that's the only one, remove
2338
	 * jail_remove added a reference.  If that's the only one, remove
2335
	 * the prison now.
2339
	 * the prison now.
(-)b/sys/kern/sysv_ipc.c (+17 lines)
Lines 47-55 __FBSDID("$FreeBSD$"); Link Here
47
#include <sys/priv.h>
47
#include <sys/priv.h>
48
#include <sys/proc.h>
48
#include <sys/proc.h>
49
#include <sys/ucred.h>
49
#include <sys/ucred.h>
50
#include <sys/jail.h>
50
51
51
void (*shmfork_hook)(struct proc *, struct proc *) = NULL;
52
void (*shmfork_hook)(struct proc *, struct proc *) = NULL;
52
void (*shmexit_hook)(struct vmspace *) = NULL;
53
void (*shmexit_hook)(struct vmspace *) = NULL;
54
void (*sysvshm_cleanup_for_prison_hook)(struct prison *) = NULL;
55
void (*sysvmsg_cleanup_for_prison_hook)(struct prison *) = NULL;
56
void (*sysvsem_cleanup_for_prison_hook)(struct prison *) = NULL;
53
57
54
/* called from kern_fork.c */
58
/* called from kern_fork.c */
55
void
59
void
Lines 72-77 shmexit(struct vmspace *vm) Link Here
72
	return;
76
	return;
73
}
77
}
74
78
79
/* called from kern_jail.c */
80
void
81
ipc_cleanup_for_prison(struct prison *pr)
82
{
83
84
	if (sysvshm_cleanup_for_prison_hook != NULL)
85
		sysvshm_cleanup_for_prison_hook(pr);
86
	if (sysvmsg_cleanup_for_prison_hook != NULL)
87
		sysvmsg_cleanup_for_prison_hook(pr);
88
	if (sysvsem_cleanup_for_prison_hook != NULL)
89
		sysvsem_cleanup_for_prison_hook(pr);
90
}
91
75
/*
92
/*
76
 * Check for IPC permission.
93
 * Check for IPC permission.
77
 *
94
 *
(-)b/sys/kern/sysv_msg.c (-33 / +110 lines)
Lines 68-73 __FBSDID("$FreeBSD$"); Link Here
68
#include <sys/syscallsubr.h>
68
#include <sys/syscallsubr.h>
69
#include <sys/sysent.h>
69
#include <sys/sysent.h>
70
#include <sys/sysctl.h>
70
#include <sys/sysctl.h>
71
#include <sys/sbuf.h>
71
#include <sys/malloc.h>
72
#include <sys/malloc.h>
72
#include <sys/jail.h>
73
#include <sys/jail.h>
73
74
Lines 80-85 static MALLOC_DEFINE(M_MSG, "msg", "SVID compatible message queues"); Link Here
80
static int msginit(void);
81
static int msginit(void);
81
static int msgunload(void);
82
static int msgunload(void);
82
static int sysvmsg_modload(struct module *, int, void *);
83
static int sysvmsg_modload(struct module *, int, void *);
84
static int cr_cansee_msq(struct ucred *, struct msqid_kernel *);
85
static void msq_remove(struct msqid_kernel *);
86
static void sysvmsg_cleanup_for_prison_myhook(struct prison *);
83
87
84
88
85
#ifdef MSG_DEBUG
89
#ifdef MSG_DEBUG
Lines 257-262 msginit() Link Here
257
#endif
261
#endif
258
	}
262
	}
259
	mtx_init(&msq_mtx, "msq", NULL, MTX_DEF);
263
	mtx_init(&msq_mtx, "msq", NULL, MTX_DEF);
264
	sysvmsg_cleanup_for_prison_hook = &sysvmsg_cleanup_for_prison_myhook;
260
265
261
	error = syscall_helper_register(msg_syscalls);
266
	error = syscall_helper_register(msg_syscalls);
262
	if (error != 0)
267
	if (error != 0)
Lines 282-287 msgunload() Link Here
282
#ifdef COMPAT_FREEBSD32
287
#ifdef COMPAT_FREEBSD32
283
	syscall32_helper_unregister(msg32_syscalls);
288
	syscall32_helper_unregister(msg32_syscalls);
284
#endif
289
#endif
290
	sysvmsg_cleanup_for_prison_hook = NULL;
285
291
286
	for (msqid = 0; msqid < msginfo.msgmni; msqid++) {
292
	for (msqid = 0; msqid < msginfo.msgmni; msqid++) {
287
		/*
293
		/*
Lines 372-377 msg_freehdr(msghdr) Link Here
372
#endif
378
#endif
373
}
379
}
374
380
381
static int
382
cr_cansee_msq(struct ucred *cred, struct msqid_kernel *msqkptr)
383
{
384
385
	if (msqkptr->cred == NULL || prison_check(cred, msqkptr->cred))
386
		return (EINVAL);
387
	return (0);
388
}
389
390
static void
391
msq_remove(struct msqid_kernel *msqkptr)
392
{
393
	struct msg *msghdr;
394
395
	racct_sub_cred(msqkptr->cred, RACCT_NMSGQ, 1);
396
	racct_sub_cred(msqkptr->cred, RACCT_MSGQQUEUED, msqkptr->u.msg_qnum);
397
	racct_sub_cred(msqkptr->cred, RACCT_MSGQSIZE, msqkptr->u.msg_cbytes);
398
	crfree(msqkptr->cred);
399
	msqkptr->cred = NULL;
400
401
	/* Free the message headers */
402
	msghdr = msqkptr->u.msg_first;
403
	while (msghdr != NULL) {
404
		struct msg *msghdr_tmp;
405
406
		/* Free the segments of each message */
407
		msqkptr->u.msg_cbytes -= msghdr->msg_ts;
408
		msqkptr->u.msg_qnum--;
409
		msghdr_tmp = msghdr;
410
		msghdr = msghdr->msg_next;
411
		msg_freehdr(msghdr_tmp);
412
	}
413
414
	if (msqkptr->u.msg_cbytes != 0)
415
		panic("msg_cbytes is screwed up");
416
	if (msqkptr->u.msg_qnum != 0)
417
		panic("msg_qnum is screwed up");
418
419
	msqkptr->u.msg_qbytes = 0;	/* Mark it as free */
420
421
#ifdef MAC
422
	mac_sysvmsq_cleanup(msqkptr);
423
#endif
424
425
	wakeup(msqkptr);
426
}
427
428
static void
429
sysvmsg_cleanup_for_prison_myhook(struct prison *pr)
430
{
431
	int i;
432
	struct msqid_kernel *msqkptr;
433
434
	mtx_lock(&msq_mtx);
435
	for (i = 0; i < msginfo.msgmni; i++) {
436
		msqkptr = &msqids[i];
437
		if (msqkptr->u.msg_qbytes != 0 &&
438
		    msqkptr->cred && msqkptr->cred->cr_prison == pr)
439
			msq_remove(msqkptr);
440
	}
441
	mtx_unlock(&msq_mtx);
442
}
443
375
#ifndef _SYS_SYSPROTO_H_
444
#ifndef _SYS_SYSPROTO_H_
376
struct msgctl_args {
445
struct msgctl_args {
377
	int	msqid;
446
	int	msqid;
Lines 433-438 kern_msgctl(td, msqid, cmd, msqbuf) Link Here
433
		error = EINVAL;
502
		error = EINVAL;
434
		goto done2;
503
		goto done2;
435
	}
504
	}
505
	error = cr_cansee_msq(td->td_ucred, msqkptr);
506
	if (error != 0)
507
		goto done2;
436
#ifdef MAC
508
#ifdef MAC
437
	error = mac_sysvmsq_check_msqctl(td->td_ucred, msqkptr, cmd);
509
	error = mac_sysvmsq_check_msqctl(td->td_ucred, msqkptr, cmd);
438
	if (error != 0)
510
	if (error != 0)
Lines 446-452 kern_msgctl(td, msqid, cmd, msqbuf) Link Here
446
518
447
	case IPC_RMID:
519
	case IPC_RMID:
448
	{
520
	{
521
#ifdef MAC
449
		struct msg *msghdr;
522
		struct msg *msghdr;
523
#endif
450
		if ((error = ipcperm(td, &msqkptr->u.msg_perm, IPC_M)))
524
		if ((error = ipcperm(td, &msqkptr->u.msg_perm, IPC_M)))
451
			goto done2;
525
			goto done2;
452
526
Lines 468-504 kern_msgctl(td, msqid, cmd, msqbuf) Link Here
468
		}
542
		}
469
#endif
543
#endif
470
544
471
		racct_sub_cred(msqkptr->cred, RACCT_NMSGQ, 1);
545
		msq_remove(msqkptr);
472
		racct_sub_cred(msqkptr->cred, RACCT_MSGQQUEUED, msqkptr->u.msg_qnum);
473
		racct_sub_cred(msqkptr->cred, RACCT_MSGQSIZE, msqkptr->u.msg_cbytes);
474
		crfree(msqkptr->cred);
475
		msqkptr->cred = NULL;
476
477
		/* Free the message headers */
478
		msghdr = msqkptr->u.msg_first;
479
		while (msghdr != NULL) {
480
			struct msg *msghdr_tmp;
481
482
			/* Free the segments of each message */
483
			msqkptr->u.msg_cbytes -= msghdr->msg_ts;
484
			msqkptr->u.msg_qnum--;
485
			msghdr_tmp = msghdr;
486
			msghdr = msghdr->msg_next;
487
			msg_freehdr(msghdr_tmp);
488
		}
489
490
		if (msqkptr->u.msg_cbytes != 0)
491
			panic("msg_cbytes is screwed up");
492
		if (msqkptr->u.msg_qnum != 0)
493
			panic("msg_qnum is screwed up");
494
495
		msqkptr->u.msg_qbytes = 0;	/* Mark it as free */
496
497
#ifdef MAC
498
		mac_sysvmsq_cleanup(msqkptr);
499
#endif
500
501
		wakeup(msqkptr);
502
	}
546
	}
503
547
504
		break;
548
		break;
Lines 578-583 sys_msgget(td, uap) Link Here
578
		for (msqid = 0; msqid < msginfo.msgmni; msqid++) {
622
		for (msqid = 0; msqid < msginfo.msgmni; msqid++) {
579
			msqkptr = &msqids[msqid];
623
			msqkptr = &msqids[msqid];
580
			if (msqkptr->u.msg_qbytes != 0 &&
624
			if (msqkptr->u.msg_qbytes != 0 &&
625
			    msqkptr->cred && msqkptr->cred->cr_prison == cred->cr_prison &&
581
			    msqkptr->u.msg_perm.key == key)
626
			    msqkptr->u.msg_perm.key == key)
582
				break;
627
				break;
583
		}
628
		}
Lines 718-723 kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype) Link Here
718
		goto done2;
763
		goto done2;
719
	}
764
	}
720
765
766
	if ((error = cr_cansee_msq(td->td_ucred, msqkptr)))
767
		goto done2;
721
	if ((error = ipcperm(td, &msqkptr->u.msg_perm, IPC_W))) {
768
	if ((error = ipcperm(td, &msqkptr->u.msg_perm, IPC_W))) {
722
		DPRINTF(("requester doesn't have write access\n"));
769
		DPRINTF(("requester doesn't have write access\n"));
723
		goto done2;
770
		goto done2;
Lines 1081-1086 kern_msgrcv(td, msqid, msgp, msgsz, msgtyp, msgflg, mtype) Link Here
1081
		goto done2;
1128
		goto done2;
1082
	}
1129
	}
1083
1130
1131
	if ((error = cr_cansee_msq(td->td_ucred, msqkptr)))
1132
		goto done2;
1084
	if ((error = ipcperm(td, &msqkptr->u.msg_perm, IPC_R))) {
1133
	if ((error = ipcperm(td, &msqkptr->u.msg_perm, IPC_R))) {
1085
		DPRINTF(("requester doesn't have read access\n"));
1134
		DPRINTF(("requester doesn't have read access\n"));
1086
		goto done2;
1135
		goto done2;
Lines 1320-1328 sys_msgrcv(td, uap) Link Here
1320
static int
1369
static int
1321
sysctl_msqids(SYSCTL_HANDLER_ARGS)
1370
sysctl_msqids(SYSCTL_HANDLER_ARGS)
1322
{
1371
{
1372
	int error;
1373
	struct sbuf sb;
1374
	struct msqid_kernel tmp, empty;
1375
	int i;
1376
1377
	error = sysctl_wire_old_buffer(req, 0);
1378
	if (error != 0)
1379
		goto done;
1380
	sbuf_new_for_sysctl(&sb, NULL, sizeof(struct msqid_kernel) * msginfo.msgmni, req);
1381
1382
	bzero(&empty, sizeof(empty));
1383
	for (i = 0; i < msginfo.msgmni; i++) {
1384
		struct msqid_kernel *msqkptr;
1385
1386
		msqkptr = &msqids[i];
1387
		if (msqkptr->u.msg_qbytes == 0 ||
1388
		    cr_cansee_msq(req->td->td_ucred, msqkptr)) {
1389
			msqkptr = &empty;
1390
		} else if (req->td->td_ucred->cr_prison != msqkptr->cred->cr_prison) {
1391
			bcopy(msqkptr, &tmp, sizeof(tmp));
1392
			msqkptr = &tmp;
1393
			msqkptr->u.msg_perm.key = IPC_PRIVATE;
1394
		}
1323
1395
1324
	return (SYSCTL_OUT(req, msqids,
1396
		sbuf_bcat(&sb, msqkptr, sizeof(*msqkptr));
1325
	    sizeof(struct msqid_kernel) * msginfo.msgmni));
1397
	}
1398
	error = sbuf_finish(&sb);
1399
	sbuf_delete(&sb);
1400
1401
done:
1402
	return (error);
1326
}
1403
}
1327
1404
1328
SYSCTL_INT(_kern_ipc, OID_AUTO, msgmax, CTLFLAG_RD, &msginfo.msgmax, 0,
1405
SYSCTL_INT(_kern_ipc, OID_AUTO, msgmax, CTLFLAG_RD, &msginfo.msgmax, 0,
(-)b/sys/kern/sysv_sem.c (-30 / +127 lines)
Lines 57-62 __FBSDID("$FreeBSD$"); Link Here
57
#include <sys/syscallsubr.h>
57
#include <sys/syscallsubr.h>
58
#include <sys/sysent.h>
58
#include <sys/sysent.h>
59
#include <sys/sysctl.h>
59
#include <sys/sysctl.h>
60
#include <sys/sbuf.h>
60
#include <sys/uio.h>
61
#include <sys/uio.h>
61
#include <sys/malloc.h>
62
#include <sys/malloc.h>
62
#include <sys/jail.h>
63
#include <sys/jail.h>
Lines 79-84 static int semunload(void); Link Here
79
static void semexit_myhook(void *arg, struct proc *p);
80
static void semexit_myhook(void *arg, struct proc *p);
80
static int sysctl_sema(SYSCTL_HANDLER_ARGS);
81
static int sysctl_sema(SYSCTL_HANDLER_ARGS);
81
static int semvalid(int semid, struct semid_kernel *semakptr);
82
static int semvalid(int semid, struct semid_kernel *semakptr);
83
static int cr_cansee_sem(struct ucred *cred, struct semid_kernel *semakptr);
84
static void sem_remove(int semidx, struct ucred *cred);
85
static void sysvsem_cleanup_for_prison_myhook(struct prison *pr);
82
86
83
#ifndef _SYS_SYSPROTO_H_
87
#ifndef _SYS_SYSPROTO_H_
84
struct __semctl_args;
88
struct __semctl_args;
Lines 287-292 seminit(void) Link Here
287
	mtx_init(&sem_undo_mtx, "semu", NULL, MTX_DEF);
291
	mtx_init(&sem_undo_mtx, "semu", NULL, MTX_DEF);
288
	semexit_tag = EVENTHANDLER_REGISTER(process_exit, semexit_myhook, NULL,
292
	semexit_tag = EVENTHANDLER_REGISTER(process_exit, semexit_myhook, NULL,
289
	    EVENTHANDLER_PRI_ANY);
293
	    EVENTHANDLER_PRI_ANY);
294
	sysvsem_cleanup_for_prison_hook = &sysvsem_cleanup_for_prison_myhook;
290
295
291
	error = syscall_helper_register(sem_syscalls);
296
	error = syscall_helper_register(sem_syscalls);
292
	if (error != 0)
297
	if (error != 0)
Lines 313-318 semunload(void) Link Here
313
#endif
318
#endif
314
	syscall_helper_unregister(sem_syscalls);
319
	syscall_helper_unregister(sem_syscalls);
315
	EVENTHANDLER_DEREGISTER(process_exit, semexit_tag);
320
	EVENTHANDLER_DEREGISTER(process_exit, semexit_tag);
321
	sysvsem_cleanup_for_prison_hook = NULL;
316
#ifdef MAC
322
#ifdef MAC
317
	for (i = 0; i < seminfo.semmni; i++)
323
	for (i = 0; i < seminfo.semmni; i++)
318
		mac_sysvsem_destroy(&sema[i]);
324
		mac_sysvsem_destroy(&sema[i]);
Lines 506-511 semvalid(int semid, struct semid_kernel *semakptr) Link Here
506
	    semakptr->u.sem_perm.seq != IPCID_TO_SEQ(semid) ? EINVAL : 0);
512
	    semakptr->u.sem_perm.seq != IPCID_TO_SEQ(semid) ? EINVAL : 0);
507
}
513
}
508
514
515
static int
516
cr_cansee_sem(struct ucred *cred, struct semid_kernel *semakptr)
517
{
518
519
	if (semakptr->cred == NULL || prison_check(cred, semakptr->cred))
520
		return (EINVAL);
521
	return (0);
522
}
523
524
static void
525
sem_remove(int semidx, struct ucred *cred)
526
{
527
	int i;
528
	struct semid_kernel *semakptr;
529
530
	KASSERT(semidx >= 0 && semidx < seminfo.semmni, ("semidx out of bounds"));
531
	semakptr = &sema[semidx];
532
	semakptr->u.sem_perm.cuid = cred ? cred->cr_uid : 0;
533
	semakptr->u.sem_perm.uid = cred ? cred->cr_uid : 0;
534
	semakptr->u.sem_perm.mode = 0;
535
	racct_sub_cred(semakptr->cred, RACCT_NSEM, semakptr->u.sem_nsems);
536
	crfree(semakptr->cred);
537
	semakptr->cred = NULL;
538
	SEMUNDO_LOCK();
539
	semundo_clear(semidx, -1);
540
	SEMUNDO_UNLOCK();
541
#ifdef MAC
542
	mac_sysvsem_cleanup(semakptr);
543
#endif
544
	wakeup(semakptr);
545
	for (i = 0; i < seminfo.semmni; i++) {
546
		if ((sema[i].u.sem_perm.mode & SEM_ALLOC) &&
547
		    sema[i].u.sem_base > semakptr->u.sem_base)
548
			mtx_lock_flags(&sema_mtx[i], LOP_DUPOK);
549
	}
550
	for (i = semakptr->u.sem_base - sem; i < semtot; i++)
551
		sem[i] = sem[i + semakptr->u.sem_nsems];
552
	for (i = 0; i < seminfo.semmni; i++) {
553
		if ((sema[i].u.sem_perm.mode & SEM_ALLOC) &&
554
		    sema[i].u.sem_base > semakptr->u.sem_base) {
555
			sema[i].u.sem_base -= semakptr->u.sem_nsems;
556
			mtx_unlock(&sema_mtx[i]);
557
		}
558
	}
559
	semtot -= semakptr->u.sem_nsems;
560
}
561
562
static void
563
sysvsem_cleanup_for_prison_myhook(struct prison *pr)
564
{
565
	int i;
566
567
	mtx_lock(&sem_mtx);
568
	for (i = 0; i < seminfo.semmni; i++) {
569
		if ((sema[i].u.sem_perm.mode & SEM_ALLOC) &&
570
		    sema[i].cred && sema[i].cred->cr_prison == pr) {
571
			mtx_lock(&sema_mtx[i]);
572
			sem_remove(i, NULL);
573
			mtx_unlock(&sema_mtx[i]);
574
		}
575
	}
576
	mtx_unlock(&sem_mtx);
577
}
578
509
/*
579
/*
510
 * Note that the user-mode half of this passes a union, not a pointer.
580
 * Note that the user-mode half of this passes a union, not a pointer.
511
 */
581
 */
Lines 610-615 kern_semctl(struct thread *td, int semid, int semnum, int cmd, Link Here
610
			error = EINVAL;
680
			error = EINVAL;
611
			goto done2;
681
			goto done2;
612
		}
682
		}
683
		if ((error = cr_cansee_sem(td->td_ucred, semakptr)) != 0)
684
			goto done2;
613
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
685
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
614
			goto done2;
686
			goto done2;
615
#ifdef MAC
687
#ifdef MAC
Lines 632-637 kern_semctl(struct thread *td, int semid, int semnum, int cmd, Link Here
632
	if (cmd == IPC_RMID)
704
	if (cmd == IPC_RMID)
633
		mtx_lock(&sem_mtx);
705
		mtx_lock(&sem_mtx);
634
	mtx_lock(sema_mtxp);
706
	mtx_lock(sema_mtxp);
707
635
#ifdef MAC
708
#ifdef MAC
636
	error = mac_sysvsem_check_semctl(cred, semakptr, cmd);
709
	error = mac_sysvsem_check_semctl(cred, semakptr, cmd);
637
	if (error != 0)
710
	if (error != 0)
Lines 645-685 kern_semctl(struct thread *td, int semid, int semnum, int cmd, Link Here
645
	case IPC_RMID:
718
	case IPC_RMID:
646
		if ((error = semvalid(semid, semakptr)) != 0)
719
		if ((error = semvalid(semid, semakptr)) != 0)
647
			goto done2;
720
			goto done2;
721
		if ((error = cr_cansee_sem(td->td_ucred, semakptr)) != 0)
722
			goto done2;
648
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_M)))
723
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_M)))
649
			goto done2;
724
			goto done2;
650
		semakptr->u.sem_perm.cuid = cred->cr_uid;
725
		sem_remove(semidx, cred);
651
		semakptr->u.sem_perm.uid = cred->cr_uid;
652
		semakptr->u.sem_perm.mode = 0;
653
		racct_sub_cred(semakptr->cred, RACCT_NSEM, semakptr->u.sem_nsems);
654
		crfree(semakptr->cred);
655
		semakptr->cred = NULL;
656
		SEMUNDO_LOCK();
657
		semundo_clear(semidx, -1);
658
		SEMUNDO_UNLOCK();
659
#ifdef MAC
660
		mac_sysvsem_cleanup(semakptr);
661
#endif
662
		wakeup(semakptr);
663
		for (i = 0; i < seminfo.semmni; i++) {
664
			if ((sema[i].u.sem_perm.mode & SEM_ALLOC) &&
665
			    sema[i].u.sem_base > semakptr->u.sem_base)
666
				mtx_lock_flags(&sema_mtx[i], LOP_DUPOK);
667
		}
668
		for (i = semakptr->u.sem_base - sem; i < semtot; i++)
669
			sem[i] = sem[i + semakptr->u.sem_nsems];
670
		for (i = 0; i < seminfo.semmni; i++) {
671
			if ((sema[i].u.sem_perm.mode & SEM_ALLOC) &&
672
			    sema[i].u.sem_base > semakptr->u.sem_base) {
673
				sema[i].u.sem_base -= semakptr->u.sem_nsems;
674
				mtx_unlock(&sema_mtx[i]);
675
			}
676
		}
677
		semtot -= semakptr->u.sem_nsems;
678
		break;
726
		break;
679
727
680
	case IPC_SET:
728
	case IPC_SET:
681
		if ((error = semvalid(semid, semakptr)) != 0)
729
		if ((error = semvalid(semid, semakptr)) != 0)
682
			goto done2;
730
			goto done2;
731
		if ((error = cr_cansee_sem(td->td_ucred, semakptr)) != 0)
732
			goto done2;
683
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_M)))
733
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_M)))
684
			goto done2;
734
			goto done2;
685
		sbuf = arg->buf;
735
		sbuf = arg->buf;
Lines 693-698 kern_semctl(struct thread *td, int semid, int semnum, int cmd, Link Here
693
	case IPC_STAT:
743
	case IPC_STAT:
694
		if ((error = semvalid(semid, semakptr)) != 0)
744
		if ((error = semvalid(semid, semakptr)) != 0)
695
			goto done2;
745
			goto done2;
746
		if ((error = cr_cansee_sem(td->td_ucred, semakptr)) != 0)
747
			goto done2;
696
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
748
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
697
			goto done2;
749
			goto done2;
698
		bcopy(&semakptr->u, arg->buf, sizeof(struct semid_ds));
750
		bcopy(&semakptr->u, arg->buf, sizeof(struct semid_ds));
Lines 701-706 kern_semctl(struct thread *td, int semid, int semnum, int cmd, Link Here
701
	case GETNCNT:
753
	case GETNCNT:
702
		if ((error = semvalid(semid, semakptr)) != 0)
754
		if ((error = semvalid(semid, semakptr)) != 0)
703
			goto done2;
755
			goto done2;
756
		if ((error = cr_cansee_sem(td->td_ucred, semakptr)) != 0)
757
			goto done2;
704
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
758
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
705
			goto done2;
759
			goto done2;
706
		if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
760
		if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
Lines 713-718 kern_semctl(struct thread *td, int semid, int semnum, int cmd, Link Here
713
	case GETPID:
767
	case GETPID:
714
		if ((error = semvalid(semid, semakptr)) != 0)
768
		if ((error = semvalid(semid, semakptr)) != 0)
715
			goto done2;
769
			goto done2;
770
		if ((error = cr_cansee_sem(td->td_ucred, semakptr)) != 0)
771
			goto done2;
716
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
772
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
717
			goto done2;
773
			goto done2;
718
		if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
774
		if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
Lines 725-730 kern_semctl(struct thread *td, int semid, int semnum, int cmd, Link Here
725
	case GETVAL:
781
	case GETVAL:
726
		if ((error = semvalid(semid, semakptr)) != 0)
782
		if ((error = semvalid(semid, semakptr)) != 0)
727
			goto done2;
783
			goto done2;
784
		if ((error = cr_cansee_sem(td->td_ucred, semakptr)) != 0)
785
			goto done2;
728
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
786
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
729
			goto done2;
787
			goto done2;
730
		if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
788
		if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
Lines 762-767 kern_semctl(struct thread *td, int semid, int semnum, int cmd, Link Here
762
		if ((error = semvalid(semid, semakptr)) != 0)
820
		if ((error = semvalid(semid, semakptr)) != 0)
763
			goto done2;
821
			goto done2;
764
		KASSERT(count == semakptr->u.sem_nsems, ("nsems changed"));
822
		KASSERT(count == semakptr->u.sem_nsems, ("nsems changed"));
823
		if ((error = cr_cansee_sem(td->td_ucred, semakptr)) != 0)
824
			goto done2;
765
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
825
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
766
			goto done2;
826
			goto done2;
767
		for (i = 0; i < semakptr->u.sem_nsems; i++)
827
		for (i = 0; i < semakptr->u.sem_nsems; i++)
Lines 774-779 kern_semctl(struct thread *td, int semid, int semnum, int cmd, Link Here
774
	case GETZCNT:
834
	case GETZCNT:
775
		if ((error = semvalid(semid, semakptr)) != 0)
835
		if ((error = semvalid(semid, semakptr)) != 0)
776
			goto done2;
836
			goto done2;
837
		if ((error = cr_cansee_sem(td->td_ucred, semakptr)) != 0)
838
			goto done2;
777
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
839
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
778
			goto done2;
840
			goto done2;
779
		if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
841
		if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
Lines 786-791 kern_semctl(struct thread *td, int semid, int semnum, int cmd, Link Here
786
	case SETVAL:
848
	case SETVAL:
787
		if ((error = semvalid(semid, semakptr)) != 0)
849
		if ((error = semvalid(semid, semakptr)) != 0)
788
			goto done2;
850
			goto done2;
851
		if ((error = cr_cansee_sem(td->td_ucred, semakptr)) != 0)
852
			goto done2;
789
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_W)))
853
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_W)))
790
			goto done2;
854
			goto done2;
791
		if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
855
		if (semnum < 0 || semnum >= semakptr->u.sem_nsems) {
Lines 818-823 kern_semctl(struct thread *td, int semid, int semnum, int cmd, Link Here
818
		if ((error = semvalid(semid, semakptr)) != 0)
882
		if ((error = semvalid(semid, semakptr)) != 0)
819
			goto done2;
883
			goto done2;
820
		KASSERT(count == semakptr->u.sem_nsems, ("nsems changed"));
884
		KASSERT(count == semakptr->u.sem_nsems, ("nsems changed"));
885
		if ((error = cr_cansee_sem(td->td_ucred, semakptr)) != 0)
886
			goto done2;
821
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_W)))
887
		if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_W)))
822
			goto done2;
888
			goto done2;
823
		for (i = 0; i < semakptr->u.sem_nsems; i++) {
889
		for (i = 0; i < semakptr->u.sem_nsems; i++) {
Lines 872-877 sys_semget(struct thread *td, struct semget_args *uap) Link Here
872
	if (key != IPC_PRIVATE) {
938
	if (key != IPC_PRIVATE) {
873
		for (semid = 0; semid < seminfo.semmni; semid++) {
939
		for (semid = 0; semid < seminfo.semmni; semid++) {
874
			if ((sema[semid].u.sem_perm.mode & SEM_ALLOC) &&
940
			if ((sema[semid].u.sem_perm.mode & SEM_ALLOC) &&
941
			    sema[semid].cred && sema[semid].cred->cr_prison == cred->cr_prison &&
875
			    sema[semid].u.sem_perm.key == key)
942
			    sema[semid].u.sem_perm.key == key)
876
				break;
943
				break;
877
		}
944
		}
Lines 1049-1054 sys_semop(struct thread *td, struct semop_args *uap) Link Here
1049
		error = EINVAL;
1116
		error = EINVAL;
1050
		goto done2;
1117
		goto done2;
1051
	}
1118
	}
1119
	if ((error = cr_cansee_sem(td->td_ucred, semakptr)) != 0)
1120
		goto done2;
1052
	/*
1121
	/*
1053
	 * Initial pass thru sops to see what permissions are needed.
1122
	 * Initial pass thru sops to see what permissions are needed.
1054
	 * Also perform any checks that don't need repeating on each
1123
	 * Also perform any checks that don't need repeating on each
Lines 1372-1380 semexit_myhook(void *arg, struct proc *p) Link Here
1372
static int
1441
static int
1373
sysctl_sema(SYSCTL_HANDLER_ARGS)
1442
sysctl_sema(SYSCTL_HANDLER_ARGS)
1374
{
1443
{
1444
	int error;
1445
	struct sbuf sb;
1446
	struct semid_kernel tmp, empty;
1447
	int i;
1448
1449
	error = sysctl_wire_old_buffer(req, 0);
1450
	if (error != 0)
1451
		goto done;
1452
	sbuf_new_for_sysctl(&sb, NULL, sizeof(struct semid_kernel) * seminfo.semmni, req);
1375
1453
1376
	return (SYSCTL_OUT(req, sema,
1454
	bzero(&empty, sizeof(empty));
1377
	    sizeof(struct semid_kernel) * seminfo.semmni));
1455
	for (i = 0; i < seminfo.semmni; i++) {
1456
		struct semid_kernel *semakptr;
1457
1458
		semakptr = &sema[i];
1459
		if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0 ||
1460
		    cr_cansee_sem(req->td->td_ucred, semakptr)) {
1461
			semakptr = &empty;
1462
		} else if (req->td->td_ucred->cr_prison != semakptr->cred->cr_prison) {
1463
			bcopy(semakptr, &tmp, sizeof(tmp));
1464
			semakptr = &tmp;
1465
			semakptr->u.sem_perm.key = IPC_PRIVATE;
1466
		}
1467
1468
		sbuf_bcat(&sb, semakptr, sizeof(*semakptr));
1469
	}
1470
	error = sbuf_finish(&sb);
1471
	sbuf_delete(&sb);
1472
1473
done:
1474
	return (error);
1378
}
1475
}
1379
1476
1380
#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1477
#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
(-)b/sys/kern/sysv_shm.c (-10 / +92 lines)
Lines 86-91 __FBSDID("$FreeBSD$"); Link Here
86
#include <sys/sysent.h>
86
#include <sys/sysent.h>
87
#include <sys/sysproto.h>
87
#include <sys/sysproto.h>
88
#include <sys/jail.h>
88
#include <sys/jail.h>
89
#include <sys/sbuf.h>
89
90
90
#include <security/mac/mac_framework.h>
91
#include <security/mac/mac_framework.h>
91
92
Lines 120-126 struct shmmap_state { Link Here
120
};
121
};
121
122
122
static void shm_deallocate_segment(struct shmid_kernel *);
123
static void shm_deallocate_segment(struct shmid_kernel *);
123
static int shm_find_segment_by_key(key_t);
124
static int shm_find_segment_by_key(struct prison *, key_t);
124
static struct shmid_kernel *shm_find_segment(int, bool);
125
static struct shmid_kernel *shm_find_segment(int, bool);
125
static int shm_delete_mapping(struct vmspace *vm, struct shmmap_state *);
126
static int shm_delete_mapping(struct vmspace *vm, struct shmmap_state *);
126
static void shmrealloc(void);
127
static void shmrealloc(void);
Lines 130-135 static int shmunload(void); Link Here
130
static void shmexit_myhook(struct vmspace *vm);
131
static void shmexit_myhook(struct vmspace *vm);
131
static void shmfork_myhook(struct proc *p1, struct proc *p2);
132
static void shmfork_myhook(struct proc *p1, struct proc *p2);
132
static int sysctl_shmsegs(SYSCTL_HANDLER_ARGS);
133
static int sysctl_shmsegs(SYSCTL_HANDLER_ARGS);
134
static int cr_cansee_shm(struct ucred *, struct shmid_kernel *);
135
static void shm_remove(struct shmid_kernel *, int);
136
static void sysvshm_cleanup_for_prison_myhook(struct prison *);
133
137
134
/*
138
/*
135
 * Tuneable values.
139
 * Tuneable values.
Lines 189-200 static struct sx sysvshmsx; Link Here
189
#define	SYSVSHM_ASSERT_LOCKED()	sx_assert(&sysvshmsx, SA_XLOCKED)
193
#define	SYSVSHM_ASSERT_LOCKED()	sx_assert(&sysvshmsx, SA_XLOCKED)
190
194
191
static int
195
static int
192
shm_find_segment_by_key(key_t key)
196
shm_find_segment_by_key(struct prison *pr, key_t key)
193
{
197
{
194
	int i;
198
	int i;
195
199
196
	for (i = 0; i < shmalloced; i++)
200
	for (i = 0; i < shmalloced; i++)
197
		if ((shmsegs[i].u.shm_perm.mode & SHMSEG_ALLOCATED) &&
201
		if ((shmsegs[i].u.shm_perm.mode & SHMSEG_ALLOCATED) &&
202
		    shmsegs[i].cred && shmsegs[i].cred->cr_prison == pr &&
198
		    shmsegs[i].u.shm_perm.key == key)
203
		    shmsegs[i].u.shm_perm.key == key)
199
			return (i);
204
			return (i);
200
	return (-1);
205
	return (-1);
Lines 272-277 shm_delete_mapping(struct vmspace *vm, struct shmmap_state *shmmap_s) Link Here
272
}
277
}
273
278
274
static int
279
static int
280
cr_cansee_shm(struct ucred *cred, struct shmid_kernel *shmseg)
281
{
282
283
	if (shmseg->cred == NULL || prison_check(cred, shmseg->cred))
284
		return (EINVAL);
285
	return (0);
286
}
287
288
static void
289
shm_remove(struct shmid_kernel *shmseg, int segnum)
290
{
291
292
	shmseg->u.shm_perm.key = IPC_PRIVATE;
293
	shmseg->u.shm_perm.mode |= SHMSEG_REMOVED;
294
	if (shmseg->u.shm_nattch <= 0) {
295
		shm_deallocate_segment(shmseg);
296
		shm_last_free = segnum;
297
	}
298
}
299
300
static void
301
sysvshm_cleanup_for_prison_myhook(struct prison *pr)
302
{
303
	int i;
304
305
	SYSVSHM_LOCK();
306
	for (i = 0; i < shmalloced; i++) {
307
		struct shmid_kernel *shmseg;
308
309
		shmseg = &shmsegs[i];
310
		if ((shmseg->u.shm_perm.mode & SHMSEG_ALLOCATED) &&
311
		    shmseg->cred->cr_prison == pr) {
312
			shm_remove(shmseg, i);
313
		}
314
	}
315
	SYSVSHM_UNLOCK();
316
}
317
318
static int
275
kern_shmdt_locked(struct thread *td, const void *shmaddr)
319
kern_shmdt_locked(struct thread *td, const void *shmaddr)
276
{
320
{
277
	struct proc *p = td->td_proc;
321
	struct proc *p = td->td_proc;
Lines 348-353 kern_shmat_locked(struct thread *td, int shmid, const void *shmaddr, Link Here
348
	shmseg = shm_find_segment(shmid, true);
392
	shmseg = shm_find_segment(shmid, true);
349
	if (shmseg == NULL)
393
	if (shmseg == NULL)
350
		return (EINVAL);
394
		return (EINVAL);
395
	error = cr_cansee_shm(td->td_ucred, shmseg);
396
	if (error != 0)
397
		return (error);
351
	error = ipcperm(td, &shmseg->u.shm_perm,
398
	error = ipcperm(td, &shmseg->u.shm_perm,
352
	    (shmflg & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W);
399
	    (shmflg & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W);
353
	if (error != 0)
400
	if (error != 0)
Lines 477-482 kern_shmctl_locked(struct thread *td, int shmid, int cmd, void *buf, Link Here
477
	shmseg = shm_find_segment(shmid, cmd != SHM_STAT);
524
	shmseg = shm_find_segment(shmid, cmd != SHM_STAT);
478
	if (shmseg == NULL)
525
	if (shmseg == NULL)
479
		return (EINVAL);
526
		return (EINVAL);
527
	error = cr_cansee_shm(td->td_ucred, shmseg);
528
	if (error != 0)
529
		return (error);
480
#ifdef MAC
530
#ifdef MAC
481
	error = mac_sysvshm_check_shmctl(td->td_ucred, shmseg, cmd);
531
	error = mac_sysvshm_check_shmctl(td->td_ucred, shmseg, cmd);
482
	if (error != 0)
532
	if (error != 0)
Lines 512-523 kern_shmctl_locked(struct thread *td, int shmid, int cmd, void *buf, Link Here
512
		error = ipcperm(td, &shmseg->u.shm_perm, IPC_M);
562
		error = ipcperm(td, &shmseg->u.shm_perm, IPC_M);
513
		if (error != 0)
563
		if (error != 0)
514
			return (error);
564
			return (error);
515
		shmseg->u.shm_perm.key = IPC_PRIVATE;
565
516
		shmseg->u.shm_perm.mode |= SHMSEG_REMOVED;
566
		shm_remove(shmseg, IPCID_TO_IX(shmid));
517
		if (shmseg->u.shm_nattch <= 0) {
518
			shm_deallocate_segment(shmseg);
519
			shm_last_free = IPCID_TO_IX(shmid);
520
		}
521
		break;
567
		break;
522
#if 0
568
#if 0
523
	case SHM_LOCK:
569
	case SHM_LOCK:
Lines 727-733 sys_shmget(struct thread *td, struct shmget_args *uap) Link Here
727
	if (uap->key == IPC_PRIVATE) {
773
	if (uap->key == IPC_PRIVATE) {
728
		error = shmget_allocate_segment(td, uap, mode);
774
		error = shmget_allocate_segment(td, uap, mode);
729
	} else {
775
	} else {
730
		segnum = shm_find_segment_by_key(uap->key);
776
		segnum = shm_find_segment_by_key(td->td_ucred->cr_prison, uap->key);
731
		if (segnum >= 0)
777
		if (segnum >= 0)
732
			error = shmget_existing(td, uap, mode, segnum);
778
			error = shmget_existing(td, uap, mode, segnum);
733
		else if ((uap->shmflg & IPC_CREAT) == 0)
779
		else if ((uap->shmflg & IPC_CREAT) == 0)
Lines 883-888 shminit(void) Link Here
883
	sx_init(&sysvshmsx, "sysvshmsx");
929
	sx_init(&sysvshmsx, "sysvshmsx");
884
	shmexit_hook = &shmexit_myhook;
930
	shmexit_hook = &shmexit_myhook;
885
	shmfork_hook = &shmfork_myhook;
931
	shmfork_hook = &shmfork_myhook;
932
	sysvshm_cleanup_for_prison_hook = &sysvshm_cleanup_for_prison_myhook;
886
933
887
	error = syscall_helper_register(shm_syscalls);
934
	error = syscall_helper_register(shm_syscalls);
888
	if (error != 0)
935
	if (error != 0)
Lines 923-928 shmunload(void) Link Here
923
	free(shmsegs, M_SHM);
970
	free(shmsegs, M_SHM);
924
	shmexit_hook = NULL;
971
	shmexit_hook = NULL;
925
	shmfork_hook = NULL;
972
	shmfork_hook = NULL;
973
	sysvshm_cleanup_for_prison_hook = NULL;
926
	sx_destroy(&sysvshmsx);
974
	sx_destroy(&sysvshmsx);
927
	return (0);
975
	return (0);
928
}
976
}
Lines 931-939 static int Link Here
931
sysctl_shmsegs(SYSCTL_HANDLER_ARGS)
979
sysctl_shmsegs(SYSCTL_HANDLER_ARGS)
932
{
980
{
933
	int error;
981
	int error;
982
	struct sbuf sb;
983
	struct shmid_kernel tmp, empty;
984
	int i;
934
985
935
	SYSVSHM_LOCK();
986
	SYSVSHM_LOCK();
936
	error = SYSCTL_OUT(req, shmsegs, shmalloced * sizeof(shmsegs[0]));
987
988
	error = sysctl_wire_old_buffer(req, 0);
989
	if (error != 0)
990
		goto done;
991
	sbuf_new_for_sysctl(&sb, NULL, shmalloced * sizeof(shmsegs[0]), req);
992
993
	bzero(&empty, sizeof(empty));
994
	empty.u.shm_perm.mode = SHMSEG_FREE;
995
	for (i = 0; i < shmalloced; i++) {
996
		struct shmid_kernel *shmseg;
997
998
		shmseg = &shmsegs[i];
999
		if ((shmseg->u.shm_perm.mode & SHMSEG_ALLOCATED) == 0 ||
1000
		    cr_cansee_shm(req->td->td_ucred, &shmsegs[i])) {
1001
			shmseg = &empty;
1002
		} else if (req->td->td_ucred->cr_prison != shmseg->cred->cr_prison) {
1003
			bcopy(shmseg, &tmp, sizeof(tmp));
1004
			shmseg = &tmp;
1005
			shmseg->u.shm_perm.key = IPC_PRIVATE;
1006
		}
1007
1008
		sbuf_bcat(&sb, shmseg, sizeof(*shmseg));
1009
	}
1010
	error = sbuf_finish(&sb);
1011
	sbuf_delete(&sb);
1012
1013
done:
937
	SYSVSHM_UNLOCK();
1014
	SYSVSHM_UNLOCK();
938
	return (error);
1015
	return (error);
939
}
1016
}
Lines 977-982 oshmctl(struct thread *td, struct oshmctl_args *uap) Link Here
977
		SYSVSHM_UNLOCK();
1054
		SYSVSHM_UNLOCK();
978
		return (EINVAL);
1055
		return (EINVAL);
979
	}
1056
	}
1057
	error = cr_cansee_shm(td->td_ucred, shmseg);
1058
	if (error != 0) {
1059
		SYSVSHM_UNLOCK();
1060
		return (error);
1061
	}
980
	error = ipcperm(td, &shmseg->u.shm_perm, IPC_R);
1062
	error = ipcperm(td, &shmseg->u.shm_perm, IPC_R);
981
	if (error != 0) {
1063
	if (error != 0) {
982
		SYSVSHM_UNLOCK();
1064
		SYSVSHM_UNLOCK();
(-)b/sys/sys/ipc.h (+5 lines)
Lines 126-131 struct ipc_perm { Link Here
126
struct thread;
126
struct thread;
127
struct proc;
127
struct proc;
128
struct vmspace;
128
struct vmspace;
129
struct prison;
129
130
130
#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
131
#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
131
    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
132
    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
Lines 133-141 void ipcperm_old2new(struct ipc_perm_old *, struct ipc_perm *); Link Here
133
void	ipcperm_new2old(struct ipc_perm *, struct ipc_perm_old *);
134
void	ipcperm_new2old(struct ipc_perm *, struct ipc_perm_old *);
134
#endif
135
#endif
135
136
137
void ipc_cleanup_for_prison(struct prison *);
136
int	ipcperm(struct thread *, struct ipc_perm *, int);
138
int	ipcperm(struct thread *, struct ipc_perm *, int);
137
extern void (*shmfork_hook)(struct proc *, struct proc *);
139
extern void (*shmfork_hook)(struct proc *, struct proc *);
138
extern void (*shmexit_hook)(struct vmspace *);
140
extern void (*shmexit_hook)(struct vmspace *);
141
extern void (*sysvshm_cleanup_for_prison_hook)(struct prison *);
142
extern void (*sysvmsg_cleanup_for_prison_hook)(struct prison *);
143
extern void (*sysvsem_cleanup_for_prison_hook)(struct prison *);
139
144
140
#else /* ! _KERNEL */
145
#else /* ! _KERNEL */
141
146

Return to bug 48471