2

The code below returns correct pid value and then crashes. I don't understand the reason. The platform is x86 CPU android emulator (Nexus 5X).

long pid;
__asm__ __volatile__ ("int $0x80" : "=a"(pid) : "0"(__NR_getpid));
printf("Pid : %d", pid);

Here is the output:

D/APP: Pid:8261
A/libc: Fatal signal 31 (SIGSYS), code 1 in tid 8261 (.APP), pid 8261 (.APP)
Application terminated.

Can anybody give an idea?

Edit: I have tried to replace "0"(__NR_getpid) with "a"(__NR_getpid) and got the same result. I was calling the same syscall with __NR_getppid too, once I removed second call, I saw that it was not crashing anymore.

Platform: Android Studio - NDK Clang x86 (i386)

Test code:

#include <syscall.h>
#include <stdbool.h>
#include <stdint.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>

static inline long _syscall0(long n)
{
    long __ret;
    __asm__ __volatile__ ("int $0x80" : "=a"(__ret) : "0"(n));
    return __ret;
}

int main(void)
{
    int pid = (int)_syscall0(__NR_getpid);
    printf("Pid:%d", pid); 
    int ppid = (int)_syscall0(__NR_getppid); // <--- crashing here
    printf("PPid:%d", ppid); 
    return 0;
}

Compiler assembly output : https://godbolt.org/g/ibmxTb

Edit2 : Tried replacing ppid with pid, so it became 2 pids but still crashing.

Phillip
  • 259
  • 1
  • 2
  • 11
  • 3
    Could you show us the assembly generated for this code? And could you make a [mcve] (your snippet cannot be compiled as is)? Please also make sure that you are actually compiling in 32 bit mode, as your code may not work in 64 bit mode if the x86 ABI has been disabled. – fuz Jun 05 '18 at 21:23
  • 1
    `"0"(__NR_getpid)` looks incorrect. I thought the syscall is placed in `eax`, so `"a"(__NR_getpid)` seems more like I expect to see. You also seem to be missing a clobber. Also see [syscall from within GCC inline assembly](https://stackoverflow.com/a/45535396/608639). Ping @PeterCordes. – jww Jun 05 '18 at 22:03
  • Hi, I have improved the question, please take a look at **Edit** section – Phillip Jun 06 '18 at 08:57
  • 1
    @jww: a `"0"` matching constraint is correct because `%0` uses a `"=a"` constraint. It would make more sense to use `"a"` to make it more clear you mean "in EAX" rather than "in the same reg as the first output", though. (BTW, @user notify only works for users that have commented or made edits on the post you're commenting on. I didn't get notified, I just saw this in active x86 / assembly questions.) – Peter Cordes Jun 06 '18 at 09:10
  • 1
    Interesting, `SIGSYS` is apparently getting delivered on `int $0x80`. Normal Linux will just return `-ENOSYS` if you pass a bad value in EAX, or some kind of error code if the args are bogus for the system-call you invoke. IDK what changes Android makes to the kernel. `signal(7)` mentions SIGSYS. Possibly Android doesn't allow `sys_getppid`? That's what you should be googling on; I think you're invoking it correctly (if your `asm/unistd.h` / `syscall.h` has correct constants for `__NR_getppid`) so the question is why *that* system call raises SIGSYS. Try running under `strace`? – Peter Cordes Jun 06 '18 at 09:20
  • 1
    @jww: there is no missing clobber. `"=a"(pid)` tells the compiler that EAX will be modified, and the `int 0x80` ABI preserves all other registers. If you were passing any pointer args, you'd want a `"memory"` clobber to tell the compiler about that, or dummy `"m"` or `"=m"` constraints to tell the compiler exactly which memory you read or write on a per-syscall basis. (See [GCC: putchar(char) in inline assembly](https://stackoverflow.com/a/50691215) for a case where leaving out the dummy constraint leads to wrong code, which you can try on Godbolt.) – Peter Cordes Jun 06 '18 at 09:23
  • @PeterCordes should I use `: "memory"` when I'm using syscall with a pointer? For example as file read using syscall with 3 parameters. – Phillip Jun 06 '18 at 09:33
  • 1
    @PeterCordes, I have other cpu versions of the same syscall macro and they work without crash. Android allows getppid on other versions. I will check how can I strace it. – Phillip Jun 06 '18 at 09:36
  • 1
    Yes, `:"memory"` is necessary for correctness in a generic syscall macro that might be used with pointer args. A wrapper for `write` could just use a dummy input as shown in that link in the previous comment, to avoid forcing the compiler to spill/reload everything except local vars. – Peter Cordes Jun 06 '18 at 09:43
  • A seccomp rule can raise SIGSYS on any system call. – Timothy Baldwin Jun 07 '18 at 08:51
  • Any other idea or equivalent code suggestions? – Phillip Jun 11 '18 at 06:49

0 Answers0