<p>C# 无法在代码中配置 SELinux 或 AppArmor,因其是内核级 MAC 机制,需管理员通过策略工具(如 semanage、aa-genprof)预先配置;.NET 进程仅通过系统调用间接受控,无 API 支持运行时策略修改或上下文读写。</p>

C# 运行在 Linux 上时,SELinux 和 AppArmor 对它完全透明——.NET 进程本身不感知、也不直接配置这些机制。
为什么 C# 代码里写不了 SELinux 或 AppArmor 规则
SELinux 和 AppArmor 是内核级强制访问控制(MAC)模块,作用于进程粒度,由系统管理员通过策略文件和工具(如 semanage、aa-genprof)配置,不是应用层 API。C# 的 System.IO 或 FileStream 等类只调用 libc 的 open()、stat() 等系统调用,内核在底层拦截并检查策略——你的 C# 代码既不能读取当前 SELinux 上下文,也无法在运行时修改策略。
- 试图在 C# 中调用
setcon()或写/sys/fs/selinux会直接抛出Operation not permitted -
Process.Start("sestatus")可以查状态,但只是只读信息,无法用于“启用限制” - .NET 的
File.Exists()或Directory.GetDirectories()失败时,报的仍是UnauthorizedAccessException或IOException,不会透露是 SELinux 拒绝还是 DAC 权限不足
真正起作用的是进程启动前的上下文绑定
限制 C# 进程能访问哪些路径,关键在它被哪个安全上下文(SELinux)或配置文件(AppArmor)约束,而这取决于它如何启动:
- 如果用 systemd 启动:在
.service文件中设SELinuxContext=system_u:system_r:myapp_t:s0,再配好myapp_t策略允许读/var/myapp/data - 如果用 AppArmor:先用
aa-genprof dotnet生成基础 profile,再手动加/var/myapp/** rw,,最后用aa-enforce /etc/apparmor.d/usr.bin.dotnet - 直接执行
dotnet MyApp.dll?那它继承 shell 的上下文(通常是unconfined_t),等于没限制——必须用runcon或封装脚本切换上下文
路径安全性得靠 .NET 自身 + 系统策略双保险
别指望 SELinux/AppArmor 替你做路径校验。C# 仍需主动防御路径遍历、空字节注入等:Path.GetFullPath() 后检查是否落在白名单目录内,禁用 ~ 或 .. 解析,不用 string.Format 拼接路径。
-
Path.Combine("uploads", userInput)不安全——userInput是"../etc/shadow"就穿了 - SELinux 即使允许读
/var/www,也拦不住你代码自己把../../etc/passwd传给File.OpenRead() - AppArmor 的
/var/www/** rw,规则对../../../etc/passwd是否生效,取决于内核是否做了路径规范化——不同版本行为不一致,不能依赖
真正的难点从来不是“怎么写 C#”,而是让运维愿意为你这个 .NET 服务单独维护一套 SELinux 策略,或者说服团队接受 AppArmor profile 的持续更新流程。路径检查逻辑写错一次,可能比策略漏一条规则更早出事。










