• 如何 dump 一个进程的 seccomp filters ?


    如何获取一个进程的 seccomp filters?

    man ptrace 获取到如下内容:

           Since Linux 4.4, the ptrace(2) PTRACE_SECCOMP_GET_FILTER operation can be used to dump a process's seccomp filters.
    
           PTRACE_SECCOMP_GET_FILTER (since Linux 4.4)
                  This operation allows the tracer to dump the tracee's classic BPF filters.
    
                  addr is an integer specifying the index of the filter to be dumped.  The most recently installed filter has the index 0.  If addr is greater than the num‐
                  ber of installed filters, the operation fails with the error ENOENT.
    
                  data is either a pointer to a struct sock_filter array that is large enough to store the BPF program, or NULL if the program is not to be stored.
    
                  Upon  success,  the return value is the number of instructions in the BPF program.  If data was NULL, then this return value can be used to correctly size
                  the struct sock_filter array passed in a subsequent call.
    
                  This operation fails with the error EACCES if the caller does not have the CAP_SYS_ADMIN capability or if the caller is in strict or filter seccomp  mode.
                  If the filter referred to by addr is not a classic BPF filter, the operation fails with the error EMEDIUMTYPE.
    
                  This operation is available if the kernel was configured with both the CONFIG_SECCOMP_FILTER and the CONFIG_CHECKPOINT_RESTORE options.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    manual 信息表明使用 PTRACE_SECCOMP_GET_FILTER 参数就能够获取到进程的 seccomp filter 内容。

    seccomp filter 测试 demo

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    static int install_filter(int nr, int arch, int error) {
      struct sock_filter filter[] = {
        BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (offsetof(struct seccomp_data, arch))),
        BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch, 0, 3),
        BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (offsetof(struct seccomp_data, nr))),
        BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1),
        BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (error & SECCOMP_RET_DATA)),
        BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
      };
      struct sock_fprog prog = {
        .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
        .filter = filter,
      };
      if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
        perror("prctl(PR_SET_SECCOMP)");
        return 1;
      }
      return 0;
    }
    
    int main(int argc, char const *argv[]) {
      if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
        perror("prctl(NO_NEW_PRIVS)");
        return 1;
      }
      install_filter(__NR_chroot, AUDIT_ARCH_X86_64, EPERM);
      install_filter(__NR_socket, AUDIT_ARCH_X86_64, EPERM);
      return system(argv[1]);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    上述文件给当前进程注册两个 seccomp filter 规则,用以禁止进程使用 chroot 与 socket 系统调用,然后使用 system 函数执行传递的命令。

    将上述文件保存为 seccomp.c 并编译生成 seccomp 程序。

    获取 seccomp filter 的示例 demo

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    int main(int argc, char const *argv[]) {
    	struct sock_filter *filter = NULL;
    	int number = 0;
    	int index = -1;
    	int pid;
    	
    	if (argc != 3) {
    		printf("%s pid filter-index", argv[0]);
    		exit(-1);
    	}
    	pid = atoi(argv[1]);
    	index = atoi(argv[2]);
    	
    	memset(&filter, 0x00, sizeof(filter));
    	ptrace(PTRACE_ATTACH, pid);
    
    	number = ptrace(PTRACE_SECCOMP_GET_FILTER, pid, (void *)index, NULL);
    	filter = malloc(sizeof(struct sock_filter) * number);
    	ptrace(PTRACE_SECCOMP_GET_FILTER, pid, (void *)index, (void *)filter);
    	
    	for (int i = 0; i < number; i++) {
    		printf("0x%x%x%x\n", filter[i].code, filter[i].jt, 
    				filter[i].jf, filter[i].k);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    上述代码首先使用 ptrace跟踪目标进程,然后使用 PTRACE_SECCOMP_GET_FILTER参数执行 ptrace并将最后一个参数设置为 NULL来获取 index 指向的 seccomp filter 的 bpf 字节码长度,然后申请相应大小的 sock_filter。此后重新使用 PTRACE_SECCOMP_GET_FILTER参数执行 ptrace获取到进程的 seccomp filter,最后将获取到的指令码打印出来。

    将上述文件保存为 dump.c 并编译生成 dump 程序。

    给 dump 程序单独添加权限

    执行如下命令添加 cap_sys_admin 权限:

    [longyu@debian] tmp $ sudo setcap cap_sys_admin+ep ./dump
    
    • 1

    查看添加后的权限:

    [longyu@debian] tmp $ sudo getcap ./dump
    ./dump cap_sys_admin=ep
    
    • 1
    • 2

    成功添加权限后就可以使用 dump 程序来 dump 进程的 seccomp filter 内容。

    dump 一个进程的 seccomp filters 的示例步骤

    1. 在一个终端中执行 ./seccomp bash 命令给 bash 命令添加 seccomp filter
    2. 获取 bash 命令的 pid
    3. 在另外一个终端使运行 dump 程序并指定 pid 参数与 seccomp filter index

    测试示例如下:

    [longyu@debian] tmp $ ./dump 33449 0
    0x2000
    0x1503
    0x2000
    0x1501
    0x600
    0x600
    [longyu@debian] tmp $ ./dump 33449 1
    0x2000
    0x1503
    0x2000
    0x1501
    0x600
    0x600
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    获取成功!

    注意事项

    1. 在使用 PTRACE_SECCOMP_GET_FILTER参数执行 ptrace前需要先使用 PTRACE_ATTACH 与待 trace 进程的 pid 参数来调用 ptrace trace 到目标进程中。
    2. 进程支持 PTRACE_SECCOMP_GET_FILTER 的最小权限为 cap_sys_admin,setcap 赋予此权限后不需要 root 权限就能够成功 dump。
    3. seccomp 支持同时添加多个 filter 且可被子进程继承
  • 相关阅读:
    聚观早报 | 神舟十四号飞行任务圆满成功;大众ID大面积车机故障
    关于交互3d的问题,请各位专家解答!
    IDEA的快捷键大全
    MES必懂知识,市场需求下的生产管理系统
    【前端性能优化】 --- 一次总结明白
    二叉排序树的删除操作的实现(思路分析)
    Pico Neo3使用Unity开发简明教程
    Node.js 入门教程 9 如何从 Node.js 读取环境变量 & 10 如何使用 Node.js REPL
    79、SpringBoot 整合 R2DBC --- R2DBC 就是 JDBC 的 反应式版本, R2DBC 是 JDBC 的升级版。
    MySQL索引优化
  • 原文地址:https://blog.csdn.net/Longyu_wlz/article/details/126256405