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` 👀) 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
This commit is contained in:
commit
add972649f
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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" {
|
||||
|
|
Loading…
Reference in New Issue