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 = ∅ |
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) || \ |