/* capabilities.c — Linux Capabilities 权限收窄模块 * * 将 root 的"万能权限"拆解为 30+ 个细粒度的 capability, * 本模块 drop 掉容器不需要的 20 个危险 capability, * 只保留最小权限集。 * * 两步操作: * 1. prctl(PR_CAPBSET_DROP) — 从 bounding set 移除,子进程也无法获取 * 2. cap_set_flag(CAP_INHERITABLE, CAP_CLEAR) — 清除 inheritable 集 */ #include #include #include #include #include "capabilities.h" int capabilities(void) { fprintf(stderr, "=> dropping capabilities..."); /* 需要 drop 的危险 capability 列表 */ int drop_caps[] = { CAP_AUDIT_CONTROL, /* 修改审计日志 */ CAP_AUDIT_READ, /* 读取审计日志 */ CAP_AUDIT_WRITE, /* 写入审计日志 */ CAP_BLOCK_SUSPEND, /* 阻止系统挂起 */ CAP_DAC_READ_SEARCH, /* 绕过文件读权限检查 */ CAP_FSETID, /* 设置 setuid/setgid 位 */ CAP_IPC_LOCK, /* 锁定共享内存 */ CAP_MAC_ADMIN, /* 修改 MAC 策略(如 SELinux) */ CAP_MAC_OVERRIDE, /* 覆盖 MAC 策略 */ CAP_MKNOD, /* 创建设备文件 */ CAP_SETFCAP, /* 设置文件 capability */ CAP_SYSLOG, /* 操作内核日志 */ CAP_SYS_ADMIN, /* 挂载、namespace 等大量特权操作 */ CAP_SYS_BOOT, /* 重启系统 */ CAP_SYS_MODULE, /* 加载/卸载内核模块 */ CAP_SYS_NICE, /* 调整进程优先级 */ CAP_SYS_RAWIO, /* 直接 I/O 端口操作 */ CAP_SYS_RESOURCE, /* 修改资源限制 */ CAP_SYS_TIME, /* 修改系统时间 */ CAP_WAKE_ALARM /* 设置唤醒闹钟 */ }; size_t num_caps = sizeof(drop_caps) / sizeof(*drop_caps); /* 第一步:从 bounding set 中移除 * bounding set 限制了进程能获取的最大能力集, * 一旦 drop,即使后续 execve setuid 程序也无法获取 */ fprintf(stderr, "bounding..."); for (size_t i = 0; i < num_caps; i++) { if (prctl(PR_CAPBSET_DROP, drop_caps[i], 0, 0, 0)) { fprintf(stderr, "prctl failed: %m\n"); return 1; } } /* 第二步:从 inheritable set 中清除 * inheritable set 控制 execve 后哪些 capability 可被继承 */ fprintf(stderr, "inheritable..."); cap_t caps = NULL; if (!(caps = cap_get_proc()) || cap_set_flag(caps, CAP_INHERITABLE, num_caps, drop_caps, CAP_CLEAR) || cap_set_proc(caps)) { fprintf(stderr, "failed: %m\n"); if (caps) cap_free(caps); return 1; } cap_free(caps); fprintf(stderr, "done.\n"); return 0; }