上手 seccomp

前言

vdso——虚拟 elf 动态共享库 这篇博客中,我描述了 vdso 的相关内容。其中有提到在 vdso 中导出的符号(系统调用)不会被 strace、seccomp 捕获到的情况。

seccomp 对我来说相当陌生,man seccomp 发现它能够用来限定程序能够执行的系统调用,并且是通过 bpf 虚拟机完成的,基于这两个因素,我在本篇文章中描述下上手 seccomp 的过程。

上手 seccomp

使用 seccomp 前需要开启必要的内核选项,一般来说需要开启下面这三个内核配置项目:

  • CONFIG_SECCOMP
  • CONFIG_HAVE_ARCH_SECCOMP_FILTER
  • CONFIG_SECCOMP_FILTER

我使用如下 demo 进行测试,此 demo 摘自 《Linux 内核观测技术BPF》第 8 章。

#include <errno.h>
#include <linux/audit.h>
#include <linux/bpf.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <linux/unistd.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/prctl.h>
#include <unistd.h>

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_write, AUDIT_ARCH_X86_64, EPERM);
  return system(argv[1]);
}

此程序使用 install_filter 注册了一个阻止 write 系统调用的过滤条件,它使用 cbpf 虚拟机实现。

这个程序并没有使用 seccomp 系统调用,而是使用 prctl 的 PR_SET_SECCOMP option 来设定,seccomp 系统调用能够提供更多的功能,不过在这里用以限定系统调用的执行倒是绰绰有余了!

与普通 c 程序一样,直接执行 gcc 编译即可。编译后执行如下命令进行测试:

$ ls
README.md  capabilities  main.c  output  seccomp  test.c  test.go
$ ./seccomp  ls
$ 

第一次 ls 命令输出了当前目录的文件内容,第二次 ls 命令由上述 demo 编译生成的 seccomp 程序执行,没有任何输出,与预期一致。

使用 strace -f 跟踪 ls 命令的执行过程,能够看到下面这几个关键的系统调用执行结果:

[pid  7399] write(1, "README.md  capabilities  main.c "..., 66) = -1 EPERM (Operation not permitted)
[pid  7399] close(1)                    = 0
[pid  7399] write(2, "ls: ", 4)         = -1 EPERM (Operation not permitted)
[pid  7399] write(2, "write error", 11) = -1 EPERM (Operation not permitted)
[pid  7399] write(2, "\n", 1)           = -1 EPERM (Operation not permitted)

可以确定,由于设定了过滤 write 系统调用,ls 命令在执行 write 系统调用时返回了 EPERM (操作不被允许)的错误值,seccomp 上手了!

demo 中的隐含内容

上面 demo 中我们用 seccomp 去加载 ls 命令,而设定过滤规则却是在 seccomp 程序中完成的,这说明在 fork 后 ls 命令继承了来自 seccomp 的过滤规则。

其实 seccomp 程序设定的系统调用过滤规则能传递给子程序的关键在于如下系统调用:

prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)

man prctl 得到了如下信息:

       PR_SET_NO_NEW_PRIVS (since Linux 3.5)
              Set  the  calling  thread's  no_new_privs bit to the value in arg2.  With no_new_privs set to 1, execve(2) promises not to grant privileges to do anything
              that could not have been done without the execve(2) call (for example, rendering the set-user-ID and set-group-ID mode bits, and  file  capabilities  non-
              functional).   Once set, this bit cannot be unset.  The setting of this bit is inherited by children created by fork(2) and clone(2), and preserved across
              execve(2).

              Since Linux 4.10, the value of a thread's no_new_privs bit can be viewed via the NoNewPrivs field in the /proc/[pid]/status file.

              For more information, see the kernel source file Documentation/userspace-api/no_new_privs.rst (or Documentation/prctl/no_new_privs.txt before Linux 4.13).
              See also seccomp(2).

设置了 PR_SET_NO_NEW_PRIVS 后,子进程将不会拥有比父进程更大的权限,并且 PR_SET_NO_NEW_PRIVS 的设定将会被使用 fork 与 clone 创建的子进程继承,并且在 execve 时也会保留。

总结

seccomp 并不是什么新技术,它已经问世了好些年头,可我对这个技术还非常陌生,通过本篇文章上手 seccomp,希望以后能够用上这一功能!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flowable是一个用于实现工作流的技术框架。如果你对工作流这块没有接触过,可以通过查看Flowable的官方文档来了解。\[1\]官方文档可以帮助你了解Flowable的基本概念和使用方法。在文档中,你可以找到关于Flowable的介绍、配置、API文档以及示例代码等内容。 在实际项目中,我们通常需要将流程流转到指定的人或拥有指定权限的人那边进行处理。对于这个问题,你可以参考官方文档中关于Flowable的权限管理和任务分配的章节。\[2\]通过配置相关的权限和任务分配规则,你可以确保只有具备相应权限的人才能执行特定的命令。 此外,Flowable还提供了Flowable UI应用,可以通过绘制流程图的方式来设计工作流,并导出BPMN的xml结构。\[3\]这样可以避免手动编写繁琐的xml配置。你可以下载最新稳定版本的Apache Tomcat和Flowable 6,将Flowable的war文件复制到Tomcat的webapps文件夹下,并启动Tomcat服务器。然后,通过访问http://localhost:8080/flowable-modeler来使用Flowable UI应用。 总之,要上手Flowable,你可以先阅读官方文档,了解Flowable的基本概念和使用方法。然后,根据实际项目需求,配置权限和任务分配规则。最后,可以使用Flowable UI应用来设计和管理工作流程。 #### 引用[.reference_title] - *1* *2* *3* [Flowable使用初体验](https://blog.csdn.net/ITlikeyou/article/details/124041657)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v4^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值