7

As far as I know, ptrace can only get syscall number by PTRACE_SYSCALL, but syscall number is different in x86 and x64. So is there any way to figure out where this syscall real origin?

I am now coding a program to limit some others' syscall by syscall number, I know the syscall number on both x86 and x64, but some of the programs using 'int 80h' instead of 'syscall' so that they can do dangerous thing which I limited on x64. For example,I banned fork() on x64, they can use 'int 80h(2)'(fork()) and I fell they are using 'syscall(2)'(open()), thus they can break the limit. Although ptrace can track both of them and get the syscall number, I cannot distinguish where the syscall actually comes.

Peter Cordes
  • 6,345
Criyle
  • 71

2 Answers2

1

Looks like as of writing (2019-02-08), this is impossible.

And even strace gets it wrong.

Edit: Linus Torvalds talks about it here, also analysing possible (but commented-out) workarounds in the strace code that directly look at the instructions made in the binary. This code was removed here as part of the patchset I mention below. It says It works, but is too complicated, and strictly speaking, unreliable, but it is unclear to me in which cases the "strictly speaking, unreliably" applies, if that is only in the case of a multi-threaded executable rewriting itself at runtime (thus not suitable for forbidding certain syscalls for security use cases), or also in other cases.

Edit: The "unreliable" part was added in this commit.

Edit: I have now tried out strace's opcode-peeking implementation (version v4.25), and suspect that it was bugged: When activating that code path by changing this line to #if 0 and this line to #elif 1, no syscalls are printed because scno is not set at all. I added scno = x86_64_regs.orig_rax; after this line to make it work.

See the presentation How to make strace happy, slide 2, problem 2:

There is no reliable way to distinguish between x86_64 and x86 syscalls.

Details shown on slides 4-6. There is a proposed solution to be added to the kernel:

Extend the ptrace API with PTRACE_GET_SYSCALL_INFO request

But this solution isn't merged to the kernel.

The patchset is called ptrace: add PTRACE_GET_SYSCALL_INFO request and it's still being worked on in January 2019. Hopefully it will soon be merged.


strace already has support for it since release 4.26 (but it shouldn't work unless you apply the kernel patch manually):

Implemented obtainment of system call information using PTRACE_GET_SYSCALL_INFO ptrace API.

nh2
  • 977
-2

It's the system call sys_rt_sigtimedwait (since kernel 2.2). See the manpage of it by:

man 2 rt_sigtimedwait

That syscall suspends the execution, until a signal (or a set of singals) specified by the argument is delivered. A timeout is also been given.

To be 100% sure there is a file called unistd_64.h. Search your system for that file. Mostly it's in the include folder (/usr/include/x86_64-linux-gnu/asm/unistd_64.h). In there are the numbers defined. Here the relevant line in my case (it's also a 64-bit system, kernel 3.2.0-58):

#define __NR_rt_sigtimedwait                    128
__SYSCALL(__NR_rt_sigtimedwait, sys_rt_sigtimedwait)

Note 128 is decimal for 80 in hex.

chaos
  • 4,304