linux-user getsockopt(fd, SOL_SOCKET, SO_ERROR) returns host errno to target

The SO_ERROR option in getsockopt with SOL_SOCKET returns a pending socket error code. Currently qemu provides the host error code. It appears it should call host_to_target_errno to provide the appropriate target-specific error code.

Specifically, the following patch fixes the problem for me:

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index b9b18a7eaf..a8eae3c4ac 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2767,6 +2767,9 @@ get_timeout:
         if (optname == SO_TYPE) {
             val = host_to_target_sock_type(val);
         }
+        if (level == SOL_SOCKET && optname == SO_ERROR) {
+            val = host_to_target_errno(val);
+        }
         if (len > lv)
             len = lv;
         if (len == 4) {

I noticed this while porting some Rust code to MIPS. Rust's standard library uses SO_ERROR:

https://github.com/rust-lang/rust/blob/734368a200904ef9c21db86c595dc04263c87be0/library/std/src/sys/unix/net.rs#L436

and the value of ECONNREFUSED on MIPS is different from most other CPU architectures. Application code testing for ECONNREFUSED didn't see it, because the code was looking for the target value, and it was getting the host value.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information