summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-02-27 13:11:19 +0000
committerbors <bors@rust-lang.org>2021-02-27 13:11:19 +0000
commit31a2777d8f72db9eb3c3105f13afa94a47ca90d5 (patch)
treee7e9d09e62d96d33fa16d4aecfca6bfdb510d63e /src
parentec101fadd69ab081e33132f3f295cd02d6b2bc39 (diff)
downloadrust-libc-31a2777d8f72db9eb3c3105f13afa94a47ca90d5.tar.gz
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
Diffstat (limited to 'src')
-rw-r--r--src/unix/linux_like/android/b32/x86/mod.rs29
-rw-r--r--src/unix/linux_like/android/b64/mod.rs16
-rw-r--r--src/unix/linux_like/android/mod.rs14
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" {