Message ID | 20230708054249.10245-3-deller@gmx.de |
---|---|
State | New |
Headers | show |
Series | linux-user: Fix fcntl64() and accept4() for 32-bit targets | expand |
On 7/8/23 06:42, Helge Deller wrote: > The Linux accept4() syscall allows two flags only: SOCK_NONBLOCK and > SOCK_CLOEXEC, and returns -EINVAL if any other bits have been set. > > Change the qemu implementation accordingly, which means we can not use > the fcntl_flags_tbl[] translation table which allows too many other > values. > > Beside the correction in behaviour, this actually fixes the accept4() > emulation for hppa, mips and alpha targets for which SOCK_NONBLOCK is > different than TARGET_SOCK_NONBLOCK (aka O_NONBLOCK). > > The fix can be verified with the testcase of the debian lwt package, > which hangs forever in a read() syscall without this patch. > > Signed-off-by: Helge Deller<deller@gmx.de> > --- > linux-user/syscall.c | 12 +++++++++++- > 1 file changed, 11 insertions(+), 1 deletion(-) Reviewed-by: Richard Henderson <richard.henderson@linaro.org> r~
08.07.2023 08:42, Helge Deller wrote: > The Linux accept4() syscall allows two flags only: SOCK_NONBLOCK and > SOCK_CLOEXEC, and returns -EINVAL if any other bits have been set. > > Change the qemu implementation accordingly, which means we can not use > the fcntl_flags_tbl[] translation table which allows too many other > values. > > Beside the correction in behaviour, this actually fixes the accept4() > emulation for hppa, mips and alpha targets for which SOCK_NONBLOCK is > different than TARGET_SOCK_NONBLOCK (aka O_NONBLOCK). > > The fix can be verified with the testcase of the debian lwt package, > which hangs forever in a read() syscall without this patch. This smells like -stable material too. Queued this one. Thanks, /mjt
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 10f05b1e55..9b9e3bd5e3 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3440,7 +3440,17 @@ static abi_long do_accept4(int fd, abi_ulong target_addr, abi_long ret; int host_flags; - host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl); + if (flags & ~(TARGET_SOCK_CLOEXEC | TARGET_SOCK_NONBLOCK)) { + return -TARGET_EINVAL; + } + + host_flags = 0; + if (flags & TARGET_SOCK_NONBLOCK) { + host_flags |= SOCK_NONBLOCK; + } + if (flags & TARGET_SOCK_CLOEXEC) { + host_flags |= SOCK_CLOEXEC; + } if (target_addr == 0) { return get_errno(safe_accept4(fd, NULL, NULL, host_flags));
The Linux accept4() syscall allows two flags only: SOCK_NONBLOCK and SOCK_CLOEXEC, and returns -EINVAL if any other bits have been set. Change the qemu implementation accordingly, which means we can not use the fcntl_flags_tbl[] translation table which allows too many other values. Beside the correction in behaviour, this actually fixes the accept4() emulation for hppa, mips and alpha targets for which SOCK_NONBLOCK is different than TARGET_SOCK_NONBLOCK (aka O_NONBLOCK). The fix can be verified with the testcase of the debian lwt package, which hangs forever in a read() syscall without this patch. Signed-off-by: Helge Deller <deller@gmx.de> --- linux-user/syscall.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) -- 2.41.0