aboutsummaryrefslogtreecommitdiff
path: root/linux-user/syscall.c
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2022-12-12 18:34:16 +0100
committerLaurent Vivier <laurent@vivier.eu>2023-02-03 22:55:12 +0100
commit3f0744f98b07c6fd2ce9d5840726d0915b2ae7c1 (patch)
treef7743dab9c75dae5ce3652284bb1bb0159e1a971 /linux-user/syscall.c
parent27404b6c15c1cddae54e1044c8da815eade109fa (diff)
linux-user: Allow sendmsg() without IOV
Applications do call sendmsg() without any IOV, e.g.: sendmsg(4, {msg_name=NULL, msg_namelen=0, msg_iov=NULL, msg_iovlen=0, msg_control=[{cmsg_len=36, cmsg_level=SOL_ALG, cmsg_type=0x2}], msg_controllen=40, msg_flags=0}, MSG_MORE) = 0 sendmsg(4, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="The quick brown fox jumps over t"..., iov_len=183}], msg_iovlen=1, msg_control=[{cmsg_len=20, cmsg_level=SOL_ALG, cmsg_type=0x3}], msg_controllen=24, msg_flags=0}, 0) = 183 The function do_sendrecvmsg_locked() is used for sndmsg() and recvmsg() and calls lock_iovec() to lock the IOV into memory. For the first sendmsg() above it returns NULL and thus wrongly skips the call the host sendmsg() syscall, which will break the calling application. Fix this issue by: - allowing sendmsg() even with empty IOV - skip recvmsg() if IOV is NULL - skip both if the return code of do_sendrecvmsg_locked() != 0, which indicates some failure like EFAULT on the IOV Tested with the debian "ell" package with hppa guest on x86_64 host. Signed-off-by: Helge Deller <deller@gmx.de> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20221212173416.90590-2-deller@gmx.de> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Diffstat (limited to 'linux-user/syscall.c')
-rw-r--r--linux-user/syscall.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index a0d2beddaa..1e868e9b0e 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -3293,7 +3293,10 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
target_vec, count, send);
if (vec == NULL) {
ret = -host_to_target_errno(errno);
- goto out2;
+ /* allow sending packet without any iov, e.g. with MSG_MORE flag */
+ if (!send || ret) {
+ goto out2;
+ }
}
msg.msg_iovlen = count;
msg.msg_iov = vec;
@@ -3345,7 +3348,9 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
}
out:
- unlock_iovec(vec, target_vec, count, !send);
+ if (vec) {
+ unlock_iovec(vec, target_vec, count, !send);
+ }
out2:
return ret;
}