PTRACE_GET_SYSCALL_INFO未声明:包括sys / ptrace.h似乎并未获得所有ptrace代码

问题描述 投票:0回答:1

从手册页:

PTRACE_GET_SYSCALL_INFO(自Linux 5.3起)

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

>cat /proc/version
Linux version 5.3.0-kali2-amd64 ([email protected]) (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 <linux/ptrace.h>,那么我没有得到这些错误,但是它说的是函数ptrace.h的隐式声明,说实话,我认为也不是很好。

[应该为使此功能按预期包括的内容?我也包含了sys/types.h,但是我仍然收到有关__u8是未知类型名称的错误,但这是在ptrace.c源代码,因此它不应引发任何错误。

ptrace手册页的顶部说:

包括

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

因此,我本以为只有这个include就足够了,但是不起作用。

提前感谢。

c system-calls ptrace
1个回答
0
投票

这是因为glibc在所有最新的Linux功能上都不是最新的。您可以#include <linux/ptrace.h>#include <sys/ptrace.h>获得PTRACE_GET_SYSCALL_INFO

© www.soinside.com 2019 - 2024. All rights reserved.