嵌入式Linux安全加固:SELinux、Capabilities与Seccomp——强制访问控制与沙箱

文章目录


每日一句正能量

人生要活得洒脱,就是三要素,无所谓,没必要,不至于。

对别人的评价、无伤大雅的得失,不必挂心。对消耗你的人、争不出对错的事,及时止损。把灾难化想象拉回现实------天塌不下来,别自己吓自己。用好这三词,能省下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

欢迎 👍点赞✍评论⭐收藏,欢迎指正

相关推荐
HackTwoHub2 小时前
ARL灯塔重构版:支持APP/小程序/WEB资产同步扫描
人工智能·安全·web安全·网络安全·小程序·重构·自动化
AAA@峥2 小时前
容器数据不丢失:Docker 分层存储 + Volume 共享、备份迁移完整指南
运维·docker·容器
MDM.Plus2 小时前
苹果MDM技术演进:从远程控制到设备信任体系的构建
运维·服务器·安全·ios·mdm·手机店
REDcker3 小时前
macOS 挂载 Linux 远程目录详解
linux·运维·macos
2601_961593423 小时前
Mac 上搭建Linux环境吗?VMware + CentOS Stream 9 镜像快速部署
linux·运维·ide·macos·centos
dddwjzx3 小时前
嵌入式Linux C应用编程入门——线程 (二)
linux·嵌入式
写代码的学渣3 小时前
Linux systemd 开机启动日志逐行详细解析报告
linux·运维·服务器
❀͜͡傀儡师3 小时前
2026年7月高危安全态势速览
安全
田里的水稻3 小时前
EP_XML\JSON配置文件和YAML
xml·运维·人工智能·机器人·自动驾驶·json