本文最后编辑于 前,其中的内容可能需要更新。
注
本文章为对 Litchi Pi
的《Writing a container in Rust》 的翻译转载,不享受任何著作权利,不用于任何商业目的,不以任何许可证进行授权,不对任何转载行为尤其是商业转载行为负责。一切权利均由原作者 Litchi Pi 保有。个人翻译能力有限,如有疑问可查看原文。
系统调用与资源限制 系统调用限制 什么是系统调用(syscall)? 当应用程序因错误而崩溃时,必须以不影响底层操作系统的方式来解决问题。 想象一下,如果你的的俄罗斯方块游戏在保存高分时崩溃了。 由于它没有结束对磁盘的操作,因此可能会损坏磁盘,或者会对其他程序使用磁盘造成麻烦。
这一原则的一个有趣的例子是通过非常著名的Windows 98 现场失败 进行现场演示,这也是预录制视频取代现场演示的原因.
为了避免这种情况,Linux 将软件分为两个“区域”:内核区域(Kernel-land)和用户区域(User-land)。
内核区域(Kernel-land)具有特权,这意味着它可以完全掌控整个机器(除了一些例外情况,例如 Arm TrustZone 的处理器级上下文分离),它可以读取和写入所有内存,并使用驱动程序与连接的外设进行交互。
用户区域(User-land)是无特权的,这意味着即使root帐户也不能直接完全控制机器,但这种权限允许运行所有系统调用。
系统调用(syscall)是用户区域(User-land)的应用程序执行需要内核来完成的操作的方式。
syscalls是一种特殊的汇编机器代码,每个系统调用都有一个“索引”,这个索引被传递到一个寄存器中,当执行syscall
命令时,它会切换到负责处理对应系统调用的内核代码。
下面是使用write
系统调用写入磁盘的应用程序的表示。
当在Python等其他语言中使用write
时,通常会调用C的write
函数,因为该函数在编译时会直接翻译为相应的系统调用。
驱动程序作为模块嵌入到内核中,并在内部管理其内部状态和操作。 通过这种形式,当发生错误并且另一个应用程序想要执行写入操作时,它可以重置其状态,处理底层物理设备所需的特殊操作(我正在看着你,eMMC !)
有关 Linux 内核驱动程序的更多信息,请参阅本文 (说真的,为了保护您的眼睛,请注意文章的颜色)。
此处 提供了可以使用 Linux 内核调用的所有系统调用的完整列表
Seccomp 和系统调用限制 由于系统调用允许用户控制系统,因此我们需要限制可能允许容器内的处理损害我们的底层操作系统的系统调用。
让我们了解一下Seccomp
正如seccomp的维基百科页面 所给出的:
seccomp(secure computing mode,即安全计算模式的缩写)是 Linux 内核中的计算机安全设施。 seccomp 允许进程单向转换到“安全”状态,在这种状态下,除了对已打开的文件描述符执行 exit()、sigreturn()、read() 和 write() 之外,它不能进行任何系统调用 。 如果它尝试进行任何其他系统调用,内核将使用SIGKILL 或SIGSYS 终止该进程。 从这个意义上说,它并不是虚拟化系统的资源,而是将进程与系统资源完全隔离。
通过 prctl(2)系统调用使用PR_SET_SECCOMP参数或者(自 Linux 内核 3.17 起)通过 seccomp(2) 系统调用可启用seccomp模式。
译者注
prctl是基本的进程管理函数,最原始的沙箱规则就是通过prctl函数来实现的,它可以决定可调用的系统调用函数。当第一个参数是PR_SET_SECCOMP,第二个参数为1的时候(严格模式),允许的系统调用只有read,write,exit和sigereturn。 在Linux 3.5内核版本中, 引入了seccomp第二种匹配模式:SECCOMP_MODE_FILTER。 该模式使用BPF程序做过滤规则匹配。
我们很容易看出 seccomp 是 Docker 等容器的支柱之一,它将进程隔离到只能读取和写入文件系统或退出的状态。
在默认情况下,这种安全计算模式具有很大的限制性,因为它拒绝了所有限制外的系统调用尝试。为了容器的良好功能,我们可能需要对其进行配置并添加例外。 为此,我们可以为 seccomp 设置一个定义了特殊规则、允许某些系统调用或触发特殊操作的配置文件。 对于我们的容器来说,我们要做的就是配置 seccomp 以默认允许所有系统调用,然后使用配置文件来拒绝某些系统调用。
要对哪些系统调用进行限制? 在本教程中,我们不会仔细研究我们将拒绝/允许的每个系统调用,因为原始教程的“系统调用”部分 给出了一些利用示例的深入描述。 此外,正如原始教程中所指出的,你可以通过docker文档 和 moby 的 seccomp 配置文件 来获取系统调用限制相关的配置资源。
以下是我们将在容器中拒绝的系统调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // Kernel keyring keyctl add_key request_key // NUMA (memory management) mbind migrate_pages move_pages set_mempolicy // Allow userland to handle memory faults in the kernel userfaultfd // Trace / profile syscalls perf_event_open
有关我们限制的一些额外资源:Kernel keyring NUMA Userland memory handling Syscalls tracing
应用seccomp 我们通过syscallz
包来对子进程的seccomp进行限制,此外这个操作也依赖libc
, 以下是Cargo.toml
新增内容:
1 2 3 4 [dependencies] syscallz = "0.16.1" libc = "0.2.102"
接下来我们新建一个src/syscalls.rs
文件,像这样创建一个函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 use syscallz::{Context, Action};pub fn setsyscalls () -> Result <(), Errcode> { log::debug!("Refusing / Filtering unwanted syscalls" ); if let Ok (mut ctx) = Context::init_with_action(Action::Allow) { if let Err (_) = ctx.load(){ return Err (Errcode::SyscallsError(0 )); } Ok (()) } else { Err (Errcode::SyscallsError(1 )) } }
接下来我们引入这个模块,然后在子配置函数中调用此函数。 修改src/main.rs
:
修改src/errors.rs
:
1 2 3 4 pub enum Errcode { SyscallsError(u8 ), }
接下来是src/child.rs
1 2 3 4 5 6 7 use crate::syscalls::setsyscalls;pub fn setup_container_configurations (config: &ContainerOpts) -> Result <(), Errcode> { setsyscalls()?; Ok (()) }
无条件系统调用限制(Unconditionnal syscalls restriction) 让我们先来拒绝我们不希望子进程执行的系统调用。 为此,我们创建函数refuse_syscall
来完全拒绝在子进程中调用该系统调用的任何尝试。
1 2 3 4 5 6 7 8 const EPERM: u16 = 1 ;fn refuse_syscall (ctx: &mut Context, sc: &Syscall) -> Result <(), Errcode>{ match ctx.set_action_for_syscall(Action::Errno(EPERM), *sc){ Ok (_) => Ok (()), Err (_) => Err (Errcode::SyscallsError(2 )), } }
接下来,我们列出要拒绝的系统调用,并遍历它们以填充配置文件。
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 use crate::syscallz::Syscall;pub fn setsyscalls () -> Result <(), Errcode> { let syscalls_refused = [ Syscall::keyctl, Syscall::add_key, Syscall::request_key, Syscall::mbind, Syscall::migrate_pages, Syscall::move_pages, Syscall::set_mempolicy, Syscall::userfaultfd, Syscall::perf_event_open, ]; if let Ok (mut ctx) = Context::init_with_action(Action::Allow){ for sc in syscalls_refused.iter() { refuse_syscall(&mut ctx, sc)?; } } }
条件系统调用限制(Conditionnal syscalls restriction) 当满足特定条件时,限制系统调用。 为此,我们创建一个规则,该规则接受一个值并返回是否应设置权限。 由于我们有此功能的基本用法,因此我们只需测试变量是否等于预期值。 让我们创建refuse_if_comp
函数来实现这一点:
1 2 3 4 5 6 7 8 9 use syscallz::{Comparator, Cmp};fn refuse_if_comp (ctx: &mut Context, ind: u32 , sc: &Syscall, biteq: u64 )-> Result <(), Errcode>{ match ctx.set_rule_for_syscall(Action::Errno(EPERM), *sc, &[Comparator::new(ind, Cmp::MaskedEq, biteq, Some (biteq))]){ Ok (_) => Ok (()), Err (_) => Err (Errcode::SyscallsError(3 )), } }
这个Comparator
将获取传递给系统调用的参数号ind ,并使用掩码biteq
与值biteq
进行比较。 这相当于测试biteq
位是否已设置。 让我们添加要为系统调用设置的所有规则:
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 use libc::TIOCSTI;use nix::sys::stat::Mode;use nix::sched::CloneFlags;pub fn setsyscalls () -> Result <(), Errcode> { let s_isuid: u64 = Mode::S_ISUID.bits().into(); let s_isgid: u64 = Mode::S_ISGID.bits().into(); let clone_new_user: u64 = CloneFlags::CLONE_NEWUSER.bits() as u64 ; let syscalls_refuse_ifcomp = [ (Syscall::chmod, 1 , s_isuid), (Syscall::chmod, 1 , s_isgid), (Syscall::fchmod, 1 , s_isuid), (Syscall::fchmod, 1 , s_isgid), (Syscall::fchmodat, 2 , s_isuid), (Syscall::fchmodat, 2 , s_isgid), (Syscall::unshare, 0 , clone_new_user), (Syscall::clone, 0 , clone_new_user), (Syscall::ioctl, 1 , TIOCSTI), ]; if let Ok (mut ctx) = Context::init_with_action(Action::Allow){ for (sc, ind, biteq) in syscalls_refuse_ifcomp.iter(){ refuse_if_comp(&mut ctx, *ind, sc, *biteq)?; } } }
测试 现在一切准备就绪,让我们简单测试一下
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 [2022-03-09T09:08:27Z INFO crabcan] Args { debug: true, command: "/bin/bash", uid: 0, mount_dir: "./mountdir/" } [2022-03-09T09:08:27Z DEBUG crabcan::container] Linux release: 5.13.0-30-generic [2022-03-09T09:08:27Z DEBUG crabcan::container] Container sockets: (3, 4) [2022-03-09T09:08:27Z DEBUG crabcan::hostname] Container hostname is now soft-world-116 [2022-03-09T09:08:27Z DEBUG crabcan::mounts] Setting mount points ... [2022-03-09T09:08:27Z DEBUG crabcan::mounts] Mounting temp directory /tmp/crabcan.Qo04pP4PBG9U [2022-03-09T09:08:27Z DEBUG crabcan::mounts] Pivoting root [2022-03-09T09:08:27Z DEBUG crabcan::mounts] Unmounting old root [2022-03-09T09:08:27Z DEBUG crabcan::namespaces] Setting up user namespace with UID 0 [2022-03-09T09:08:27Z DEBUG crabcan::namespaces] Child UID/GID map done, sending signal to child to continue... [2022-03-09T09:08:27Z DEBUG crabcan::container] Creation finished [2022-03-09T09:08:27Z DEBUG crabcan::container] Container child PID: Some(Pid(130688)) [2022-03-09T09:08:27Z DEBUG crabcan::container] Waiting for child (pid 130688) to finish [2022-03-09T09:08:27Z INFO crabcan::namespaces] User namespaces set up [2022-03-09T09:08:27Z DEBUG crabcan::namespaces] Switching to uid 0 / gid 0... [2022-03-09T09:08:27Z DEBUG crabcan::capabilities] Clearing unwanted capabilities ... [2022-03-09T09:08:27Z DEBUG crabcan::syscalls] Refusing / Filtering unwanted syscalls [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=chmod comparators=[Comparator { arg: 1, op: MaskedEq, datum_a: 2048, datum_b: 2048 }] [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=chmod comparators=[Comparator { arg: 1, op: MaskedEq, datum_a: 1024, datum_b: 1024 }] [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=fchmod comparators=[Comparator { arg: 1, op: MaskedEq, datum_a: 2048, datum_b: 2048 }] [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=fchmod comparators=[Comparator { arg: 1, op: MaskedEq, datum_a: 1024, datum_b: 1024 }] [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=fchmodat comparators=[Comparator { arg: 2, op: MaskedEq, datum_a: 2048, datum_b: 2048 }] [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=fchmodat comparators=[Comparator { arg: 2, op: MaskedEq, datum_a: 1024, datum_b: 1024 }] [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=unshare comparators=[Comparator { arg: 0, op: MaskedEq, datum_a: 268435456, datum_b: 268435456 }] [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=clone comparators=[Comparator { arg: 0, op: MaskedEq, datum_a: 268435456, datum_b: 268435456 }] [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=ioctl comparators=[Comparator { arg: 1, op: MaskedEq, datum_a: 21522, datum_b: 21522 }] [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=keyctl [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=add_key [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=request_key [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=mbind [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=migrate_pages [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=move_pages [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=set_mempolicy [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=userfaultfd [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=perf_event_open [2022-03-09T09:08:27Z DEBUG syscallz] seccomp: loading policy [2022-03-09T09:08:27Z INFO crabcan::child] Container set up successfully [2022-03-09T09:08:27Z INFO crabcan::child] Starting container with command /bin/bash and args ["/bin/bash"] [2022-03-09T09:08:27Z DEBUG crabcan::container] Finished, cleaning & exit [2022-03-09T09:08:27Z DEBUG crabcan::container] Cleaning container [2022-03-09T09:08:27Z DEBUG crabcan::errors] Exit without any error, returning 0
它会生成一些日志记录,因为syscallz
包和我们的我们的项目一样设置了log
。 它很好地表明我们的系统调用现在已被过滤,我们可以进入下一步!
Patch for this step 这一步的代码可以在github litchipi/crabcan branch “step13” 中找到. 前一步到这一步的原始补丁可以在此处 找到
资源限制 Cgroups Cgroups 是 Linux v2.6.4 中引入的一种机制,允许为一组进程“分配”资源。 对于给定的进程组,系统“看起来”只拥有 X 个给定资源。
资源数量不能高于系统最初拥有的数量,它不是虚拟化功能,而是限制功能。
在Linux系统中,您可以使用/sys/fs/cgroup/
来设置进程限制,方法如下:
1 2 # 100 Mib echo 100000000 > /sys/fs/cgroup/memory/<groupname>/memory.limit_in_bytes
由于此功能已被重新设计,因此两个版本在 Linux 内核中共存。 对于我们用户来说,主要区别在于v2
将给定组的所有配置分组在同一目录下。
有关它们的更多信息,您可以查看 LWN 上的这一系列精彩文章 。
此功能在同一服务器上的应用程序容器化中大量使用,并且能够向客户出售服务器上的一组特定性能,然后在客户购买性能提升时进行升级。
此功能对于容器非常重要,以至于最近的一个漏洞 让攻击者可以逃逸出容器并直接感染主机系统。 您必须记住,当我们向所包含的应用程序授予完全权限时 ,如果该应用程序成功逃逸出沙盒环境,它可能会在主机系统上保留其权限。
限制CPU使用时长 为了限制CPU的使用,cgroup使用权重来确定进程将获得多少CPU使用时间。 默认情况下,cgroup 将授予进程权重 1024,但该权重可以从1到2^64的范围内进行调整。 与其他程序相比,权重越大,CPU份额就越多。
如果 3 个进程的权重都为 25000,则它们的 CPU 时间与全部为 1024 时的 CPU 时间相同。较大的值范围允许对该值进行微调。
更多关于CPU共享的信息可以查看redhat的这篇文章
Rlimit Rlimit 是一个用于限制单个进程的系统。 它的重点更集中于该进程可以做什么,而不是它消耗的实时系统资源。
有关 rlimit 的详细信息,您可以查看这篇文章 ,我从中提取了所有可用 rlimit 的列表:
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 RLIMIT_CPU RLIMIT_FSIZE RLIMIT_DATA RLIMIT_STACK RLIMIT_CORE RLIMIT_RSS RLIMIT_NPROC RLIMIT_NOFILE RLIMIT_MEMLOCK RLIMIT_AS RLIMIT_LOCKS RLIMIT_SIGPENDING RLIMIT_MSGQUE RLIMIT_NICE RLIMIT_RTPRIO RLIMIT_RTTIME
我们将使用 rlimit 来限制进程可以打开的文件描述符的数量,因为,如原始教程 中所述:
文件描述符数量与 pid 数量一样,是针对每个用户的,因此我们希望防止容器内进程占用所有文件描述符数量。
所以我们需要设置RLIMIT_NOFILE
从理论上讲,rlimit 和 cgroups 的限制可能“重叠”(先达到上限的规则会成为实际限制),但实际上它们的应用领域不同,这种情况几乎不会发生。
注意,由于rlimit使用系统调用,因此进程可以重新配置这些设置 ,这就是我们将CAP_SYS_RESOURCE
添加到系统调用黑名单中的原因。
限制资源 有一个叫做cgroups_rs
的包可以简化与cgroups
定义相关的所有内容,但请记住,由于Unix中一切皆文件 (Linux 遵循 Unix 的哲学),即使我们没有这个包,我们要完成这项工作也只需要写入正确的文件 。
我们还将使用rlimit包 来包装对我们需要的系统调用的调用。
在新文件src/resources.rs
中,我们创建一个函数来限制容器内的资源。
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 42 43 44 45 use rlimit::{setrlimit, Resource};use cgroups_rs::cgroup_builder::CgroupBuilder;const KMEM_LIMIT: i64 = 1024 * 1024 * 1024 ;const MEM_LIMIT: i64 = KMEM_LIMIT;const MAX_PID: MaxValue = MaxValue::Value(64 );const NOFILE_RLIMIT: u64 = 64 ;pub fn restrict_resources (hostname: &String ) -> Result <(), Errcode>{ log::debug!("Restricting resources for hostname {}" , hostname); let cgs = CgroupBuilder::new(hostname) .cpu().shares(256 ).done() .memory().kernel_memory_limit(KMEM_LIMIT).memory_hard_limit(MEM_LIMIT).done() .pid().maximum_number_of_processes(MAX_PID).done() .blkio().weight(50 ).done() .build(Box ::new(V2::new())); let pid : u64 = pid.as_raw().try_into().unwrap(); if let Err (_) = cgs.add_task(CgroupPid::from(pid)) { return Err (Errcode::ResourcesError(0 )); }; if let Err (_) = setrlimit(Resource::NOFILE, NOFILE_RLIMIT, NOFILE_RLIMIT){ return Err (Errcode::ResourcesError(0 )); } Ok (()) }
我们可以在容器的create
函数中使用这个新函数,因为它只需要主机名来应用限制。
1 2 3 4 5 6 7 8 9 10 11 use crate::resources::restrict_resources;impl Container { pub fn create (&mut self ) -> Result <(), Errcode> { let pid = generate_child_process(self .config.clone())?; restrict_resources(&self .config.hostname, pid)?; } }
接下来在Cargo.toml
中添加依赖
1 2 3 4 [dependencies] cgroups-rs = "0.2.6" rlimit = "0.6.2"
同样的,在src/main.rs
中添加这个模块
在src/error.rs
中添加错误变体
1 2 3 4 pub enum Errcode { ResourcesError(u8 ), }
清除限制 子进程退出后,我们需要清除所有添加的cgroup限制。 这非常简单,因为cgroups v2将所有内容集中在/sys/fs/cgroup/<groupname>/
下的目录中,因此我们只需删除它即可。
在src/resources.rs
中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 pub fn clean_cgroups (hostname: &String ) -> Result <(), Errcode>{ log::debug!("Cleaning cgroups" ); match canonicalize(format! ("/sys/fs/cgroup/{}/" , hostname)){ Ok (d) => { if let Err (_) = remove_dir(d) { return Err (Errcode::ResourcesError(2 )); } }, Err (e) => { log::error!("Error while canonicalize path: {}" , e); return Err (Errcode::ResourcesError(3 )); } } Ok (()) }
该函数将在文件src/container.rs
的clean_exit
函数中调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 use crate::resources::clean_cgroups;impl Container { pub fn clean_exit (&mut self ) -> Result <(), Errcode> { if let Err (e) = clean_cgroups(&self .config.hostname){ log::error!("Cgroups cleaning failed: {}" , e); return Err (e); } Ok (()) } }
测试 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 [2022-03-09T13:58:37Z INFO crabcan] Args { debug: true, command: "/bin/bash", uid: 0, mount_dir: "./mountdir/" } [2022-03-09T13:58:37Z DEBUG crabcan::container] Linux release: 5.13.0-30-generic [2022-03-09T13:58:37Z DEBUG crabcan::container] Container sockets: (3, 4) [2022-03-09T13:58:37Z DEBUG crabcan::resources] Restricting resources for hostname small-girl-247 [2022-03-09T13:58:37Z DEBUG crabcan::hostname] Container hostname is now small-girl-247 [2022-03-09T13:58:37Z DEBUG crabcan::mounts] Setting mount points ... [2022-03-09T13:58:37Z DEBUG crabcan::mounts] Mounting temp directory /tmp/crabcan.LH9HSKzfsmN7 [2022-03-09T13:58:37Z DEBUG crabcan::mounts] Pivoting root [2022-03-09T13:58:37Z DEBUG crabcan::mounts] Unmounting old root [2022-03-09T13:58:37Z DEBUG crabcan::namespaces] Setting up user namespace with UID 0 [2022-03-09T13:58:37Z DEBUG crabcan::namespaces] Child UID/GID map done, sending signal to child to continue... [2022-03-09T13:58:37Z DEBUG crabcan::container] Creation finished [2022-03-09T13:58:37Z DEBUG crabcan::container] Container child PID: Some(Pid(162889)) [2022-03-09T13:58:37Z DEBUG crabcan::container] Waiting for child (pid 162889) to finish [2022-03-09T13:58:37Z INFO crabcan::namespaces] User namespaces set up [2022-03-09T13:58:37Z DEBUG crabcan::namespaces] Switching to uid 0 / gid 0... [2022-03-09T13:58:37Z DEBUG crabcan::capabilities] Clearing unwanted capabilities ... [2022-03-09T13:58:37Z DEBUG crabcan::syscalls] Refusing / Filtering unwanted syscalls [2022-03-09T13:58:37Z DEBUG syscallz] seccomp: setting action=Errno(1) syscall=chmod comparators=[Comparator { arg: 1, op: MaskedEq, datum_a: 2048, datum_b: 2048 }] ... [2022-03-09T13:58:37Z DEBUG syscallz] seccomp: loading policy [2022-03-09T13:58:37Z INFO crabcan::child] Container set up successfully [2022-03-09T13:58:37Z INFO crabcan::child] Starting container with command /bin/bash and args ["/bin/bash"] [2022-03-09T13:58:37Z DEBUG crabcan::container] Finished, cleaning & exit [2022-03-09T13:58:37Z DEBUG crabcan::container] Cleaning container [2022-03-09T13:58:37Z DEBUG crabcan::resources] Cleaning cgroups [2022-03-09T13:58:37Z DEBUG crabcan::errors] Exit without any error, returning 0
Patch for this step 这一步的代码可以在github litchipi/crabcan branch “step14” 中找到. 前一步到这一步的原始补丁可以在此处 找到