@samitouri / QOSamiQemu / commits / bc903963bf

bsd-user: Add message queue implementations

Add implementations for: - msgsnd(2): Send message to queue with size validation - msgget(2): Get message queue identifier - msgrcv(2): Receive message from queue with size validation Signed-off-by: Stacey Son <sson@FreeBSD.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Warner Losh <imp@bsdimp.com>

Stacey Son committed Feb 2, 2026 at 16:46 UTC bc903963bffbc63931d87f5e8bb98ea335d7dd3a
1 file changed +97
bsd-user/bsd-misc.h
+97
@@ -17,6 +17,8 @@
17
18 #include "qemu-bsd.h"
19
20 +static int bsd_msgmax;
21 +
22 /* quotactl(2) */
23 static inline abi_long do_bsd_quotactl(abi_ulong path, abi_long cmd,
24 __unused abi_ulong target_addr)
@@ -260,6 +262,101 @@ static inline abi_long do_bsd_msgctl(int msgid, int target_cmd, abi_long ptr)
262 return ret;
263 }
264
265 +struct kern_mymsg {
266 + long mtype;
267 + char mtext[1];
268 +};
269 +
270 +static inline abi_long bsd_validate_msgsz(abi_ulong msgsz)
271 +{
272 + /* Fetch msgmax the first time we need it. */
273 + if (bsd_msgmax == 0) {
274 + size_t len = sizeof(bsd_msgmax);
275 +
276 + if (sysctlbyname("kern.ipc.msgmax", &bsd_msgmax, &len, NULL, 0) == -1) {
277 + return -TARGET_EINVAL;
278 + }
279 + }
280 +
281 + if (msgsz > bsd_msgmax) {
282 + return -TARGET_EINVAL;
283 + }
284 + return 0;
285 +}
286 +
287 +/* msgsnd(2) */
288 +static inline abi_long do_bsd_msgsnd(int msqid, abi_long msgp,
289 + abi_ulong msgsz, int msgflg)
290 +{
291 + struct target_msgbuf *target_mb;
292 + struct kern_mymsg *host_mb;
293 + abi_long ret;
294 +
295 + ret = bsd_validate_msgsz(msgsz);
296 + if (is_error(ret)) {
297 + return ret;
298 + }
299 + if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0)) {
300 + return -TARGET_EFAULT;
301 + }
302 + host_mb = g_malloc(msgsz + sizeof(long));
303 + host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
304 + memcpy(host_mb->mtext, target_mb->mtext, msgsz);
305 + ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
306 + g_free(host_mb);
307 + unlock_user_struct(target_mb, msgp, 0);
308 +
309 + return ret;
310 +}
311 +
312 +/* msgget(2) */
313 +static inline abi_long do_bsd_msgget(abi_long key, abi_long msgflag)
314 +{
315 + abi_long ret;
316 +
317 + ret = get_errno(msgget(key, msgflag));
318 + return ret;
319 +}
320 +
321 +/* msgrcv(2) */
322 +static inline abi_long do_bsd_msgrcv(int msqid, abi_long msgp,
323 + abi_ulong msgsz, abi_long msgtyp, int msgflg)
324 +{
325 + struct target_msgbuf *target_mb = NULL;
326 + char *target_mtext;
327 + struct kern_mymsg *host_mb;
328 + abi_long ret = 0;
329 +
330 + ret = bsd_validate_msgsz(msgsz);
331 + if (is_error(ret)) {
332 + return ret;
333 + }
334 + if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0)) {
335 + return -TARGET_EFAULT;
336 + }
337 + host_mb = g_malloc(msgsz + sizeof(long));
338 + ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapal(msgtyp), msgflg));
339 + if (ret > 0) {
340 + abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
341 + target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
342 + if (target_mtext == NULL) {
343 + ret = -TARGET_EFAULT;
344 + goto end;
345 + }
346 + memcpy(target_mb->mtext, host_mb->mtext, ret);
347 + unlock_user(target_mtext, target_mtext_addr, ret);
348 + }
349 + if (!is_error(ret)) {
350 + target_mb->mtype = tswapal(host_mb->mtype);
351 + }
352 +end:
353 + if (target_mb != NULL) {
354 + unlock_user_struct(target_mb, msgp, 1);
355 + }
356 + g_free(host_mb);
357 + return ret;
358 +}
359 +
360 /* getdtablesize(2) */
361 static inline abi_long do_bsd_getdtablesize(void)
362 {