61#include "opt_sysvipc.h"
65#include <sys/sysproto.h>
66#include <sys/kernel.h>
71#include <sys/module.h>
76#include <sys/syscall.h>
77#include <sys/syscallsubr.h>
78#include <sys/sysent.h>
79#include <sys/sysctl.h>
80#include <sys/malloc.h>
83#include <security/audit/audit.h>
84#include <security/mac/mac_framework.h>
86FEATURE(sysv_msg,
"System V message queues support");
103#define DPRINTF(a) printf a
105#define DPRINTF(a) (void)0
116#define MSGMAX (MSGSSZ*MSGSEG)
151#define MSQID(ix,ds) ((ix) & 0xffff | (((ds).msg_perm.seq << 16) & 0xffff0000))
152#define MSQID_IX(id) ((id) & 0xffff)
153#define MSQID_SEQ(id) (((id) >> 16) & 0xffff)
165#define MSG_LOCKED 01000
178 SYSCALL_INIT_HELPER(msgctl),
179 SYSCALL_INIT_HELPER(msgget),
180 SYSCALL_INIT_HELPER(msgsnd),
181 SYSCALL_INIT_HELPER(msgrcv),
182#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
183 defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
184 SYSCALL_INIT_HELPER(msgsys),
185 SYSCALL_INIT_HELPER_COMPAT(freebsd7_msgctl),
190#ifdef COMPAT_FREEBSD32
191#include <compat/freebsd32/freebsd32.h>
192#include <compat/freebsd32/freebsd32_ipc.h>
193#include <compat/freebsd32/freebsd32_proto.h>
194#include <compat/freebsd32/freebsd32_signal.h>
195#include <compat/freebsd32/freebsd32_syscall.h>
196#include <compat/freebsd32/freebsd32_util.h>
198static struct syscall_helper_data msg32_syscalls[] = {
199 SYSCALL32_INIT_HELPER(freebsd32_msgctl),
200 SYSCALL32_INIT_HELPER(freebsd32_msgsnd),
201 SYSCALL32_INIT_HELPER(freebsd32_msgrcv),
202 SYSCALL32_INIT_HELPER_COMPAT(msgget),
203 SYSCALL32_INIT_HELPER(freebsd32_msgsys),
204#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
205 defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
206 SYSCALL32_INIT_HELPER(freebsd7_freebsd32_msgctl),
218 osd_method_t methods[PR_MAXMETHOD] = {
239 while (i < 1024 && i !=
msginfo.msgssz)
244 panic(
"msginfo.msgssz not a small power of 2");
249 panic(
"msginfo.msgseg > 32767");
252 for (i = 0; i <
msginfo.msgseg; i++) {
260 for (i = 0; i <
msginfo.msgtql; i++) {
271 for (i = 0; i <
msginfo.msgmni; i++) {
272 msqids[i].u.msg_qbytes = 0;
273 msqids[i].u.msg_perm.seq = 0;
274 msqids[i].u.msg_perm.mode = 0;
276 mac_sysvmsq_init(&
msqids[i]);
279 mtx_init(&
msq_mtx,
"msq", NULL, MTX_DEF);
293 if (
pr->pr_allow & PR_ALLOW_SYSVIPC) {
307#ifdef COMPAT_FREEBSD32
308 error = syscall32_helper_register(msg32_syscalls, SY_THR_STATIC_KLD);
318 struct msqid_kernel *msqkptr;
325#ifdef COMPAT_FREEBSD32
326 syscall32_helper_unregister(msg32_syscalls);
329 for (msqid = 0; msqid <
msginfo.msgmni; msqid++) {
331 if (msqkptr->u.msg_qbytes != 0 ||
341 for (i = 0; i <
msginfo.msgtql; i++)
342 mac_sysvmsg_destroy(&
msghdrs[i]);
343 for (msqid = 0; msqid <
msginfo.msgmni; msqid++)
344 mac_sysvmsq_destroy(&
msqids[msqid]);
389 while (msghdr->msg_ts > 0) {
391 if (msghdr->msg_spot < 0 || msghdr->msg_spot >=
msginfo.msgseg)
392 panic(
"msghdr->msg_spot out of range");
397 msghdr->msg_spot = next;
398 if (msghdr->msg_ts >=
msginfo.msgssz)
399 msghdr->msg_ts -=
msginfo.msgssz;
403 if (msghdr->msg_spot != -1)
404 panic(
"msghdr->msg_spot != -1");
408 mac_sysvmsg_cleanup(msghdr);
417 racct_sub_cred(msqkptr->cred, RACCT_NMSGQ, 1);
418 racct_sub_cred(msqkptr->cred, RACCT_MSGQQUEUED, msqkptr->u.msg_qnum);
419 racct_sub_cred(msqkptr->cred, RACCT_MSGQSIZE, msqkptr->u.msg_cbytes);
421 msqkptr->cred = NULL;
424 msghdr = msqkptr->u.__msg_first;
425 while (msghdr != NULL) {
426 struct msg *msghdr_tmp;
429 msqkptr->u.msg_cbytes -= msghdr->msg_ts;
430 msqkptr->u.msg_qnum--;
432 msghdr = msghdr->msg_next;
436 if (msqkptr->u.msg_cbytes != 0)
437 panic(
"msg_cbytes is screwed up");
438 if (msqkptr->u.msg_qnum != 0)
439 panic(
"msg_qnum is screwed up");
441 msqkptr->u.msg_qbytes = 0;
444 mac_sysvmsq_cleanup(msqkptr);
450static struct prison *
453 struct prison *
pr, *rpr;
455 pr = cred->cr_prison;
466 if (msqkptr->cred == NULL ||
467 !(rpr == msqkptr->cred->cr_prison ||
473#ifndef _SYS_SYSPROTO_H_
483 int msqid = uap->
msqid;
485 struct msqid_ds msqbuf;
488 DPRINTF((
"call to msgctl(%d, %d, %p)\n", msqid, cmd, uap->
buf));
489 if (cmd == IPC_SET &&
490 (error = copyin(uap->
buf, &msqbuf,
sizeof(msqbuf))) != 0)
493 if (cmd == IPC_STAT && error == 0)
494 error = copyout(&msqbuf, uap->
buf,
sizeof(
struct msqid_ds));
499kern_msgctl(
struct thread *td,
int msqid,
int cmd,
struct msqid_ds *msqbuf)
501 int rval, error, msqix;
502 struct msqid_kernel *msqkptr;
509 AUDIT_ARG_SVIPC_CMD(cmd);
510 AUDIT_ARG_SVIPC_ID(msqid);
511 msqix = IPCID_TO_IX(msqid);
513 if (msqix < 0 || msqix >=
msginfo.msgmni) {
514 DPRINTF((
"msqid (%d) out of range (0<=msqid<%d)\n", msqix,
522 if (msqkptr->u.msg_qbytes == 0) {
527 if (msqkptr->u.msg_perm.seq != IPCID_TO_SEQ(msqid)) {
528 DPRINTF((
"wrong sequence number\n"));
535 DPRINTF((
"requester can't see prison\n"));
540 error = mac_sysvmsq_check_msqctl(td->td_ucred, msqkptr, cmd);
554 if ((error =
ipcperm(td, &msqkptr->u.msg_perm, IPC_M)))
567 for (msghdr = msqkptr->u.__msg_first; msghdr != NULL;
568 msghdr = msghdr->msg_next) {
569 error = mac_sysvmsq_check_msgrmid(td->td_ucred, msghdr);
581 AUDIT_ARG_SVIPC_PERM(&msqbuf->msg_perm);
582 if ((error =
ipcperm(td, &msqkptr->u.msg_perm, IPC_M)))
584 if (msqbuf->msg_qbytes > msqkptr->u.msg_qbytes) {
589 if (msqbuf->msg_qbytes >
msginfo.msgmnb) {
590 DPRINTF((
"can't increase msg_qbytes beyond %d"
591 "(truncating)\n",
msginfo.msgmnb));
592 msqbuf->msg_qbytes =
msginfo.msgmnb;
594 if (msqbuf->msg_qbytes == 0) {
595 DPRINTF((
"can't reduce msg_qbytes to 0\n"));
599 msqkptr->u.msg_perm.uid = msqbuf->msg_perm.uid;
600 msqkptr->u.msg_perm.gid = msqbuf->msg_perm.gid;
601 msqkptr->u.msg_perm.mode = (msqkptr->u.msg_perm.mode & ~0777) |
602 (msqbuf->msg_perm.mode & 0777);
603 msqkptr->u.msg_qbytes = msqbuf->msg_qbytes;
608 if ((error =
ipcperm(td, &msqkptr->u.msg_perm, IPC_R))) {
609 DPRINTF((
"requester doesn't have read access\n"));
612 *msqbuf = msqkptr->u;
613 if (td->td_ucred->cr_prison != msqkptr->cred->cr_prison)
614 msqbuf->msg_perm.key = IPC_PRIVATE;
621 msqbuf->__msg_first = msqbuf->__msg_last = NULL;
625 DPRINTF((
"invalid command %d\n", cmd));
631 td->td_retval[0] = rval;
637#ifndef _SYS_SYSPROTO_H_
647 int msqid, error = 0;
650 struct ucred *cred = td->td_ucred;
651 struct msqid_kernel *msqkptr = NULL;
653 DPRINTF((
"msgget(0x%x, 0%o)\n", key, msgflg));
659 if (key != IPC_PRIVATE) {
660 for (msqid = 0; msqid <
msginfo.msgmni; msqid++) {
662 if (msqkptr->u.msg_qbytes != 0 &&
663 msqkptr->cred != NULL &&
664 msqkptr->cred->cr_prison == cred->cr_prison &&
665 msqkptr->u.msg_perm.key == key)
669 DPRINTF((
"found public key\n"));
670 if ((msgflg & IPC_CREAT) && (msgflg & IPC_EXCL)) {
675 AUDIT_ARG_SVIPC_ID(IXSEQ_TO_IPCID(msqid,
676 msqkptr->u.msg_perm));
677 if ((error =
ipcperm(td, &msqkptr->u.msg_perm,
679 DPRINTF((
"requester doesn't have 0%o access\n",
684 error = mac_sysvmsq_check_msqget(cred, msqkptr);
692 DPRINTF((
"need to allocate the msqid_ds\n"));
693 if (key == IPC_PRIVATE || (msgflg & IPC_CREAT)) {
694 for (msqid = 0; msqid <
msginfo.msgmni; msqid++) {
702 if (msqkptr->u.msg_qbytes == 0 &&
707 DPRINTF((
"no more msqid_ds's available\n"));
713 PROC_LOCK(td->td_proc);
714 error = racct_add(td->td_proc, RACCT_NMSGQ, 1);
715 PROC_UNLOCK(td->td_proc);
722 DPRINTF((
"msqid %d is available\n", msqid));
723 msqkptr->u.msg_perm.key = key;
724 msqkptr->u.msg_perm.cuid = cred->cr_uid;
725 msqkptr->u.msg_perm.uid = cred->cr_uid;
726 msqkptr->u.msg_perm.cgid = cred->cr_gid;
727 msqkptr->u.msg_perm.gid = cred->cr_gid;
728 msqkptr->u.msg_perm.mode = (msgflg & 0777);
729 msqkptr->cred =
crhold(cred);
731 msqkptr->u.msg_perm.seq = (msqkptr->u.msg_perm.seq + 1) & 0x7fff;
732 msqkptr->u.__msg_first = NULL;
733 msqkptr->u.__msg_last = NULL;
734 msqkptr->u.msg_cbytes = 0;
735 msqkptr->u.msg_qnum = 0;
736 msqkptr->u.msg_qbytes =
msginfo.msgmnb;
737 msqkptr->u.msg_lspid = 0;
738 msqkptr->u.msg_lrpid = 0;
739 msqkptr->u.msg_stime = 0;
740 msqkptr->u.msg_rtime = 0;
743 mac_sysvmsq_create(cred, msqkptr);
745 AUDIT_ARG_SVIPC_PERM(&msqkptr->u.msg_perm);
747 DPRINTF((
"didn't find it and wasn't asked to create it\n"));
754 td->td_retval[0] = IXSEQ_TO_IPCID(msqid, msqkptr->u.msg_perm);
760#ifndef _SYS_SYSPROTO_H_
770 size_t msgsz,
int msgflg,
long mtype)
772 int msqix, segs_needed, error = 0;
773 struct msqid_kernel *msqkptr;
778 size_t saved_msgsz = 0;
786 AUDIT_ARG_SVIPC_ID(msqid);
787 msqix = IPCID_TO_IX(msqid);
789 if (msqix < 0 || msqix >=
msginfo.msgmni) {
790 DPRINTF((
"msqid (%d) out of range (0<=msqid<%d)\n", msqix,
797 AUDIT_ARG_SVIPC_PERM(&msqkptr->u.msg_perm);
798 if (msqkptr->u.msg_qbytes == 0) {
799 DPRINTF((
"no such message queue id\n"));
803 if (msqkptr->u.msg_perm.seq != IPCID_TO_SEQ(msqid)) {
804 DPRINTF((
"wrong sequence number\n"));
810 DPRINTF((
"requester can't see prison\n"));
814 if ((error =
ipcperm(td, &msqkptr->u.msg_perm, IPC_W))) {
815 DPRINTF((
"requester doesn't have write access\n"));
820 error = mac_sysvmsq_check_msqsnd(td->td_ucred, msqkptr);
827 PROC_LOCK(td->td_proc);
828 if (racct_add(td->td_proc, RACCT_MSGQQUEUED, 1)) {
829 PROC_UNLOCK(td->td_proc);
834 if (racct_add(td->td_proc, RACCT_MSGQSIZE, msgsz)) {
835 racct_sub(td->td_proc, RACCT_MSGQQUEUED, 1);
836 PROC_UNLOCK(td->td_proc);
840 PROC_UNLOCK(td->td_proc);
844 segs_needed = howmany(msgsz,
msginfo.msgssz);
845 DPRINTF((
"msgsz=%zu, msgssz=%d, segs_needed=%d\n", msgsz,
848 int need_more_resources = 0;
855 if (msgsz > msqkptr->u.msg_qbytes) {
856 DPRINTF((
"msgsz > msqkptr->u.msg_qbytes\n"));
862 DPRINTF((
"msqid is locked\n"));
863 need_more_resources = 1;
865 if (msgsz + msqkptr->u.msg_cbytes > msqkptr->u.msg_qbytes) {
866 DPRINTF((
"msgsz + msg_cbytes > msg_qbytes\n"));
867 need_more_resources = 1;
870 DPRINTF((
"segs_needed > nfree_msgmaps\n"));
871 need_more_resources = 1;
874 DPRINTF((
"no more msghdrs\n"));
875 need_more_resources = 1;
878 if (need_more_resources) {
881 if ((msgflg & IPC_NOWAIT) != 0) {
882 DPRINTF((
"need more resources but caller "
883 "doesn't want to wait\n"));
888 if ((msqkptr->u.msg_perm.mode &
MSG_LOCKED) != 0) {
889 DPRINTF((
"we don't own the msqid_ds\n"));
894 DPRINTF((
"we own the msqid_ds\n"));
898 DPRINTF((
"msgsnd: goodnight\n"));
899 error = msleep(msqkptr, &
msq_mtx, (PZERO - 4) | PCATCH,
901 DPRINTF((
"msgsnd: good morning, error=%d\n", error));
903 msqkptr->u.msg_perm.mode &= ~MSG_LOCKED;
904 if (error == EWOULDBLOCK) {
905 DPRINTF((
"msgsnd: timed out\n"));
909 DPRINTF((
"msgsnd: interrupted system call\n"));
918 if (msqkptr->u.msg_qbytes == 0) {
925 DPRINTF((
"got all the resources that we need\n"));
936 panic(
"msg_perm.mode & MSG_LOCKED");
938 panic(
"segs_needed > nfree_msgmaps");
939 if (msgsz + msqkptr->u.msg_cbytes > msqkptr->u.msg_qbytes)
940 panic(
"msgsz + msg_cbytes > msg_qbytes");
942 panic(
"no more msghdrs");
949 if ((msqkptr->u.msg_perm.mode &
MSG_LOCKED) != 0)
950 panic(
"msqid_ds is already locked");
959 msghdr->msg_spot = -1;
960 msghdr->msg_ts = msgsz;
961 msghdr->msg_type = mtype;
968 mac_sysvmsg_create(td->td_ucred, msqkptr, msghdr);
975 while (segs_needed > 0) {
977 panic(
"not enough msgmaps");
979 panic(
"nil free_msgmaps");
982 panic(
"next too low #1");
984 panic(
"next out of range #1");
985 DPRINTF((
"allocating segment %d to message\n", next));
989 msghdr->msg_spot = next;
997 if (msghdr->msg_type < 1) {
999 msqkptr->u.msg_perm.mode &= ~MSG_LOCKED;
1001 DPRINTF((
"mtype (%ld) < 1\n", msghdr->msg_type));
1010 next = msghdr->msg_spot;
1018 panic(
"next too low #2");
1020 panic(
"next out of range #2");
1025 DPRINTF((
"error %d copying in message segment\n",
1028 msqkptr->u.msg_perm.mode &= ~MSG_LOCKED;
1034 msgp = (
const char *)msgp + tlen;
1038 panic(
"didn't use all the msg segments");
1044 msqkptr->u.msg_perm.mode &= ~MSG_LOCKED;
1050 if (msqkptr->u.msg_qbytes == 0) {
1069 error = mac_sysvmsq_check_msgmsq(td->td_ucred, msghdr, msqkptr);
1080 if (msqkptr->u.__msg_first == NULL) {
1081 msqkptr->u.__msg_first = msghdr;
1082 msqkptr->u.__msg_last = msghdr;
1084 msqkptr->u.__msg_last->msg_next = msghdr;
1085 msqkptr->u.__msg_last = msghdr;
1087 msqkptr->u.__msg_last->msg_next = NULL;
1089 msqkptr->u.msg_cbytes += msghdr->msg_ts;
1090 msqkptr->u.msg_qnum++;
1091 msqkptr->u.msg_lspid = td->td_proc->p_pid;
1095 td->td_retval[0] = 0;
1098 if (racct_enable && error != 0) {
1099 PROC_LOCK(td->td_proc);
1100 racct_sub(td->td_proc, RACCT_MSGQQUEUED, 1);
1101 racct_sub(td->td_proc, RACCT_MSGQSIZE, saved_msgsz);
1102 PROC_UNLOCK(td->td_proc);
1119 if ((error = copyin(uap->
msgp, &mtype,
sizeof(mtype))) != 0) {
1120 DPRINTF((
"error %d copying the message type\n", error));
1124 (
const char *)uap->
msgp +
sizeof(mtype),
1128#ifndef _SYS_SYSPROTO_H_
1139kern_msgrcv(
struct thread *td,
int msqid,
void *msgp,
size_t msgsz,
long msgtyp,
1140 int msgflg,
long *mtype)
1143 struct msqid_kernel *msqkptr;
1146 int msqix, error = 0;
1153 AUDIT_ARG_SVIPC_ID(msqid);
1154 msqix = IPCID_TO_IX(msqid);
1156 if (msqix < 0 || msqix >=
msginfo.msgmni) {
1157 DPRINTF((
"msqid (%d) out of range (0<=msqid<%d)\n", msqix,
1162 msqkptr = &
msqids[msqix];
1164 AUDIT_ARG_SVIPC_PERM(&msqkptr->u.msg_perm);
1165 if (msqkptr->u.msg_qbytes == 0) {
1166 DPRINTF((
"no such message queue id\n"));
1170 if (msqkptr->u.msg_perm.seq != IPCID_TO_SEQ(msqid)) {
1171 DPRINTF((
"wrong sequence number\n"));
1177 DPRINTF((
"requester can't see prison\n"));
1181 if ((error =
ipcperm(td, &msqkptr->u.msg_perm, IPC_R))) {
1182 DPRINTF((
"requester doesn't have read access\n"));
1187 error = mac_sysvmsq_check_msqrcv(td->td_ucred, msqkptr);
1193 while (msghdr == NULL) {
1195 msghdr = msqkptr->u.__msg_first;
1196 if (msghdr != NULL) {
1197 if (msgsz < msghdr->msg_ts &&
1198 (msgflg & MSG_NOERROR) == 0) {
1199 DPRINTF((
"first message on the queue "
1200 "is too big (want %zu, got %d)\n",
1201 msgsz, msghdr->msg_ts));
1206 error = mac_sysvmsq_check_msgrcv(td->td_ucred,
1211 if (msqkptr->u.__msg_first ==
1212 msqkptr->u.__msg_last) {
1213 msqkptr->u.__msg_first = NULL;
1214 msqkptr->u.__msg_last = NULL;
1216 msqkptr->u.__msg_first = msghdr->msg_next;
1217 if (msqkptr->u.__msg_first == NULL)
1218 panic(
"msg_first/last screwed up #1");
1222 struct msg *previous;
1226 prev = &(msqkptr->u.__msg_first);
1227 while ((msghdr = *prev) != NULL) {
1237 if (msgtyp == msghdr->msg_type ||
1238 msghdr->msg_type <= -msgtyp) {
1239 DPRINTF((
"found message type %ld, "
1241 msghdr->msg_type, msgtyp));
1242 if (msgsz < msghdr->msg_ts &&
1243 (msgflg & MSG_NOERROR) == 0) {
1245 "on the queue is too big "
1246 "(want %zu, got %hu)\n",
1247 msgsz, msghdr->msg_ts));
1252 error = mac_sysvmsq_check_msgrcv(
1253 td->td_ucred, msghdr);
1257 *prev = msghdr->msg_next;
1258 if (msghdr == msqkptr->u.__msg_last) {
1259 if (previous == NULL) {
1261 &msqkptr->u.__msg_first)
1262 panic(
"__msg_first/last screwed up #2");
1263 msqkptr->u.__msg_first =
1265 msqkptr->u.__msg_last =
1269 &msqkptr->u.__msg_first)
1270 panic(
"__msg_first/last screwed up #3");
1271 msqkptr->u.__msg_last =
1278 prev = &(msghdr->msg_next);
1295 if ((msgflg & IPC_NOWAIT) != 0) {
1296 DPRINTF((
"no appropriate message found (msgtyp=%ld)\n",
1307 DPRINTF((
"msgrcv: goodnight\n"));
1308 error = msleep(msqkptr, &
msq_mtx, (PZERO - 4) | PCATCH,
1310 DPRINTF((
"msgrcv: good morning (error=%d)\n", error));
1313 DPRINTF((
"msgrcv: interrupted system call\n"));
1322 if (msqkptr->u.msg_qbytes == 0 ||
1323 msqkptr->u.msg_perm.seq != IPCID_TO_SEQ(msqid)) {
1336 msqkptr->u.msg_cbytes -= msghdr->msg_ts;
1337 msqkptr->u.msg_qnum--;
1338 msqkptr->u.msg_lrpid = td->td_proc->p_pid;
1341 racct_sub_cred(msqkptr->cred, RACCT_MSGQQUEUED, 1);
1342 racct_sub_cred(msqkptr->cred, RACCT_MSGQSIZE, msghdr->msg_ts);
1350 DPRINTF((
"found a message, msgsz=%zu, msg_ts=%hu\n", msgsz,
1352 if (msgsz > msghdr->msg_ts)
1353 msgsz = msghdr->msg_ts;
1354 *mtype = msghdr->msg_type;
1360 next = msghdr->msg_spot;
1361 for (len = 0; len < msgsz; len +=
msginfo.msgssz) {
1364 if (msgsz - len >
msginfo.msgssz)
1369 panic(
"next too low #3");
1371 panic(
"next out of range #3");
1376 DPRINTF((
"error (%d) copying out message segment\n",
1382 msgp = (
char *)msgp + tlen;
1392 td->td_retval[0] = msgsz;
1404 DPRINTF((
"call to msgrcv(%d, %p, %zu, %ld, %d)\n", uap->
msqid,
1408 (
char *)uap->
msgp +
sizeof(mtype), uap->
msgsz,
1411 if ((error = copyout(&mtype, uap->
msgp,
sizeof(mtype))) != 0)
1412 DPRINTF((
"error %d copying the message type\n", error));
1419 struct msqid_kernel tmsqk;
1420#ifdef COMPAT_FREEBSD32
1421 struct msqid_kernel32 tmsqk32;
1423 struct prison *
pr, *rpr;
1428 pr = req->td->td_ucred->cr_prison;
1431 for (i = 0; i <
msginfo.msgmni; i++) {
1433 if (
msqids[i].u.msg_qbytes == 0 || rpr == NULL ||
1435 bzero(&tmsqk,
sizeof(tmsqk));
1438 if (tmsqk.cred->cr_prison !=
pr)
1439 tmsqk.u.msg_perm.key = IPC_PRIVATE;
1442#ifdef COMPAT_FREEBSD32
1443 if (SV_CURPROC_FLAG(SV_ILP32)) {
1444 bzero(&tmsqk32,
sizeof(tmsqk32));
1445 freebsd32_ipcperm_out(&tmsqk.u.msg_perm,
1446 &tmsqk32.u.msg_perm);
1448 CP(tmsqk, tmsqk32, u.msg_cbytes);
1449 CP(tmsqk, tmsqk32, u.msg_qnum);
1450 CP(tmsqk, tmsqk32, u.msg_qbytes);
1451 CP(tmsqk, tmsqk32, u.msg_lspid);
1452 CP(tmsqk, tmsqk32, u.msg_lrpid);
1453 CP(tmsqk, tmsqk32, u.msg_stime);
1454 CP(tmsqk, tmsqk32, u.msg_rtime);
1455 CP(tmsqk, tmsqk32, u.msg_ctime);
1458 outsize =
sizeof(tmsqk32);
1463 tmsqk.u.__msg_first = NULL;
1464 tmsqk.u.__msg_last = NULL;
1473 outsize =
sizeof(tmsqk);
1475 error = SYSCTL_OUT(req, outaddr, outsize);
1483 "Maximum message size");
1485 "Number of message queue identifiers");
1487 "Maximum number of bytes in a queue");
1489 "Maximum number of messages in the system");
1491 "Size of a message segment");
1493 "Number of message segments");
1495 CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
1497 "Array of struct msqid_kernel for each potential message queue");
1502 struct prison *
pr = obj;
1503 struct prison *prpr;
1504 struct vfsoptlist *opts =
data;
1511 error =
vfs_copyopt(opts,
"sysvmsg", &jsys,
sizeof(jsys));
1512 if (error != ENOENT) {
1516 case JAIL_SYS_DISABLE:
1519 case JAIL_SYS_INHERIT:
1520 prison_lock(
pr->pr_parent);
1522 prison_unlock(
pr->pr_parent);
1537 struct prison *
pr = obj;
1538 struct prison *tpr, *orpr, *nrpr, *trpr;
1539 struct vfsoptlist *opts =
data;
1547 if (
vfs_copyopt(opts,
"sysvmsg", &jsys,
sizeof(jsys)) == ENOENT)
1548 jsys =
vfs_flagopt(opts,
"allow.sysvipc", NULL, 0)
1553 if (jsys == JAIL_SYS_DISABLE) {
1563 FOREACH_PRISON_DESCENDANT(
pr, tpr, descend) {
1577 }
else if (jsys != -1) {
1578 if (jsys == JAIL_SYS_NEW)
1581 prison_lock(
pr->pr_parent);
1583 prison_unlock(
pr->pr_parent);
1599 FOREACH_PRISON_DESCENDANT(
pr, tpr, descend) {
1601 trpr = osd_jail_get(tpr,
1604 (void)osd_jail_set(tpr,
1624 struct prison *
pr = obj;
1626 struct vfsoptlist *opts =
data;
1633 jsys = rpr == NULL ? JAIL_SYS_DISABLE
1634 : rpr ==
pr ? JAIL_SYS_NEW : JAIL_SYS_INHERIT;
1635 error =
vfs_setopt(opts,
"sysvmsg", &jsys,
sizeof(jsys));
1636 if (error == ENOENT)
1644 struct prison *
pr = obj;
1658 struct msqid_kernel *msqkptr;
1663 for (i = 0; i <
msginfo.msgmni; i++) {
1665 if (msqkptr->u.msg_qbytes != 0 &&
1666 msqkptr->cred != NULL && msqkptr->cred->cr_prison ==
pr)
1674#ifdef COMPAT_FREEBSD32
1676freebsd32_msgsys(
struct thread *td,
struct freebsd32_msgsys_args *uap)
1679#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1680 defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1681 AUDIT_ARG_SVIPC_WHICH(uap->which);
1682 switch (uap->which) {
1684 return (freebsd7_freebsd32_msgctl(td,
1685 (
struct freebsd7_freebsd32_msgctl_args *)&uap->a2));
1687 return (freebsd32_msgsnd(td,
1688 (
struct freebsd32_msgsnd_args *)&uap->a2));
1690 return (freebsd32_msgrcv(td,
1691 (
struct freebsd32_msgrcv_args *)&uap->a2));
1693 return (sys_msgsys(td, (
struct msgsys_args *)uap));
1696 return (
nosys(td, NULL));
1700#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1701 defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1703freebsd7_freebsd32_msgctl(
struct thread *td,
1704 struct freebsd7_freebsd32_msgctl_args *uap)
1706 struct msqid_ds msqbuf;
1707 struct msqid_ds_old32 msqbuf32;
1710 if (uap->cmd == IPC_SET) {
1711 error = copyin(uap->buf, &msqbuf32,
sizeof(msqbuf32));
1714 freebsd32_ipcperm_old_in(&msqbuf32.msg_perm, &msqbuf.msg_perm);
1715 PTRIN_CP(msqbuf32, msqbuf, __msg_first);
1716 PTRIN_CP(msqbuf32, msqbuf, __msg_last);
1717 CP(msqbuf32, msqbuf, msg_cbytes);
1718 CP(msqbuf32, msqbuf, msg_qnum);
1719 CP(msqbuf32, msqbuf, msg_qbytes);
1720 CP(msqbuf32, msqbuf, msg_lspid);
1721 CP(msqbuf32, msqbuf, msg_lrpid);
1722 CP(msqbuf32, msqbuf, msg_stime);
1723 CP(msqbuf32, msqbuf, msg_rtime);
1724 CP(msqbuf32, msqbuf, msg_ctime);
1726 error =
kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf);
1729 if (uap->cmd == IPC_STAT) {
1730 bzero(&msqbuf32,
sizeof(msqbuf32));
1731 freebsd32_ipcperm_old_out(&msqbuf.msg_perm, &msqbuf32.msg_perm);
1732 PTROUT_CP(msqbuf, msqbuf32, __msg_first);
1733 PTROUT_CP(msqbuf, msqbuf32, __msg_last);
1734 CP(msqbuf, msqbuf32, msg_cbytes);
1735 CP(msqbuf, msqbuf32, msg_qnum);
1736 CP(msqbuf, msqbuf32, msg_qbytes);
1737 CP(msqbuf, msqbuf32, msg_lspid);
1738 CP(msqbuf, msqbuf32, msg_lrpid);
1739 CP(msqbuf, msqbuf32, msg_stime);
1740 CP(msqbuf, msqbuf32, msg_rtime);
1741 CP(msqbuf, msqbuf32, msg_ctime);
1742 error = copyout(&msqbuf32, uap->buf,
sizeof(
struct msqid_ds32));
1749freebsd32_msgctl(
struct thread *td,
struct freebsd32_msgctl_args *uap)
1751 struct msqid_ds msqbuf;
1752 struct msqid_ds32 msqbuf32;
1755 if (uap->cmd == IPC_SET) {
1756 error = copyin(uap->buf, &msqbuf32,
sizeof(msqbuf32));
1759 freebsd32_ipcperm_in(&msqbuf32.msg_perm, &msqbuf.msg_perm);
1760 PTRIN_CP(msqbuf32, msqbuf, __msg_first);
1761 PTRIN_CP(msqbuf32, msqbuf, __msg_last);
1762 CP(msqbuf32, msqbuf, msg_cbytes);
1763 CP(msqbuf32, msqbuf, msg_qnum);
1764 CP(msqbuf32, msqbuf, msg_qbytes);
1765 CP(msqbuf32, msqbuf, msg_lspid);
1766 CP(msqbuf32, msqbuf, msg_lrpid);
1767 CP(msqbuf32, msqbuf, msg_stime);
1768 CP(msqbuf32, msqbuf, msg_rtime);
1769 CP(msqbuf32, msqbuf, msg_ctime);
1771 error =
kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf);
1774 if (uap->cmd == IPC_STAT) {
1775 freebsd32_ipcperm_out(&msqbuf.msg_perm, &msqbuf32.msg_perm);
1776 PTROUT_CP(msqbuf, msqbuf32, __msg_first);
1777 PTROUT_CP(msqbuf, msqbuf32, __msg_last);
1778 CP(msqbuf, msqbuf32, msg_cbytes);
1779 CP(msqbuf, msqbuf32, msg_qnum);
1780 CP(msqbuf, msqbuf32, msg_qbytes);
1781 CP(msqbuf, msqbuf32, msg_lspid);
1782 CP(msqbuf, msqbuf32, msg_lrpid);
1783 CP(msqbuf, msqbuf32, msg_stime);
1784 CP(msqbuf, msqbuf32, msg_rtime);
1785 CP(msqbuf, msqbuf32, msg_ctime);
1786 error = copyout(&msqbuf32, uap->buf,
sizeof(
struct msqid_ds32));
1792freebsd32_msgsnd(
struct thread *td,
struct freebsd32_msgsnd_args *uap)
1799 msgp = PTRIN(uap->msgp);
1800 if ((error = copyin(msgp, &mtype32,
sizeof(mtype32))) != 0)
1804 (
const char *)msgp +
sizeof(mtype32),
1805 uap->msgsz, uap->msgflg, mtype));
1809freebsd32_msgrcv(
struct thread *td,
struct freebsd32_msgrcv_args *uap)
1816 msgp = PTRIN(uap->msgp);
1818 (
char *)msgp +
sizeof(mtype32), uap->msgsz,
1819 uap->msgtyp, uap->msgflg, &mtype)) != 0)
1821 mtype32 = (int32_t)mtype;
1822 return (copyout(&mtype32, msgp,
sizeof(mtype32)));
1826#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
1827 defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
1830static sy_call_t *msgcalls[] = {
1831 (sy_call_t *)freebsd7_msgctl, (sy_call_t *)
sys_msgget,
1849sys_msgsys(
struct thread *td,
struct msgsys_args *uap)
1853 AUDIT_ARG_SVIPC_WHICH(uap->which);
1854 if (uap->which < 0 || uap->which >= nitems(msgcalls))
1856 error = (*msgcalls[uap->which])(td, &uap->a2);
1861#define CP(src, dst, fld) do { (dst).fld = (src).fld; } while (0)
1864#ifndef _SYS_SYSPROTO_H_
1865struct freebsd7_msgctl_args {
1868 struct msqid_ds_old *
buf;
1872freebsd7_msgctl(
struct thread *td,
struct freebsd7_msgctl_args *uap)
1874 struct msqid_ds_old msqold;
1875 struct msqid_ds msqbuf;
1878 DPRINTF((
"call to freebsd7_msgctl(%d, %d, %p)\n", uap->msqid, uap->cmd,
1880 if (uap->cmd == IPC_SET) {
1881 error = copyin(uap->buf, &msqold,
sizeof(msqold));
1884 ipcperm_old2new(&msqold.msg_perm, &msqbuf.msg_perm);
1885 CP(msqold, msqbuf, __msg_first);
1886 CP(msqold, msqbuf, __msg_last);
1887 CP(msqold, msqbuf, msg_cbytes);
1888 CP(msqold, msqbuf, msg_qnum);
1889 CP(msqold, msqbuf, msg_qbytes);
1890 CP(msqold, msqbuf, msg_lspid);
1891 CP(msqold, msqbuf, msg_lrpid);
1892 CP(msqold, msqbuf, msg_stime);
1893 CP(msqold, msqbuf, msg_rtime);
1894 CP(msqold, msqbuf, msg_ctime);
1896 error =
kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf);
1899 if (uap->cmd == IPC_STAT) {
1900 bzero(&msqold,
sizeof(msqold));
1901 ipcperm_new2old(&msqbuf.msg_perm, &msqold.msg_perm);
1902 CP(msqbuf, msqold, __msg_first);
1903 CP(msqbuf, msqold, __msg_last);
1904 CP(msqbuf, msqold, msg_cbytes);
1905 CP(msqbuf, msqold, msg_qnum);
1906 CP(msqbuf, msqold, msg_qbytes);
1907 CP(msqbuf, msqold, msg_lspid);
1908 CP(msqbuf, msqold, msg_lrpid);
1909 CP(msqbuf, msqold, msg_stime);
1910 CP(msqbuf, msqold, msg_rtime);
1911 CP(msqbuf, msqold, msg_ctime);
1912 error = copyout(&msqold, uap->buf,
sizeof(
struct msqid_ds_old));
int prison_ischild(struct prison *pr1, struct prison *pr2)
struct prisonlist allprison
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void free(void *addr, struct malloc_type *mtp)
void osd_free_reserved(void **rsv)
void ** osd_reserve(u_int slot)
static struct pollrec pr[POLL_LIST_LEN]
int priv_check(struct thread *td, int priv)
struct ucred * crhold(struct ucred *cr)
void crfree(struct ucred *cr)
void panic(const char *fmt,...)
int nosys(struct thread *td, struct nosys_args *args)
void wakeup(const void *ident)
int syscall_helper_unregister(struct syscall_helper_data *sd)
int syscall_helper_register(struct syscall_helper_data *sd, int flags)
volatile time_t time_second
int ipcperm(struct thread *td, struct ipc_perm *perm, int acc_mode)
int kern_msgrcv(struct thread *td, int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg, long *mtype)
SYSCTL_JAIL_PARAM_SYS_NODE(sysvmsg, CTLFLAG_RW, "SYSV message queues")
static unsigned msg_prison_slot
int kern_msgsnd(struct thread *td, int msqid, const void *msgp, size_t msgsz, int msgflg, long mtype)
int sys_msgctl(struct thread *td, struct msgctl_args *uap)
FEATURE(sysv_msg, "System V message queues support")
static short free_msgmaps
static struct syscall_helper_data msg_syscalls[]
static MALLOC_DEFINE(M_MSG, "msg", "SVID compatible message queues")
static void msg_prison_cleanup(struct prison *)
int sys_msgget(struct thread *td, struct msgget_args *uap)
static struct mtx msq_mtx
static int msg_prison_check(void *, void *)
SYSCTL_PROC(_kern_ipc, OID_AUTO, msqids, CTLTYPE_OPAQUE|CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, 0, sysctl_msqids, "", "Array of struct msqid_kernel for each potential message queue")
static struct prison * msg_find_prison(struct ucred *)
static int msgunload(void)
MODULE_VERSION(sysvmsg, 1)
int sys_msgsnd(struct thread *td, struct msgsnd_args *uap)
int sys_msgrcv(struct thread *td, struct msgrcv_args *uap)
static int msg_prison_remove(void *, void *)
static struct msgmap * msgmaps
static int sysctl_msqids(SYSCTL_HANDLER_ARGS)
DECLARE_MODULE(sysvmsg, sysvmsg_mod, SI_SUB_SYSV_MSG, SI_ORDER_FIRST)
static int msg_prison_get(void *, void *)
static int sysvmsg_modload(struct module *, int, void *)
static struct msqid_kernel * msqids
static int msg_prison_set(void *, void *)
static void msg_freehdr(struct msg *msghdr)
static struct msg * free_msghdrs
int kern_msgctl(struct thread *td, int msqid, int cmd, struct msqid_ds *msqbuf)
static moduledata_t sysvmsg_mod
static struct msg * msghdrs
static void msq_remove(struct msqid_kernel *)
static int msq_prison_cansee(struct prison *, struct msqid_kernel *)
SYSCTL_INT(_kern_ipc, OID_AUTO, msgmax, CTLFLAG_RD, &msginfo.msgmax, 0, "Maximum message size")
int vfs_copyopt(struct vfsoptlist *opts, const char *name, void *dest, int len)
int vfs_flagopt(struct vfsoptlist *opts, const char *name, uint64_t *w, uint64_t val)
int vfs_setopt(struct vfsoptlist *opts, const char *name, void *value, int len)