【问题标题】:PTRACE_GET_SYSCALL_INFO undeclared: including sys/ptrace.h doesn't seem to get all ptrace codePTRACE_GET_SYSCALL_INFO 未声明:包括 sys/ptrace.h 似乎没有得到所有 ptrace 代码
【发布时间】:2020-04-19 15:03:05
【问题描述】:

来自手册页:

PTRACE_GET_SYSCALL_INFO(自 Linux 5.3 起)

检索有关导致停止的系统调用的信息。这 信息被放入数据参数指向的缓冲区中, 它应该是指向结构类型缓冲区的指针 ptrace_syscall_info。 addr 参数包含 数据参数指向的缓冲区(即 sizeof(struct ptrace_syscall_info))。返回值包含数量 可供内核写入的字节数。如果大小 内核写入的数据超过了指定的大小 addr 参数,输出数据被截断。

>cat /proc/version
Linux version 5.3.0-kali2-amd64 (devel@kali.org) (gcc version 9.2.1 20191109 (Debian 9.2.1-19)) #1 SMP Debian 5.3.9-3kali1 (2019-11-20)
>

现在,我编写了这个小程序,由两个文件组成。

helpers.h

#ifndef HELPERS
#define HELPERS
//helpers.h
#include <errno.h>
#include <sys/ptrace.h>
#include <sys/types.h>


const char* op_to_string(__u8 op)
{
    switch (op) {
        case (PTRACE_SYSCALL_INFO_ENTRY):
            return "SYSCALL_INFO_ENTRY";
            break;
        case (PTRACE_SYSCALL_INFO_EXIT):
            return "SYSCALL_INFO_EXIT";
            break;
        case (PTRACE_SYSCALL_INFO_SECCOMP):
            return "SYSCALL_INFO_SECCOMP";
            break;
        default:
            fprintf(stderr, "op-to-string: Invalid op code");
    }
}


void err_wrap(const int ret, const int success, const char *msg)
{
    if (ret != success)
    {
        perror(msg);
    }
}


void print_regs(const struct user_regs_struct regs) {
  printf ("r15:     %16llx %30s\n", regs.r15, "general purpose registers");
  printf ("r14:     %16llx\n", regs.r14);
  printf ("r13:     %16llx\n", regs.r13);
  printf ("r12:     %16llx\n", regs.r12);
  printf ("rbp:     %16llx\n", regs.rbp);
  printf ("rbx:     %16llx\n", regs.rbx);
  printf ("r11:     %16llx\n", regs.r11);
  printf ("r10:     %16llx\n", regs.r10);
  printf ("r9:      %16llx   %s\n", regs.r9, "6.");
  printf ("r8:      %16llx   %s\n", regs.r8, "5.");
  printf ("rax:     %16llx\n", regs.rax);
  printf ("rcx:     %16llx   %s\n", regs.rcx, "4.");
  printf ("rdx:     %16llx   %s\n", regs.rdx, "3.");
  printf ("rsi:     %16llx   %s\n", regs.rsi, "2.");
  printf ("rdi:     %16llx %30s\n", regs.rdi, "1. function/syscall argument"); // aka "parameter registers"
  printf ("orig_rax:%16llx\n", regs.orig_rax);
  printf ("rip:     %16llx %30s\n", regs.rip, "instruction pointer");
  printf ("cs:      %16llx\n", regs.cs);
  printf ("eflags:  %16llx\n", regs.eflags);
  printf ("rsp:     %16llx %30s\n", regs.rsp, "  Stack Pointer (current location in stack)");
  printf ("ss:      %16llx\n", regs.ss);
  printf ("fs_base: %16llx\n", regs.fs_base);
  printf ("gs_base: %16llx\n", regs.gs_base);
  printf ("ds:      %16llx\n", regs.ds);
  printf ("es:      %16llx\n", regs.es);
  printf ("fs:      %16llx\n", regs.fs);
  printf ("gs:      %16llx\n", regs.gs);
}

void print_syscall_info(struct ptrace_syscall_info sys_info) {
    __u8 op = sys_info.op;
    printf("Type of system call stop:   %20s   (%x)\n", op_to_string(op), op);
    printf("Arch:   %16llx\n", sys_info.arch);
}

#endif

tracetest.c

#include <stdio.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
#include <sys/user.h>

#include <syscall.h>

#include "helpers.h"

// long ptrace(enum __ptrace_request request, pid_t pid,
                   // void *addr, void *data);



void child_code();
void parent_code(pid_t pid);

int main(const int argc, char *argv[])
{
    pid_t pid;
    switch (pid = fork())
    {
        case -1:
            perror("fork");
            break;
        case 0:
            child_code();
            break;
        default: //parent code
            parent_code(pid);
    }

    return 0;
}

void parent_code(pid_t pid)
{
    printf("Parent code\n");
    int status;
    if (wait(&status) == -1)
    {
        perror("parent wait one");
    }
    printf("Finished waiting\n");
    printf("PID wait status is:     %llx\n", status);
    printf("My PID is     %d\n", getpid());
    err_wrap(
        ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_EXITKILL), 
        0, "ptrace-set-options");
    struct user_regs_struct regs;
    struct ptrace_syscall_info syscall_info;

    while(1)
    {
        err_wrap(ptrace(PTRACE_SYSCALL, pid, 0, 0), 0, "ptrace-syscall first"); //Stop at next syscall.
        if (wait(&status) == -1)
        {
            perror("parent wait one");
        }
        printf("syscall-entry-stop\n");
        err_wrap(
            ptrace(PTRACE_GET_SYSCALL_INFO, pid, sizeof(struct ptrace_syscall_info), &syscall_info),
            0, "ptrace-get-syscall-info");
        err_wrap(
            ptrace(PTRACE_GETREGS, pid, 0, &regs),
            0,
            "ptrace-getregs");

        print_regs(regs);
        print_syscall_info(syscall_info);
    }

}

void child_code() {
    printf("Child code\n");
    printf("Parent is:   %d\n", getppid());
    err_wrap(ptrace(PTRACE_TRACEME, 0,0,0), 0, "ptrace-traceme");
    err_wrap(raise(SIGSTOP), 0, "raise");

    unsigned int pleb = 0xffbbcde8;
    int x = 0;
    printf("Hello WoRld\n");

    printf("Pleb is:     %llx\n", pleb);
    printf("x is:        %d\n", x);
}

考虑到所有因素,我的代码应该可以正常运行而没有错误,但似乎 PTRACE_GET_SYSCALL_INFO 内容实际上并未包含在内,因为 gcc 抱怨:

>gcc -g -o tracetest tracetest.c
In file included from tracetest.c:10:
helpers.h:9:26: error: unknown type name ‘__u8’
    9 | const char* op_to_string(__u8 op)
      |                          ^~~~
helpers.h:72:32: warning: ‘struct ptrace_syscall_info’ declared inside parameter list will not be visible outside of this definition or declaration
   72 | void print_syscall_info(struct ptrace_syscall_info sys_info) {
      |                                ^~~~~~~~~~~~~~~~~~~
helpers.h:72:52: error: parameter 1 (‘sys_info’) has incomplete type
   72 | void print_syscall_info(struct ptrace_syscall_info sys_info) {
      |                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
helpers.h: In function ‘print_syscall_info’:
helpers.h:73:2: error: unknown type name ‘__u8’
   73 |  __u8 op = sys_info.op;
      |  ^~~~
helpers.h:74:54: warning: implicit declaration of function ‘op_to_string’ [-Wimplicit-function-declaration]
   74 |  printf("Type of system call stop:   %20s   (%x)\n", op_to_string(op), op);
      |                                                      ^~~~~~~~~~~~
tracetest.c: In function ‘parent_code’:
tracetest.c:55:29: error: storage size of ‘syscall_info’ isn’t known
   55 |  struct ptrace_syscall_info syscall_info;
      |                             ^~~~~~~~~~~~
tracetest.c:66:11: error: ‘PTRACE_GET_SYSCALL_INFO’ undeclared (first use in this function); did you mean ‘PTRACE_GETSIGINFO’?
   66 |    ptrace(PTRACE_GET_SYSCALL_INFO, pid, sizeof(struct ptrace_syscall_info), &syscall_info),
      |           ^~~~~~~~~~~~~~~~~~~~~~~
      |           PTRACE_GETSIGINFO
tracetest.c:66:11: note: each undeclared identifier is reported only once for each function it appears in
tracetest.c:66:48: error: invalid application of ‘sizeof’ to incomplete type ‘struct ptrace_syscall_info’
   66 |    ptrace(PTRACE_GET_SYSCALL_INFO, pid, sizeof(struct ptrace_syscall_info), &syscall_info),
      |                                                ^~~~~~

但是,如果我#include &lt;linux/ptrace.h&gt;,那么我不会收到这些错误,而是显示函数 ptrace.h 的隐式声明,老实说我认为这也不是很好。

我应该包括什么才能使这个功能达到预期?我还包括了 sys/types.h,但我仍然收到关于 __u8 是未知类型名称的错误,但它是ptrace.c 源代码中使用的类型,因此它不应该抛出任何错误。

ptrace 手册页的顶部说:

#include <sys/ptrace.h>
long ptrace(enum __ptrace_request request, pid_t pid,
            void *addr, void *data);`

所以我认为这个单一的包含就足够了,但它不起作用。

提前致谢。

【问题讨论】:

    标签: c system-calls ptrace


    【解决方案1】:

    这是因为 glibc 在所有最新的 Linux 功能上都不是最新的。您可以通过#include &lt;linux/ptrace.h&gt;#include &lt;sys/ptrace.h&gt; 获取PTRACE_GET_SYSCALL_INFO

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-22
      • 2013-08-07
      • 1970-01-01
      • 1970-01-01
      • 2017-04-15
      相关资源
      最近更新 更多