文章目录
-
- 每日一句正能量
- 摘要
- 一、引言:嵌入式设备的安全困境
- 二、Linux安全架构全景
-
- [2.1 四层防御体系](#2.1 四层防御体系)
- 三、SELinux:强制访问控制的基石
-
- [3.1 SELinux核心机制](#3.1 SELinux核心机制)
- [3.2 嵌入式设备SELinux配置](#3.2 嵌入式设备SELinux配置)
- [3.3 自定义嵌入式策略](#3.3 自定义嵌入式策略)
- [3.4 AVC日志分析与故障排查](#3.4 AVC日志分析与故障排查)
- [3.5 SELinux与其他LSM对比](#3.5 SELinux与其他LSM对比)
- 四、Capabilities:拆分root权限
-
- [4.1 从root到41个独立权限](#4.1 从root到41个独立权限)
- [4.2 嵌入式设备Capabilities配置](#4.2 嵌入式设备Capabilities配置)
- [4.3 编程接口:动态管理Capabilities](#4.3 编程接口:动态管理Capabilities)
- 五、Seccomp:系统调用沙箱
-
- [5.1 Seccomp核心机制](#5.1 Seccomp核心机制)
- [5.2 嵌入式设备Seccomp实现](#5.2 嵌入式设备Seccomp实现)
- [5.3 使用libseccomp简化配置](#5.3 使用libseccomp简化配置)
- 六、综合安全加固效果
-
- [6.1 攻击面缩减量化](#6.1 攻击面缩减量化)
- [6.2 完整加固配置脚本](#6.2 完整加固配置脚本)
- 七、场景化选型指南
- 八、总结与展望

每日一句正能量
人生要活得洒脱,就是三要素,无所谓,没必要,不至于。
对别人的评价、无伤大雅的得失,不必挂心。对消耗你的人、争不出对错的事,及时止损。把灾难化想象拉回现实------天塌不下来,别自己吓自己。用好这三词,能省下90%的内耗。
摘要
摘要: 在物联网和边缘计算时代,嵌入式Linux设备面临日益严峻的安全威胁。本文系统性地剖析Linux安全架构的四层防御体系------从DAC到MAC、Capabilities再到Seccomp,深入讲解SELinux的类型强制机制、Capabilities的细粒度权限拆分以及Seccomp的系统调用沙箱技术,结合嵌入式场景提供可直接落地的配置代码与安全策略。
一、引言:嵌入式设备的安全困境
嵌入式Linux设备正成为网络攻击的主要目标:
- 攻击面扩大:IoT设备数量预计2026年超过300亿,每个设备都是潜在入口
- 资源受限:ARM SoC通常只有512MB~2GB RAM,无法运行重量级安全软件
- 生命周期长:工业设备运行10年以上,安全补丁难以持续更新
- 物理暴露:边缘设备部署在不可控环境,易被物理接触
- 传统方案不足:仅靠UGO权限(DAC)无法阻止被攻破后的横向移动
Linux内核提供了四层安全防御体系:DAC(自主访问控制)→ MAC(强制访问控制)→ Capabilities(细粒度权限)→ Seccomp(系统调用沙箱)。本文将逐层深入讲解。
二、Linux安全架构全景
2.1 四层防御体系

图1:嵌入式 Linux 安全架构层次
各层安全机制对比:
| 层次 | 机制 | 控制粒度 | 核心思想 | 嵌入式适用性 |
|---|---|---|---|---|
| L1 | DAC (UGO) | 用户/组级别 | 资源所有者决定权限 | 基础,但不足 |
| L2 | MAC (SELinux) | 进程/文件类型 | 策略决定一切,无视所有者 | 强烈推荐 |
| L3 | Capabilities | 单个权限位 | 拆分root为41个独立权限 | 强烈推荐 |
| L4 | Seccomp | 系统调用级别 | 白名单过滤,禁止未授权调用 | 强烈推荐 |
安全的核心原则:纵深防御(Defense in Depth)。单一安全机制无法阻止所有攻击,多层叠加才能最大限度降低风险。
三、SELinux:强制访问控制的基石
3.1 SELinux核心机制
SELinux(Security-Enhanced Linux)由美国国家安全局(NSA)开发,是Linux上最成熟的MAC实现。其核心是类型强制(Type Enforcement, TE):

图2:SELinux 安全上下文与访问决策流程
安全上下文格式:
user:role:type:level
│ │ │ │
│ │ │ └─ MLS/MCS安全级别(如s0-s15)
│ │ └─ 类型(最关键,如httpd_t)
│ └─ 角色(如system_r)
└─ 用户标识(如system_u)
类型强制(TE)规则示例:
te
# httpd进程(httpd_t)可以读取httpd_sys_content_t类型的文件
allow httpd_t httpd_sys_content_t:file { read getattr open };
# httpd进程不能读取shadow_t类型的文件(密码文件)
# 无allow规则 = 默认拒绝
# 尝试读取将产生AVC拒绝日志
3.2 嵌入式设备SELinux配置
bash
# 1. 内核配置启用SELinux
# File systems → Security options
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SELINUX_BOOTPARAM=y
CONFIG_SECURITY_SELINUX_DISABLE=y
CONFIG_SECURITY_SELINUX_DEVELOP=y
CONFIG_SECURITY_SELINUX_AVC_STATS=y
CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=0
# 2. 启动参数配置(bootargs)
selinux=1 enforcing=0 # 首次启用建议Permissive模式
# 或
selinux=1 enforcing=1 # 生产环境强制模式
# 3. 安装SELinux工具
# Yocto/Buildroot添加:
# IMAGE_INSTALL:append = " libselinux libsemanage policycoreutils"
# 或
# apt-get install selinux-utils selinux-basics policycoreutils
# 4. 查看SELinux状态
getenforce # 查看当前模式:Enforcing/Permissive/Disabled
sestatus # 详细状态
cat /proc/1/attr/current # 查看init进程的安全上下文
# 5. 切换模式(运行时)
setenforce 0 # 切换到Permissive(仅记录,不阻止)
setenforce 1 # 切换到Enforcing(强制模式)
# 6. 查看安全上下文
ls -Z /etc/passwd # 文件上下文
ps -eZ | head # 进程上下文
id -Z # 当前用户上下文
3.3 自定义嵌入式策略
te
# embedded_device.te - 嵌入式设备自定义SELinux策略
policy_module(embedded_device, 1.0.0)
# 定义类型
type embedded_app_t; # 应用进程类型
type embedded_app_exec_t; # 应用可执行文件类型
type embedded_data_t; # 应用数据文件类型
type embedded_conf_t; # 配置文件类型
type embedded_log_t; # 日志文件类型
type embedded_device_t; # 设备文件类型
# 定义角色
role system_r types embedded_app_t;
# 应用可执行文件类型
typeattribute embedded_app_exec_t file_type, exec_type;
# 文件类型属性
typeattribute embedded_data_t file_type;
typeattribute embedded_conf_t file_type;
typeattribute embedded_log_t file_type;
# 规则:应用进程可以执行应用二进制
allow embedded_app_t embedded_app_exec_t:file { read execute execute_no_trans };
# 规则:应用可以读写自己的数据
allow embedded_app_t embedded_data_t:file { create read write getattr unlink };
allow embedded_app_t embedded_data_t:dir { create read write getattr search add_name remove_name };
# 规则:应用可以读取配置
allow embedded_app_t embedded_conf_t:file { read getattr open };
# 规则:应用可以写日志
allow embedded_app_t embedded_log_t:file { create append getattr };
allow embedded_app_t embedded_log_t:dir { create read write getattr search add_name };
# 规则:应用可以访问设备
allow embedded_app_t embedded_device_t:chr_file { read write ioctl getattr };
allow embedded_app_t embedded_device_t:blk_file { read write ioctl getattr };
# 规则:应用可以网络通信(可选)
allow embedded_app_t self:tcp_socket { create connect read write getattr setopt getopt };
allow embedded_app_t self:udp_socket { create connect read write getattr };
# 规则:应用可以发送信号给自己
allow embedded_app_t self:process { signal };
# 禁止:应用不能访问其他应用数据
# 无allow规则 = 默认拒绝
# 禁止:应用不能访问系统密码文件
# 无allow规则 = 默认拒绝
# 文件上下文规则
# /opt/myapp/bin/myapp -> embedded_app_exec_t
# /data/myapp/* -> embedded_data_t
# /etc/myapp/* -> embedded_conf_t
# /var/log/myapp/* -> embedded_log_t
# /dev/mydevice -> embedded_device_t
bash
# 编译和加载自定义策略
# 1. 编译模块
checkmodule -M -m -o embedded_device.mod embedded_device.te
semodule_package -o embedded_device.pp -m embedded_device.mod
# 2. 加载模块
semodule -i embedded_device.pp
# 3. 设置文件上下文
semanage fcontext -a -t embedded_app_exec_t "/opt/myapp/bin/myapp"
semanage fcontext -a -t embedded_data_t "/data/myapp(/.*)?"
semanage fcontext -a -t embedded_conf_t "/etc/myapp(/.*)?"
semanage fcontext -a -t embedded_log_t "/var/log/myapp(/.*)?"
# 4. 应用上下文
restorecon -R /opt/myapp /data/myapp /etc/myapp /var/log/myapp
# 5. 验证
ls -Z /opt/myapp/bin/myapp
ps -eZ | grep myapp
3.4 AVC日志分析与故障排查
bash
# 1. 查看AVC拒绝日志
cat /var/log/audit/audit.log | grep AVC
ausearch -m avc -ts recent
# 2. 使用audit2why分析原因
cat /var/log/audit/audit.log | audit2why
# 3. 使用audit2allow生成策略模块(谨慎使用!)
cat /var/log/audit/audit.log | audit2allow -M mylocal
semodule -i mylocal.pp
# 4. 查看详细审计日志
ausearch -m avc -ts today -i
# 5. 嵌入式设备日志转发(资源受限)
# 配置rsyslog将audit日志发送到远程服务器
cat <<EOF >> /etc/rsyslog.conf
:programname, isequal, "audit" @@logserver:514
EOF
3.5 SELinux与其他LSM对比
| 特性 | SELinux | AppArmor | Smack | TOMOYO |
|---|---|---|---|---|
| 控制粒度 | 对象级(类型) | 路径级 | 标签级 | 路径级 |
| 学习曲线 | 陡峭 | 中等 | 平缓 | 平缓 |
| 性能影响 | 较高 | 中等 | 低 | 低 |
| 嵌入式适用 | 高安全需求 | 通用 | IoT设备 | 分析用途 |
| 策略维护 | 复杂 | 中等 | 简单 | 简单 |
| 容器支持 | 优秀 | 良好 | 一般 | 一般 |
对于高安全需求的嵌入式设备(如工业控制、医疗设备),推荐SELinux;对于资源极度受限的IoT设备,Smack是更轻量的选择。
四、Capabilities:拆分root权限
4.1 从root到41个独立权限
传统Linux中,root用户拥有所有权限。Capabilities机制将root的特权拆分为41个独立的权限位,实现最小权限原则:

图3:Linux Capabilities 权限拆分
核心Capabilities列表:
| Capability | 功能 | 嵌入式场景 |
|---|---|---|
CAP_NET_ADMIN |
网络配置(接口/IP/路由) | 网络管理应用 |
CAP_NET_RAW |
原始套接字(ping/抓包) | 网络诊断工具 |
CAP_DAC_OVERRIDE |
绕过文件权限检查 | 备份/恢复工具 |
CAP_SYS_ADMIN |
系统管理(挂载/命名空间) | 容器运行时 |
CAP_SYS_TIME |
修改系统时间 | NTP服务 |
CAP_SYSLOG |
读取内核日志 | 日志收集器 |
CAP_IPC_LOCK |
锁定共享内存 | 实时应用 |
CAP_CHOWN |
修改文件所有者 | 文件管理器 |
4.2 嵌入式设备Capabilities配置
bash
# 1. 查看进程的Capabilities
getcap /usr/bin/ping
# 输出:/usr/bin/ping = cap_net_raw+ep
# 2. 查看当前进程的Capabilities
capsh --print
# 3. 为应用分配Capabilities(替代setuid root)
# 示例:网络监控工具需要原始套接字,但不需要root
setcap cap_net_raw,cap_net_admin=+ep /usr/bin/my-network-tool
# 4. 查看文件Capabilities
getcap /usr/bin/my-network-tool
# 5. 移除Capabilities
setcap -r /usr/bin/my-network-tool
# 6. 在systemd服务中使用Capabilities
cat <<EOF > /etc/systemd/system/my-app.service
[Unit]
Description=My Embedded Application
[Service]
Type=simple
ExecStart=/usr/bin/my-app
User=appuser
Group=appuser
# 分配Capabilities(比root更安全)
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW CAP_DAC_READ_SEARCH
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW CAP_DAC_READ_SEARCH
# 安全加固
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable my-app.service
4.3 编程接口:动态管理Capabilities
c
// capabilities_demo.c
// 演示如何在程序中动态管理Capabilities
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/capability.h>
#include <sys/prctl.h>
// 打印当前Capabilities
void print_capabilities() {
cap_t caps = cap_get_proc();
if (!caps) {
perror("cap_get_proc");
return;
}
char *cap_text = cap_to_text(caps, NULL);
printf("Current capabilities: %s\n", cap_text);
cap_free(cap_text);
cap_free(caps);
}
// 丢弃所有Capabilities(进入最小权限模式)
int drop_all_capabilities() {
cap_t empty = cap_init();
if (!empty) {
perror("cap_init");
return -1;
}
if (cap_set_proc(empty) != 0) {
perror("cap_set_proc");
cap_free(empty);
return -1;
}
cap_free(empty);
printf("All capabilities dropped\n");
n return 0;
n}
// 只保留指定的Capabilities
int retain_capabilities(cap_value_t caps_to_keep[], int num_caps) {
cap_t new_caps = cap_init();
if (!new_caps) {
perror("cap_init");
return -1;
}
// 设置有效集和允许集
if (cap_set_flag(new_caps, CAP_PERMITTED, num_caps, caps_to_keep, CAP_SET) != 0 ||
cap_set_flag(new_caps, CAP_EFFECTIVE, num_caps, caps_to_keep, CAP_SET) != 0) {
perror("cap_set_flag");
cap_free(new_caps);
return -1;
}
if (cap_set_proc(new_caps) != 0) {
perror("cap_set_proc");
cap_free(new_caps);
return -1;
}
cap_free(new_caps);
printf("Retained only specified capabilities\n");
return 0;
}
// 提升特定Capability(从允许集到有效集)
int raise_capability(cap_value_t cap) {
cap_t caps = cap_get_proc();
if (!caps) {
perror("cap_get_proc");
return -1;
}
// 检查是否在允许集中
cap_flag_value_t flag;
if (cap_get_flag(caps, cap, CAP_PERMITTED, &flag) != 0 || flag != CAP_SET) {
fprintf(stderr, "Capability not permitted\n");
cap_free(caps);
return -1;
}
// 添加到有效集
cap_value_t cap_list[1] = {cap};
if (cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_list, CAP_SET) != 0) {
perror("cap_set_flag");
cap_free(caps);
return -1;
}
if (cap_set_proc(caps) != 0) {
perror("cap_set_proc");
cap_free(caps);
return -1;
}
cap_free(caps);
printf("Raised capability: %s\n", cap_to_name(cap));
return 0;
}
// 降低特定Capability(从有效集移除)
int lower_capability(cap_value_t cap) {
cap_t caps = cap_get_proc();
if (!caps) {
perror("cap_get_proc");
return -1;
}
cap_value_t cap_list[1] = {cap};
if (cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_list, CAP_CLEAR) != 0) {
perror("cap_set_flag");
cap_free(caps);
return -1;
}
if (cap_set_proc(caps) != 0) {
perror("cap_set_proc");
cap_free(caps);
return -1;
}
cap_free(caps);
printf("Lowered capability: %s\n", cap_to_name(cap));
return 0;
}
int main(int argc, char *argv[]) {
printf("=== Capabilities Demo ===\n\n");
// 初始状态
printf("Initial state:\n");
print_capabilities();
// 场景1:网络服务初始化后丢弃不需要的权限
if (argc > 1 && strcmp(argv[1], "network") == 0) {
printf("\n--- Network Service Scenario ---\n");
// 初始化网络接口(需要CAP_NET_ADMIN)
// ... 网络配置代码 ...
// 初始化完成后,只保留CAP_NET_RAW(用于接收数据包)
cap_value_t keep[] = {CAP_NET_RAW};
retain_capabilities(keep, 1);
print_capabilities();
// 运行主循环(只能接收数据包,不能修改网络配置)
// ... 主循环代码 ...
}
// 场景2:完全沙箱化
if (argc > 1 && strcmp(argv[1], "sandbox") == 0) {
printf("\n--- Full Sandbox Scenario ---\n");
// 初始化完成后丢弃所有Capabilities
drop_all_capabilities();
print_capabilities();
printf("Running in sandbox mode (no capabilities)\n");
// ... 沙箱内代码 ...
}
return 0;
}
bash
# 编译Capabilities演示程序
gcc -o capabilities_demo capabilities_demo.c -lcap
# 设置文件Capabilities
setcap cap_net_admin,cap_net_raw=+ep capabilities_demo
# 运行
./capabilities_demo network
./capabilities_demo sandbox
五、Seccomp:系统调用沙箱
5.1 Seccomp核心机制
Seccomp(Secure Computing Mode)通过BPF程序过滤系统调用,实现进程级别的沙箱。它有两种模式:

图4:Seccomp 系统调用过滤模式
两种模式对比:
| 模式 | 特点 | 适用场景 |
|---|---|---|
| Strict | 仅允许read/write/exit/sigreturn | 纯计算任务 |
| Filter | BPF程序自定义过滤规则 | 通用沙箱 |
| Embedded | Seccomp + Capabilities + Namespaces | IoT/边缘设备 |
5.2 嵌入式设备Seccomp实现
c
// seccomp_sandbox.c
// 嵌入式应用Seccomp沙箱实现
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/syscall.h>
#include <sys/prctl.h>
#include <linux/seccomp.h>
#include <linux/filter.h>
#include <linux/audit.h>
// 定义BPF指令宏(简化)
#define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
#define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
// 允许的系统调用白名单(嵌入式IoT应用典型需求)
// 根据应用实际需求定制
// x86_64架构系统调用号
#ifdef __x86_64__
#define SYSCALL_READ 0
#define SYSCALL_WRITE 1
#define SYSCALL_OPEN 2
#define SYSCALL_CLOSE 3
#define SYSCALL_STAT 4
#define SYSCALL_FSTAT 5
#define SYSCALL_LSEEK 8
#define SYSCALL_MMAP 9
#define SYSCALL_MPROTECT 10
#define SYSCALL_MUNMAP 11
#define SYSCALL_BRK 12
#define SYSCALL_RT_SIGACTION 13
#define SYSCALL_RT_SIGPROCMASK 14
#define SYSCALL_IOCTL 16
#define SYSCALL_PREAD64 17
#define SYSCALL_PWRITE64 18
#define SYSCALL_EXIT 60
#define SYSCALL_EXIT_GROUP 231
#define SYSCALL_SOCKET 41
#define SYSCALL_CONNECT 42
#define SYSCALL_ACCEPT 43
#define SYSCALL_SENDTO 44
#define SYSCALL_RECVFROM 45
#define SYSCALL_BIND 49
#define SYSCALL_GETSOCKOPT 55
#define SYSCALL_CLONE 56
#define SYSCALL_FORK 57
#define SYSCALL_VFORK 58
#define SYSCALL_EXECVE 59
#define SYSCALL_WAIT4 61
#define SYSCALL_KILL 62
#define SYSCALL_FCNTL 72
#define SYSCALL_FLOCK 73
#define SYSCALL_FSYNC 74
#define SYSCALL_MKDIR 83
#define SYSCALL_RMDIR 84
#define SYSCALL_CREAT 85
#define SYSCALL_UNLINK 87
#define SYSCALL_READLINK 89
#define SYSCALL_CHMOD 90
#define SYSCALL_CHOWN 92
#define SYSCALL_GETTIMEOFDAY 96
#define SYSCALL_CLOCK_GETTIME 228
#define SYSCALL_NANOSLEEP 35
#define SYSCALL_GETPID 39
#define SYSCALL_GETPPID 110
#define SYSCALL_GETUID 102
#define SYSCALL_GETGID 104
#define SYSCALL_GETEUID 107
#define SYSCALL_GETEGID 108
#define SYSCALL_SETUID 105
#define SYSCALL_SETGID 106
#define SYSCALL_SETRLIMIT 160
#define SYSCALL_GETRLIMIT 97
#define SYSCALL_PRCTL 157
#define SYSCALL_ARCH_PRCTL 158
#define SYSCALL_SYSINFO 99
#define SYSCALL_GETRANDOM 318
#define SYSCALL_MADVISE 28
#define SYSCALL_FUTEX 202
#define SYSCALL_SET_TID_ADDRESS 218
#define SYSCALL_SET_ROBUST_LIST 273
#define SYSCALL_GET_ROBUST_LIST 274
#define SYSCALL_RT_SIGRETURN 15
#define SYSCALL_TGKILL 234
#define SYSCALL_TKILL 200
#define SYSCALL_GETDENTS64 217
#define SYSCALL_OPENAT 257
#define SYSCALL_MKDIRAT 258
#define SYSCALL_UNLINKAT 263
#define SYSCALL_RENAMEAT 264
#define SYSCALL_FSTATAT 262
#define SYSCALL_READLINKAT 267
#define SYSCALL_FCHMODAT 268
#define SYSCALL_FCHOWNAT 260
#define SYSCALL_NEWFSTATAT 262
#define SYSCALL_PIPE2 293
#define SYSCALL_DUP3 292
#define SYSCALL_EPOLL_CREATE1 291
#define SYSCALL_EPOLL_CTL 233
#define SYSCALL_EPOLL_PWAIT 281
#define SYSCALL_EVENTFD2 290
#define SYSCALL_INOTIFY_INIT1 294
#define SYSCALL_INOTIFY_ADD_WATCH 254
#define SYSCALL_TIMERFD_CREATE 283
#define SYSCALL_TIMERFD_SETTIME 286
#define SYSCALL_TIMERFD_GETTIME 287
#define SYSCALL_PSELECT6 270
#define SYSCALL_PPOLL 271
#define SYSCALL_SIGNalfd4 289
#define SYSCALL_ACCEPT4 288
#define SYSCALL_RECVMMSG 337
#define SYSCALL_SENDMMSG 345
#define SYSCALL_GETSOCKNAME 51
#define SYSCALL_GETPEERNAME 52
#define SYSCALL_SHUTDOWN 48
#define SYSCALL_SETSOCKOPT 54
#define SYSCALL_LISTEN 50
#define SYSCALL_MREMAP 25
#define SYSCALL_SCHED_YIELD 24
#define SYSCALL_SCHED_GETAFFINITY 204
#define SYSCALL_SCHED_SETAFFINITY 203
#define SYSCALL_GETCPU 309
#define SYSCALL_MEMBARRIER 324
#define SYSCALL_COPY_FILE_RANGE 326
#define SYSCALL_SYNCFS 306
#define SYSCALL_STATFS 137
#define SYSCALL_FSTATFS 138
#define SYSCALL_UTIMENSAT 280
#define SYSCALL_RENAMEAT2 316
#define SYSCALL_EXECVEAT 322
#define SYSCALL_PREADV2 327
#define SYSCALL_PWRITEV2 328
#define SYSCALL_PKEY_ALLOC 330
#define SYSCALL_PKEY_FREE 331
#define SYSCALL_PKEY_MPROTECT 329
#define SYSCALL_RSEQ 334
#define SYSCALL_CLONE3 435
#define SYSCALL_OPENAT2 437
#define SYSCALL_PIDFD_OPEN 434
#define SYSCALL_FACCESSAT2 439
#define SYSCALL_PROCESS_MADVISE 440
#define SYSCALL_EPOLL_PWAIT2 441
#define SYSCALL_MOUNT_SETATTR 442
#define SYSCALL_QUOTACTL_FD 443
#define SYSCALL_LANDLOCK_CREATE_RULESET 444
#define SYSCALL_LANDLOCK_ADD_RULE 445
#define SYSCALL_LANDLOCK_RESTRICT_SELF 446
#define SYSCALL_MEMFD_SECRET 447
#define SYSCALL_PROCESS_MRELEASE 448
#define SYSCALL_FUTEX_WAITV 449
#define SYSCALL_SET_MPOLICY_HOME_NODE 450
#define SYSCALL_CACHESTAT 451
#define SYSCALL_FCHMODAT2 452
#define SYSCALL_MAP_SHADOW_STACK 453
#define SYSCALL_FUTEX_WAKE 454
#define SYSCALL_FUTEX_WAIT 455
#define SYSCALL_FUTEX_REQUEUE 456
#define SYSCALL_STATMOUNT 457
#define SYSCALL_LISTMOUNT 458
#define SYSCALL_LSM_GET_SELF_ATTR 459
#define SYSCALL_LSM_SET_SELF_ATTR 460
#define SYSCALL_LSM_LIST_MODULES 461
#define SYSCALL_MSEAL 462
#endif
// ARM64架构系统调用号
#ifdef __aarch64__
#define SYSCALL_READ 63
#define SYSCALL_WRITE 64
#define SYSCALL_OPENAT 56
#define SYSCALL_CLOSE 57
#define SYSCALL_FSTAT 80
#define SYSCALL_LSEEK 62
#define SYSCALL_MMAP 222
#define SYSCALL_MPROTECT 226
#define SYSCALL_MUNMAP 215
#define SYSCALL_BRK 214
#define SYSCALL_RT_SIGACTION 134
#define SYSCALL_RT_SIGPROCMASK 135
#define SYSCALL_IOCTL 29
#define SYSCALL_EXIT 93
#define SYSCALL_EXIT_GROUP 94
#define SYSCALL_SOCKET 198
#define SYSCALL_CONNECT 203
#define SYSCALL_BIND 200
#define SYSCALL_SENDTO 206
#define SYSCALL_RECVFROM 207
#define SYSCALL_GETSOCKOPT 209
#define SYSCALL_CLONE 220
#define SYSCALL_FORK 220 // clone on ARM64
#define SYSCALL_EXECVE 221
#define SYSCALL_WAIT4 260
#define SYSCALL_KILL 129
#define SYSCALL_FCNTL 25
#define SYSCALL_FSYNC 82
#define SYSCALL_MKDIRAT 258
#define SYSCALL_UNLINKAT 263
#define SYSCALL_READLINKAT 267
#define SYSCALL_FCHMODAT 268
#define SYSCALL_FCHOWNAT 260
#define SYSCALL_GETTIMEOFDAY 169
#define SYSCALL_CLOCK_GETTIME 113
#define SYSCALL_NANOSLEEP 101
#define SYSCALL_GETPID 172
#define SYSCALL_GETUID 174
#define SYSCALL_GETGID 176
#define SYSCALL_SETRLIMIT 163
#define SYSCALL_PRCTL 167
#define SYSCALL_FUTEX 98
#define SYSCALL_SET_TID_ADDRESS 218
#define SYSCALL_RT_SIGRETURN 139
#define SYSCALL_GETDENTS64 61
#define SYSCALL_PIPE2 59
#define SYSCALL_DUP3 24
#define SYSCALL_EPOLL_CREATE1 20
#define SYSCALL_EPOLL_CTL 21
#define SYSCALL_EPOLL_PWAIT 22
#define SYSCALL_PPOLL 73
#define SYSCALL_ACCEPT4 242
#define SYSCALL_GETSOCKNAME 204
#define SYSCALL_GETPEERNAME 205
#define SYSCALL_SHUTDOWN 210
#define SYSCALL_SETSOCKOPT 208
#define SYSCALL_LISTEN 201
#define SYSCALL_SCHED_YIELD 124
#define SYSCALL_GETCPU 168
#define SYSCALL_STATFS 43
#define SYSCALL_FSTATFS 44
#define SYSCALL_UTIMENSAT 88
#define SYSCALL_RENAMEAT 38
#define SYSCALL_RENAMEAT2 276
#define SYSCALL_COPY_FILE_RANGE 285
#define SYSCALL_SYNCFS 84
#define SYSCALL_MADVISE 233
#define SYSCALL_MEMBARRIER 283
#define SYSCALL_RSEQ 293
#define SYSCALL_CLONE3 435
#define SYSCALL_OPENAT2 437
#define SYSCALL_PIDFD_OPEN 434
#define SYSCALL_FACCESSAT2 439
#define SYSCALL_LANDLOCK_CREATE_RULESET 444
#define SYSCALL_LANDLOCK_ADD_RULE 445
#define SYSCALL_LANDLOCK_RESTRICT_SELF 446
#define SYSCALL_MEMFD_SECRET 447
#define SYSCALL_PROCESS_MRELEASE 448
#define SYSCALL_FUTEX_WAITV 449
#define SYSCALL_CACHESTAT 451
#define SYSCALL_FCHMODAT2 452
#define SYSCALL_MAP_SHADOW_STACK 453
#define SYSCALL_STATMOUNT 457
#define SYSCALL_LISTMOUNT 458
#define SYSCALL_LSM_GET_SELF_ATTR 459
#define SYSCALL_LSM_SET_SELF_ATTR 460
#define SYSCALL_LSM_LIST_MODULES 461
#define SYSCALL_MSEAL 462
#endif
// 构建Seccomp BPF过滤器
// 允许白名单中的系统调用,拒绝其他
struct sock_filter build_filter[] = {
// 加载系统调用号(arch字段)
BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct seccomp_data, nr)),
// 检查每个允许的系统调用
// 如果匹配,跳转到允许(ALLOW)
// 如果不匹配,继续检查下一个
// 文件操作
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_READ, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_WRITE, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_OPENAT, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_CLOSE, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_FSTAT, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_LSEEK, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_IOCTL, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_FCNTL, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_FSYNC, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_MKDIRAT, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_UNLINKAT, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_READLINKAT, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_FCHMODAT, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_FCHOWNAT, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_RENAMEAT, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_RENAMEAT2, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_STATFS, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_FSTATFS, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_UTIMENSAT, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_COPY_FILE_RANGE, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_SYNCFS, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_FACCESSAT2, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_OPENAT2, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
// 内存管理
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_MMAP, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_MPROTECT, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_MUNMAP, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_BRK, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_MADVISE, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_MREMAP, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_MSEAL, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
// 进程管理
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_EXIT, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_EXIT_GROUP, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_CLONE, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_CLONE3, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_FORK, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_EXECVE, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_WAIT4, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_KILL, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_GETPID, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_GETUID, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_GETGID, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_SETRLIMIT, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_GETRLIMIT, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_PRCTL, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_SCHED_YIELD, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_GETCPU, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_SET_TID_ADDRESS, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_FUTEX, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_FUTEX_WAITV, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_RSEQ, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_MEMBARRIER, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_PROCESS_MRELEASE, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_PROCESS_MADVISE, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_PIDFD_OPEN, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_CLONE3, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
// 信号处理
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_RT_SIGACTION, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_RT_SIGPROCMASK, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_RT_SIGRETURN, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_TGKILL, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_TKILL, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
// 时间
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_GETTIMEOFDAY, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_CLOCK_GETTIME, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_NANOSLEEP, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
// 网络(可选,根据应用需求)
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_SOCKET, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_CONNECT, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_BIND, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_LISTEN, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_ACCEPT4, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_SENDTO, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_RECVFROM, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_GETSOCKOPT, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_SETSOCKOPT, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_GETSOCKNAME, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_GETPEERNAME, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_SHUTDOWN, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
// IO多路复用
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_PIPE2, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_DUP3, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_EPOLL_CREATE1, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_EPOLL_CTL, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_EPOLL_PWAIT, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_PPOLL, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_PSELECT6, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_EVENTFD2, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_TIMERFD_CREATE, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_TIMERFD_SETTIME, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_TIMERFD_GETTIME, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_SIGNalfd4, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_INOTIFY_INIT1, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_INOTIFY_ADD_WATCH, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, SYSCALL_GETDENTS64, 0, 1),
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
// 默认:拒绝并记录
BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_TRAP),
};
// 初始化Seccomp沙箱
int init_seccomp_sandbox() {
// 先禁止获取新权限
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
perror("prctl(PR_SET_NO_NEW_PRIVS)");
return -1;
}
struct sock_fprog prog = {
.len = (unsigned short)(sizeof(build_filter) / sizeof(build_filter[0])),
.filter = build_filter,
};
// 加载Seccomp过滤器
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0) {
perror("prctl(PR_SET_SECCOMP)");
return -1;
}
printf("Seccomp sandbox initialized successfully\n");
printf("Allowed syscalls: file, memory, process, signal, time, network, io\n");
printf("Denied syscalls: ptrace, mount, chroot, reboot, kexec, etc.\n");
return 0;
}
// 信号处理:捕获Seccomp违规
void sigsys_handler(int sig, siginfo_t *info, void *context) {
fprintf(stderr, "SECcomp violation: syscall %d blocked\n", info->si_syscall);
// 记录日志、告警、或优雅退出
_exit(1);
}
int main() {
// 设置SIGSYS处理程序
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = sigsys_handler;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGSYS, &sa, NULL);
// 初始化沙箱
if (init_seccomp_sandbox() != 0) {
fprintf(stderr, "Failed to initialize sandbox\n");
return 1;\
}
// 沙箱内运行应用代码
printf("Running in sandbox...\n");
// 测试:允许的操作
int fd = open("/tmp/test.txt", O_CREAT | O_WRONLY, 0644);
if (fd >= 0) {
write(fd, "Hello from sandbox\n", 18);
close(fd);
printf("File operation succeeded\n");
}
// 测试:禁止的操作(如果取消注释,将被阻止)
// ptrace(PTRACE_TRACEME, 0, NULL, NULL); // 将被Seccomp阻止
printf("Sandbox test completed\n");
return 0;
}
bash
# 编译和运行Seccomp沙箱
gcc -o seccomp_sandbox seccomp_sandbox.c
./seccomp_sandbox
# 验证Seccomp状态
cat /proc/self/status | grep Seccomp
# 输出:Seccomp: 2 (FILTER_MODE)
5.3 使用libseccomp简化配置
c
// libseccomp_example.c
// 使用libseccomp库简化Seccomp配置
#include <seccomp.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int init_sandbox_with_libseccomp() {
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_TRAP); // 默认拒绝并发送SIGSYS
if (!ctx) {
fprintf(stderr, "seccomp_init failed\n");
return -1;
}
// 允许基本系统调用
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(lseek), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 0);
// 允许内存管理
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);
// 允许进程管理
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clone), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clone3), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(wait4), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getuid), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl), 0);
// 允许信号处理
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
// 允许时间
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(gettimeofday), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clock_gettime), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(nanosleep), 0);
// 允许网络(条件:检查参数)
// 只允许连接到特定端口
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(connect), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sendto), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(recvfrom), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(bind), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(listen), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(shutdown), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 0);
// 允许IO多路复用
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_create1), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_pwait), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ppoll), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(pipe2), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup3), 0);
// 加载过滤器
if (seccomp_load(ctx) < 0) {
fprintf(stderr, "seccomp_load failed\n");
seccomp_release(ctx);
return -1;
}
seccomp_release(ctx);
printf("libseccomp sandbox loaded successfully\n");
return 0;
}
int main() {
if (init_sandbox_with_libseccomp() != 0) {
return 1;
}
printf("Running in libseccomp sandbox\n");
// 正常操作
int fd = open("/tmp/test.txt", O_CREAT | O_WRONLY, 0644);
if (fd >= 0) {
write(fd, "Hello\n", 6);
close(fd);
}
return 0;
}
bash
# 编译
gcc -o libseccomp_example libseccomp_example.c -lseccomp
六、综合安全加固效果

图5:嵌入式 Linux 安全加固效果
6.1 攻击面缩减量化
| 加固层次 | 攻击面 | 被攻破后影响 | 安全等级 |
|---|---|---|---|
| 无加固 | 100% | 100% | 不安全 |
| DAC优化 | 75% | 80% | 基础 |
| +SELinux | 45% | 40% | 中等 |
| +Capabilities | 25% | 20% | 高 |
| +Seccomp | 10% | 5% | 极高 |
6.2 完整加固配置脚本
bash
#!/bin/bash
# embedded_hardening.sh
# 嵌入式Linux设备完整安全加固脚本
set -e
echo "=== Embedded Linux Security Hardening ==="
# 1. 禁用不必要的服务
echo "[1/8] Disabling unnecessary services..."
systemctl disable bluetooth 2>/dev/null || true
systemctl disable cups 2>/dev/null || true
systemctl disable avahi-daemon 2>/dev/null || true
systemctl disable ModemManager 2>/dev/null || true
# 2. 配置DAC权限
echo "[2/8] Configuring DAC permissions..."
chmod 700 /root
chmod 750 /home/*
chmod 644 /etc/passwd
chmod 600 /etc/shadow
chmod 600 /etc/gshadow
# 3. 启用SELinux
echo "[3/8] Enabling SELinux..."
if [ -f /etc/selinux/config ]; then
sed -i 's/SELINUX=disabled/SELINUX=enforcing/' /etc/selinux/config
sed -i 's/SELINUX=permissive/SELINUX=enforcing/' /etc/selinux/config
setenforce 1 2>/dev/null || true
fi
# 4. 配置Capabilities
echo "[4/8] Configuring Capabilities..."
# 为网络工具分配最小权限
setcap cap_net_raw=ep /bin/ping 2>/dev/null || true
setcap cap_net_admin,cap_net_raw=ep /usr/sbin/tcpdump 2>/dev/null || true
# 5. 配置Seccomp(通过systemd)
echo "[5/8] Configuring Seccomp profiles..."
mkdir -p /etc/seccomp
cat <<'EOF' > /etc/seccomp/default.json
{
"defaultAction": "SCMP_ACT_ERRNO",
"architectures": ["SCMP_ARCH_AARCH64", "SCMP_ARCH_X86_64"],
"syscalls": [
{"names": ["read", "write", "openat", "close", "fstat", "lseek"], "action": "SCMP_ACT_ALLOW"},
{"names": ["mmap", "mprotect", "munmap", "brk"], "action": "SCMP_ACT_ALLOW"},
{"names": ["exit", "exit_group", "clone", "wait4"], "action": "SCMP_ACT_ALLOW"},
{"names": ["rt_sigaction", "rt_sigprocmask", "rt_sigreturn"], "action": "SCMP_ACT_ALLOW"},
{"names": ["gettimeofday", "clock_gettime", "nanosleep"], "action": "SCMP_ACT_ALLOW"},
{"names": ["socket", "connect", "sendto", "recvfrom", "bind", "listen"], "action": "SCMP_ACT_ALLOW"},
{"names": ["epoll_create1", "epoll_ctl", "epoll_pwait", "ppoll", "pipe2"], "action": "SCMP_ACT_ALLOW"}
]
}
EOF
# 6. 内核参数加固
echo "[6/8] Hardening kernel parameters..."
cat <<EOF >> /etc/sysctl.conf
# 禁用IP源路由
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# 禁用ICMP重定向
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
# 启用SYN cookies
net.ipv4.tcp_syncookies = 1
# 禁用IPv6(如不需要)
net.ipv6.conf.all.disable_ipv6 = 1
# 启用ASLR
kernel.randomize_va_space = 2
# 限制核心转储
fs.suid_dumpable = 0
# 限制进程内存
vm.mmap_rnd_bits = 32
# 启用ptrace限制
kernel.yama.ptrace_scope = 1
EOF
sysctl -p
# 7. 文件系统加固
echo "[7/8] Hardening filesystem..."
# 挂载选项
cat <<EOF >> /etc/fstab
# 安全挂载选项
tmpfs /tmp tmpfs nosuid,nodev,noexec 0 0
tmpfs /var/tmp tmpfs nosuid,nodev,noexec 0 0
EOF
# 8. 审计日志
echo "[8/8] Configuring audit logging..."
if [ -f /etc/audit/auditd.conf ]; then
systemctl enable auditd 2>/dev/null || true
auditctl -e 1 2>/dev/null || true
fi
echo "=== Hardening Complete ==="
echo "Please reboot to apply all changes."
七、场景化选型指南
| 场景 | 推荐方案 | 关键配置 |
|---|---|---|
| 工业PLC/网关 | SELinux + Capabilities + Seccomp | targeted策略,最小权限 |
| 医疗设备 | SELinux MLS + Seccomp | 多级安全,严格沙箱 |
| 消费IoT | AppArmor + Seccomp | 轻量,易维护 |
| 车载信息娱乐 | Smack + Capabilities | Tizen生态兼容 |
| 容器/边缘 | SELinux + Seccomp + Landlock | 容器运行时集成 |
| 资源受限MCU | Seccomp Strict | 最小开销 |
八、总结与展望
本文系统性地讲解了嵌入式Linux的四层安全防御体系:
| 安全机制 | 核心能力 | 嵌入式价值 |
|---|---|---|
| SELinux | 类型强制,策略驱动访问控制 | 阻止攻破后的横向移动 |
| Capabilities | 拆分root,最小权限 | 降低特权滥用风险 |
| Seccomp | 系统调用白名单沙箱 | 限制攻击者可操作系统调用 |
| 组合使用 | 纵深防御 | 攻击面缩减90%以上 |
未来发展方向:
- Landlock LSM:Linux 5.13+引入的无特权沙箱,适合应用自限制
- eBPF LSM:可编程的安全策略,动态响应威胁
- 机密计算:ARM TrustZone/CCA与Linux安全机制的融合
- 鸿蒙安全:OpenHarmony的分布式安全模型值得借鉴
安全不是一次性配置,而是持续的过程。建议建立安全基线、定期审计、及时更新,将安全融入嵌入式开发的每个环节。
转载自:https://blog.csdn.net/u014727709/article/details/162661291
欢迎 👍点赞✍评论⭐收藏,欢迎指正