Deleted Added
full compact
sysv_msg.c (220388) sysv_msg.c (220398)
1/*-
2 * Implementation of SVID messages
3 *
4 * Author: Daniel Boulet
5 *
6 * Copyright 1993 Daniel Boulet and RTMX Inc.
7 *
8 * This system call was implemented by Daniel Boulet under contract from RTMX.

--- 34 unchanged lines hidden (view full) ---

43 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * SUCH DAMAGE.
48 */
49
50#include <sys/cdefs.h>
1/*-
2 * Implementation of SVID messages
3 *
4 * Author: Daniel Boulet
5 *
6 * Copyright 1993 Daniel Boulet and RTMX Inc.
7 *
8 * This system call was implemented by Daniel Boulet under contract from RTMX.

--- 34 unchanged lines hidden (view full) ---

43 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * SUCH DAMAGE.
48 */
49
50#include <sys/cdefs.h>
51__FBSDID("$FreeBSD: head/sys/kern/sysv_msg.c 220388 2011-04-06 16:59:54Z trasz $");
51__FBSDID("$FreeBSD: head/sys/kern/sysv_msg.c 220398 2011-04-06 18:11:24Z trasz $");
52
53#include "opt_compat.h"
54#include "opt_sysvipc.h"
55
56#include <sys/param.h>
57#include <sys/systm.h>
58#include <sys/sysproto.h>
59#include <sys/kernel.h>
60#include <sys/priv.h>
61#include <sys/proc.h>
62#include <sys/lock.h>
63#include <sys/mutex.h>
64#include <sys/module.h>
65#include <sys/msg.h>
52
53#include "opt_compat.h"
54#include "opt_sysvipc.h"
55
56#include <sys/param.h>
57#include <sys/systm.h>
58#include <sys/sysproto.h>
59#include <sys/kernel.h>
60#include <sys/priv.h>
61#include <sys/proc.h>
62#include <sys/lock.h>
63#include <sys/mutex.h>
64#include <sys/module.h>
65#include <sys/msg.h>
66#include <sys/racct.h>
66#include <sys/syscall.h>
67#include <sys/syscallsubr.h>
68#include <sys/sysent.h>
69#include <sys/sysctl.h>
70#include <sys/malloc.h>
71#include <sys/jail.h>
72
73#include <security/mac/mac_framework.h>

--- 387 unchanged lines hidden (view full) ---

461 for (msghdr = msqkptr->u.msg_first; msghdr != NULL;
462 msghdr = msghdr->msg_next) {
463 error = mac_sysvmsq_check_msgrmid(td->td_ucred, msghdr);
464 if (error != 0)
465 goto done2;
466 }
467#endif
468
67#include <sys/syscall.h>
68#include <sys/syscallsubr.h>
69#include <sys/sysent.h>
70#include <sys/sysctl.h>
71#include <sys/malloc.h>
72#include <sys/jail.h>
73
74#include <security/mac/mac_framework.h>

--- 387 unchanged lines hidden (view full) ---

462 for (msghdr = msqkptr->u.msg_first; msghdr != NULL;
463 msghdr = msghdr->msg_next) {
464 error = mac_sysvmsq_check_msgrmid(td->td_ucred, msghdr);
465 if (error != 0)
466 goto done2;
467 }
468#endif
469
470 racct_sub_cred(msqkptr->cred, RACCT_NMSGQ, 1);
471 racct_sub_cred(msqkptr->cred, RACCT_MSGQQUEUED, msqkptr->u.msg_qnum);
472 racct_sub_cred(msqkptr->cred, RACCT_MSGQSIZE, msqkptr->u.msg_cbytes);
469 crfree(msqkptr->cred);
470 msqkptr->cred = NULL;
471
472 /* Free the message headers */
473 msghdr = msqkptr->u.msg_first;
474 while (msghdr != NULL) {
475 struct msg *msghdr_tmp;
476

--- 134 unchanged lines hidden (view full) ---

611 (msqkptr->u.msg_perm.mode & MSG_LOCKED) == 0)
612 break;
613 }
614 if (msqid == msginfo.msgmni) {
615 DPRINTF(("no more msqid_ds's available\n"));
616 error = ENOSPC;
617 goto done2;
618 }
473 crfree(msqkptr->cred);
474 msqkptr->cred = NULL;
475
476 /* Free the message headers */
477 msghdr = msqkptr->u.msg_first;
478 while (msghdr != NULL) {
479 struct msg *msghdr_tmp;
480

--- 134 unchanged lines hidden (view full) ---

615 (msqkptr->u.msg_perm.mode & MSG_LOCKED) == 0)
616 break;
617 }
618 if (msqid == msginfo.msgmni) {
619 DPRINTF(("no more msqid_ds's available\n"));
620 error = ENOSPC;
621 goto done2;
622 }
623 PROC_LOCK(td->td_proc);
624 error = racct_add(td->td_proc, RACCT_NMSGQ, 1);
625 PROC_UNLOCK(td->td_proc);
626 if (error != 0) {
627 error = ENOSPC;
628 goto done2;
629 }
619 DPRINTF(("msqid %d is available\n", msqid));
620 msqkptr->u.msg_perm.key = key;
621 msqkptr->u.msg_perm.cuid = cred->cr_uid;
622 msqkptr->u.msg_perm.uid = cred->cr_uid;
623 msqkptr->u.msg_perm.cgid = cred->cr_gid;
624 msqkptr->u.msg_perm.gid = cred->cr_gid;
625 msqkptr->u.msg_perm.mode = (msgflg & 0777);
626 crhold(cred);

--- 43 unchanged lines hidden (view full) ---

670 size_t msgsz;
671 int msgflg;
672 long mtype;
673{
674 int msqix, segs_needed, error = 0;
675 register struct msqid_kernel *msqkptr;
676 register struct msg *msghdr;
677 short next;
630 DPRINTF(("msqid %d is available\n", msqid));
631 msqkptr->u.msg_perm.key = key;
632 msqkptr->u.msg_perm.cuid = cred->cr_uid;
633 msqkptr->u.msg_perm.uid = cred->cr_uid;
634 msqkptr->u.msg_perm.cgid = cred->cr_gid;
635 msqkptr->u.msg_perm.gid = cred->cr_gid;
636 msqkptr->u.msg_perm.mode = (msgflg & 0777);
637 crhold(cred);

--- 43 unchanged lines hidden (view full) ---

681 size_t msgsz;
682 int msgflg;
683 long mtype;
684{
685 int msqix, segs_needed, error = 0;
686 register struct msqid_kernel *msqkptr;
687 register struct msg *msghdr;
688 short next;
689 size_t saved_msgsz;
678
679 if (!prison_allow(td->td_ucred, PR_ALLOW_SYSVIPC))
680 return (ENOSYS);
681
682 mtx_lock(&msq_mtx);
683 msqix = IPCID_TO_IX(msqid);
684
685 if (msqix < 0 || msqix >= msginfo.msgmni) {

--- 21 unchanged lines hidden (view full) ---

707 }
708
709#ifdef MAC
710 error = mac_sysvmsq_check_msqsnd(td->td_ucred, msqkptr);
711 if (error != 0)
712 goto done2;
713#endif
714
690
691 if (!prison_allow(td->td_ucred, PR_ALLOW_SYSVIPC))
692 return (ENOSYS);
693
694 mtx_lock(&msq_mtx);
695 msqix = IPCID_TO_IX(msqid);
696
697 if (msqix < 0 || msqix >= msginfo.msgmni) {

--- 21 unchanged lines hidden (view full) ---

719 }
720
721#ifdef MAC
722 error = mac_sysvmsq_check_msqsnd(td->td_ucred, msqkptr);
723 if (error != 0)
724 goto done2;
725#endif
726
727 PROC_LOCK(td->td_proc);
728 if (racct_add(td->td_proc, RACCT_MSGQQUEUED, 1)) {
729 PROC_UNLOCK(td->td_proc);
730 error = EAGAIN;
731 goto done2;
732 }
733 saved_msgsz = msgsz;
734 if (racct_add(td->td_proc, RACCT_MSGQSIZE, msgsz)) {
735 racct_sub(td->td_proc, RACCT_MSGQQUEUED, 1);
736 PROC_UNLOCK(td->td_proc);
737 error = EAGAIN;
738 goto done2;
739 }
740 PROC_UNLOCK(td->td_proc);
741
715 segs_needed = (msgsz + msginfo.msgssz - 1) / msginfo.msgssz;
716 DPRINTF(("msgsz=%zu, msgssz=%d, segs_needed=%d\n", msgsz,
717 msginfo.msgssz, segs_needed));
718 for (;;) {
719 int need_more_resources = 0;
720
721 /*
722 * check msgsz
723 * (inside this loop in case msg_qbytes changes while we sleep)
724 */
725
726 if (msgsz > msqkptr->u.msg_qbytes) {
727 DPRINTF(("msgsz > msqkptr->u.msg_qbytes\n"));
728 error = EINVAL;
742 segs_needed = (msgsz + msginfo.msgssz - 1) / msginfo.msgssz;
743 DPRINTF(("msgsz=%zu, msgssz=%d, segs_needed=%d\n", msgsz,
744 msginfo.msgssz, segs_needed));
745 for (;;) {
746 int need_more_resources = 0;
747
748 /*
749 * check msgsz
750 * (inside this loop in case msg_qbytes changes while we sleep)
751 */
752
753 if (msgsz > msqkptr->u.msg_qbytes) {
754 DPRINTF(("msgsz > msqkptr->u.msg_qbytes\n"));
755 error = EINVAL;
729 goto done2;
756 goto done3;
730 }
731
732 if (msqkptr->u.msg_perm.mode & MSG_LOCKED) {
733 DPRINTF(("msqid is locked\n"));
734 need_more_resources = 1;
735 }
736 if (msgsz + msqkptr->u.msg_cbytes > msqkptr->u.msg_qbytes) {
737 DPRINTF(("msgsz + msg_cbytes > msg_qbytes\n"));

--- 10 unchanged lines hidden (view full) ---

748
749 if (need_more_resources) {
750 int we_own_it;
751
752 if ((msgflg & IPC_NOWAIT) != 0) {
753 DPRINTF(("need more resources but caller "
754 "doesn't want to wait\n"));
755 error = EAGAIN;
757 }
758
759 if (msqkptr->u.msg_perm.mode & MSG_LOCKED) {
760 DPRINTF(("msqid is locked\n"));
761 need_more_resources = 1;
762 }
763 if (msgsz + msqkptr->u.msg_cbytes > msqkptr->u.msg_qbytes) {
764 DPRINTF(("msgsz + msg_cbytes > msg_qbytes\n"));

--- 10 unchanged lines hidden (view full) ---

775
776 if (need_more_resources) {
777 int we_own_it;
778
779 if ((msgflg & IPC_NOWAIT) != 0) {
780 DPRINTF(("need more resources but caller "
781 "doesn't want to wait\n"));
782 error = EAGAIN;
756 goto done2;
783 goto done3;
757 }
758
759 if ((msqkptr->u.msg_perm.mode & MSG_LOCKED) != 0) {
760 DPRINTF(("we don't own the msqid_ds\n"));
761 we_own_it = 0;
762 } else {
763 /* Force later arrivals to wait for our
764 request */

--- 9 unchanged lines hidden (view full) ---

774 msqkptr->u.msg_perm.mode &= ~MSG_LOCKED;
775 if (error == EWOULDBLOCK) {
776 DPRINTF(("msgsnd: timed out\n"));
777 continue;
778 }
779 if (error != 0) {
780 DPRINTF(("msgsnd: interrupted system call\n"));
781 error = EINTR;
784 }
785
786 if ((msqkptr->u.msg_perm.mode & MSG_LOCKED) != 0) {
787 DPRINTF(("we don't own the msqid_ds\n"));
788 we_own_it = 0;
789 } else {
790 /* Force later arrivals to wait for our
791 request */

--- 9 unchanged lines hidden (view full) ---

801 msqkptr->u.msg_perm.mode &= ~MSG_LOCKED;
802 if (error == EWOULDBLOCK) {
803 DPRINTF(("msgsnd: timed out\n"));
804 continue;
805 }
806 if (error != 0) {
807 DPRINTF(("msgsnd: interrupted system call\n"));
808 error = EINTR;
782 goto done2;
809 goto done3;
783 }
784
785 /*
786 * Make sure that the msq queue still exists
787 */
788
789 if (msqkptr->u.msg_qbytes == 0) {
790 DPRINTF(("msqid deleted\n"));
791 error = EIDRM;
810 }
811
812 /*
813 * Make sure that the msq queue still exists
814 */
815
816 if (msqkptr->u.msg_qbytes == 0) {
817 DPRINTF(("msqid deleted\n"));
818 error = EIDRM;
792 goto done2;
819 goto done3;
793 }
794
795 } else {
796 DPRINTF(("got all the resources that we need\n"));
797 break;
798 }
799 }
800

--- 65 unchanged lines hidden (view full) ---

866 */
867
868 if (msghdr->msg_type < 1) {
869 msg_freehdr(msghdr);
870 msqkptr->u.msg_perm.mode &= ~MSG_LOCKED;
871 wakeup(msqkptr);
872 DPRINTF(("mtype (%ld) < 1\n", msghdr->msg_type));
873 error = EINVAL;
820 }
821
822 } else {
823 DPRINTF(("got all the resources that we need\n"));
824 break;
825 }
826 }
827

--- 65 unchanged lines hidden (view full) ---

893 */
894
895 if (msghdr->msg_type < 1) {
896 msg_freehdr(msghdr);
897 msqkptr->u.msg_perm.mode &= ~MSG_LOCKED;
898 wakeup(msqkptr);
899 DPRINTF(("mtype (%ld) < 1\n", msghdr->msg_type));
900 error = EINVAL;
874 goto done2;
901 goto done3;
875 }
876
877 /*
878 * Copy in the message body
879 */
880
881 next = msghdr->msg_spot;
882 while (msgsz > 0) {

--- 10 unchanged lines hidden (view full) ---

893 if ((error = copyin(msgp, &msgpool[next * msginfo.msgssz],
894 tlen)) != 0) {
895 mtx_lock(&msq_mtx);
896 DPRINTF(("error %d copying in message segment\n",
897 error));
898 msg_freehdr(msghdr);
899 msqkptr->u.msg_perm.mode &= ~MSG_LOCKED;
900 wakeup(msqkptr);
902 }
903
904 /*
905 * Copy in the message body
906 */
907
908 next = msghdr->msg_spot;
909 while (msgsz > 0) {

--- 10 unchanged lines hidden (view full) ---

920 if ((error = copyin(msgp, &msgpool[next * msginfo.msgssz],
921 tlen)) != 0) {
922 mtx_lock(&msq_mtx);
923 DPRINTF(("error %d copying in message segment\n",
924 error));
925 msg_freehdr(msghdr);
926 msqkptr->u.msg_perm.mode &= ~MSG_LOCKED;
927 wakeup(msqkptr);
901 goto done2;
928 goto done3;
902 }
903 mtx_lock(&msq_mtx);
904 msgsz -= tlen;
905 msgp = (const char *)msgp + tlen;
906 next = msgmaps[next].next;
907 }
908 if (next != -1)
909 panic("didn't use all the msg segments");

--- 7 unchanged lines hidden (view full) ---

917 /*
918 * Make sure that the msqid_ds is still allocated.
919 */
920
921 if (msqkptr->u.msg_qbytes == 0) {
922 msg_freehdr(msghdr);
923 wakeup(msqkptr);
924 error = EIDRM;
929 }
930 mtx_lock(&msq_mtx);
931 msgsz -= tlen;
932 msgp = (const char *)msgp + tlen;
933 next = msgmaps[next].next;
934 }
935 if (next != -1)
936 panic("didn't use all the msg segments");

--- 7 unchanged lines hidden (view full) ---

944 /*
945 * Make sure that the msqid_ds is still allocated.
946 */
947
948 if (msqkptr->u.msg_qbytes == 0) {
949 msg_freehdr(msghdr);
950 wakeup(msqkptr);
951 error = EIDRM;
925 goto done2;
952 goto done3;
926 }
927
928#ifdef MAC
929 /*
930 * Note: Since the task/thread allocates the msghdr and usually
931 * primes it with its own MAC label, for a majority of policies, it
932 * won't be necessary to check whether the msghdr has access
933 * permissions to the msgq. The mac_sysvmsq_check_msqsnd check would
934 * suffice in that case. However, this hook may be required where
935 * individual policies derive a non-identical label for the msghdr
936 * from the current thread label and may want to check the msghdr
937 * enqueue permissions, along with read/write permissions to the
938 * msgq.
939 */
940 error = mac_sysvmsq_check_msgmsq(td->td_ucred, msghdr, msqkptr);
941 if (error != 0) {
942 msg_freehdr(msghdr);
943 wakeup(msqkptr);
953 }
954
955#ifdef MAC
956 /*
957 * Note: Since the task/thread allocates the msghdr and usually
958 * primes it with its own MAC label, for a majority of policies, it
959 * won't be necessary to check whether the msghdr has access
960 * permissions to the msgq. The mac_sysvmsq_check_msqsnd check would
961 * suffice in that case. However, this hook may be required where
962 * individual policies derive a non-identical label for the msghdr
963 * from the current thread label and may want to check the msghdr
964 * enqueue permissions, along with read/write permissions to the
965 * msgq.
966 */
967 error = mac_sysvmsq_check_msgmsq(td->td_ucred, msghdr, msqkptr);
968 if (error != 0) {
969 msg_freehdr(msghdr);
970 wakeup(msqkptr);
944 goto done2;
971 goto done3;
945 }
946#endif
947
948 /*
949 * Put the message into the queue
950 */
951 if (msqkptr->u.msg_first == NULL) {
952 msqkptr->u.msg_first = msghdr;

--- 6 unchanged lines hidden (view full) ---

959
960 msqkptr->u.msg_cbytes += msghdr->msg_ts;
961 msqkptr->u.msg_qnum++;
962 msqkptr->u.msg_lspid = td->td_proc->p_pid;
963 msqkptr->u.msg_stime = time_second;
964
965 wakeup(msqkptr);
966 td->td_retval[0] = 0;
972 }
973#endif
974
975 /*
976 * Put the message into the queue
977 */
978 if (msqkptr->u.msg_first == NULL) {
979 msqkptr->u.msg_first = msghdr;

--- 6 unchanged lines hidden (view full) ---

986
987 msqkptr->u.msg_cbytes += msghdr->msg_ts;
988 msqkptr->u.msg_qnum++;
989 msqkptr->u.msg_lspid = td->td_proc->p_pid;
990 msqkptr->u.msg_stime = time_second;
991
992 wakeup(msqkptr);
993 td->td_retval[0] = 0;
994done3:
995 if (error != 0) {
996 PROC_LOCK(td->td_proc);
997 racct_sub(td->td_proc, RACCT_MSGQQUEUED, 1);
998 racct_sub(td->td_proc, RACCT_MSGQSIZE, saved_msgsz);
999 PROC_UNLOCK(td->td_proc);
1000 }
967done2:
968 mtx_unlock(&msq_mtx);
969 return (error);
970}
971
972int
973msgsnd(td, uap)
974 struct thread *td;

--- 217 unchanged lines hidden (view full) ---

1192 * First, do the bookkeeping (before we risk being interrupted).
1193 */
1194
1195 msqkptr->u.msg_cbytes -= msghdr->msg_ts;
1196 msqkptr->u.msg_qnum--;
1197 msqkptr->u.msg_lrpid = td->td_proc->p_pid;
1198 msqkptr->u.msg_rtime = time_second;
1199
1001done2:
1002 mtx_unlock(&msq_mtx);
1003 return (error);
1004}
1005
1006int
1007msgsnd(td, uap)
1008 struct thread *td;

--- 217 unchanged lines hidden (view full) ---

1226 * First, do the bookkeeping (before we risk being interrupted).
1227 */
1228
1229 msqkptr->u.msg_cbytes -= msghdr->msg_ts;
1230 msqkptr->u.msg_qnum--;
1231 msqkptr->u.msg_lrpid = td->td_proc->p_pid;
1232 msqkptr->u.msg_rtime = time_second;
1233
1234 racct_sub_cred(msqkptr->cred, RACCT_MSGQQUEUED, 1);
1235 racct_sub_cred(msqkptr->cred, RACCT_MSGQSIZE, msghdr->msg_ts);
1236
1200 /*
1201 * Make msgsz the actual amount that we'll be returning.
1202 * Note that this effectively truncates the message if it is too long
1203 * (since msgsz is never increased).
1204 */
1205
1206 DPRINTF(("found a message, msgsz=%zu, msg_ts=%hu\n", msgsz,
1207 msghdr->msg_ts));

--- 339 unchanged lines hidden ---
1237 /*
1238 * Make msgsz the actual amount that we'll be returning.
1239 * Note that this effectively truncates the message if it is too long
1240 * (since msgsz is never increased).
1241 */
1242
1243 DPRINTF(("found a message, msgsz=%zu, msg_ts=%hu\n", msgsz,
1244 msghdr->msg_ts));

--- 339 unchanged lines hidden ---