From 446f7a7f8dce1c0d8c9448f5dcaa29de78ca57f6 Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Wed, 24 Feb 2021 11:45:23 +0100 Subject: [PATCH] Implement accept4 on x86 android with `socketcall` syscall. --- src/unix/linux_like/android/b32/x86/mod.rs | 29 ++++++++++++++++++++++ src/unix/linux_like/android/b64/mod.rs | 16 ++++++++++++ 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 879ea1a174d38..6507cb4e07da3 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 96244d10fe1e6..d761c20ee7b9d 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 09ecdd62f6bad..dfbef65028af6 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" {