Description
Starting with Android Oreo (8), Android started using a seccomp based filter approach to syscalls, explicitly allowing syscalls, see https://android-developers.googleblog.com/2017/07/seccomp-filter-in-android-o.html.
https://android.googlesource.com/platform/bionic.git/+/master/libc/SYSCALLS.TXT enumerates the allowed syscalls.
This means, that dispatching a generic syscall mechanism as introduced with this PR #78572 will result in a panic.
On top of that, I found that older versions of Android, such as Android 6, will return Function not implemented (os error 38)
for this syscall.
My tests showed that this only happens on x86, although I can't explain why.
As there's no way to detect the target android API level, the safest way would probably be to always use the accept
syscall, and remove the special handling of the accept4
syscall. This could also be just guarded for x86 -- but would be happy to get an explanation on why it's only on that architecture (see tokio-rs/mio#1446).
I have tested this with both real devices as well as Android emulators.
Code
I tried this code:
use std::net::TcpListener;
let listener = TcpListener::bind("0.0.0.0:8080").unwrap();
match listener.accept() {
Ok((_socket, addr)) => println!("new client: {:?}", addr),
Err(e) => println!("couldn't get client: {:?}", e),
}
and poked it with telnet <android_host> 8080
.
I expected to see this happen: accept
returns Ok(_)
Instead, this happened:
- Android >= 8.0: panic because of seccomp
02-22 13:14:23.287 6015 6041 F my.app.DEBUG: Build fingerprint: 'Android/sdk_phone_x86/generic_x86:10/QPP6.190730.005.B1/5775370:userdebug/test-keys'
02-22 13:14:23.287 6015 6041 F my.app.DEBUG: Revision: '0'
02-22 13:14:23.287 6015 6041 F my.app.DEBUG: ABI: 'x86'
02-22 13:14:23.288 6015 6041 F my.app.DEBUG: Timestamp: 2021-02-22 13:14:23+0000
02-22 13:14:23.288 6015 6041 F my.app.DEBUG: pid: 6015, tid: 6057, name: tokio-runtime-w >>> my.app:background_services <<<
02-22 13:14:23.288 6015 6041 F my.app.DEBUG: uid: 10103
02-22 13:14:23.288 6015 6041 F my.app.DEBUG: signal 31 (SIGSYS), code 1 (SYS_SECCOMP), fault addr --------
02-22 13:14:23.288 6015 6041 F my.app.DEBUG: Cause: seccomp prevented call to disallowed x86 system call 364
02-22 13:14:23.289 6015 6041 F my.app.DEBUG: Abort message: 'Fatal signal 31 (SIGSYS), code 1 (SYS_SECCOMP) in tid 4784 (tokio-runtime-w), pid 4735 (ground_services)'
02-22 13:14:23.289 6015 6041 F my.app.DEBUG: eax 0000016c ebx 0000003f ecx bfccfdb0 edx bfccfd6c
02-22 13:14:23.289 6015 6041 F my.app.DEBUG: edi eae65c34 esi 00080000
02-22 13:14:23.289 6015 6041 F my.app.DEBUG: ebp bfccfd88 esp bfccfd18 eip ee70cad9
- Android < 8.0: strace output
[pid 10918] syscall_364(0x34, 0x9d5c9cf8, 0x9d5c9ca0, 0x80800, 0x9fda9dc8, 0x9fda9dc8 <unfinished ...>
[pid 10918] <... syscall_364 resumed> ) = -1 (errno 38)
Which translate to Function not implemented.
Version it worked on
It most recently worked on: Rust 1.48
Version with regression
rustc --version --verbose
:
rustc --version --verbose
rustc 1.49.0 (e1884a8e3 2020-12-29)
binary: rustc
commit-hash: e1884a8e3c3e813aada8254edfa120e85bf5ffca
commit-date: 2020-12-29
host: x86_64-unknown-linux-gnu
release: 1.49.0
Backtrace
Backtrace
<backtrace>
Activity
nagisa commentedon Feb 22, 2021
Is the x86 thing an emulator? From the strace output it would seem that an entirely wrong syscall is being invoked.
Can this issue reproduce if you call
accept4
from C? If so, consider reporting a bug against Android as well.wngr commentedon Feb 22, 2021
Happens both on an Emulator and a real x86 device (Zebra ET50).
I will try to whip up a minimal reproducer using the socket4 API.
Edit:
This works fine on my linux machine, but running it on an Android API 23 x86 emulator yields:
This also fails when using the generic syscall with errno 38:
Seems my guess on why that started happening is wrong; now I wonder why that ever worked .. 😕
Just for reference:
apiraino commentedon Feb 24, 2021
@de-vri-es and @rustbot ping libs
any insights to share about this?
rustbot commentedon Feb 24, 2021
Error: This team (
libs
) cannot be pinged via this command; it may need to be added totriagebot.toml
on the master branch.Please let
@rust-lang/release
know if you're having trouble with this bot.de-vri-es commentedon Feb 24, 2021
Hmm, maybe this has something to do with it: https://android.googlesource.com/platform/bionic.git/+/master/libc/SYSCALLS.TXT#264
I've never heard of the "socketcall syscall" before, but apparently, on x86 Linux (before 4.3), you have to call
socketcall(SYS_ACCEPT4, &args)
.A bit annoying, because there is no documentation on what args should be. It "points to a block containing the actual arguments". The Linux man page specifically says this:
Linux 4.3 also added the regular syscalls for x86, but that's not something we can rely on for the android target :(
So I think there are two options:
socketcall
correctly for x86 Android inlibc
.de-vri-es commentedon Feb 24, 2021
Note: although the same weird syscall is required for Linux < 4.3 (which is still a tier 1 platform), it shouldn't affect the Linux target because there rust libc is just calling
accept4
. from the real libc.joshtriplett commentedon Feb 24, 2021
It would be nice if Android's seccomp filter allowed the direct syscalls on x86 too, not just on arm; that'd be worth trying to get added to Android.
But in the meantime, it looks like Android targets on 32-bit x86 will need to invoke
socketcall
for all socket syscalls, rather than making the syscalls directly.de-vri-es commentedon Feb 24, 2021
It may not be the seccomp filter though. Older x86 kernels really do not have the accept4 syscall.
Anyway, I'm working on a PR for libc to switch to
socketcall
on x86 android.socketcall
syscall. rust-lang/libc#207924 remaining items
de-vri-es commentedon Mar 1, 2021
Since the
libc
PR is merged, andstd
now useslibc::accept4
, all that is left to fix this on the main branch is to have alibc
version bump (and a matching bump of thelibc
dependency forstd
).Is that going to be on time for 1.49.0, or should someone be pinged to ask for a
libc
release?Auto merge of #2092 - JohnTitor:version-bump, r=JohnTitor
Auto merge of #2092 - JohnTitor:version-bump, r=JohnTitor
Auto merge of #2092 - JohnTitor:version-bump, r=JohnTitor
JohnTitor commentedon Mar 3, 2021
@de-vri-es Released libc 0.2.87, you can now update the
libc
dependency :)de-vri-es commentedon Mar 3, 2021
Thanks! Opened #82731 :)
Auto merge of rust-lang#82476 - de-vri-es:beta-android-x86-accept4, r…
Rollup merge of rust-lang#82731 - de-vri-es:bump-libc-for-std, r=Mark…
Rollup merge of rust-lang#82731 - de-vri-es:bump-libc-for-std, r=Mark…
fix: accepting incoming tcp connection x86 Android
recvmmsg
is disallowed by seccomp on Android x86 quinn-rs/quinn#1947