第一百六十四章:策略之网
渡劫期涉及内核源码:
一
林小源在档案室深处发现了一扇门,门后是一张巨大的网。网上的每一根丝线都连接着两个节点,节点上刻着类型名称。
"这是策略,"policydb.c 说,他是一位织网者,手中握着一根银色的丝线。"策略定义了谁可以对什么做什么。类型、规则、角色——它们组成一张精密的访问控制网。"
林小源走近那张网,看到丝线上刻着 "allow httpd_t httpd_sys_content_t:file { read getattr open }"。
"这是 allow 规则,"织网者说,"它允许 httpd_t 类型的进程读取 httpd_sys_content_t 类型的文件。"
"如果违反规则呢?"
"拒绝,"织网者说,"并记录到 audit 日志。"
二
"策略可以动态调整吗?"林小源问。
织网者指向网上的几个开关:"布尔值。httpd_enable_homedirs 控制是否允许 httpd 访问用户家目录,httpd_can_network_connect 控制是否允许 httpd 网络连接。管理员可以通过 setsebool 启用或禁用,不需要重新编译策略。"
"这很方便。"
"但也很危险,"织网者说,"开启 httpd_enable_homedirs 会让 httpd 可以读取所有用户的家目录。如果配置错误,会导致安全漏洞。"
"方便和安全,"林小源叹了口气,"果然是一对冤家。"
三
"如果策略配置错误,怎么调试?"林小源问。
织网者放下手中的丝线,说:"SELinux 拒绝操作时会记录到 audit 日志。ausearch -m avc 查看拒绝记录,sealert 分析拒绝原因。然后根据分析结果调整策略。"
"这需要经验吧?"
"确实,"织网者说,"策略调试是 SELinux 最难的部分。但一旦配置正确,SELinux 就能提供强大的安全保护。"
林小源望着那张巨大的网,心中感慨。在这片内核的深处,每一根丝线都是一份守护。
/*
* SELinux 策略的组成:
*
* 1. 类型声明
* type httpd_t;
* type httpd_sys_content_t;
*
* 2. 类型转换规则
* type_transition httpd_t httpd_sys_content_t:file httpd_tmp_t;
*
* 3. 访问规则 (allow)
* allow httpd_t httpd_sys_content_t:file { read getattr open };
* allow httpd_t httpd_sys_content_t:dir { search getattr };
*
* 4. 角色规则
* role system_r types httpd_t;
*
* 5. 布尔值
* httpd_enable_homedirs — 启用家目录访问
* httpd_can_network_connect — 允许网络连接
*
* 策略编译:
* .te (源文件) → .pp (策略包) → 加载到内核
*
* 工具:
* semanage — 管理策略
* setsebool — 设置布尔值
* seinfo — 查询策略信息
* sesearch — 搜索策略规则
*/
/* 模拟策略规则 */
struct policy_entry {
char source[64];
char target[64];
char class[32];
char perms[128];
};
struct policy_entry policy[] = {
{"httpd_t", "httpd_sys_content_t", "file",
"read getattr open lock ioctl"},
{"httpd_t", "httpd_sys_content_t", "dir",
"search getattr read"},
{"httpd_t", "httpd_log_t", "file",
"append create getattr open"},
{"httpd_t", "httpd_tmp_t", "file",
"read write create unlink getattr"},
{"httpd_t", "httpd_t", "process",
"signal sigkill"},
{"sshd_t", "sshd_var_run_t", "file",
"read write getattr"},
{"sshd_t", "ptmx_t", "chr_file",
"read write getattr open"},
{"sysadm_t", "unconfined_t", "process",
"sigkill signal transition"},
};
/* 模拟布尔值 */
struct bool_entry {
char name[64];
int value;
char desc[128];
};
struct bool_entry booleans[] = {
{"httpd_enable_homedirs", 0, "允许 httpd 访问用户家目录"},
{"httpd_can_network_connect", 1, "允许 httpd 网络连接"},
{"httpd_read_user_content", 0, "允许 httpd 读取用户内容"},
};
void print_rule(struct policy_entry *e) {
printf(" allow %s %s:%s { %s }\n",
e->source, e->target, e->class, e->perms);
}
printf("=== 策略之网 — 访问控制的规则 ===\n\n");
printf("SELinux 策略定义访问控制规则:\n\n");
int n = sizeof(policy) / sizeof(policy[0]);
printf("--- 策略规则 ---\n");
for (int i = 0; i < n; i++) {
print_rule(&policy[i]);
}
printf("\n--- 布尔值 ---\n");
int nb = sizeof(booleans) / sizeof(booleans[0]);
for (int i = 0; i < nb; i++) {
printf("%s = %d\n", booleans[i].name, booleans[i].value);
printf(" %s\n", booleans[i].desc);
}
printf("\n--- 策略类型 ---\n");
printf("targeted:\n");
printf(" 只保护特定服务\n");
printf(" 大部分进程非限制\n\n");
printf("MLS:\n");
printf(" 多级安全\n");
printf(" 军事级别\n\n");
printf("minimum:\n");
printf(" 最小策略\n");
printf("\n--- 策略管理 ---\n");
printf("查看规则:\n");
printf(" sesearch -A -s httpd_t\n\n");
printf("设置布尔值:\n");
printf(" setsebool -P httpd_enable_homedirs on\n\n");
printf("添加规则:\n");
printf(" semanage fcontext -a -t httpd_sys_content_t\n");
printf(" restorecon -Rv /path\n\n");
printf("查看拒绝:\n");
printf(" ausearch -m avc -ts recent\n");
printf(" sealert -a /var/log/audit/audit.log\n");#include <stdio.h>
#include <string.h>
/*
* SELinux 策略的组成:
*
* 1. 类型声明
* type httpd_t;
* type httpd_sys_content_t;
*
* 2. 类型转换规则
* type_transition httpd_t httpd_sys_content_t:file httpd_tmp_t;
*
* 3. 访问规则 (allow)
* allow httpd_t httpd_sys_content_t:file { read getattr open };
* allow httpd_t httpd_sys_content_t:dir { search getattr };
*
* 4. 角色规则
* role system_r types httpd_t;
*
* 5. 布尔值
* httpd_enable_homedirs — 启用家目录访问
* httpd_can_network_connect — 允许网络连接
*
* 策略编译:
* .te (源文件) → .pp (策略包) → 加载到内核
*
* 工具:
* semanage — 管理策略
* setsebool — 设置布尔值
* seinfo — 查询策略信息
* sesearch — 搜索策略规则
*/
/* 模拟策略规则 */
struct policy_entry {
char source[64];
char target[64];
char class[32];
char perms[128];
};
struct policy_entry policy[] = {
{"httpd_t", "httpd_sys_content_t", "file",
"read getattr open lock ioctl"},
{"httpd_t", "httpd_sys_content_t", "dir",
"search getattr read"},
{"httpd_t", "httpd_log_t", "file",
"append create getattr open"},
{"httpd_t", "httpd_tmp_t", "file",
"read write create unlink getattr"},
{"httpd_t", "httpd_t", "process",
"signal sigkill"},
{"sshd_t", "sshd_var_run_t", "file",
"read write getattr"},
{"sshd_t", "ptmx_t", "chr_file",
"read write getattr open"},
{"sysadm_t", "unconfined_t", "process",
"sigkill signal transition"},
};
/* 模拟布尔值 */
struct bool_entry {
char name[64];
int value;
char desc[128];
};
struct bool_entry booleans[] = {
{"httpd_enable_homedirs", 0, "允许 httpd 访问用户家目录"},
{"httpd_can_network_connect", 1, "允许 httpd 网络连接"},
{"httpd_read_user_content", 0, "允许 httpd 读取用户内容"},
};
void print_rule(struct policy_entry *e) {
printf(" allow %s %s:%s { %s }\n",
e->source, e->target, e->class, e->perms);
}
int main() {
printf("=== 策略之网 — 访问控制的规则 ===\n\n");
printf("SELinux 策略定义访问控制规则:\n\n");
int n = sizeof(policy) / sizeof(policy[0]);
printf("--- 策略规则 ---\n");
for (int i = 0; i < n; i++) {
print_rule(&policy[i]);
}
printf("\n--- 布尔值 ---\n");
int nb = sizeof(booleans) / sizeof(booleans[0]);
for (int i = 0; i < nb; i++) {
printf("%s = %d\n", booleans[i].name, booleans[i].value);
printf(" %s\n", booleans[i].desc);
}
printf("\n--- 策略类型 ---\n");
printf("targeted:\n");
printf(" 只保护特定服务\n");
printf(" 大部分进程非限制\n\n");
printf("MLS:\n");
printf(" 多级安全\n");
printf(" 军事级别\n\n");
printf("minimum:\n");
printf(" 最小策略\n");
printf("\n--- 策略管理 ---\n");
printf("查看规则:\n");
printf(" sesearch -A -s httpd_t\n\n");
printf("设置布尔值:\n");
printf(" setsebool -P httpd_enable_homedirs on\n\n");
printf("添加规则:\n");
printf(" semanage fcontext -a -t httpd_sys_content_t\n");
printf(" restorecon -Rv /path\n\n");
printf("查看拒绝:\n");
printf(" ausearch -m avc -ts recent\n");
printf(" sealert -a /var/log/audit/audit.log\n");
return 0;
}道藏笔记
内核启示
SELinux 策略就是一张大网,把谁能对什么做什么写得明明白白。类型声明定义有哪些 domain 和 type,allow 规则把它们连起来,type_transition 规定新文件该打什么标签。还有布尔值——httpd_enable_homedirs 一开,httpd 就能访问家目录,用 setsebool 就能调,不用重新编译策略。
策略出错时别慌,ausearch -m avc 看拒绝记录,sealert 帮你分析原因,然后用 semanage 调整。策略类型方面,targeted 最常用(只保护关键服务),MLS 是军事级别的多级安全。
策略是网络——精密的访问控制。
策略之试
策略之网一章中,allow 规则和类型转换服务于哪套强制访问控制系统?