From b8618fe4772c0fd6004d002ef23bca502235102a Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Fri, 25 Oct 2024 18:34:00 +0300 Subject: [PATCH] Android: Added syscall support --- ci/ci.sh | 2 +- src/shims/unix/android/foreign_items.rs | 4 ++ src/shims/unix/linux/foreign_items.rs | 51 +----------------- src/shims/unix/linux/mod.rs | 1 + src/shims/unix/linux/syscall.rs | 63 +++++++++++++++++++++++ tests/pass-dep/concurrency/linux-futex.rs | 1 + tests/pass-dep/libc/libc-random.rs | 41 ++++++++------- 7 files changed, 93 insertions(+), 70 deletions(-) create mode 100644 src/shims/unix/linux/syscall.rs diff --git a/ci/ci.sh b/ci/ci.sh index 4e7cbc50ca..0356d7ecf1 100755 --- a/ci/ci.sh +++ b/ci/ci.sh @@ -154,7 +154,7 @@ case $HOST_TARGET in TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe - TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap threadname pthread + TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync threadname pthread TEST_TARGET=wasm32-wasip2 run_tests_minimal $BASIC wasm TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std diff --git a/src/shims/unix/android/foreign_items.rs b/src/shims/unix/android/foreign_items.rs index b6f04951fc..2e10e82d93 100644 --- a/src/shims/unix/android/foreign_items.rs +++ b/src/shims/unix/android/foreign_items.rs @@ -2,6 +2,7 @@ use rustc_span::Symbol; use rustc_target::spec::abi::Abi; use crate::shims::unix::android::thread::prctl; +use crate::shims::unix::linux::syscall::syscall; use crate::*; pub fn is_dyn_sym(_name: &str) -> bool { @@ -26,6 +27,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; } + // Dynamically invoked syscalls + "syscall" => syscall(this, link_name, abi, args, dest)?, + // Threading "prctl" => prctl(this, link_name, abi, args, dest)?, diff --git a/src/shims/unix/linux/foreign_items.rs b/src/shims/unix/linux/foreign_items.rs index 6616a9845c..a126d5b4fa 100644 --- a/src/shims/unix/linux/foreign_items.rs +++ b/src/shims/unix/linux/foreign_items.rs @@ -4,8 +4,7 @@ use rustc_target::spec::abi::Abi; use self::shims::unix::linux::epoll::EvalContextExt as _; use self::shims::unix::linux::eventfd::EvalContextExt as _; use self::shims::unix::linux::mem::EvalContextExt as _; -use self::shims::unix::linux::sync::futex; -use crate::helpers::check_min_arg_count; +use self::shims::unix::linux::syscall::syscall; use crate::machine::{SIGRTMAX, SIGRTMIN}; use crate::shims::unix::*; use crate::*; @@ -117,53 +116,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Dynamically invoked syscalls "syscall" => { - // We do not use `check_shim` here because `syscall` is variadic. The argument - // count is checked bellow. - this.check_abi_and_shim_symbol_clash(abi, Abi::C { unwind: false }, link_name)?; - // The syscall variadic function is legal to call with more arguments than needed, - // extra arguments are simply ignored. The important check is that when we use an - // argument, we have to also check all arguments *before* it to ensure that they - // have the right type. - - let sys_getrandom = this.eval_libc("SYS_getrandom").to_target_usize(this)?; - let sys_futex = this.eval_libc("SYS_futex").to_target_usize(this)?; - let sys_eventfd2 = this.eval_libc("SYS_eventfd2").to_target_usize(this)?; - - let [op] = check_min_arg_count("syscall", args)?; - match this.read_target_usize(op)? { - // `libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)` - // is called if a `HashMap` is created the regular way (e.g. HashMap). - num if num == sys_getrandom => { - // Used by getrandom 0.1 - // The first argument is the syscall id, so skip over it. - let [_, ptr, len, flags] = - check_min_arg_count("syscall(SYS_getrandom, ...)", args)?; - - let ptr = this.read_pointer(ptr)?; - let len = this.read_target_usize(len)?; - // The only supported flags are GRND_RANDOM and GRND_NONBLOCK, - // neither of which have any effect on our current PRNG. - // See for a discussion of argument sizes. - let _flags = this.read_scalar(flags)?.to_i32()?; - - this.gen_random(ptr, len)?; - this.write_scalar(Scalar::from_target_usize(len, this), dest)?; - } - // `futex` is used by some synchronization primitives. - num if num == sys_futex => { - futex(this, args, dest)?; - } - num if num == sys_eventfd2 => { - let [_, initval, flags] = - check_min_arg_count("syscall(SYS_evetfd2, ...)", args)?; - - let result = this.eventfd(initval, flags)?; - this.write_int(result.to_i32()?, dest)?; - } - num => { - throw_unsup_format!("syscall: unsupported syscall number {num}"); - } - } + syscall(this, link_name, abi, args, dest)?; } // Miscellaneous diff --git a/src/shims/unix/linux/mod.rs b/src/shims/unix/linux/mod.rs index 84b604eb9b..159e5aca03 100644 --- a/src/shims/unix/linux/mod.rs +++ b/src/shims/unix/linux/mod.rs @@ -3,3 +3,4 @@ pub mod eventfd; pub mod foreign_items; pub mod mem; pub mod sync; +pub mod syscall; diff --git a/src/shims/unix/linux/syscall.rs b/src/shims/unix/linux/syscall.rs new file mode 100644 index 0000000000..72e02447d8 --- /dev/null +++ b/src/shims/unix/linux/syscall.rs @@ -0,0 +1,63 @@ +use rustc_span::Symbol; +use rustc_target::spec::abi::Abi; + +use self::shims::unix::linux::eventfd::EvalContextExt as _; +use crate::helpers::check_min_arg_count; +use crate::shims::unix::linux::sync::futex; +use crate::*; + +pub fn syscall<'tcx>( + this: &mut MiriInterpCx<'tcx>, + link_name: Symbol, + abi: Abi, + args: &[OpTy<'tcx>], + dest: &MPlaceTy<'tcx>, +) -> InterpResult<'tcx> { + // We do not use `check_shim` here because `syscall` is variadic. The argument + // count is checked bellow. + this.check_abi_and_shim_symbol_clash(abi, Abi::C { unwind: false }, link_name)?; + // The syscall variadic function is legal to call with more arguments than needed, + // extra arguments are simply ignored. The important check is that when we use an + // argument, we have to also check all arguments *before* it to ensure that they + // have the right type. + + let sys_getrandom = this.eval_libc("SYS_getrandom").to_target_usize(this)?; + let sys_futex = this.eval_libc("SYS_futex").to_target_usize(this)?; + let sys_eventfd2 = this.eval_libc("SYS_eventfd2").to_target_usize(this)?; + + let [op] = check_min_arg_count("syscall", args)?; + match this.read_target_usize(op)? { + // `libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)` + // is called if a `HashMap` is created the regular way (e.g. HashMap). + num if num == sys_getrandom => { + // Used by getrandom 0.1 + // The first argument is the syscall id, so skip over it. + let [_, ptr, len, flags] = check_min_arg_count("syscall(SYS_getrandom, ...)", args)?; + + let ptr = this.read_pointer(ptr)?; + let len = this.read_target_usize(len)?; + // The only supported flags are GRND_RANDOM and GRND_NONBLOCK, + // neither of which have any effect on our current PRNG. + // See for a discussion of argument sizes. + let _flags = this.read_scalar(flags)?.to_i32()?; + + this.gen_random(ptr, len)?; + this.write_scalar(Scalar::from_target_usize(len, this), dest)?; + } + // `futex` is used by some synchronization primitives. + num if num == sys_futex => { + futex(this, args, dest)?; + } + num if num == sys_eventfd2 => { + let [_, initval, flags] = check_min_arg_count("syscall(SYS_evetfd2, ...)", args)?; + + let result = this.eventfd(initval, flags)?; + this.write_int(result.to_i32()?, dest)?; + } + num => { + throw_unsup_format!("syscall: unsupported syscall number {num}"); + } + }; + + interp_ok(()) +} diff --git a/tests/pass-dep/concurrency/linux-futex.rs b/tests/pass-dep/concurrency/linux-futex.rs index 20e642a0a2..2a36c10f7d 100644 --- a/tests/pass-dep/concurrency/linux-futex.rs +++ b/tests/pass-dep/concurrency/linux-futex.rs @@ -1,4 +1,5 @@ //@only-target: linux +//@only-target: android //@compile-flags: -Zmiri-disable-isolation // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint diff --git a/tests/pass-dep/libc/libc-random.rs b/tests/pass-dep/libc/libc-random.rs index 8f4398cbd8..7c4010f6c0 100644 --- a/tests/pass-dep/libc/libc-random.rs +++ b/tests/pass-dep/libc/libc-random.rs @@ -28,26 +28,27 @@ fn test_getrandom() { let mut buf = [0u8; 5]; unsafe { - #[cfg(target_os = "linux")] - assert_eq!( - libc::syscall( - libc::SYS_getrandom, - ptr::null_mut::(), - 0 as libc::size_t, - 0 as libc::c_uint, - ), - 0, - ); - #[cfg(target_os = "linux")] - assert_eq!( - libc::syscall( - libc::SYS_getrandom, - buf.as_mut_ptr() as *mut libc::c_void, - 5 as libc::size_t, - 0 as libc::c_uint, - ), - 5, - ); + #[cfg(any(target_os = "linux", target_os = "android"))] + { + assert_eq!( + libc::syscall( + libc::SYS_getrandom, + ptr::null_mut::(), + 0 as libc::size_t, + 0 as libc::c_uint, + ), + 0, + ); + assert_eq!( + libc::syscall( + libc::SYS_getrandom, + buf.as_mut_ptr() as *mut libc::c_void, + 5 as libc::size_t, + 0 as libc::c_uint, + ), + 5, + ); + } assert_eq!( libc::getrandom(ptr::null_mut::(), 0 as libc::size_t, 0 as libc::c_uint),