XXX msgp is actually mtext. */
| 1136 | #endif |
| 1137 | /* XXX msgp is actually mtext. */ |
| 1138 | int |
| 1139 | kern_msgrcv(struct thread *td, int msqid, void *msgp, size_t msgsz, long msgtyp, |
| 1140 | int msgflg, long *mtype) |
| 1141 | { |
| 1142 | size_t len; |
| 1143 | struct msqid_kernel *msqkptr; |
| 1144 | struct msg *msghdr; |
| 1145 | struct prison *rpr; |
| 1146 | int msqix, error = 0; |
| 1147 | short next; |
| 1148 | |
| 1149 | rpr = msg_find_prison(td->td_ucred); |
| 1150 | if (rpr == NULL) |
| 1151 | return (ENOSYS); |
| 1152 | |
| 1153 | AUDIT_ARG_SVIPC_ID(msqid); |
| 1154 | msqix = IPCID_TO_IX(msqid); |
| 1155 | |
| 1156 | if (msqix < 0 || msqix >= msginfo.msgmni) { |
| 1157 | DPRINTF(("msqid (%d) out of range (0<=msqid<%d)\n", msqix, |
| 1158 | msginfo.msgmni)); |
| 1159 | return (EINVAL); |
| 1160 | } |
| 1161 | |
| 1162 | msqkptr = &msqids[msqix]; |
| 1163 | mtx_lock(&msq_mtx); |
| 1164 | AUDIT_ARG_SVIPC_PERM(&msqkptr->u.msg_perm); |
| 1165 | if (msqkptr->u.msg_qbytes == 0) { |
| 1166 | DPRINTF(("no such message queue id\n")); |
| 1167 | error = EINVAL; |
| 1168 | goto done2; |
| 1169 | } |
| 1170 | if (msqkptr->u.msg_perm.seq != IPCID_TO_SEQ(msqid)) { |
| 1171 | DPRINTF(("wrong sequence number\n")); |
| 1172 | error = EINVAL; |
| 1173 | goto done2; |
| 1174 | } |
| 1175 | |
| 1176 | if ((error = msq_prison_cansee(rpr, msqkptr))) { |
| 1177 | DPRINTF(("requester can't see prison\n")); |
| 1178 | goto done2; |
| 1179 | } |
| 1180 | |
| 1181 | if ((error = ipcperm(td, &msqkptr->u.msg_perm, IPC_R))) { |
| 1182 | DPRINTF(("requester doesn't have read access\n")); |
| 1183 | goto done2; |
| 1184 | } |
| 1185 | |
| 1186 | #ifdef MAC |
| 1187 | error = mac_sysvmsq_check_msqrcv(td->td_ucred, msqkptr); |
| 1188 | if (error != 0) |
| 1189 | goto done2; |
| 1190 | #endif |
| 1191 | |
| 1192 | msghdr = NULL; |
| 1193 | while (msghdr == NULL) { |
| 1194 | if (msgtyp == 0) { |
| 1195 | msghdr = msqkptr->u.__msg_first; |
no test coverage detected