diff options
author | bors <bors@rust-lang.org> | 2021-02-27 13:11:19 +0000 |
---|---|---|
committer | bors <bors@rust-lang.org> | 2021-02-27 13:11:19 +0000 |
commit | add972649f03a75255dd2bbc5789a1d501beb2e9 (patch) | |
tree | da012704bd761a1178c48c7dfb276707d16f3160 | |
parent | d8fc4b2d5c282595d814ccf2ff69d44accae6e19 (diff) | |
parent | 31a2777d8f72db9eb3c3105f13afa94a47ca90d5 (diff) | |
download | rust-libc-add972649f03a75255dd2bbc5789a1d501beb2e9.tar.gz |
Auto merge of #2079 - de-vri-es:android-x86-accept4, r=joshtriplett,JohnTitor
Implement accept4 on x86 android with `socketcall` syscall.
Linux x86 kernels before 4.3 only support the `socketcall` syscall rather than individual syscalls for socket operations. Since `libc` does a raw syscall for `accept4` on Android, it doesn't work on x86 systems.
This PR instead implements `accept4` for x86 android using `socketcall`. The value for `SYS_ACCEPT4` (in contrast to `SYS_accept4` :eyes:) is taken from the `linux/net.h` header.
Also note that the `socketcall` syscall takes all arguments as array of long ints. I've double checked with `glibc` to check how they pass arguments, since the Linux man page only says this: "args points to a block containing the actual arguments" and "only standard library implementors and kernel hackers need to know about socketcall()".
This should fix https://github.com/rust-lang/rust/issues/82400
-rw-r--r-- | src/unix/linux_like/android/b32/x86/mod.rs | 29 | ||||
-rw-r--r-- | src/unix/linux_like/android/b64/mod.rs | 16 | ||||
-rw-r--r-- | src/unix/linux_like/android/mod.rs | 14 |
3 files changed, 45 insertions, 14 deletions
diff --git a/src/unix/linux_like/android/b32/x86/mod.rs b/src/unix/linux_like/android/b32/x86/mod.rs index 879ea1a174..6507cb4e07 100644 --- a/src/unix/linux_like/android/b32/x86/mod.rs +++ b/src/unix/linux_like/android/b32/x86/mod.rs @@ -574,6 +574,35 @@ pub const REG_EFL: ::c_int = 16; pub const REG_UESP: ::c_int = 17; pub const REG_SS: ::c_int = 18; +// socketcall values from linux/net.h (only the needed ones, and not public) +const SYS_ACCEPT4: ::c_int = 18; + +f! { + // Sadly, Android before 5.0 (API level 21), the accept4 syscall is not + // exposed by the libc. As work-around, we implement it as raw syscall. + // Note that for x86, the `accept4` syscall is not available either, + // and we must use the `socketcall` syscall instead. + // This workaround can be removed if the minimum Android version is bumped. + // When the workaround is removed, `accept4` can be moved back + // to `linux_like/mod.rs` + pub fn accept4( + fd: ::c_int, + addr: *mut ::sockaddr, + len: *mut ::socklen_t, + flg: ::c_int + ) -> ::c_int { + // Arguments are passed as array of `long int` + // (which is big enough on x86 for a pointer). + let mut args = [ + fd as ::c_long, + addr as ::c_long, + len as ::c_long, + flg as ::c_long, + ]; + ::syscall(SYS_socketcall, SYS_ACCEPT4, args[..].as_mut_ptr()) + } +} + cfg_if! { if #[cfg(libc_align)] { mod align; diff --git a/src/unix/linux_like/android/b64/mod.rs b/src/unix/linux_like/android/b64/mod.rs index 96244d10fe..c23e2dbf2d 100644 --- a/src/unix/linux_like/android/b64/mod.rs +++ b/src/unix/linux_like/android/b64/mod.rs @@ -305,6 +305,22 @@ pub const UT_LINESIZE: usize = 32; pub const UT_NAMESIZE: usize = 32; pub const UT_HOSTSIZE: usize = 256; +f! { + // Sadly, Android before 5.0 (API level 21), the accept4 syscall is not + // exposed by the libc. As work-around, we implement it through `syscall` + // directly. This workaround can be removed if the minimum version of + // Android is bumped. When the workaround is removed, `accept4` can be + // moved back to `linux_like/mod.rs` + pub fn accept4( + fd: ::c_int, + addr: *mut ::sockaddr, + len: *mut ::socklen_t, + flg: ::c_int + ) -> ::c_int { + ::syscall(SYS_accept4, fd, addr, len, flg) as ::c_int + } +} + extern "C" { pub fn getauxval(type_: ::c_ulong) -> ::c_ulong; } diff --git a/src/unix/linux_like/android/mod.rs b/src/unix/linux_like/android/mod.rs index 09ecdd62f6..dfbef65028 100644 --- a/src/unix/linux_like/android/mod.rs +++ b/src/unix/linux_like/android/mod.rs @@ -2350,20 +2350,6 @@ f! { pub fn SO_EE_OFFENDER(ee: *const ::sock_extended_err) -> *mut ::sockaddr { ee.offset(1) as *mut ::sockaddr } - - // Sadly, Android before 5.0 (API level 21), the accept4 syscall is not - // exposed by the libc. As work-around, we implement it through `syscall` - // directly. This workaround can be removed if the minimum version of - // Android is bumped. When the workaround is removed, `accept4` can be - // moved back to `linux_like/mod.rs` - pub fn accept4( - fd: ::c_int, - addr: *mut ::sockaddr, - len: *mut ::socklen_t, - flg: ::c_int - ) -> ::c_int { - syscall(SYS_accept4, fd, addr, len, flg) as ::c_int - } } extern "C" { |