- include/container.h: document struct fields and constants - src/main.c: explain argument parsing, clone flow, parent/child roles - src/mount.c: describe 6-step mount isolation process - src/cgroup.c: explain cgroup data structures and resource setup/cleanup - src/capabilities.c: document capability drop (bounding + inheritable) - src/seccomp.c: explain each seccomp rule's security purpose - src/userns.c: describe parent-child sync and uid_map/gid_map format - src/hostname.c: document tarot card random naming scheme
72 lines
2.5 KiB
C
72 lines
2.5 KiB
C
/* 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 <stdio.h>
|
||
#include <sys/capability.h>
|
||
#include <sys/prctl.h>
|
||
#include <linux/capability.h>
|
||
#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;
|
||
}
|