Fix MIPS socket option (SO_*) values

linux_mips_socket_options used generic/incorrect values. MIPS has its own
SO_* numbering (arch/mips/include/uapi/asm/socket.h) with the buffer/timeout/
type options in the 0x1000 range. The table listed SO_SNDBUF=0x01,
SO_RCVBUF=0x02 (should be 0x1001/0x1002), SO_SND/RCVLOWAT and SO_SND/RCVTIMEO_OLD
all wrong, SO_RCVLOWAT=0x04 silently collided with SO_REUSEADDR (Enum alias),
and SO_OOBINLINE/SO_REUSEPORT were 0x00.

A guest setsockopt(SOL_SOCKET, SO_RCVBUF, ...) (e.g. busybox ping) therefore
raised 'Could not convert emulated socket option 4098'. Correct all values to
the MIPS uapi and add the missing SO_TYPE/SO_ERROR/SO_ACCEPTCONN/SO_PROTOCOL/
SO_DOMAIN.

Add test_elf.ELFTest.test_setsockopt_mips_so_rcvbuf: opens a socket on a MIPS
guest and asserts setsockopt(SOL_SOCKET, SO_RCVBUF) succeeds. Self-contained,
runs on stock unicorn; fails on dev, passes with the fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
retrocpugeek
2026-06-25 22:38:50 +10:00
co-authored by Claude Opus 4.8
parent a42fb28579
commit 9e21eb9d66
2 changed files with 53 additions and 18 deletions
+26 -18
View File
@@ -380,24 +380,32 @@ class linux_mips_socket_level(Enum):
# https://docs.huihoo.com/doxygen/linux/kernel/3.7/arch_2mips_2include_2uapi_2asm_2socket_8h_source.html
# https://github.com/torvalds/linux/blob/master/arch/mips/include/uapi/asm/socket.h
class linux_mips_socket_options(Enum):
SO_DEBUG = 0x01
SO_REUSEADDR = 0x04
SO_KEEPALIVE = 0x08
SO_DONTROUTE = 0x10
SO_BINDTODEVICE = 0x19
SO_BROADCAST = 0x20
SO_LINGER = 0x80
SO_OOBINLINE = 0x00
SO_REUSEPORT = 0x00
SO_SNDBUF = 0x01
SO_RCVBUF = 0x02
SO_SNDLOWAT = 0x03
SO_RCVLOWAT = 0x04
SO_SNDTIMEO_OLD = 0x05
SO_RCVTIMEO_OLD = 0x06
SO_TIMESTAMP_OLD = 0x1d
# SO_TIMESTAMPNS_OLD = 0x23
# SO_TIMESTAMPING_OLD = 0x25
# MIPS uses its own SO_* numbering (arch/mips/include/uapi/asm/socket.h);
# the buffer/timeout/type options live in the 0x1000 range, unlike the
# generic asm-generic values.
SO_DEBUG = 0x0001
SO_REUSEADDR = 0x0004
SO_KEEPALIVE = 0x0008
SO_DONTROUTE = 0x0010
SO_BINDTODEVICE = 0x0019
SO_BROADCAST = 0x0020
SO_LINGER = 0x0080
SO_OOBINLINE = 0x0100
SO_REUSEPORT = 0x0200
SO_TYPE = 0x1008
SO_ERROR = 0x1007
SO_SNDBUF = 0x1001
SO_RCVBUF = 0x1002
SO_SNDLOWAT = 0x1003
SO_RCVLOWAT = 0x1004
SO_SNDTIMEO_OLD = 0x1005
SO_RCVTIMEO_OLD = 0x1006
SO_ACCEPTCONN = 0x1009
SO_PROTOCOL = 0x1028
SO_DOMAIN = 0x1029
SO_TIMESTAMP_OLD = 0x001d
# SO_TIMESTAMPNS_OLD = 0x0023
# SO_TIMESTAMPING_OLD = 0x0025
SO_TIMESTAMP_NEW = 0x3f
SO_TIMESTAMPNS_NEW = 0x40
SO_TIMESTAMPING_NEW = 0x41
+27
View File
@@ -404,6 +404,33 @@ class ELFTest(unittest.TestCase):
ql.run()
del ql
def test_setsockopt_mips_so_rcvbuf(self):
# MIPS uses its own SO_* numbering (SO_RCVBUF = 0x1002, not the generic
# 0x08). The MIPS socket-option table had the wrong values, so e.g.
# busybox ping's setsockopt(SOL_SOCKET, SO_RCVBUF, ...) raised
# NotImplementedError ("Could not convert emulated socket option 4098").
from qiling.const import QL_ENDIAN
from qiling.os.posix.syscall.socket import ql_syscall_socket, ql_syscall_setsockopt
ql = Qiling(code=b"\x00\x00\x00\x00", archtype=QL_ARCH.MIPS, ostype=QL_OS.LINUX,
endian=QL_ENDIAN.EB, rootfs="../examples/rootfs/mips32_linux",
verbose=QL_VERBOSE.OFF)
AF_INET, SOCK_DGRAM = 2, 2
SOL_SOCKET, SO_RCVBUF = 0xffff, 0x1002 # MIPS values
fd = ql_syscall_socket(ql, AF_INET, SOCK_DGRAM, 0)
self.assertGreaterEqual(fd, 0)
base = 0x100000
ql.mem.map(base, 0x1000)
ql.mem.write_ptr(base, 16384, 4) # requested SO_RCVBUF size
# must map SO_RCVBUF (0x1002) to the host option and succeed, not raise
self.assertEqual(ql_syscall_setsockopt(ql, fd, SOL_SOCKET, SO_RCVBUF, base, 4), 0)
del ql
def test_elf_linux_arm_static(self):
ql = Qiling(["../examples/rootfs/arm_linux/bin/arm_hello_static"], "../examples/rootfs/arm_linux", verbose=QL_VERBOSE.DEFAULT)
all_mem = ql.mem.save()