Firecracker Seccompiler 完全指南:从 JSON 策略文件到 seccomp-BPF 二进制过滤器
导读
Firecracker 使用 seccomp-BPF(Berkeley Packet Filter)把每个线程可用的系统调用面压缩到最小集合,以此缩小攻击面;而seccompiler 正是支撑这套机制的编译工具链。本指南以 docs/seccompiler.md 为骨架,结合当前仓库中 seccompiler 的 bin.rs、lib.rs、types.rs 实现,以及 Firecracker/VMM 侧的加载代码,完整讲解:JSON 策略文件的语法细节、seccompiler-bin 与 seccompiler 库的用法、BPF 二进制产物的生成与反序列化安装链路。读完你将能独立撰写一份线程级 seccomp 策略 JSON,编译为 BPF 过滤器,并正确接入 Firecracker 的启动流程或 --seccomp-filter 自定义机制。
1. 概览:seccompiler 在整个安全架构中的位置
Firecracker 的默认安全模型要求:进程内的每个线程只能调用"维持功能所需的最小系统调用子集及其合法参数",这是通过 Linux seccomp-BPF 实现的。在 docs/seccomp.md 中说明,这些过滤器按线程分类(vmm、api、vcpu)分别安装:
- VMM(主)线程:在进入主循环、准备启动 vCPU 前安装;
- API 线程:在启动 HTTP 控制面服务之前安装;
- 每个 vCPU 线程:在执行客户机代码之前安装。
策略的"书写与发布"则完全交由 seccompiler 完成。它包含两层:
seccompiler-bin:命令行可执行程序,把 JSON 格式的 seccomp 策略编译为"序列化后的二进制 BPF 代码",Firecracker 在构建期或启动期直接消费;- seccompiler 库(crate
seccompiler):导出数据类型与编译函数,供构建脚本及其他 crate 调用。
在代码层面,它是 Firecracker Cargo workspace 中的一个独立包,声明于 src/seccompiler/Cargo.toml。该 Cargo.toml 定义了库本体与可执行目标:
- 库名:
seccompiler; - 二进制名:
seccompiler-bin,入口为 src/seccompiler/src/bin.rs; - 描述为:"Program that compiles multi-threaded seccomp-bpf filters expressed as JSON into raw BPF programs, serializing them and outputting them to a file."
- 关键依赖包括
libseccomp的 Rust 绑定(libc+ 自生成 bindings)、serde/serde_json(JSON 解析)、bitcode(二进制序列化)、clap(CLI 解析)以及zerocopy(字节级转换)。
二进制过滤器采用 bitcode 格式序列化(lib.rs 中的
bitcode::serialize),而不是人类可读的文本格式。
2. 使用 seccompiler-bin 命令行工具
2.1 查看参数
seccompiler-bin 使用 clap 声明命令行参数(见 bin.rs),运行时可传入 --help 查看完整帮助:
./seccompiler-bin --help
2.2 命令行参数表
| 参数 | 类型/取值 | 说明 |
|---|---|---|
-a / --target-arch |
x86_64、aarch64(必填) |
BPF 程序将要运行的 CPU 架构 |
-i / --input-file |
文件路径(必填) | 输入 JSON 策略文件的路径 |
-o / --output-file |
文件路径(可选) | 输出文件路径,默认值 seccomp_binary_filter.out |
-b / --basic |
布尔(可选) | 已废弃:生成忽略一切参数检查的"基础过滤器" |
--split-output |
布尔(可选) | 为每个线程类别单独输出 .bpf 原始字节码文件(便于测试) |
示例(与文档一致的完整调用):
./seccompiler-bin \
--target-arch "x86_64" \
--input-file "x86_64_musl.json" \
--output-file "bpf_x86_64_musl"
其中各字段含义为:
--target-arch "x86_64"—— 指定 BPF 的目标架构(支持x86_64与aarch64);--input-file "x86_64_musl.json"—— JSON 输入文件路径;--output-file "bpf_x86_64_musl"—— 输出文件路径(可选,默认seccomp_binary_filter.out);--basic——(已废弃)忽略所有参数条件检查,仅按系统调用名放行;--split-output—— 额外为每个线程类别生成独立的 BPF 文件。
对应地,bin.rs 中的 CLI 定义直接验证了上述全部选项,其中输出文件名默认常量被定义为 DEFAULT_OUTPUT_FILENAME = "seccomp_binary_filter.out",--basic 的帮助文本明确标注为 "Deprecated! ... Drops all argument checks and rule-level actions. Not recommended."。
2.3 构建与运行方法
作为 workspace 包,可用 cargo 直接构建并调用(构建前需具备 libseccomp 开发库,seccompiler 在编译期链接它):
# 在仓库根目录
cargo build -p seccompiler
# 运行编译后的可执行文件
./build/seccompiler-bin --target-arch x86_64 --input-file resources/seccomp/x86_64-unknown-linux-musl.json --output-file my_filter.bpf
Firecracker 官方开发环境还提供了 tools/devtool 封装容器化构建流程,日常开发时可参考 tools/devtool 与仓库 CONTRIBUTING.md 中的构建指引。
2.4 seccompiler 库文档
文档建议:进入源码目录后通过 cargo doc 生成本地库文档浏览 API:
cd src/seccompiler/src
cargo doc --lib --open
3. 编译流水线与库接口:JSON 如何变成 BPF
3.1 compile_bpf 全流程
库的核心编译入口是 lib.rs 中的 compile_bpf(input_path, arch, out_path, basic, split_output),其完整处理链路为:
- 读取并解析 JSON:把整个文件读入字符串,用
serde_json反序列化为顶层结构BpfJson(内部是"线程类别名 → Filter"的有序映射); - 解析目标架构:
TargetArch::from_str,仅接受x86_64/aarch64(见 types.rs); - 创建匿名内存文件(memfd):通过
libc::memfd_create("bpf")得到一块内核内存文件,作为 libseccomp 导出 BPF 的中转缓冲; - 初始化 libseccomp 上下文:对每个线程类别的
Filter,调用seccomp_init(default_action)并以默认动作建立过滤器上下文,随后seccomp_arch_add注册目标架构; - 逐个注册规则:对
filter数组中的每个SyscallRule:- 通过
seccomp_syscall_resolve_name把 系统调用名字(如accept4)解析为当前架构下的调用号; - 若带
--basic:调用seccomp_rule_add(ctx, action, syscall, 0)——不带任何参数比较器; - 否则,若规则带
args:把每条参数条件转换成scmp_arg_cmp结构,调用seccomp_rule_add_array一次性注册全部 and-bound 比较器; - 若规则不带
args:仍以 0 个比较器注册,表示该调用名任意参数都命中;
- 通过
- 导出与读取 BPF:
seccomp_export_bpf把编译好的指令写入 memfd,再按 8 字节u64对齐读回为Vec<u64>(BPF 指令本身 8 字节长、4 字节对齐,用u64可以同时满足内核的字节数和对齐要求); - 输出:
- 若指定
--split-output:把每个线程类别的原始字节分别写成<thread_name>.bpf文件(用于测试); - 否则:把整张
BTreeMap<String, Vec<u64>>(线程名 → BPF 指令序列)用bitcode::serialize序列化写入输出文件。
- 若指定
该函数还内置一项反序列化防护:DESERIALIZATION_BYTES_LIMIT = 100_000 字节。由于单个 BPF 过滤器长度上限为 4096 条指令、且 Firecracker 线程数有限,这个上限足以拦截"超大过滤器导致内存分配耗尽(DOS)"的攻击。
3.2 库与 VMM 侧的分工
需要注意的是,当前仓库版本里"反序列化 + 安装"这类运行时辅助逻辑并不在 seccompiler crate 内部,而是实现在 VMM crate 中:vmm/src/seccomp.rs 定义了
BpfInstruction(u64)、BpfProgram(指令序列)、BpfThreadMap(HashMap<String, Arc<BpfProgram>>);deserialize_binary:带大小上限地读取二进制文件并用bitcode反序列化为BpfThreadMap,同时把线程名统一转为小写;apply_filter:真正把一个 BPF 程序装进内核——先prctl(PR_SET_NO_NEW_PRIVS, 1),再通过seccomp(SECCOMP_SET_MODE_FILTER, ...)系统调用安装;空过滤器直接跳过,超过BPF_MAX_LEN = 4096条指令时快速报错而非抛给内核晦涩错误码。
也就是说,seccompiler-bin 负责"编译期压缩",Firecracker/VMM 负责"启动期消费",二者通过 bitcode 二进制格式衔接。
3.3 JSON 中"动作"到 libseccomp 的映射
在 types.rs 中,JSON 动作(SeccompAction)实际对应如下枚举(serde 以小写 snake_case 反序列化,见下文):
pub enum SeccompAction {
Allow, // JSON: "allow" —— 直接放行
Errno(u16), // JSON: {"errno": n} —— 以指定错误码返回
KillThread, // JSON: "kill_thread" —— 仅杀死当前线程
KillProcess, // JSON: "kill_process" —— 杀死整个进程
Log, // JSON: "log" —— 同 allow 但记录日志
Trace(u16), // JSON: {"trace": n} —— 通知 tracer 进程
Trap, // JSON: "trap" —— 向线程发送 SIGSYS
}
注意:文档中的早期示例把动作写作
"errno": -1,而当前源码中Errno携带的是u16错误码;仓库里真实使用的默认过滤器(见下文resources/seccomp)中动作都写作简单字符串,如"default_action": "trap"、"filter_action": "allow"。撰写自定义策略时,应遵循源码中枚举的实际表示。
编译期由 to_scmp_type() 把上述枚举翻译成 libseccomp 的 SCMP_ACT_* 常量(见 types.rs)。
4. JSON 文件格式详解
4.1 顶层结构:一个文件表达整进程的多线程策略
一个 JSON 文件表达的是整个 Firecracker 进程的 seccomp 策略,里面包含"每个线程类别"各自独立的过滤器;同时该文件只针对一个目标平台(架构 + libc 组合)。因此 Firecracker 为每个受支持的 target 各维护一份 JSON,真实文件放在仓库的 resources/seccomp 目录下,当前版本包含:
x86_64-unknown-linux-musl.jsonaarch64-unknown-linux-musl.jsonunimplemented.json(占位/未实现的策略标记)
顶层要求是一个对象,把线程类别(vmm、api、vcpu)映射到各自的过滤器:
{
"vmm": {
"default_action": "trap",
"filter_action": "allow",
"filter": []
},
"api": {
"default_action": "trap",
"filter_action": "allow",
"filter": []
},
"vcpu": {
"default_action": "trap",
"filter_action": "allow",
"filter": []
}
}
真实文件中每个类别都拥有几十上百条规则。以 x86_64-unknown-linux-musl.json 为例,其 vmm 类别的 default_action 是 "trap",filter_action 是 "allow"——这正是文档描述的 allowlist(白名单)模式:只有显式列出的规则命中时才放行,未命中的调用触发默认动作(trap,向进程发 SIGSYS)。
4.2 Filter 对象:default_action / filter_action / filter
每个过滤器(对应一个线程类别)是包含三个键的 JSON 对象:
default_action:当filter中没有任何规则命中时执行的动作(兜底策略);filter_action:当filter中某条规则命中时执行的动作(白名单场景下通常为"allow");filter:规则数组。
4.3 SyscallRule:规则对象
filter 属性是或(or)语义的规则列表:数组内任意一条 SyscallRule 命中都会触发对应动作。规则对象的结构:
{
"syscall": "accept4",
"comment": "Used by vsock & api thread",
"args": []
}
syscall:必填,系统调用名。格式只认名字而非架构相关的调用号(提升可移植性与可读性),编译时由 libseccomp 解析成调用号;comment:可选,便于给规则加说明;args:可选,一组与(and)语义的参数条件——只有当所有条件都满足时该规则才算命中。若省略args,则该调用名无论参数如何都会触发对应动作。
若要为"同一组参数"表达多种合法取值,需要写多条平级规则:因为一个 SyscallRule 内的 args 条件之间是与关系,而不同规则之间是或关系。例如放行 accept4 在 flags 位带与不带 SOCK_CLOEXEC 的两种情况,就应写成两条规则而非一条。
4.4 参数条件(Condition)对象
条件对象由以下属性构成:
| 属性 | 说明 |
|---|---|
index |
要检查的系统调用参数的下标(0 起始) |
type |
dword(4 字节)或 qword(8 字节),表示参数宽度 |
op |
比较操作符 |
val |
参与比较的整数值 |
comment |
可选,说明该数值的含义 |
支持的比较操作符 op 有:eq、ge、gt、le、lt、ne 以及带掩码的 masked_eq。其中 masked_eq 需要额外的掩码载荷,JSON 中写为对象形式 {"masked_eq": <mask>};其余无载荷的操作符直接写作字符串。
与 SeccompCmpOp 枚举(types.rs)对应,其反序列化定义为 #[serde(rename_all = "snake_case")]:
pub enum SeccompCmpOp {
Eq, // "eq"
Ge, // "ge"
Gt, // "gt"
Le, // "le"
Lt, // "lt"
MaskedEq(u64), // {"masked_eq": <mask>}
Ne, // "ne"
}
条件对象(SeccompCondition)在源码中的实际字段为 index: u8、op、val: u64、type(映射到 SeccompCmpArgLen)。这里有一个值得注意的底层细节:type 为 dword 且 op 为 eq 时,types.rs 中的 to_scmp_type() 并不会直接生成 32 位比较指令,而是改用 SCMP_CMP_MASKED_EQ 并配合掩码 0x00000000FFFFFFFF——这是因为 libseccomp 的 EQ 默认比较完整的 64 位,而某些 libc(如 musl 的 ioctl)会在参数高位残留垃圾值;加一条掩码比较指令可消除误杀,且该指令通常会被内核 BPF JIT 优化掉。
文档示例中给条件对象标注注释的做法如下:
{
"syscall": "accept4",
"args": [
{
"index": 3,
"type": "dword",
"op": "eq",
"val": 1,
"comment": "libc::AF_UNIX"
}
]
}
注意:这个 comment 仅是给人看的说明(serde 反序列化时会忽略未声明字段),JSON 只接受数字常量,不接受具名参数或符号常量。
4.5 真实仓库中的规则长什么样
Firecracker 自带 JSON 过滤器是理解这套语法的活教材。以 resources/seccomp/x86_64-unknown-linux-musl.json 的 vmm 类别为例,能看到大量"调用名 + 参数条件"组合:
{
"syscall": "accept4",
"comment": "Called to accept vsock connections",
"args": [
{
"index": 3,
"type": "dword",
"op": "eq",
"val": 524288,
"comment": "libc::SOCK_CLOEXEC"
}
]
},
{
"syscall": "fcntl",
"comment": "Used by snapshotting, drive patching and rescanning",
"args": [
{
"index": 1,
"type": "dword",
"op": "eq",
"val": 2,
"comment": "FCNTL_F_SETFD"
},
{
"index": 2,
"type": "dword",
"op": "eq",
"val": 1,
"comment": "FCNTL_FD_CLOEXEC"
}
]
},
{
"syscall": "futex",
"comment": "Used for synchronization (during thread teardown when joining multiple vcpu threads at once)",
"args": [
{
"index": 1,
"type": "dword",
"op": "eq",
"val": 0,
"comment": "FUTEX_WAIT"
}
]
}
从中可以验证多个语法要点:
fcntl例子展示了args数组内多个条件是 and 关系(cmd == F_SETFD且第 3 个参数== FD_CLOEXEC);accept4例子展示了index: 3定位到第 4 个参数(flags),且type: dword只比较低 32 位;- 同一文件里
futex因为 WAIT/WAKE 等不同操作而出现多条平级规则(每条各带自己的参数条件),印证了"同名系统调用多规则 = 或多个合法取值"的写法; - 文件中还能看到
ioctl使用"op": {"masked_eq": 4}这种带掩码的语法,用于表达_IOC_WRITE等位运算型参数约束。
每条无 args 的规则(如 epoll_ctl、write、read、clock_gettime)则意味着"只要调用名匹配就放行,不检查参数"。
5. 输出格式:bitcode 序列化与 split-output
5.1 主输出文件
不带 --split-output 时,seccompiler-bin 输出单个文件,内容是 bitcode 序列化后的"线程名 → BPF 指令序列"映射。文档与源码均说明:
- 输出文件名可通过
--output-file覆盖,默认seccomp_binary_filter.out; - 内部表示是
BTreeMap<String, Vec<u64>>:键是线程类别(vmm/api/vcpu),值是 8 字节对齐的 BPF 指令数组。
5.2 --split-output 独立文件
当传入 --split-output 时,seccompiler-bin 会在主输出文件所在目录为每个线程类别生成独立的 .bpf 文件,文件命名为 <thread_name>.bpf,内容为未序列化的原始 BPF 字节码。这在 lib.rs 中实现为:遍历 bpf_map,把 bpf_data 以原始字节写入 parent.join(format!("{}.bpf", thread_name))。由于它是纯指令字节,很适合直接喂给 BPF 调试/校验工具做单线程验证,这也是文档强调其"useful for testing"的原因。
6. 与 Firecracker 启动流程的集成
6.1 构建期:build.rs 自动编译并内嵌
在默认(推荐)路径下,Firecracker 并不在运行时调用 seccompiler-bin,而是在构建期完成编译并把产物内嵌进二进制。机制如下:
- 默认的目标特定 JSON 文件在
cargo build时由 src/firecracker/build.rs 自动调用seccompiler::compile_bpf(&seccomp_json_path, &target_arch, &out_path, false, false)(即不使用--basic、不 split),生成文件名为seccomp_filter.bpf; - 编译产物经
include_bytes!(concat!(env!("OUT_DIR"), "/seccomp_filter.bpf"))在 src/firecracker/src/seccomp.rs 中直接嵌入二进制; - cargo 的构建缓存保证:只有 JSON 文件发生修改时才会重新编译过滤器,从而避免重复构建开销(这一点在 docs/seccomp.md 中也有说明)。
6.2 启动期:三种 SeccompConfig
src/firecracker/src/seccomp.rs 把启动配置建模为三种状态:
| 配置 | 触发条件 | 行为 |
|---|---|---|
SeccompConfig::Advanced |
未传任何相关参数(默认) | 反序列化并安装构建期内嵌的默认高级过滤器 |
SeccompConfig::Custom(File) |
传入 --seccomp-filter <path> |
从指定路径读取 seccompiler-bin 编译好的过滤器 |
SeccompConfig::None |
传入 --no-seccomp |
得到三张空过滤器,等于完全禁用 seccomp |
其中 SeccompConfig::from_args 的判定顺序是:--no-seccomp 优先;否则若有 --seccomp-filter 则视为自定义;否则使用默认高级过滤器。get_filters() 还通过 filter_thread_categories 校验反序列化结果:只接受 vmm/api/vcpu 三种键,出现未知类别或缺类别都会报错(对应单元测试 test_filter_thread_categories 覆盖了这一行为)。
在 src/firecracker/src/main.rs 中,主流程在启动早期即完成这一解析:
let mut seccomp_filters: BpfThreadMap = SeccompConfig::from_args(
arguments.flag_present("no-seccomp"),
arguments.single_value("seccomp-filter"),
)
.and_then(seccomp::get_filters)
.map_err(MainError::SeccompFilter)?;
随后各线程按文档描述在各自的"安全时机"调用 vmm::seccomp::apply_filter 完成安装(例如 API 线程在 src/firecracker/src/api_server/mod.rs 启动 HTTP 服务前调用)。
6.3 自定义过滤器的用例与风险
--seccomp-filter 主要面向高级用户,文档列出的典型场景包括:
- 使用实验性目标(如 GNU libc 构建)的用户,无需定制编译 Firecracker 即可施加自己的 seccomp 策略;
- 使用 debug 构建却仍需要 seccomp 的场景(注意 debug 与 release 的调用面存在差异,例如 debug 断言的
fcntl(F_GETFD),因此不能照搬 release 的过滤器); - 线上遇到"进程发起了一个策略未放行的系统调用"这类生产问题时,可用临时自定义过滤器快速缓解,不必重新构建与发布 Firecracker 二进制。但这只是权宜之计,需充分测试,不能作为长期方案。
必须强调,自定义过滤器会完全覆盖默认过滤器,配置错误可能导致进程被立刻杀死,或反过来彻底关闭安全边界,因此 docs/seccomp.md 明确建议非必要不覆盖;同时自定义过滤器文件需要使用者自行管理,下载/传输时应配合校验和等手段防范中间人篡改(Firecracker 二进制等其它产物同理)。
6.4 何时不要用:--no-seccomp 与 debug 构建的例外
- Firecracker 还提供
--no-seccomp参数,会禁用全部 seccomp 过滤,适合在快速原型验证、引入新系统调用时临时使用,严禁用于生产; - 在 debug 二进制与实验性 GNU 目标上,默认不安装任何 seccomp 过滤器,因为这些构建不适合生产(详见 docs/seccomp.md 的警告框)。
7. 如何编写并接入一份自定义过滤器(端到端实战)
综合以上内容,完整的自定义策略工作流如下:
第 1 步:编写 JSON 策略。以仓库自带文件为模板(参考 resources/seccomp/x86_64-unknown-linux-musl.json),确保:
- 顶层包含
vmm、api、vcpu三类过滤器,否则 Firecracker 侧校验会拒绝; - 每个过滤器给出
default_action(白名单一般写"trap")与filter_action(写"allow"); - 规则中只写系统调用名字、十进制整数参数与合法的
op/type。
第 2 步:编译。构建 seccompiler-bin 后执行:
./seccompiler-bin \
--target-arch x86_64 \
--input-file my_filter.json \
--output-file my_filter.bpf
调试规则时可用 --split-output 输出各线程独立的 <thread_name>.bpf,配合 BPF 检查工具定位问题;务必不要在生产策略中使用已废弃的 --basic(它会静默丢弃全部参数条件)。
第 3 步:接入启动。把编译产物交给 Firecracker:
./firecracker --api-sock /tmp/firecracker.socket \
--seccomp-filter my_filter.bpf
第 4 步:验证。启动后观察进程是否因 SIGSYS 被杀;通过 prctl(PR_GET_SECCOMP) 或 strace 复核过滤器是否已生效。VMM crate 自身的单元测试(见 vmm/src/seccomp.rs 的 test_deserialize_binary / test_filter_apply)分别覆盖了"反序列化把线程键转小写、超限文件被拒"与"空过滤器跳过安装、超长过滤器报 FilterTooLarge"等边界;Firecracker 的集成测试 tests/integration_tests/security/test_seccomp.py 则从端到端角度校验 seccomp 行为,可作为回归依据。
8. 支持平台与发布策略
- 支持平台:
seccompiler-bin支持范围与 Firecracker 本身一致,参见仓库根目录 README.md#supported-platforms 中的平台矩阵;当前--target-arch仅接受x86_64与aarch64两种架构令牌。 - 发布策略:seccompiler 随 Firecracker 一同发布,遵循 docs/RELEASE_POLICY.md,使用相同的版本号并处于相同的支持窗口内;与某一版本配套的默认 JSON 过滤器也会随该版本的发布归档一同提供。
- 序列化限制:无论编译端还是消费端(
DESERIALIZATION_BYTES_LIMIT = 100_000),都对反序列化输入做大小上限检查,防止被构造的超大过滤器触发内存分配放大攻击;安装端还有单过滤器BPF_MAX_LEN = 4096条指令的内核上限校验。
9. 小结
围绕 docs/seccompiler.md,本文把这套 JSON → BPF 编译工具链拆成了"策略编写(JSON 语法)、策略编译(seccompiler-bin/compile_bpf)、策略消费(build.rs 内嵌 + 启动期反序列化安装)"三段,并结合 src/seccompiler/src/types.rs、src/seccompiler/src/lib.rs、src/firecracker/src/seccomp.rs、src/vmm/src/seccomp.rs 以及真实策略 resources/seccomp/x86_64-unknown-linux-musl.json 逐条验证。掌握了白名单 + or/and 规则语义、dword/qword 与 masked_eq 的参数约束写法,以及 --seccomp-filter/--no-seccomp 的取舍,你就能安全地裁剪 Firecracker 各线程的系统调用面。更完整的运行时策略说明(默认过滤器、加载时机与注意事项)可继续阅读配套文档 docs/seccomp.md。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00