1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate /* 34*7c478bd9Sstevel@tonic-gate * Inter-Process Communication Message Facility. 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * See os/ipc.c for a description of common IPC functionality. 37*7c478bd9Sstevel@tonic-gate * 38*7c478bd9Sstevel@tonic-gate * Resource controls 39*7c478bd9Sstevel@tonic-gate * ----------------- 40*7c478bd9Sstevel@tonic-gate * 41*7c478bd9Sstevel@tonic-gate * Control: project.max-msg-ids (rc_project_msgmni) 42*7c478bd9Sstevel@tonic-gate * Description: Maximum number of message queue ids allowed a project. 43*7c478bd9Sstevel@tonic-gate * 44*7c478bd9Sstevel@tonic-gate * When msgget() is used to allocate a message queue, one id is 45*7c478bd9Sstevel@tonic-gate * allocated. If the id allocation doesn't succeed, msgget() fails 46*7c478bd9Sstevel@tonic-gate * and errno is set to ENOSPC. Upon successful msgctl(, IPC_RMID) 47*7c478bd9Sstevel@tonic-gate * the id is deallocated. 48*7c478bd9Sstevel@tonic-gate * 49*7c478bd9Sstevel@tonic-gate * Control: process.max-msg-qbytes (rc_process_msgmnb) 50*7c478bd9Sstevel@tonic-gate * Description: Maximum number of bytes of messages on a message queue. 51*7c478bd9Sstevel@tonic-gate * 52*7c478bd9Sstevel@tonic-gate * When msgget() successfully allocates a message queue, the minimum 53*7c478bd9Sstevel@tonic-gate * enforced value of this limit is used to initialize msg_qbytes. 54*7c478bd9Sstevel@tonic-gate * 55*7c478bd9Sstevel@tonic-gate * Control: process.max-msg-messages (rc_process_msgtql) 56*7c478bd9Sstevel@tonic-gate * Description: Maximum number of messages on a message queue. 57*7c478bd9Sstevel@tonic-gate * 58*7c478bd9Sstevel@tonic-gate * When msgget() successfully allocates a message queue, the minimum 59*7c478bd9Sstevel@tonic-gate * enforced value of this limit is used to initialize a per-queue 60*7c478bd9Sstevel@tonic-gate * limit on the number of messages. 61*7c478bd9Sstevel@tonic-gate */ 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 64*7c478bd9Sstevel@tonic-gate #include <sys/t_lock.h> 65*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 66*7c478bd9Sstevel@tonic-gate #include <sys/cred.h> 67*7c478bd9Sstevel@tonic-gate #include <sys/user.h> 68*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 69*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 70*7c478bd9Sstevel@tonic-gate #include <sys/ipc.h> 71*7c478bd9Sstevel@tonic-gate #include <sys/ipc_impl.h> 72*7c478bd9Sstevel@tonic-gate #include <sys/msg.h> 73*7c478bd9Sstevel@tonic-gate #include <sys/msg_impl.h> 74*7c478bd9Sstevel@tonic-gate #include <sys/list.h> 75*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 76*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 77*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 78*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 79*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 80*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 81*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 82*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 83*7c478bd9Sstevel@tonic-gate #include <sys/project.h> 84*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 85*7c478bd9Sstevel@tonic-gate #include <sys/syscall.h> 86*7c478bd9Sstevel@tonic-gate #include <sys/policy.h> 87*7c478bd9Sstevel@tonic-gate #include <sys/zone.h> 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate #include <c2/audit.h> 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate /* 92*7c478bd9Sstevel@tonic-gate * The following tunables are obsolete. Though for compatibility we 93*7c478bd9Sstevel@tonic-gate * still read and interpret msginfo_msgmnb, msginfo_msgmni, and 94*7c478bd9Sstevel@tonic-gate * msginfo_msgtql (see os/project.c and os/rctl_proc.c), the preferred 95*7c478bd9Sstevel@tonic-gate * mechanism for administrating the IPC Message facility is through the 96*7c478bd9Sstevel@tonic-gate * resource controls described at the top of this file. 97*7c478bd9Sstevel@tonic-gate */ 98*7c478bd9Sstevel@tonic-gate size_t msginfo_msgmax = 2048; /* (obsolete) */ 99*7c478bd9Sstevel@tonic-gate size_t msginfo_msgmnb = 4096; /* (obsolete) */ 100*7c478bd9Sstevel@tonic-gate int msginfo_msgmni = 50; /* (obsolete) */ 101*7c478bd9Sstevel@tonic-gate int msginfo_msgtql = 40; /* (obsolete) */ 102*7c478bd9Sstevel@tonic-gate int msginfo_msgssz = 8; /* (obsolete) */ 103*7c478bd9Sstevel@tonic-gate int msginfo_msgmap = 0; /* (obsolete) */ 104*7c478bd9Sstevel@tonic-gate ushort_t msginfo_msgseg = 1024; /* (obsolete) */ 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate extern rctl_hndl_t rc_project_msgmni; 107*7c478bd9Sstevel@tonic-gate extern rctl_hndl_t rc_process_msgmnb; 108*7c478bd9Sstevel@tonic-gate extern rctl_hndl_t rc_process_msgtql; 109*7c478bd9Sstevel@tonic-gate static ipc_service_t *msq_svc; 110*7c478bd9Sstevel@tonic-gate static zone_key_t msg_zone_key; 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate static void msg_dtor(kipc_perm_t *); 113*7c478bd9Sstevel@tonic-gate static void msg_rmid(kipc_perm_t *); 114*7c478bd9Sstevel@tonic-gate static void msg_remove_zone(zoneid_t, void *); 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate /* 117*7c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 118*7c478bd9Sstevel@tonic-gate */ 119*7c478bd9Sstevel@tonic-gate static ssize_t msgsys(int opcode, uintptr_t a0, uintptr_t a1, uintptr_t a2, 120*7c478bd9Sstevel@tonic-gate uintptr_t a4, uintptr_t a5); 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate static struct sysent ipcmsg_sysent = { 123*7c478bd9Sstevel@tonic-gate 6, 124*7c478bd9Sstevel@tonic-gate #ifdef _LP64 125*7c478bd9Sstevel@tonic-gate SE_ARGC | SE_NOUNLOAD | SE_64RVAL, 126*7c478bd9Sstevel@tonic-gate #else 127*7c478bd9Sstevel@tonic-gate SE_ARGC | SE_NOUNLOAD | SE_32RVAL1, 128*7c478bd9Sstevel@tonic-gate #endif 129*7c478bd9Sstevel@tonic-gate (int (*)())msgsys 130*7c478bd9Sstevel@tonic-gate }; 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 133*7c478bd9Sstevel@tonic-gate static ssize32_t msgsys32(int opcode, uint32_t a0, uint32_t a1, uint32_t a2, 134*7c478bd9Sstevel@tonic-gate uint32_t a4, uint32_t a5); 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate static struct sysent ipcmsg_sysent32 = { 137*7c478bd9Sstevel@tonic-gate 6, 138*7c478bd9Sstevel@tonic-gate SE_ARGC | SE_NOUNLOAD | SE_32RVAL1, 139*7c478bd9Sstevel@tonic-gate (int (*)())msgsys32 140*7c478bd9Sstevel@tonic-gate }; 141*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate static struct modlsys modlsys = { 144*7c478bd9Sstevel@tonic-gate &mod_syscallops, "System V message facility", &ipcmsg_sysent 145*7c478bd9Sstevel@tonic-gate }; 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 148*7c478bd9Sstevel@tonic-gate static struct modlsys modlsys32 = { 149*7c478bd9Sstevel@tonic-gate &mod_syscallops32, "32-bit System V message facility", &ipcmsg_sysent32 150*7c478bd9Sstevel@tonic-gate }; 151*7c478bd9Sstevel@tonic-gate #endif 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 154*7c478bd9Sstevel@tonic-gate MODREV_1, 155*7c478bd9Sstevel@tonic-gate &modlsys, 156*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 157*7c478bd9Sstevel@tonic-gate &modlsys32, 158*7c478bd9Sstevel@tonic-gate #endif 159*7c478bd9Sstevel@tonic-gate NULL 160*7c478bd9Sstevel@tonic-gate }; 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate int 164*7c478bd9Sstevel@tonic-gate _init(void) 165*7c478bd9Sstevel@tonic-gate { 166*7c478bd9Sstevel@tonic-gate int result; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate msq_svc = ipcs_create("msqids", rc_project_msgmni, sizeof (kmsqid_t), 169*7c478bd9Sstevel@tonic-gate msg_dtor, msg_rmid, AT_IPC_MSG, 170*7c478bd9Sstevel@tonic-gate offsetof(kproject_data_t, kpd_msgmni)); 171*7c478bd9Sstevel@tonic-gate zone_key_create(&msg_zone_key, NULL, msg_remove_zone, NULL); 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate if ((result = mod_install(&modlinkage)) == 0) 174*7c478bd9Sstevel@tonic-gate return (0); 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate (void) zone_key_delete(msg_zone_key); 177*7c478bd9Sstevel@tonic-gate ipcs_destroy(msq_svc); 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate return (result); 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate int 183*7c478bd9Sstevel@tonic-gate _fini(void) 184*7c478bd9Sstevel@tonic-gate { 185*7c478bd9Sstevel@tonic-gate return (EBUSY); 186*7c478bd9Sstevel@tonic-gate } 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate int 189*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 190*7c478bd9Sstevel@tonic-gate { 191*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate static void 195*7c478bd9Sstevel@tonic-gate msg_dtor(kipc_perm_t *perm) 196*7c478bd9Sstevel@tonic-gate { 197*7c478bd9Sstevel@tonic-gate kmsqid_t *qp = (kmsqid_t *)perm; 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate ASSERT(qp->msg_rcv_cnt == 0); 200*7c478bd9Sstevel@tonic-gate ASSERT(qp->msg_snd_cnt == 0); 201*7c478bd9Sstevel@tonic-gate ASSERT(qp->msg_cbytes == 0); 202*7c478bd9Sstevel@tonic-gate list_destroy(&qp->msg_list); 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate #define msg_hold(mp) (mp)->msg_copycnt++ 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate /* 209*7c478bd9Sstevel@tonic-gate * msg_rele - decrement the reference count on the message. When count 210*7c478bd9Sstevel@tonic-gate * reaches zero, free message header and contents. 211*7c478bd9Sstevel@tonic-gate */ 212*7c478bd9Sstevel@tonic-gate static void 213*7c478bd9Sstevel@tonic-gate msg_rele(struct msg *mp) 214*7c478bd9Sstevel@tonic-gate { 215*7c478bd9Sstevel@tonic-gate ASSERT(mp->msg_copycnt > 0); 216*7c478bd9Sstevel@tonic-gate if (mp->msg_copycnt-- == 1) { 217*7c478bd9Sstevel@tonic-gate if (mp->msg_addr) 218*7c478bd9Sstevel@tonic-gate kmem_free(mp->msg_addr, mp->msg_size); 219*7c478bd9Sstevel@tonic-gate kmem_free(mp, sizeof (struct msg)); 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate /* 224*7c478bd9Sstevel@tonic-gate * msgunlink - Unlink msg from queue, decrement byte count and wake up anyone 225*7c478bd9Sstevel@tonic-gate * waiting for free bytes on queue. 226*7c478bd9Sstevel@tonic-gate * 227*7c478bd9Sstevel@tonic-gate * Called with queue locked. 228*7c478bd9Sstevel@tonic-gate */ 229*7c478bd9Sstevel@tonic-gate static void 230*7c478bd9Sstevel@tonic-gate msgunlink(kmsqid_t *qp, struct msg *mp) 231*7c478bd9Sstevel@tonic-gate { 232*7c478bd9Sstevel@tonic-gate list_remove(&qp->msg_list, mp); 233*7c478bd9Sstevel@tonic-gate qp->msg_qnum--; 234*7c478bd9Sstevel@tonic-gate qp->msg_cbytes -= mp->msg_size; 235*7c478bd9Sstevel@tonic-gate msg_rele(mp); 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate /* Wake up waiting writers */ 238*7c478bd9Sstevel@tonic-gate if (qp->msg_snd_cnt) 239*7c478bd9Sstevel@tonic-gate cv_broadcast(&qp->msg_snd_cv); 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate static void 243*7c478bd9Sstevel@tonic-gate msg_rmid(kipc_perm_t *perm) 244*7c478bd9Sstevel@tonic-gate { 245*7c478bd9Sstevel@tonic-gate kmsqid_t *qp = (kmsqid_t *)perm; 246*7c478bd9Sstevel@tonic-gate struct msg *mp; 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate while ((mp = list_head(&qp->msg_list)) != NULL) 250*7c478bd9Sstevel@tonic-gate msgunlink(qp, mp); 251*7c478bd9Sstevel@tonic-gate ASSERT(qp->msg_cbytes == 0); 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate if (qp->msg_rcv_cnt) 254*7c478bd9Sstevel@tonic-gate cv_broadcast(&qp->msg_rcv_cv); 255*7c478bd9Sstevel@tonic-gate if (qp->msg_snd_cnt) 256*7c478bd9Sstevel@tonic-gate cv_broadcast(&qp->msg_snd_cv); 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate /* 260*7c478bd9Sstevel@tonic-gate * msgctl system call. 261*7c478bd9Sstevel@tonic-gate * 262*7c478bd9Sstevel@tonic-gate * gets q lock (via ipc_lookup), releases before return. 263*7c478bd9Sstevel@tonic-gate * may call users of msg_lock 264*7c478bd9Sstevel@tonic-gate */ 265*7c478bd9Sstevel@tonic-gate static int 266*7c478bd9Sstevel@tonic-gate msgctl(int msgid, int cmd, void *arg) 267*7c478bd9Sstevel@tonic-gate { 268*7c478bd9Sstevel@tonic-gate STRUCT_DECL(msqid_ds, ds); /* SVR4 queue work area */ 269*7c478bd9Sstevel@tonic-gate kmsqid_t *qp; /* ptr to associated q */ 270*7c478bd9Sstevel@tonic-gate int error; 271*7c478bd9Sstevel@tonic-gate struct cred *cr; 272*7c478bd9Sstevel@tonic-gate model_t mdl = get_udatamodel(); 273*7c478bd9Sstevel@tonic-gate struct msqid_ds64 ds64; 274*7c478bd9Sstevel@tonic-gate kmutex_t *lock; 275*7c478bd9Sstevel@tonic-gate proc_t *pp = curproc; 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate STRUCT_INIT(ds, mdl); 278*7c478bd9Sstevel@tonic-gate cr = CRED(); 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate /* 281*7c478bd9Sstevel@tonic-gate * Perform pre- or non-lookup actions (e.g. copyins, RMID). 282*7c478bd9Sstevel@tonic-gate */ 283*7c478bd9Sstevel@tonic-gate switch (cmd) { 284*7c478bd9Sstevel@tonic-gate case IPC_SET: 285*7c478bd9Sstevel@tonic-gate if (copyin(arg, STRUCT_BUF(ds), STRUCT_SIZE(ds))) 286*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 287*7c478bd9Sstevel@tonic-gate break; 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate case IPC_SET64: 290*7c478bd9Sstevel@tonic-gate if (copyin(arg, &ds64, sizeof (struct msqid_ds64))) 291*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 292*7c478bd9Sstevel@tonic-gate break; 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate case IPC_RMID: 295*7c478bd9Sstevel@tonic-gate if (error = ipc_rmid(msq_svc, msgid, cr)) 296*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 297*7c478bd9Sstevel@tonic-gate return (0); 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate /* 301*7c478bd9Sstevel@tonic-gate * get msqid_ds for this msgid 302*7c478bd9Sstevel@tonic-gate */ 303*7c478bd9Sstevel@tonic-gate if ((lock = ipc_lookup(msq_svc, msgid, (kipc_perm_t **)&qp)) == NULL) 304*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate switch (cmd) { 307*7c478bd9Sstevel@tonic-gate case IPC_SET: 308*7c478bd9Sstevel@tonic-gate if (STRUCT_FGET(ds, msg_qbytes) > qp->msg_qbytes && 309*7c478bd9Sstevel@tonic-gate secpolicy_ipc_config(cr) != 0) { 310*7c478bd9Sstevel@tonic-gate mutex_exit(lock); 311*7c478bd9Sstevel@tonic-gate return (set_errno(EPERM)); 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate if (error = ipcperm_set(msq_svc, cr, &qp->msg_perm, 314*7c478bd9Sstevel@tonic-gate &STRUCT_BUF(ds)->msg_perm, mdl)) { 315*7c478bd9Sstevel@tonic-gate mutex_exit(lock); 316*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate qp->msg_qbytes = STRUCT_FGET(ds, msg_qbytes); 319*7c478bd9Sstevel@tonic-gate qp->msg_ctime = gethrestime_sec(); 320*7c478bd9Sstevel@tonic-gate break; 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate case IPC_STAT: 323*7c478bd9Sstevel@tonic-gate if (error = ipcperm_access(&qp->msg_perm, MSG_R, cr)) { 324*7c478bd9Sstevel@tonic-gate mutex_exit(lock); 325*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate if (qp->msg_rcv_cnt) 329*7c478bd9Sstevel@tonic-gate qp->msg_perm.ipc_mode |= MSG_RWAIT; 330*7c478bd9Sstevel@tonic-gate if (qp->msg_snd_cnt) 331*7c478bd9Sstevel@tonic-gate qp->msg_perm.ipc_mode |= MSG_WWAIT; 332*7c478bd9Sstevel@tonic-gate ipcperm_stat(&STRUCT_BUF(ds)->msg_perm, &qp->msg_perm, mdl); 333*7c478bd9Sstevel@tonic-gate qp->msg_perm.ipc_mode &= ~(MSG_RWAIT|MSG_WWAIT); 334*7c478bd9Sstevel@tonic-gate STRUCT_FSETP(ds, msg_first, NULL); /* kernel addr */ 335*7c478bd9Sstevel@tonic-gate STRUCT_FSETP(ds, msg_last, NULL); 336*7c478bd9Sstevel@tonic-gate STRUCT_FSET(ds, msg_cbytes, qp->msg_cbytes); 337*7c478bd9Sstevel@tonic-gate STRUCT_FSET(ds, msg_qnum, qp->msg_qnum); 338*7c478bd9Sstevel@tonic-gate STRUCT_FSET(ds, msg_qbytes, qp->msg_qbytes); 339*7c478bd9Sstevel@tonic-gate STRUCT_FSET(ds, msg_lspid, qp->msg_lspid); 340*7c478bd9Sstevel@tonic-gate STRUCT_FSET(ds, msg_lrpid, qp->msg_lrpid); 341*7c478bd9Sstevel@tonic-gate STRUCT_FSET(ds, msg_stime, qp->msg_stime); 342*7c478bd9Sstevel@tonic-gate STRUCT_FSET(ds, msg_rtime, qp->msg_rtime); 343*7c478bd9Sstevel@tonic-gate STRUCT_FSET(ds, msg_ctime, qp->msg_ctime); 344*7c478bd9Sstevel@tonic-gate break; 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate case IPC_SET64: 347*7c478bd9Sstevel@tonic-gate mutex_enter(&pp->p_lock); 348*7c478bd9Sstevel@tonic-gate if ((ds64.msgx_qbytes > qp->msg_qbytes) && 349*7c478bd9Sstevel@tonic-gate secpolicy_ipc_config(cr) != 0 && 350*7c478bd9Sstevel@tonic-gate rctl_test(rc_process_msgmnb, pp->p_rctls, pp, 351*7c478bd9Sstevel@tonic-gate ds64.msgx_qbytes, RCA_SAFE) & RCT_DENY) { 352*7c478bd9Sstevel@tonic-gate mutex_exit(&pp->p_lock); 353*7c478bd9Sstevel@tonic-gate mutex_exit(lock); 354*7c478bd9Sstevel@tonic-gate return (set_errno(EPERM)); 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate mutex_exit(&pp->p_lock); 357*7c478bd9Sstevel@tonic-gate if (error = ipcperm_set64(msq_svc, cr, &qp->msg_perm, 358*7c478bd9Sstevel@tonic-gate &ds64.msgx_perm)) { 359*7c478bd9Sstevel@tonic-gate mutex_exit(lock); 360*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 361*7c478bd9Sstevel@tonic-gate } 362*7c478bd9Sstevel@tonic-gate qp->msg_qbytes = ds64.msgx_qbytes; 363*7c478bd9Sstevel@tonic-gate qp->msg_ctime = gethrestime_sec(); 364*7c478bd9Sstevel@tonic-gate break; 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate case IPC_STAT64: 367*7c478bd9Sstevel@tonic-gate if (qp->msg_rcv_cnt) 368*7c478bd9Sstevel@tonic-gate qp->msg_perm.ipc_mode |= MSG_RWAIT; 369*7c478bd9Sstevel@tonic-gate if (qp->msg_snd_cnt) 370*7c478bd9Sstevel@tonic-gate qp->msg_perm.ipc_mode |= MSG_WWAIT; 371*7c478bd9Sstevel@tonic-gate ipcperm_stat64(&ds64.msgx_perm, &qp->msg_perm); 372*7c478bd9Sstevel@tonic-gate qp->msg_perm.ipc_mode &= ~(MSG_RWAIT|MSG_WWAIT); 373*7c478bd9Sstevel@tonic-gate ds64.msgx_cbytes = qp->msg_cbytes; 374*7c478bd9Sstevel@tonic-gate ds64.msgx_qnum = qp->msg_qnum; 375*7c478bd9Sstevel@tonic-gate ds64.msgx_qbytes = qp->msg_qbytes; 376*7c478bd9Sstevel@tonic-gate ds64.msgx_lspid = qp->msg_lspid; 377*7c478bd9Sstevel@tonic-gate ds64.msgx_lrpid = qp->msg_lrpid; 378*7c478bd9Sstevel@tonic-gate ds64.msgx_stime = qp->msg_stime; 379*7c478bd9Sstevel@tonic-gate ds64.msgx_rtime = qp->msg_rtime; 380*7c478bd9Sstevel@tonic-gate ds64.msgx_ctime = qp->msg_ctime; 381*7c478bd9Sstevel@tonic-gate break; 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate default: 384*7c478bd9Sstevel@tonic-gate mutex_exit(lock); 385*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate mutex_exit(lock); 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate /* 391*7c478bd9Sstevel@tonic-gate * Do copyout last (after releasing mutex). 392*7c478bd9Sstevel@tonic-gate */ 393*7c478bd9Sstevel@tonic-gate switch (cmd) { 394*7c478bd9Sstevel@tonic-gate case IPC_STAT: 395*7c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(ds), arg, STRUCT_SIZE(ds))) 396*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 397*7c478bd9Sstevel@tonic-gate break; 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate case IPC_STAT64: 400*7c478bd9Sstevel@tonic-gate if (copyout(&ds64, arg, sizeof (struct msqid_ds64))) 401*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 402*7c478bd9Sstevel@tonic-gate break; 403*7c478bd9Sstevel@tonic-gate } 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate return (0); 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate /* 409*7c478bd9Sstevel@tonic-gate * Remove all message queues associated with a given zone. Called by 410*7c478bd9Sstevel@tonic-gate * zone_shutdown when the zone is halted. 411*7c478bd9Sstevel@tonic-gate */ 412*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 413*7c478bd9Sstevel@tonic-gate static void 414*7c478bd9Sstevel@tonic-gate msg_remove_zone(zoneid_t zoneid, void *arg) 415*7c478bd9Sstevel@tonic-gate { 416*7c478bd9Sstevel@tonic-gate ipc_remove_zone(msq_svc, zoneid); 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate /* 420*7c478bd9Sstevel@tonic-gate * msgget system call. 421*7c478bd9Sstevel@tonic-gate */ 422*7c478bd9Sstevel@tonic-gate static int 423*7c478bd9Sstevel@tonic-gate msgget(key_t key, int msgflg) 424*7c478bd9Sstevel@tonic-gate { 425*7c478bd9Sstevel@tonic-gate kmsqid_t *qp; 426*7c478bd9Sstevel@tonic-gate kmutex_t *lock; 427*7c478bd9Sstevel@tonic-gate int id, error; 428*7c478bd9Sstevel@tonic-gate proc_t *pp = curproc; 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate top: 431*7c478bd9Sstevel@tonic-gate if (error = ipc_get(msq_svc, key, msgflg, (kipc_perm_t **)&qp, &lock)) 432*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate if (IPC_FREE(&qp->msg_perm)) { 435*7c478bd9Sstevel@tonic-gate mutex_exit(lock); 436*7c478bd9Sstevel@tonic-gate mutex_exit(&pp->p_lock); 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate list_create(&qp->msg_list, sizeof (struct msg), 439*7c478bd9Sstevel@tonic-gate offsetof(struct msg, msg_node)); 440*7c478bd9Sstevel@tonic-gate qp->msg_qnum = 0; 441*7c478bd9Sstevel@tonic-gate qp->msg_lspid = qp->msg_lrpid = 0; 442*7c478bd9Sstevel@tonic-gate qp->msg_stime = qp->msg_rtime = 0; 443*7c478bd9Sstevel@tonic-gate qp->msg_ctime = gethrestime_sec(); 444*7c478bd9Sstevel@tonic-gate qp->msg_rcv_cnt = qp->msg_snd_cnt = 0; 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate if (error = ipc_commit_begin(msq_svc, key, msgflg, 447*7c478bd9Sstevel@tonic-gate (kipc_perm_t *)qp)) { 448*7c478bd9Sstevel@tonic-gate if (error == EAGAIN) 449*7c478bd9Sstevel@tonic-gate goto top; 450*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 451*7c478bd9Sstevel@tonic-gate } 452*7c478bd9Sstevel@tonic-gate qp->msg_qbytes = rctl_enforced_value(rc_process_msgmnb, 453*7c478bd9Sstevel@tonic-gate pp->p_rctls, pp); 454*7c478bd9Sstevel@tonic-gate qp->msg_qmax = rctl_enforced_value(rc_process_msgtql, 455*7c478bd9Sstevel@tonic-gate pp->p_rctls, pp); 456*7c478bd9Sstevel@tonic-gate lock = ipc_commit_end(msq_svc, &qp->msg_perm); 457*7c478bd9Sstevel@tonic-gate } 458*7c478bd9Sstevel@tonic-gate #ifdef C2_AUDIT 459*7c478bd9Sstevel@tonic-gate if (audit_active) 460*7c478bd9Sstevel@tonic-gate audit_ipcget(AT_IPC_MSG, (void *)qp); 461*7c478bd9Sstevel@tonic-gate #endif 462*7c478bd9Sstevel@tonic-gate id = qp->msg_perm.ipc_id; 463*7c478bd9Sstevel@tonic-gate mutex_exit(lock); 464*7c478bd9Sstevel@tonic-gate return (id); 465*7c478bd9Sstevel@tonic-gate } 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate /* 468*7c478bd9Sstevel@tonic-gate * msgrcv system call. 469*7c478bd9Sstevel@tonic-gate */ 470*7c478bd9Sstevel@tonic-gate static ssize_t 471*7c478bd9Sstevel@tonic-gate msgrcv(int msqid, struct ipcmsgbuf *msgp, size_t msgsz, long msgtyp, int msgflg) 472*7c478bd9Sstevel@tonic-gate { 473*7c478bd9Sstevel@tonic-gate struct msg *mp; /* ptr to msg on q */ 474*7c478bd9Sstevel@tonic-gate struct msg *smp; /* ptr to best msg on q */ 475*7c478bd9Sstevel@tonic-gate kmsqid_t *qp; /* ptr to associated q */ 476*7c478bd9Sstevel@tonic-gate kmutex_t *lock; 477*7c478bd9Sstevel@tonic-gate size_t xtsz; /* transfer byte count */ 478*7c478bd9Sstevel@tonic-gate int error = 0, copyerror = 0; 479*7c478bd9Sstevel@tonic-gate int cvres; 480*7c478bd9Sstevel@tonic-gate STRUCT_HANDLE(ipcmsgbuf, umsgp); 481*7c478bd9Sstevel@tonic-gate model_t mdl = get_udatamodel(); 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, msg, 1); /* bump msg send/rcv count */ 484*7c478bd9Sstevel@tonic-gate STRUCT_SET_HANDLE(umsgp, mdl, msgp); 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate if ((lock = ipc_lookup(msq_svc, msqid, (kipc_perm_t **)&qp)) == NULL) 487*7c478bd9Sstevel@tonic-gate return ((ssize_t)set_errno(EINVAL)); 488*7c478bd9Sstevel@tonic-gate ipc_hold(msq_svc, (kipc_perm_t *)qp); 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate if (error = ipcperm_access(&qp->msg_perm, MSG_R, CRED())) 491*7c478bd9Sstevel@tonic-gate goto msgrcv_out; 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate findmsg: 494*7c478bd9Sstevel@tonic-gate smp = NULL; 495*7c478bd9Sstevel@tonic-gate mp = list_head(&qp->msg_list); 496*7c478bd9Sstevel@tonic-gate if (msgtyp == 0) { 497*7c478bd9Sstevel@tonic-gate smp = mp; 498*7c478bd9Sstevel@tonic-gate } else { 499*7c478bd9Sstevel@tonic-gate for (; mp; mp = list_next(&qp->msg_list, mp)) { 500*7c478bd9Sstevel@tonic-gate if (msgtyp > 0) { 501*7c478bd9Sstevel@tonic-gate if (msgtyp != mp->msg_type) 502*7c478bd9Sstevel@tonic-gate continue; 503*7c478bd9Sstevel@tonic-gate smp = mp; 504*7c478bd9Sstevel@tonic-gate break; 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate if (mp->msg_type <= -msgtyp) { 507*7c478bd9Sstevel@tonic-gate if (smp && smp->msg_type <= mp->msg_type) 508*7c478bd9Sstevel@tonic-gate continue; 509*7c478bd9Sstevel@tonic-gate smp = mp; 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate } 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate if (smp) { 515*7c478bd9Sstevel@tonic-gate /* 516*7c478bd9Sstevel@tonic-gate * Message found. 517*7c478bd9Sstevel@tonic-gate */ 518*7c478bd9Sstevel@tonic-gate if ((smp->msg_flags & MSG_RCVCOPY) == 0) { 519*7c478bd9Sstevel@tonic-gate /* 520*7c478bd9Sstevel@tonic-gate * No one else is copying this message. Copy it. 521*7c478bd9Sstevel@tonic-gate */ 522*7c478bd9Sstevel@tonic-gate if (msgsz < smp->msg_size) { 523*7c478bd9Sstevel@tonic-gate if ((msgflg & MSG_NOERROR) == 0) { 524*7c478bd9Sstevel@tonic-gate error = E2BIG; 525*7c478bd9Sstevel@tonic-gate goto msgrcv_out; 526*7c478bd9Sstevel@tonic-gate } else { 527*7c478bd9Sstevel@tonic-gate xtsz = msgsz; 528*7c478bd9Sstevel@tonic-gate } 529*7c478bd9Sstevel@tonic-gate } else { 530*7c478bd9Sstevel@tonic-gate xtsz = smp->msg_size; 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate /* 534*7c478bd9Sstevel@tonic-gate * Mark message as being copied out. Release mutex 535*7c478bd9Sstevel@tonic-gate * while copying out. 536*7c478bd9Sstevel@tonic-gate */ 537*7c478bd9Sstevel@tonic-gate ASSERT((smp->msg_flags & MSG_RCVCOPY) == 0); 538*7c478bd9Sstevel@tonic-gate smp->msg_flags |= MSG_RCVCOPY; 539*7c478bd9Sstevel@tonic-gate msg_hold(smp); 540*7c478bd9Sstevel@tonic-gate mutex_exit(lock); 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate if (mdl == DATAMODEL_NATIVE) { 543*7c478bd9Sstevel@tonic-gate copyerror = copyout(&smp->msg_type, msgp, 544*7c478bd9Sstevel@tonic-gate sizeof (smp->msg_type)); 545*7c478bd9Sstevel@tonic-gate } else { 546*7c478bd9Sstevel@tonic-gate /* 547*7c478bd9Sstevel@tonic-gate * 32-bit callers need an imploded msg type. 548*7c478bd9Sstevel@tonic-gate */ 549*7c478bd9Sstevel@tonic-gate int32_t msg_type32 = smp->msg_type; 550*7c478bd9Sstevel@tonic-gate 551*7c478bd9Sstevel@tonic-gate copyerror = copyout(&msg_type32, msgp, 552*7c478bd9Sstevel@tonic-gate sizeof (msg_type32)); 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate if (copyerror == 0 && xtsz) 556*7c478bd9Sstevel@tonic-gate copyerror = copyout(smp->msg_addr, 557*7c478bd9Sstevel@tonic-gate STRUCT_FADDR(umsgp, mtext), xtsz); 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate /* 560*7c478bd9Sstevel@tonic-gate * Reclaim mutex, make sure queue still exists, 561*7c478bd9Sstevel@tonic-gate * and remove message. 562*7c478bd9Sstevel@tonic-gate */ 563*7c478bd9Sstevel@tonic-gate lock = ipc_lock(msq_svc, qp->msg_perm.ipc_id); 564*7c478bd9Sstevel@tonic-gate ASSERT(smp->msg_flags & MSG_RCVCOPY); 565*7c478bd9Sstevel@tonic-gate smp->msg_flags &= ~MSG_RCVCOPY; 566*7c478bd9Sstevel@tonic-gate msg_rele(smp); 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate if (IPC_FREE(&qp->msg_perm)) { 569*7c478bd9Sstevel@tonic-gate error = EIDRM; 570*7c478bd9Sstevel@tonic-gate goto msgrcv_out; 571*7c478bd9Sstevel@tonic-gate } 572*7c478bd9Sstevel@tonic-gate cv_broadcast(&qp->msg_rcv_cv); 573*7c478bd9Sstevel@tonic-gate 574*7c478bd9Sstevel@tonic-gate if (copyerror) { 575*7c478bd9Sstevel@tonic-gate error = EFAULT; 576*7c478bd9Sstevel@tonic-gate goto msgrcv_out; 577*7c478bd9Sstevel@tonic-gate } 578*7c478bd9Sstevel@tonic-gate qp->msg_lrpid = ttoproc(curthread)->p_pid; 579*7c478bd9Sstevel@tonic-gate qp->msg_rtime = gethrestime_sec(); 580*7c478bd9Sstevel@tonic-gate msgunlink(qp, smp); 581*7c478bd9Sstevel@tonic-gate goto msgrcv_out; 582*7c478bd9Sstevel@tonic-gate } 583*7c478bd9Sstevel@tonic-gate 584*7c478bd9Sstevel@tonic-gate } else { 585*7c478bd9Sstevel@tonic-gate /* 586*7c478bd9Sstevel@tonic-gate * No message found. 587*7c478bd9Sstevel@tonic-gate */ 588*7c478bd9Sstevel@tonic-gate if (msgflg & IPC_NOWAIT) { 589*7c478bd9Sstevel@tonic-gate error = ENOMSG; 590*7c478bd9Sstevel@tonic-gate goto msgrcv_out; 591*7c478bd9Sstevel@tonic-gate } 592*7c478bd9Sstevel@tonic-gate } 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate /* Wait for new message */ 595*7c478bd9Sstevel@tonic-gate qp->msg_rcv_cnt++; 596*7c478bd9Sstevel@tonic-gate cvres = cv_wait_sig(&qp->msg_rcv_cv, lock); 597*7c478bd9Sstevel@tonic-gate lock = ipc_relock(msq_svc, qp->msg_perm.ipc_id, lock); 598*7c478bd9Sstevel@tonic-gate qp->msg_rcv_cnt--; 599*7c478bd9Sstevel@tonic-gate 600*7c478bd9Sstevel@tonic-gate if (IPC_FREE(&qp->msg_perm)) { 601*7c478bd9Sstevel@tonic-gate error = EIDRM; 602*7c478bd9Sstevel@tonic-gate goto msgrcv_out; 603*7c478bd9Sstevel@tonic-gate } 604*7c478bd9Sstevel@tonic-gate if (cvres == 0) { 605*7c478bd9Sstevel@tonic-gate error = EINTR; 606*7c478bd9Sstevel@tonic-gate goto msgrcv_out; 607*7c478bd9Sstevel@tonic-gate } 608*7c478bd9Sstevel@tonic-gate 609*7c478bd9Sstevel@tonic-gate goto findmsg; 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate msgrcv_out: 612*7c478bd9Sstevel@tonic-gate ipc_rele(msq_svc, (kipc_perm_t *)qp); 613*7c478bd9Sstevel@tonic-gate if (error) 614*7c478bd9Sstevel@tonic-gate return ((ssize_t)set_errno(error)); 615*7c478bd9Sstevel@tonic-gate return ((ssize_t)xtsz); 616*7c478bd9Sstevel@tonic-gate } 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate /* 619*7c478bd9Sstevel@tonic-gate * msgids system call. 620*7c478bd9Sstevel@tonic-gate */ 621*7c478bd9Sstevel@tonic-gate static int 622*7c478bd9Sstevel@tonic-gate msgids(int *buf, uint_t nids, uint_t *pnids) 623*7c478bd9Sstevel@tonic-gate { 624*7c478bd9Sstevel@tonic-gate int error; 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate if (error = ipc_ids(msq_svc, buf, nids, pnids)) 627*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate return (0); 630*7c478bd9Sstevel@tonic-gate } 631*7c478bd9Sstevel@tonic-gate 632*7c478bd9Sstevel@tonic-gate #define RND(x) roundup((x), sizeof (size_t)) 633*7c478bd9Sstevel@tonic-gate #define RND32(x) roundup((x), sizeof (size32_t)) 634*7c478bd9Sstevel@tonic-gate 635*7c478bd9Sstevel@tonic-gate /* 636*7c478bd9Sstevel@tonic-gate * msgsnap system call. 637*7c478bd9Sstevel@tonic-gate */ 638*7c478bd9Sstevel@tonic-gate static int 639*7c478bd9Sstevel@tonic-gate msgsnap(int msqid, caddr_t buf, size_t bufsz, long msgtyp) 640*7c478bd9Sstevel@tonic-gate { 641*7c478bd9Sstevel@tonic-gate struct msg *mp; /* ptr to msg on q */ 642*7c478bd9Sstevel@tonic-gate kmsqid_t *qp; /* ptr to associated q */ 643*7c478bd9Sstevel@tonic-gate kmutex_t *lock; 644*7c478bd9Sstevel@tonic-gate size_t size; 645*7c478bd9Sstevel@tonic-gate size_t nmsg; 646*7c478bd9Sstevel@tonic-gate struct msg **snaplist; 647*7c478bd9Sstevel@tonic-gate int error, i; 648*7c478bd9Sstevel@tonic-gate model_t mdl = get_udatamodel(); 649*7c478bd9Sstevel@tonic-gate STRUCT_DECL(msgsnap_head, head); 650*7c478bd9Sstevel@tonic-gate STRUCT_DECL(msgsnap_mhead, mhead); 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate STRUCT_INIT(head, mdl); 653*7c478bd9Sstevel@tonic-gate STRUCT_INIT(mhead, mdl); 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate if (bufsz < STRUCT_SIZE(head)) 656*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate if ((lock = ipc_lookup(msq_svc, msqid, (kipc_perm_t **)&qp)) == NULL) 659*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate if (error = ipcperm_access(&qp->msg_perm, MSG_R, CRED())) { 662*7c478bd9Sstevel@tonic-gate mutex_exit(lock); 663*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 664*7c478bd9Sstevel@tonic-gate } 665*7c478bd9Sstevel@tonic-gate ipc_hold(msq_svc, (kipc_perm_t *)qp); 666*7c478bd9Sstevel@tonic-gate 667*7c478bd9Sstevel@tonic-gate /* 668*7c478bd9Sstevel@tonic-gate * First compute the required buffer size and 669*7c478bd9Sstevel@tonic-gate * the number of messages on the queue. 670*7c478bd9Sstevel@tonic-gate */ 671*7c478bd9Sstevel@tonic-gate size = nmsg = 0; 672*7c478bd9Sstevel@tonic-gate for (mp = list_head(&qp->msg_list); mp; 673*7c478bd9Sstevel@tonic-gate mp = list_next(&qp->msg_list, mp)) { 674*7c478bd9Sstevel@tonic-gate if (msgtyp == 0 || 675*7c478bd9Sstevel@tonic-gate (msgtyp > 0 && msgtyp == mp->msg_type) || 676*7c478bd9Sstevel@tonic-gate (msgtyp < 0 && mp->msg_type <= -msgtyp)) { 677*7c478bd9Sstevel@tonic-gate nmsg++; 678*7c478bd9Sstevel@tonic-gate if (mdl == DATAMODEL_NATIVE) 679*7c478bd9Sstevel@tonic-gate size += RND(mp->msg_size); 680*7c478bd9Sstevel@tonic-gate else 681*7c478bd9Sstevel@tonic-gate size += RND32(mp->msg_size); 682*7c478bd9Sstevel@tonic-gate } 683*7c478bd9Sstevel@tonic-gate } 684*7c478bd9Sstevel@tonic-gate 685*7c478bd9Sstevel@tonic-gate size += STRUCT_SIZE(head) + nmsg * STRUCT_SIZE(mhead); 686*7c478bd9Sstevel@tonic-gate if (size > bufsz) 687*7c478bd9Sstevel@tonic-gate nmsg = 0; 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate if (nmsg > 0) { 690*7c478bd9Sstevel@tonic-gate /* 691*7c478bd9Sstevel@tonic-gate * Mark the messages as being copied. 692*7c478bd9Sstevel@tonic-gate */ 693*7c478bd9Sstevel@tonic-gate snaplist = (struct msg **)kmem_alloc(nmsg * 694*7c478bd9Sstevel@tonic-gate sizeof (struct msg *), KM_SLEEP); 695*7c478bd9Sstevel@tonic-gate i = 0; 696*7c478bd9Sstevel@tonic-gate for (mp = list_head(&qp->msg_list); mp; 697*7c478bd9Sstevel@tonic-gate mp = list_next(&qp->msg_list, mp)) { 698*7c478bd9Sstevel@tonic-gate if (msgtyp == 0 || 699*7c478bd9Sstevel@tonic-gate (msgtyp > 0 && msgtyp == mp->msg_type) || 700*7c478bd9Sstevel@tonic-gate (msgtyp < 0 && mp->msg_type <= -msgtyp)) { 701*7c478bd9Sstevel@tonic-gate msg_hold(mp); 702*7c478bd9Sstevel@tonic-gate snaplist[i] = mp; 703*7c478bd9Sstevel@tonic-gate i++; 704*7c478bd9Sstevel@tonic-gate } 705*7c478bd9Sstevel@tonic-gate } 706*7c478bd9Sstevel@tonic-gate } 707*7c478bd9Sstevel@tonic-gate mutex_exit(lock); 708*7c478bd9Sstevel@tonic-gate 709*7c478bd9Sstevel@tonic-gate /* 710*7c478bd9Sstevel@tonic-gate * Copy out the buffer header. 711*7c478bd9Sstevel@tonic-gate */ 712*7c478bd9Sstevel@tonic-gate STRUCT_FSET(head, msgsnap_size, size); 713*7c478bd9Sstevel@tonic-gate STRUCT_FSET(head, msgsnap_nmsg, nmsg); 714*7c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(head), buf, STRUCT_SIZE(head))) 715*7c478bd9Sstevel@tonic-gate error = EFAULT; 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate buf += STRUCT_SIZE(head); 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate /* 720*7c478bd9Sstevel@tonic-gate * Now copy out the messages one by one. 721*7c478bd9Sstevel@tonic-gate */ 722*7c478bd9Sstevel@tonic-gate for (i = 0; i < nmsg; i++) { 723*7c478bd9Sstevel@tonic-gate mp = snaplist[i]; 724*7c478bd9Sstevel@tonic-gate if (error == 0) { 725*7c478bd9Sstevel@tonic-gate STRUCT_FSET(mhead, msgsnap_mlen, mp->msg_size); 726*7c478bd9Sstevel@tonic-gate STRUCT_FSET(mhead, msgsnap_mtype, mp->msg_type); 727*7c478bd9Sstevel@tonic-gate if (copyout(STRUCT_BUF(mhead), buf, STRUCT_SIZE(mhead))) 728*7c478bd9Sstevel@tonic-gate error = EFAULT; 729*7c478bd9Sstevel@tonic-gate buf += STRUCT_SIZE(mhead); 730*7c478bd9Sstevel@tonic-gate 731*7c478bd9Sstevel@tonic-gate if (error == 0 && 732*7c478bd9Sstevel@tonic-gate mp->msg_size != 0 && 733*7c478bd9Sstevel@tonic-gate copyout(mp->msg_addr, buf, mp->msg_size)) 734*7c478bd9Sstevel@tonic-gate error = EFAULT; 735*7c478bd9Sstevel@tonic-gate if (mdl == DATAMODEL_NATIVE) 736*7c478bd9Sstevel@tonic-gate buf += RND(mp->msg_size); 737*7c478bd9Sstevel@tonic-gate else 738*7c478bd9Sstevel@tonic-gate buf += RND32(mp->msg_size); 739*7c478bd9Sstevel@tonic-gate } 740*7c478bd9Sstevel@tonic-gate lock = ipc_lock(msq_svc, qp->msg_perm.ipc_id); 741*7c478bd9Sstevel@tonic-gate msg_rele(mp); 742*7c478bd9Sstevel@tonic-gate /* Check for msg q deleted or reallocated */ 743*7c478bd9Sstevel@tonic-gate if (IPC_FREE(&qp->msg_perm)) 744*7c478bd9Sstevel@tonic-gate error = EIDRM; 745*7c478bd9Sstevel@tonic-gate mutex_exit(lock); 746*7c478bd9Sstevel@tonic-gate } 747*7c478bd9Sstevel@tonic-gate 748*7c478bd9Sstevel@tonic-gate (void) ipc_lock(msq_svc, qp->msg_perm.ipc_id); 749*7c478bd9Sstevel@tonic-gate ipc_rele(msq_svc, (kipc_perm_t *)qp); 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate if (nmsg > 0) 752*7c478bd9Sstevel@tonic-gate kmem_free(snaplist, nmsg * sizeof (struct msg *)); 753*7c478bd9Sstevel@tonic-gate 754*7c478bd9Sstevel@tonic-gate if (error) 755*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 756*7c478bd9Sstevel@tonic-gate return (0); 757*7c478bd9Sstevel@tonic-gate } 758*7c478bd9Sstevel@tonic-gate 759*7c478bd9Sstevel@tonic-gate /* 760*7c478bd9Sstevel@tonic-gate * msgsnd system call. 761*7c478bd9Sstevel@tonic-gate */ 762*7c478bd9Sstevel@tonic-gate static int 763*7c478bd9Sstevel@tonic-gate msgsnd(int msqid, struct ipcmsgbuf *msgp, size_t msgsz, int msgflg) 764*7c478bd9Sstevel@tonic-gate { 765*7c478bd9Sstevel@tonic-gate kmsqid_t *qp; 766*7c478bd9Sstevel@tonic-gate kmutex_t *lock; 767*7c478bd9Sstevel@tonic-gate struct msg *mp = NULL; 768*7c478bd9Sstevel@tonic-gate long type; 769*7c478bd9Sstevel@tonic-gate int error = 0; 770*7c478bd9Sstevel@tonic-gate model_t mdl = get_udatamodel(); 771*7c478bd9Sstevel@tonic-gate STRUCT_HANDLE(ipcmsgbuf, umsgp); 772*7c478bd9Sstevel@tonic-gate 773*7c478bd9Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, msg, 1); /* bump msg send/rcv count */ 774*7c478bd9Sstevel@tonic-gate STRUCT_SET_HANDLE(umsgp, mdl, msgp); 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate if (mdl == DATAMODEL_NATIVE) { 777*7c478bd9Sstevel@tonic-gate if (copyin(msgp, &type, sizeof (type))) 778*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 779*7c478bd9Sstevel@tonic-gate } else { 780*7c478bd9Sstevel@tonic-gate int32_t type32; 781*7c478bd9Sstevel@tonic-gate if (copyin(msgp, &type32, sizeof (type32))) 782*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 783*7c478bd9Sstevel@tonic-gate type = type32; 784*7c478bd9Sstevel@tonic-gate } 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate if (type < 1) 787*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 788*7c478bd9Sstevel@tonic-gate 789*7c478bd9Sstevel@tonic-gate if ((lock = ipc_lookup(msq_svc, msqid, (kipc_perm_t **)&qp)) == NULL) 790*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 791*7c478bd9Sstevel@tonic-gate ipc_hold(msq_svc, (kipc_perm_t *)qp); 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate if (msgsz > qp->msg_qbytes) { 794*7c478bd9Sstevel@tonic-gate error = EINVAL; 795*7c478bd9Sstevel@tonic-gate goto msgsnd_out; 796*7c478bd9Sstevel@tonic-gate } 797*7c478bd9Sstevel@tonic-gate 798*7c478bd9Sstevel@tonic-gate if (error = ipcperm_access(&qp->msg_perm, MSG_W, CRED())) 799*7c478bd9Sstevel@tonic-gate goto msgsnd_out; 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate top: 802*7c478bd9Sstevel@tonic-gate /* 803*7c478bd9Sstevel@tonic-gate * Allocate space on q, message header, & buffer space. 804*7c478bd9Sstevel@tonic-gate */ 805*7c478bd9Sstevel@tonic-gate ASSERT(qp->msg_qnum <= qp->msg_qmax); 806*7c478bd9Sstevel@tonic-gate while ((msgsz > qp->msg_qbytes - qp->msg_cbytes) || 807*7c478bd9Sstevel@tonic-gate (qp->msg_qnum == qp->msg_qmax)) { 808*7c478bd9Sstevel@tonic-gate int cvres; 809*7c478bd9Sstevel@tonic-gate 810*7c478bd9Sstevel@tonic-gate if (msgflg & IPC_NOWAIT) { 811*7c478bd9Sstevel@tonic-gate error = EAGAIN; 812*7c478bd9Sstevel@tonic-gate goto msgsnd_out; 813*7c478bd9Sstevel@tonic-gate } 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate qp->msg_snd_cnt++; 816*7c478bd9Sstevel@tonic-gate cvres = cv_wait_sig(&qp->msg_snd_cv, lock); 817*7c478bd9Sstevel@tonic-gate lock = ipc_relock(msq_svc, qp->msg_perm.ipc_id, lock); 818*7c478bd9Sstevel@tonic-gate qp->msg_snd_cnt--; 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate if (IPC_FREE(&qp->msg_perm)) { 821*7c478bd9Sstevel@tonic-gate error = EIDRM; 822*7c478bd9Sstevel@tonic-gate goto msgsnd_out; 823*7c478bd9Sstevel@tonic-gate } 824*7c478bd9Sstevel@tonic-gate 825*7c478bd9Sstevel@tonic-gate if (cvres == 0) { 826*7c478bd9Sstevel@tonic-gate error = EINTR; 827*7c478bd9Sstevel@tonic-gate goto msgsnd_out; 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate } 830*7c478bd9Sstevel@tonic-gate 831*7c478bd9Sstevel@tonic-gate if (mp == NULL) { 832*7c478bd9Sstevel@tonic-gate int failure; 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate mutex_exit(lock); 835*7c478bd9Sstevel@tonic-gate mp = kmem_zalloc(sizeof (struct msg), KM_SLEEP); 836*7c478bd9Sstevel@tonic-gate mp->msg_addr = kmem_zalloc(msgsz, KM_SLEEP); 837*7c478bd9Sstevel@tonic-gate mp->msg_size = msgsz; 838*7c478bd9Sstevel@tonic-gate mp->msg_copycnt = 1; 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate failure = msgsz && (copyin(STRUCT_FADDR(umsgp, mtext), 841*7c478bd9Sstevel@tonic-gate mp->msg_addr, msgsz) == -1); 842*7c478bd9Sstevel@tonic-gate lock = ipc_lock(msq_svc, qp->msg_perm.ipc_id); 843*7c478bd9Sstevel@tonic-gate if (IPC_FREE(&qp->msg_perm)) { 844*7c478bd9Sstevel@tonic-gate error = EIDRM; 845*7c478bd9Sstevel@tonic-gate goto msgsnd_out; 846*7c478bd9Sstevel@tonic-gate } 847*7c478bd9Sstevel@tonic-gate if (failure) { 848*7c478bd9Sstevel@tonic-gate error = EFAULT; 849*7c478bd9Sstevel@tonic-gate goto msgsnd_out; 850*7c478bd9Sstevel@tonic-gate } 851*7c478bd9Sstevel@tonic-gate goto top; 852*7c478bd9Sstevel@tonic-gate } 853*7c478bd9Sstevel@tonic-gate 854*7c478bd9Sstevel@tonic-gate /* 855*7c478bd9Sstevel@tonic-gate * Everything is available, put msg on q. 856*7c478bd9Sstevel@tonic-gate */ 857*7c478bd9Sstevel@tonic-gate qp->msg_qnum++; 858*7c478bd9Sstevel@tonic-gate qp->msg_cbytes += msgsz; 859*7c478bd9Sstevel@tonic-gate qp->msg_lspid = curproc->p_pid; 860*7c478bd9Sstevel@tonic-gate qp->msg_stime = gethrestime_sec(); 861*7c478bd9Sstevel@tonic-gate mp->msg_type = type; 862*7c478bd9Sstevel@tonic-gate mp->msg_flags = 0; 863*7c478bd9Sstevel@tonic-gate list_insert_tail(&qp->msg_list, mp); 864*7c478bd9Sstevel@tonic-gate if (qp->msg_rcv_cnt) 865*7c478bd9Sstevel@tonic-gate cv_broadcast(&qp->msg_rcv_cv); 866*7c478bd9Sstevel@tonic-gate 867*7c478bd9Sstevel@tonic-gate msgsnd_out: 868*7c478bd9Sstevel@tonic-gate ipc_rele(msq_svc, (kipc_perm_t *)qp); /* drops lock */ 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate if (error) { 871*7c478bd9Sstevel@tonic-gate if (mp) 872*7c478bd9Sstevel@tonic-gate msg_rele(mp); 873*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 874*7c478bd9Sstevel@tonic-gate } 875*7c478bd9Sstevel@tonic-gate 876*7c478bd9Sstevel@tonic-gate return (0); 877*7c478bd9Sstevel@tonic-gate } 878*7c478bd9Sstevel@tonic-gate 879*7c478bd9Sstevel@tonic-gate /* 880*7c478bd9Sstevel@tonic-gate * msgsys - System entry point for msgctl, msgget, msgrcv, and msgsnd 881*7c478bd9Sstevel@tonic-gate * system calls. 882*7c478bd9Sstevel@tonic-gate */ 883*7c478bd9Sstevel@tonic-gate static ssize_t 884*7c478bd9Sstevel@tonic-gate msgsys(int opcode, uintptr_t a1, uintptr_t a2, uintptr_t a3, 885*7c478bd9Sstevel@tonic-gate uintptr_t a4, uintptr_t a5) 886*7c478bd9Sstevel@tonic-gate { 887*7c478bd9Sstevel@tonic-gate ssize_t error; 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate switch (opcode) { 890*7c478bd9Sstevel@tonic-gate case MSGGET: 891*7c478bd9Sstevel@tonic-gate error = msgget((key_t)a1, (int)a2); 892*7c478bd9Sstevel@tonic-gate break; 893*7c478bd9Sstevel@tonic-gate case MSGCTL: 894*7c478bd9Sstevel@tonic-gate error = msgctl((int)a1, (int)a2, (void *)a3); 895*7c478bd9Sstevel@tonic-gate break; 896*7c478bd9Sstevel@tonic-gate case MSGRCV: 897*7c478bd9Sstevel@tonic-gate error = msgrcv((int)a1, (struct ipcmsgbuf *)a2, 898*7c478bd9Sstevel@tonic-gate (size_t)a3, (long)a4, (int)a5); 899*7c478bd9Sstevel@tonic-gate break; 900*7c478bd9Sstevel@tonic-gate case MSGSND: 901*7c478bd9Sstevel@tonic-gate error = msgsnd((int)a1, (struct ipcmsgbuf *)a2, 902*7c478bd9Sstevel@tonic-gate (size_t)a3, (int)a4); 903*7c478bd9Sstevel@tonic-gate break; 904*7c478bd9Sstevel@tonic-gate case MSGIDS: 905*7c478bd9Sstevel@tonic-gate error = msgids((int *)a1, (uint_t)a2, (uint_t *)a3); 906*7c478bd9Sstevel@tonic-gate break; 907*7c478bd9Sstevel@tonic-gate case MSGSNAP: 908*7c478bd9Sstevel@tonic-gate error = msgsnap((int)a1, (caddr_t)a2, (size_t)a3, (long)a4); 909*7c478bd9Sstevel@tonic-gate break; 910*7c478bd9Sstevel@tonic-gate default: 911*7c478bd9Sstevel@tonic-gate error = set_errno(EINVAL); 912*7c478bd9Sstevel@tonic-gate break; 913*7c478bd9Sstevel@tonic-gate } 914*7c478bd9Sstevel@tonic-gate 915*7c478bd9Sstevel@tonic-gate return (error); 916*7c478bd9Sstevel@tonic-gate } 917*7c478bd9Sstevel@tonic-gate 918*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 919*7c478bd9Sstevel@tonic-gate /* 920*7c478bd9Sstevel@tonic-gate * msgsys32 - System entry point for msgctl, msgget, msgrcv, and msgsnd 921*7c478bd9Sstevel@tonic-gate * system calls for 32-bit callers on LP64 kernel. 922*7c478bd9Sstevel@tonic-gate */ 923*7c478bd9Sstevel@tonic-gate static ssize32_t 924*7c478bd9Sstevel@tonic-gate msgsys32(int opcode, uint32_t a1, uint32_t a2, uint32_t a3, 925*7c478bd9Sstevel@tonic-gate uint32_t a4, uint32_t a5) 926*7c478bd9Sstevel@tonic-gate { 927*7c478bd9Sstevel@tonic-gate ssize_t error; 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate switch (opcode) { 930*7c478bd9Sstevel@tonic-gate case MSGGET: 931*7c478bd9Sstevel@tonic-gate error = msgget((key_t)a1, (int)a2); 932*7c478bd9Sstevel@tonic-gate break; 933*7c478bd9Sstevel@tonic-gate case MSGCTL: 934*7c478bd9Sstevel@tonic-gate error = msgctl((int)a1, (int)a2, (void *)(uintptr_t)a3); 935*7c478bd9Sstevel@tonic-gate break; 936*7c478bd9Sstevel@tonic-gate case MSGRCV: 937*7c478bd9Sstevel@tonic-gate error = msgrcv((int)a1, (struct ipcmsgbuf *)(uintptr_t)a2, 938*7c478bd9Sstevel@tonic-gate (size_t)a3, (long)(int32_t)a4, (int)a5); 939*7c478bd9Sstevel@tonic-gate break; 940*7c478bd9Sstevel@tonic-gate case MSGSND: 941*7c478bd9Sstevel@tonic-gate error = msgsnd((int)a1, (struct ipcmsgbuf *)(uintptr_t)a2, 942*7c478bd9Sstevel@tonic-gate (size_t)(int32_t)a3, (int)a4); 943*7c478bd9Sstevel@tonic-gate break; 944*7c478bd9Sstevel@tonic-gate case MSGIDS: 945*7c478bd9Sstevel@tonic-gate error = msgids((int *)(uintptr_t)a1, (uint_t)a2, 946*7c478bd9Sstevel@tonic-gate (uint_t *)(uintptr_t)a3); 947*7c478bd9Sstevel@tonic-gate break; 948*7c478bd9Sstevel@tonic-gate case MSGSNAP: 949*7c478bd9Sstevel@tonic-gate error = msgsnap((int)a1, (caddr_t)(uintptr_t)a2, (size_t)a3, 950*7c478bd9Sstevel@tonic-gate (long)(int32_t)a4); 951*7c478bd9Sstevel@tonic-gate break; 952*7c478bd9Sstevel@tonic-gate default: 953*7c478bd9Sstevel@tonic-gate error = set_errno(EINVAL); 954*7c478bd9Sstevel@tonic-gate break; 955*7c478bd9Sstevel@tonic-gate } 956*7c478bd9Sstevel@tonic-gate 957*7c478bd9Sstevel@tonic-gate return (error); 958*7c478bd9Sstevel@tonic-gate } 959*7c478bd9Sstevel@tonic-gate #endif /* SYSCALL32_IMPL */ 960