From: Warner Losh <imp@bsdimp.com>
To: qemu-devel@nongnu.org
Cc: "Kyle Evans" <kevans@freebsd.org>, "Warner Losh" <imp@bsdimp.com>,
"Stacey Son" <sson@FreeBSD.org>,
"Mikaël Urankar" <mikael.urankar@gmail.com>,
"Kyle Evans" <kevans@FreeBSD.org>,
"Michal Meloun" <mmel@FreeBSD.org>,
"Pierrick Bouvier" <pierrick.bouvier@oss.qualcomm.com>,
"Richard Henderson" <richard.henderson@linaro.org>
Subject: [PULL 20/41] bsd-user: Add os-socket.[ch] sendmsg, recvmsg and cmsg
Date: Thu, 17 Sep 2026 22:24:01 -0600 [thread overview]
Message-ID: <20260918042422.38713-21-imp@bsdimp.com> (raw)
In-Reply-To: <20260918042422.38713-1-imp@bsdimp.com>
Add the first part of FreeBSD socket support: do_sendrecvmsg_locked and
do_sendrecvmsg functions. Also add target_msghdr, target_cmsghdr, and
CMSG macros structures to syscall_defs.h. Add target-to-host and
host-to-target control message conversion functions (t2h_freebsd_cmsg
and h2t_freebsd_cmsg) for sendmsg/recvmsg support, and add os-socket.c
to the FreeBSD build.
Signed-off-by: Stacey Son <sson@FreeBSD.org>
Signed-off-by: Mikaël Urankar <mikael.urankar@gmail.com>
Signed-off-by: Kyle Evans <kevans@FreeBSD.org>
Signed-off-by: Michal Meloun <mmel@FreeBSD.org>
Assisted-by: Claude Opus 4.6 (1M context)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
Acked-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Warner Losh <imp@bsdimp.com>
---
bsd-user/freebsd/meson.build | 3 +-
bsd-user/freebsd/os-socket.c | 239 ++++++++++++++++++++++++++++++++++
bsd-user/freebsd/os-socket.h | 13 +-
bsd-user/freebsd/os-syscall.c | 3 +
4 files changed, 253 insertions(+), 5 deletions(-)
create mode 100644 bsd-user/freebsd/os-socket.c
diff --git a/bsd-user/freebsd/meson.build b/bsd-user/freebsd/meson.build
index 38f2debf7e..83593a1e20 100644
--- a/bsd-user/freebsd/meson.build
+++ b/bsd-user/freebsd/meson.build
@@ -4,8 +4,9 @@ bsd_syscall_nr = custom_target('bsd-syscall-h',
command: [sh, meson.current_source_dir() / 'scripts/syscallhdr.sh', '@INPUT@', '@OUTPUT@', 'FREEBSD'])
bsd_user_ss.add(files(
- 'os-stat.c',
'os-proc.c',
+ 'os-socket.c',
+ 'os-stat.c',
'os-sys.c',
'os-syscall.c'),
bsd_syscall_nr
diff --git a/bsd-user/freebsd/os-socket.c b/bsd-user/freebsd/os-socket.c
new file mode 100644
index 0000000000..9c723d7608
--- /dev/null
+++ b/bsd-user/freebsd/os-socket.c
@@ -0,0 +1,239 @@
+/*
+ * FreeBSD socket related system call helpers
+ *
+ * Copyright (c) 2013 Stacey D. Son
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "qemu.h"
+#include "qemu-os.h"
+
+abi_long t2h_freebsd_cmsg(struct msghdr *msgh,
+ struct target_msghdr *target_msgh);
+abi_long h2t_freebsd_cmsg(struct target_msghdr *target_msgh,
+ struct msghdr *msgh);
+
+abi_long t2h_freebsd_cmsg(struct msghdr *msgh,
+ struct target_msghdr *target_msgh)
+{
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
+ socklen_t msg_controllen;
+ abi_ulong target_cmsg_addr;
+ struct target_cmsghdr *target_cmsg, *target_cmsg_start;
+ socklen_t space = 0;
+
+ msg_controllen = tswap32(target_msgh->msg_controllen);
+ if (msg_controllen < sizeof(struct target_cmsghdr)) {
+ goto the_end;
+ }
+ target_cmsg_addr = tswapal(target_msgh->msg_control);
+ target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
+ target_cmsg_start = target_cmsg;
+ if (!target_cmsg) {
+ return -TARGET_EFAULT;
+ }
+
+ while (cmsg && target_cmsg) {
+ void *data = CMSG_DATA(cmsg);
+ void *target_data = TARGET_CMSG_DATA(target_cmsg);
+ int len = (unsigned char *)(target_cmsg) +
+ tswap32(target_cmsg->cmsg_len) - (unsigned char *)target_data;
+
+ space += CMSG_SPACE(len);
+ if (space > msgh->msg_controllen) {
+ space -= CMSG_SPACE(len);
+ /*
+ * This is a QEMU bug, since we allocated the payload area ourselves
+ * (unlike overflow in host-to-target conversion, which is just the
+ * guest giving us a buffer that's too small). It can't happen for
+ * the payload types we currently support; if it becomes an issue in
+ * future we would need to improve our allocation strategy to
+ * something more intelligent than "twice the size of the target
+ * buffer we're reading from".
+ */
+ gemu_log("Host cmsg overflow\n");
+ break;
+ }
+
+ if (tswap32(target_cmsg->cmsg_level) == TARGET_SOL_SOCKET) {
+ cmsg->cmsg_level = SOL_SOCKET;
+ } else {
+ cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
+ }
+ cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
+ cmsg->cmsg_len = CMSG_LEN(len);
+
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
+ int *fd = (int *)data;
+ int *target_fd = (int *)target_data;
+ int i, numfds = len / sizeof(int);
+
+ for (i = 0; i < numfds; i++) {
+ __get_user(fd[i], target_fd + i);
+ }
+ } else if ((cmsg->cmsg_level == SOL_SOCKET) &&
+ (cmsg->cmsg_type == SCM_TIMESTAMP) &&
+ (len == sizeof(struct target_freebsd_timeval))) {
+ /* copy struct timeval to host */
+ struct timeval *tv = (struct timeval *)data;
+ struct target_freebsd_timeval *target_tv =
+ (struct target_freebsd_timeval *)target_data;
+ __get_user(tv->tv_sec, &target_tv->tv_sec);
+ __get_user(tv->tv_usec, &target_tv->tv_usec);
+ } else {
+ gemu_log("Unsupported target ancillary data: %d/%d\n",
+ cmsg->cmsg_level, cmsg->cmsg_type);
+ memcpy(data, target_data, len);
+ }
+
+ cmsg = CMSG_NXTHDR(msgh, cmsg);
+ target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
+ target_cmsg_start);
+ }
+ unlock_user(target_cmsg_start, target_cmsg_addr, 0);
+the_end:
+ msgh->msg_controllen = space;
+ return 0;
+}
+
+abi_long h2t_freebsd_cmsg(struct target_msghdr *target_msgh,
+ struct msghdr *msgh)
+{
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
+ socklen_t msg_controllen;
+ abi_ulong target_cmsg_addr;
+ struct target_cmsghdr *target_cmsg, *target_cmsg_start;
+ socklen_t space = 0;
+
+ msg_controllen = tswap32(target_msgh->msg_controllen);
+ if (msg_controllen < sizeof(struct target_cmsghdr)) {
+ goto the_end;
+ }
+ target_cmsg_addr = tswapal(target_msgh->msg_control);
+ target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
+ target_cmsg_start = target_cmsg;
+ if (!target_cmsg) {
+ return -TARGET_EFAULT;
+ }
+
+ while (cmsg && target_cmsg) {
+ void *data = CMSG_DATA(cmsg);
+ void *target_data = TARGET_CMSG_DATA(target_cmsg);
+ int len = (unsigned char *)(cmsg) + cmsg->cmsg_len -
+ (unsigned char *)data;
+
+ int tgt_len, tgt_space;
+
+ /*
+ * We never copy a half-header but may copy half-data; this is Linux's
+ * behaviour in put_cmsg(). Note that truncation here is a guest problem
+ * (which we report to the guest via the CTRUNC bit), unlike truncation
+ * in target_to_host_cmsg, which is a QEMU bug.
+ */
+ if (msg_controllen < sizeof(struct target_cmsghdr)) {
+ target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
+ break;
+ }
+
+ if (cmsg->cmsg_level == SOL_SOCKET) {
+ target_cmsg->cmsg_level = tswap32(TARGET_SOL_SOCKET);
+ } else {
+ target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
+ }
+ target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
+
+ /*
+ * Payload types which need a different size of payload on the target
+ * must adjust tgt_len here.
+ */
+ tgt_len = len;
+ switch (cmsg->cmsg_level) {
+ case SOL_SOCKET:
+ switch (cmsg->cmsg_type) {
+ case SCM_TIMESTAMP:
+ tgt_len = sizeof(struct target_freebsd_timeval);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (msg_controllen < TARGET_CMSG_LEN(tgt_len)) {
+ target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
+ tgt_len = msg_controllen - sizeof(struct target_cmsghdr);
+ }
+
+ /*
+ * We must now copy-and-convert len bytes of payload into tgt_len bytes
+ * of destination space. Bear in mind that in both source and
+ * destination we may be dealing with a truncated value!
+ */
+ switch (cmsg->cmsg_level) {
+ case SOL_SOCKET:
+ switch (cmsg->cmsg_type) {
+ case SCM_RIGHTS:
+ {
+ int *fd = (int *)data;
+ int *target_fd = (int *)target_data;
+ int i, numfds = tgt_len / sizeof(int);
+
+ for (i = 0; i < numfds; i++) {
+ __put_user(fd[i], target_fd + i);
+ }
+ break;
+ }
+ case SCM_TIMESTAMP:
+ {
+ struct timeval *tv = (struct timeval *)data;
+ struct target_freebsd_timeval *target_tv =
+ (struct target_freebsd_timeval *)target_data;
+
+ if (len != sizeof(struct timeval) ||
+ tgt_len != sizeof(struct target_freebsd_timeval)) {
+ goto unimplemented;
+ }
+
+ /* copy struct timeval to target */
+ __put_user(tv->tv_sec, &target_tv->tv_sec);
+ __put_user(tv->tv_usec, &target_tv->tv_usec);
+ break;
+ }
+ default:
+ goto unimplemented;
+ }
+ break;
+ default:
+ unimplemented:
+ gemu_log("Unsupported host ancillary data: %d/%d\n",
+ cmsg->cmsg_level, cmsg->cmsg_type);
+ memcpy(target_data, data, MIN(len, tgt_len));
+ if (tgt_len > len) {
+ memset(target_data + len, 0, tgt_len - len);
+ }
+ }
+
+ target_cmsg->cmsg_len = tswap32(TARGET_CMSG_LEN(tgt_len));
+ tgt_space = TARGET_CMSG_SPACE(tgt_len);
+ if (msg_controllen < tgt_space) {
+ tgt_space = msg_controllen;
+ }
+ msg_controllen -= tgt_space;
+ space += tgt_space;
+ cmsg = CMSG_NXTHDR(msgh, cmsg);
+ target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
+ target_cmsg_start);
+ }
+ unlock_user(target_cmsg_start, target_cmsg_addr, space);
+the_end:
+ target_msgh->msg_controllen = tswap32(space);
+ return 0;
+}
diff --git a/bsd-user/freebsd/os-socket.h b/bsd-user/freebsd/os-socket.h
index b0f2498ff7..12e9ec3da8 100644
--- a/bsd-user/freebsd/os-socket.h
+++ b/bsd-user/freebsd/os-socket.h
@@ -19,9 +19,14 @@
ssize_t safe_recvmsg(int s, struct msghdr *msg, int flags);
ssize_t safe_sendmsg(int s, const struct msghdr *msg, int flags);
+abi_long t2h_freebsd_cmsg(struct msghdr *msgh,
+ struct target_msghdr *target_msgh);
+abi_long h2t_freebsd_cmsg(struct target_msghdr *target_msgh,
+ struct msghdr *msgh);
+
/* do_sendrecvmsg_locked() Must return target values and target errnos. */
-static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
- int flags, int send)
+static inline abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
+ int flags, int send)
{
abi_long ret, len;
struct msghdr msg;
@@ -122,8 +127,8 @@ out2:
}
-static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
- int flags, int send)
+static inline abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
+ int flags, int send)
{
abi_long ret;
struct target_msghdr *msgp;
diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c
index 7bc9fedfb7..46fee46336 100644
--- a/bsd-user/freebsd/os-syscall.c
+++ b/bsd-user/freebsd/os-syscall.c
@@ -47,6 +47,7 @@
#include "os-proc.h"
#include "os-signal.h"
#include "os-file.h"
+#include "os-socket.h"
#include "os-misc.h"
/* I/O */
@@ -85,6 +86,8 @@ safe_syscall6(ssize_t, recvfrom, int, fd, void *, buf, size_t, len, int, flags,
struct sockaddr *restrict, from, socklen_t *restrict, fromlen);
safe_syscall6(ssize_t, sendto, int, fd, const void *, buf, size_t, len, int,
flags, const struct sockaddr *, to, socklen_t, tolen);
+safe_syscall3(ssize_t, recvmsg, int, s, struct msghdr *, msg, int, flags);
+safe_syscall3(ssize_t, sendmsg, int, s, const struct msghdr *, msg, int, flags);
/* used in os-proc */
safe_syscall4(pid_t, wait4, pid_t, wpid, int *, status, int, options,
--
2.55.0
next prev parent reply other threads:[~2026-09-18 4:27 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-18 4:23 [PULL 00/41] Misc 2026q2 v4 patches Warner Losh
2026-09-18 4:23 ` [PULL 01/41] bsd-user: Upstream most of the remaining system calls Warner Losh
2026-09-18 4:23 ` [PULL 02/41] bsd-user: Rename cpu_env to env throughout bsd-user Warner Losh
2026-09-18 4:23 ` [PULL 03/41] bsd-user: Fix copy direciton in preadv Warner Losh
2026-09-18 4:23 ` [PULL 04/41] bsd-user: Add bsd-signal.h with sigaction through sigreturn Warner Losh
2026-09-18 4:23 ` [PULL 05/41] bsd-user: Add signal shims sigwait through kill and os-signal.h Warner Losh
2026-09-18 4:23 ` [PULL 06/41] bsd-user: Add signal system call dispatch Warner Losh
2026-09-18 4:23 ` [PULL 07/41] bsd-user: move sys/shm.h lines Warner Losh
2026-09-18 4:23 ` [PULL 08/41] bsd-user: Remove mmap defines Warner Losh
2026-09-18 4:23 ` [PULL 09/41] bsd-user: Use target_suseconds_t Warner Losh
2026-09-18 4:23 ` [PULL 10/41] bsd-user: Move sys/uuid.h defines Warner Losh
2026-09-18 4:23 ` [PULL 11/41] bsd-user: Fix realpathat for FreeBSD 15.0 and newer Warner Losh
2026-09-18 4:23 ` [PULL 12/41] bsd-user: Add os-file.h with chflagsat, close_range, and more Warner Losh
2026-09-18 4:23 ` [PULL 13/41] bsd-user: Add poll, poll2, lseek, pipe, and swap system call shims Warner Losh
2026-09-18 4:23 ` [PULL 14/41] bsd-user: Add FreeBSD socket helpers and sockaddr conversion Warner Losh
2026-09-18 4:23 ` [PULL 15/41] bsd-user: Add bsd-socket.h with bind through getsockname Warner Losh
2026-09-18 4:23 ` [PULL 16/41] bsd-user: Add socket shims socketpair through shutdown Warner Losh
2026-09-18 4:23 ` [PULL 17/41] bsd-user: Commit the generated os-sockopt.h files Warner Losh
2026-09-18 4:23 ` [PULL 18/41] bsd-user: Implement both getsockopt and setsockopt Warner Losh
2026-09-18 4:24 ` [PULL 19/41] bsd-user: Add FreeBSD socket system calls Warner Losh
2026-09-18 4:24 ` Warner Losh [this message]
2026-09-18 4:24 ` [PULL 21/41] bsd-user: Add socket system call dispatch Warner Losh
2026-09-18 4:24 ` [PULL 22/41] bsd-user: Add os-time.h with clock and time-of-day functions Warner Losh
2026-09-18 4:24 ` [PULL 23/41] bsd-user: Add utimes, futimes, and ktimer functions to os-time.h Warner Losh
2026-09-18 4:24 ` [PULL 24/41] bsd-user: Add select, pselect, and ppoll " Warner Losh
2026-09-18 4:24 ` [PULL 25/41] bsd-user: Add kqueue and kevent functions " Warner Losh
2026-09-18 4:24 ` [PULL 26/41] bsd-user: Add sigtimedwait, itimer, and futimens " Warner Losh
2026-09-18 4:24 ` [PULL 27/41] bsd-user: Add os-time.c and time-related type definitions Warner Losh
2026-09-18 4:24 ` [PULL 28/41] bsd-user: Add time system call dispatch Warner Losh
2026-09-18 4:24 ` [PULL 29/41] bsd-user: Add cpu_copy and make init_task_state non-static Warner Losh
2026-09-18 4:24 ` [PULL 30/41] bsd-user: Add os-thread.h with thr and context functions Warner Losh
2026-09-18 4:24 ` [PULL 31/41] bsd-user: Add do_freebsd__umtx_op to os-thread.h Warner Losh
2026-09-18 4:24 ` [PULL 32/41] bsd-user: Add thread system call dispatch Warner Losh
2026-09-18 4:24 ` [PULL 33/41] bsd-user: Add os-extattr.h with file and fd extattr functions Warner Losh
2026-09-18 4:24 ` [PULL 34/41] bsd-user: Add link and list extattr functions to os-extattr.h Warner Losh
2026-09-18 4:24 ` [PULL 35/41] bsd-user: Add ACL system call shims " Warner Losh
2026-09-18 4:24 ` [PULL 36/41] bsd-user: Add os-extattr.c with ACL conversion functions Warner Losh
2026-09-18 4:24 ` [PULL 37/41] bsd-user: Add extended attribute and ACL system call dispatch Warner Losh
2026-09-18 4:24 ` [PULL 38/41] bsd-user: Add scheduler and cpuset functions to os-misc.h Warner Losh
2026-09-18 4:24 ` [PULL 39/41] bsd-user: Add scheduler, cpuset, kmod, and misc syscall dispatch Warner Losh
2026-09-18 4:24 ` [PULL 40/41] bsd-user: Move qemu_guest_random_seed_main to same as linux-user Warner Losh
2026-09-18 4:24 ` [PULL 41/41] bsd-user Update random_seed on thread creation Warner Losh
2026-09-18 19:19 ` [PULL 00/41] Misc 2026q2 v4 patches Richard Henderson
2026-09-19 16:49 ` Warner Losh
-- strict thread matches above, loose matches on Subject: below --
2026-09-19 16:47 Warner Losh
2026-09-19 16:47 ` [PULL 20/41] bsd-user: Add os-socket.[ch] sendmsg, recvmsg and cmsg Warner Losh
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260918042422.38713-21-imp@bsdimp.com \
--to=imp@bsdimp.com \
--cc=kevans@freebsd.org \
--cc=mikael.urankar@gmail.com \
--cc=mmel@FreeBSD.org \
--cc=pierrick.bouvier@oss.qualcomm.com \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=sson@FreeBSD.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.