从 manual 中学习 seccomp 技术

前言

限制程序能够使用的系统调用 这篇文章中我描述了使用 seccomp 来限制程序系统调用的技术,虽然能够上手却并不了解它提供的真正功能与实际的应用场景,在本篇文章中探讨下。

seccomp 的全称是什么?

seccomp 全称为 Secure Computing,它能够用来限定程序能够执行的系统调用,这一限定可以用于实现沙盒等安全容器,让程序仅能执行受限的内核功能,强化系统的安全性。

seccomp 的作用范围

seccomp 配置单位为进程(存疑),它在每一个进程的 task_struct 结构中保存配置信息,这个配置信息在进程 fork 的时候会被子进程继承。

限制程序能够使用的系统调用 文章中描述的 demo 有如下代码:

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]);
}

此代码在当前进程中注册了一个 seccomp 的 filter 条件后,使用 system 函数创建子进程执行目标程序来限定子进程不能使用 write 系统调用,它能够工作的基础就是 seccomp 配置能够被【子进程继承】。

seccomp 的三种工作模式

SECCOMP_SET_MODE_STRICT

在此种模式下线程只被允许使用 read、 write, _exit (不包含 exit_group )、与 sigreturn 系统调用,使用其它系统调用时内核会发送 SIGKILL 信号杀死线程。

此功能需要开启 CONFIG_SECCOMP 内核配置。

SECCOMP_SET_MODE_FILTER

此模式允许用户基于 BPF 指令编写过滤规则下发到进程中,扩展了过滤规则的描述元素,同时支持过滤任意的系统调用及系统调用使用的参数。

要使用 SECCOMP_SET_MODE_FILTER,调用线程所在的命名空间需要有 CAP_SYS_ADMIN 权限、线程设定了 no_new_privs 标志位。当已经设定的 filter 允许线程使用 prctl、seccomp 系统调用时,可以添加更多的过滤规则。多个过滤规则会增加执行时间,但是能够允许进一步降低线程执行过程中可能遇到的攻击。

要使用 SECCOMP_SET_MODE_FILTER,内核需要开启 CONFIG_SECCOMP_FILTER 配置。

SECCOMP_GET_ACTION_AVAIL

此模式用于查询特定的 action 是否被内核支持。这里的 action 表示 seccomp filter 命中后内核执行的行为。

seccomp bpf filter 的结构与过滤的数据格式

fitler 信息由如下结构体描述:

           struct sock_fprog {
               unsigned short      len;    /* Number of BPF instructions */
               struct sock_filter *filter; /* Pointer to array of
                                              BPF instructions */
           };

len 表示 bpf 指令的数量,filter 指向指令存储的数组。sock_filter 结构如下:

           struct sock_filter {            /* Filter block */
               __u16 code;                 /* Actual filter code */
               __u8  jt;                   /* Jump true */
               __u8  jf;                   /* Jump false */
               __u32 k;                    /* Generic multiuse field */
           };

当执行 bpf 规则过滤时,bpf 指令码基于内核生成的系统调用信息工作,此信息的定义如下:

          struct seccomp_data {
              int   nr;                   /* System call number */
              __u32 arch;                 /* AUDIT_ARCH_* value
                                             (see <linux/audit.h>) */
              __u64 instruction_pointer;  /* CPU instruction pointer */
              __u64 args[6];              /* Up to 6 system call arguments */
          };

这个结构表明 seccomp filter 功能不仅支持过滤指定的系统调用,也能过滤传递特定参数的系统调用。

seccomp filter 命中后不同的 action

seccomp 支持在 filter 规则命中后设定不同的 action,action 按照优先级降低的顺序排列如下:

  • SECCOMP_RET_KILL_PROCESS
  • SECCOMP_RET_KILL_THREAD
  • SECCOMP_RET_TRAP
  • SECCOMP_RET_ERRNO
  • SECCOMP_RET_TRACE
  • SECCOMP_RET_LOG
  • SECCOMP_RET_ALLOW

当命中多个 action 时,优先级最高的 action 被触发。

seccomp 的使用场景

  1. 进程沙箱
  2. 监控特定进程执行的系统调用
  3. 过滤进程执行的系统调用
  4. 限定进程能够执行的系统调用

linux 发行版中有在使用 seccomp 吗?

在 debian11 发行版中使用 【ftrace】 跟踪 __seccomp_filter函数的调用栈帧,得到了如下信息:

 => 0xffffffffc0c94083
 => __seccomp_filter
 => syscall_trace_enter.constprop.0
 => do_syscall_64
 => entry_SYSCALL_64_after_hwframe
           Timer-11769   [000] ..... 25307.796774: __seccomp_filter <-syscall_trace_enter.constprop.0
           Timer-11769   [000] ..... 25307.796775: <stack trace>
 => 0xffffffffc0c94083
 => __seccomp_filter
 => syscall_trace_enter.constprop.0
 => do_syscall_64
 => entry_SYSCALL_64_after_hwframe
     Web Content-11763   [003] ..... 25307.796776: __seccomp_filter <-syscall_trace_enter.constprop.0
     Web Content-11763   [003] ..... 25307.796777: <stack trace>

11763 在系统中对应的进程信息如下:

root@debian:/sys/kernel/debug/tracing# ps aux | grep 11763
longyu     11763  7.2  4.7 3105732 371780 ?      Sl   07:56   3:26 /usr/lib/firefox-esr/firefox-esr -contentproc -childID 18 -isForBrowser -prefsLen 8791 -prefMapSize 246122 -jsInit 285636 -parentBuildID 20220623065118 -appdir /usr/lib/firefox-esr/browser 2093 true tab

可以看到该进程为火狐浏览器创建的某个进程,表明 seccomp 技术有一定的用户。

使用 seccomp 让程序无法加载内核模块

曾经在某次面试的时候被问到如何让程序无法加载内核模块,当时就想到了可以使用 seccomp 来搞,其实可以编写一条过滤 init_module、finit_module 的 seccomp filter,并将 action 设置为不允许访问来完成目标。

写到这里想到其实上面的描述遗漏了一个关键问题:seccomp filter 要加载到哪个进程中?
init?systemd?

其实可以编写一个 pam 模块来添加 filter 并在 /etc/pam.d 中用户的登录配置中增加一条配置来实现。

libseccomp 库

上手 seccomp 这篇文章中,示例程序使用如下代码设定一个 filter:

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;
}

上述代码直接使用宏封装的 bpf 指令码编写,代码逻辑难以理解。实际发行版中有提供一个 libseccomp 的三方库,它提供了一些对用户更友好的 api,可以使用这个库来实现 seccomp filter 规则。

seccomp bpf 支持的架构

  • x86-64, i386, x32 (since Linux 3.5)
  • ARM (since Linux 3.8)
  • s390 (since Linux 3.8)
  • MIPS (since Linux 3.16)
  • ARM-64 (since Linux 3.19)
  • PowerPC (since Linux 4.3)
  • Tile (since Linux 4.3)
  • PA-RISC (since Linux 4.6)

seccomp bpf filter 的两种运行模式

  1. jit
  2. vm

这两种方式隐含在 bpf 框架中,对 seccomp 不可见。

参考链接

System call filtering and no_new_privs

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PHP7是一种流行的服务器端脚本语言,它的官方手册非常详细,提供了丰富的文档和指南,以帮助开发者更好地了解和使用PHP7。 PHP7 Manual文手册是官方手册的文翻译版,被广泛使用于大量国PHP开发者的学习和开发过程。该手册涵盖了PHP7的各个方面,包括语法、数据类型、语句、函数、类和对象、错误处理等等。 PHP7 Manual文手册的主要特点如下: 1. 详细而清晰的介绍:手册提供了对PHP7的深入讲解,从基础到高级,囊括了各种重要的知识点。每个主题都有详细的介绍,并给出了示例代码和解释,方便开发者理解和运用。 2. 实用的示例代码:手册有大量的示例代码,可以帮助开发者更好地理解和学习。这些示例代码涵盖了各种情境,展示了PHP7的应用和特性。 3. 完备的索引和搜索功能:手册提供了完备的索引和搜索功能,方便开发者快速找到他们需要的信息。这样,开发者可以快速地定位到自己需要的知识点,提高了学习和开发的效率。 4. 官方认可的资源:由于是官方手册的文翻译版,PHP7 Manual文手册是官方认可的资源,可以确保其内容的准确性和权威性。 总之,PHP7 Manual文手册是学习和使用PHP7的重要参考资料,对于开发者来说是一个非常有价值的资源。无论是初学者还是有经验的开发者,都可以从获得丰富的知识和实践经验,提升自己在PHP开发领域的能力。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值