1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
| #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/syscall.h> #include <linux/capability.h> #include <errno.h> #include <string.h>
// 系统调用包装 static int capget_wrapper(cap_user_header_t hdrp, cap_user_data_t datap) { return syscall(__NR_capget, hdrp, datap); }
static int capset_wrapper(cap_user_header_t hdrp, const cap_user_data_t datap) { return syscall(__NR_capset, hdrp, datap); }
// 检查是否具有特定能力 int has_capability(__u32 caps, int cap) { return (caps & (1 << cap)) != 0; }
int main() { struct __user_cap_header_struct hdr; struct __user_cap_data_struct data[2]; printf("=== Capset 函数示例 ===\n"); printf("当前进程 PID: %d\n", getpid()); printf("当前用户 UID: %d\n", getuid()); printf("当前有效 UID: %d\n", geteuid()); // 获取当前能力 hdr.version = _LINUX_CAPABILITY_VERSION_3; hdr.pid = 0; if (capget_wrapper(&hdr, data) == -1) { perror("capget 失败"); exit(EXIT_FAILURE); } printf("\n修改前的能力状态:\n"); printf(" 有效能力: 0x%08x\n", data[0].effective); printf(" 允许能力: 0x%08x\n", data[0].permitted); printf(" 继承能力: 0x%08x\n", data[0].inheritable); // 演示能力丢弃(只能丢弃,不能增加) printf("\n能力修改演示:\n"); // 保存原始状态 __u32 original_effective = data[0].effective; __u32 original_permitted = data[0].permitted; // 检查是否具有某些能力 if (has_capability(data[0].effective, CAP_CHOWN)) { printf(" 当前具有 CAP_CHOWN 能力\n"); // 尝试丢弃该能力 data[0].effective &= ~(1 << CAP_CHOWN); if (capset_wrapper(&hdr, data) == -1) { printf(" capset 丢弃能力失败: %s\n", strerror(errno)); } else { printf(" 成功丢弃 CAP_CHOWN 能力\n"); } } else { printf(" 当前不具有 CAP_CHOWN 能力\n"); } // 再次获取能力状态验证 if (capget_wrapper(&hdr, data) == -1) { perror("重新获取能力失败"); } else { printf("\n修改后的有效能力: 0x%08x\n", data[0].effective); // 恢复原始状态 data[0].effective = original_effective; data[0].permitted = original_permitted; if (capset_wrapper(&hdr, data) == -1) { printf("恢复原始状态失败: %s\n", strerror(errno)); } else { printf("已恢复原始能力状态\n"); } } // 错误处理演示 printf("\n错误处理演示:\n"); // 权限不足错误 hdr.version = _LINUX_CAPABILITY_VERSION_3; hdr.pid = 0; if (capget_wrapper(&hdr, data) == 0) { // 尝试设置不允许的能力(会失败) __u32 temp_effective = data[0].effective; data[0].effective |= (1 << CAP_SYS_MODULE); // 尝试增加能力 if (capset_wrapper(&hdr, data) == -1) { if (errno == EPERM) { printf("权限不足错误处理正确: %s\n", strerror(errno)); printf("说明: 不能通过 capset 提升能力\n"); } } // 恢复状态 data[0].effective = temp_effective; } // 无效参数错误 hdr.version = 0x12345678; // 无效版本 if (capset_wrapper(&hdr, data) == -1) { if (errno == EINVAL) { printf("无效参数错误处理正确: %s\n", strerror(errno)); } } // 实际应用场景演示 printf("\n实际应用场景:\n"); printf("1. 网络服务器安全降权:\n"); printf(" - 启动时绑定特权端口(需要 CAP_NET_BIND_SERVICE)\n"); printf(" - 完成绑定后丢弃该能力\n"); printf(" - 切换到非特权用户运行\n\n"); printf("2. 最小权限原则:\n"); printf(" - 只保留执行任务必需的能力\n"); printf(" - 降低被攻击时的安全风险\n\n"); printf("3. 容器安全:\n"); printf(" - 限制容器内进程的能力\n"); printf(" - 防止容器逃逸攻击\n"); return 0; }
|