android - Android 中的 SYSCALL_INLINE

标签 android assembly android-ndk system-calls multiplatform

我需要在 Android NDK 内部使用系统调用来防止 Hook 包装函数。 在 Linux 中有像 SYSCALL_INLINE 这样的宏,它允许在没有包装函数的情况下使用系统调用。因此宏将系统调用汇编代码直接嵌入到项目中。

我在 Android NDK 中找不到类似的宏。

也许我可以像这样编写自己的函数; https://git.busybox.net/uClibc/tree/libc/sysdeps/linux/arm/syscall.c

但我需要具有相同功能的 arm、arm_64、x86 和 x86_64 版本。

你能帮帮我吗?我怎样才能找到解决方案?

最佳答案

Android 的 Linux 内核仍然使用与常规 Linux 相同的系统调用号和 ABI,不是吗? (所以 How to access the system call from user-space? )所以你应该能够使用正常的方法,电话号码来自 <asm/unistd.h> .

您可以在 arch/x86_64/syscall_arch.h 中使用 MUSL libc 系统调用内联函数.每个不同数量的参数都有不同的参数,而不是一个大参数。


MUSL 的版本为 syscall_arch.h对于ARM 、AArch64、i386 和 x86-64,以及它支持的其他架构。它根据 a permissive MIT license 获得许可,因此您只需复制这些 header 即可。

比如他们的ARM版本有

static inline long __syscall3(long n, long a, long b, long c)
{
    register long r7 __ASM____R7__ = n;  // macro trickery for not clobbering r7 in thumb mode (where it may be the frame pointer)
    register long r0 __asm__("r0") = a;
    register long r1 __asm__("r1") = b;
    register long r2 __asm__("r2") = c;
    __asm_syscall(R7_OPERAND, "0"(r0), "r"(r1), "r"(r2));
 // FIXME: add a "memory" clobber because pointed-to memory can be an input or output
}

不幸的是,这不是严格安全的:这不会告诉编译器指针操作数已取消引用,因此它可能会在 write() 之前将存储处理到缓冲区中作为死存储并优化它们!

这很容易修复:添加一个 "memory"破坏。

IDK 如果那是 glibc 删除其类似系统调用宏并仅提供非内联系统调用函数的动机的一部分。或者,也许他们不想鼓励人们将系统调用 ABI 嵌入到他们的程序中,这样它在理论上可以改变以在未来变得更有效率。

你会像这样使用它

#include <asm/unistd.h>   // for __NR_write
#include <stdlib.h>       // for ssize_t
#include "syscall_arch.h"

// doesn't set errno or force all error returns to -1
// return values from -1 to -4095 are errors, e.g. -EBADF or -EFAULT

__attribte__((noinline))  // hack for inline asm unsafety
ssize_t my_write(int fd, const void *buf, size_t count) {
    return __syscall3(__NR_write, fd, (long)buf, count);
}

我把这个 on the Godbolt compiler explorer有足够的 ARM syscall_arch.h复制进来进行编译。 Godbolt 的一些 ARM gcc 安装丢失了 <asm/unistd.h> , 但 gcc5.4 有一个工作的。 ARM模式下的结果是:

my_write:
    str     r7, [sp, #-4]!
    mov     r7, #4
@ system-calling convention mostly matches function-calling convention
@ so args are in the right registers already
    svc 0
    ldr     r7, [sp], #4
    bx      lr

当然,这个函数可以内联到调用者中,所以 r7 的保存/恢复整个函数只发生一次。

(编辑):如果内联到可以优化掉死存储的调用者中,这将是不安全的。 一个更好的暴力选项是在内联 asm 语句上的内存破坏,或者更多的工作是为读取或写入用户空间内存的系统调用添加一个虚拟内存操作数(参见 at&t asm inline c++ problem)。 或者 munmap确保没有存储到被释放的页面中的存储通过它并在内存未映射后发生。

关于android - Android 中的 SYSCALL_INLINE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50576767/

相关文章:

android - 使用 Sceneform 实时下载 3D 模型

android - GetStringUTFChars 中的 dvmDecodeIndirectRef 中的 dvmAbort

android - 如何设置android应用程序的背景?

C++ 设置堆栈指针

assembly - C64 上的稳定光栅

android - 将 USB 文件描述符传递给 Android NDK 程序

android - 将 tess-two(Tesseract Tools for Android)库集成到 Android 工作室并构建 ndk

android - 如何使用 Android 的 Oboe/AAudio 从多个麦克风读取数据

assembly - 无法调整尺寸指令

android - 将图像转换为无符号字符*