Linux内核安全模块深入剖析【2.4】
9.3.3 轮廓轮廓profile的作用是配置一些 Tomoyo 参数。先看一个例子rootubuntu-desktop:/sys/kernel/security/tomoyo# cat profilePROFILE_VERSION20110903 0-COMMENTdisabled 0-PREFERENCE{ max_audit_log1024 max_learning_entry2048 } 0-CONFIG{ modedisabled grant_logyes reject_logyes }轮廓的伪文件接口是/sys/kernel/security/tomoyo/profile 其格式是 第 1 行是轮廓的版本号其后各行开始于一个代表轮廓记录号的数字随后是一个“-”之后是记录的子类型最后是对应的值。上面文件中第 2 到第 4 行共同构成了一个记录号为 0 的轮廓记录。下面先看一下轮廓记录子类型㊀ 1 COMMENT这部分就是一个描述性字符串类似代码中的注释。比如 COMMENT-----Learning Mode-----上例表示这条轮廓记录让系统工作在 Tomoyo 学习模式中。2 PREFERENCE这部分包含两个子项见表 9-1。这两个选项都和内核分配给 Tomoyo 的内存相关。3 CONFIG这部分包含三个子部分见表 9-2。其中 mode 最重要它的取值的含义是 ●“disabled”表示 Tomoyo 不起作用。●“learning”表示遇到不符合策略的访问请求时 Tomoyo 不会拒绝访问但会将访问请求转换为策略加入内核的策略表中。●“permissive”表示遇到不符合策略的访问请求时 Tomoyo 不会拒绝但是也不会将其放入策略中。●“enforcing”表示遇到不符合策略的访问请求时 Tomoyo 会拒绝其访问。“disabled”和“permissive”的区别在于 permissive 会产生日志 disabled 不会也就是说在 disabled 模式下 grant_log 和 reject_log 这两个参数没有作用。举个例子CONFIG{ modelearning grant_logno reject_logyes }上述轮廓语句的意思是这条轮廓记录让系统工作于学习模式符合策略的访问不会产生日志记录不符合策略的访问会产生日志记录。神奇的是 “CONFIG”可以被用来实现细粒度控制见表 9-3。举个例子CONFIG::file{ modelearning grant_logno reject_logyes } CONFIG::network{ modeenforcing grant_logno reject_logyes }文件相关的操作处于学习模式网络相关的操作处于强制模式。还可以更细对具体操作规定模式举个例子CONFIG::file{ modeenforcing grant_logno reject_logyes } CONFIG::file::getattr{ modedisabled grant_logno reject_logyes }文件的 getattr 操作处于 disabled 模式文件的其他操作处于强制模式。综合起来看一个轮廓的例子PROFILE_VERSION20110903 0-COMMENTdisabled 0-PREFERENCE{ max_audit_log1024 max_learning_entry2048 } 0-CONFIG{ modedisabled grant_logyes reject_logyes } 1-COMMENTmisc 1-PREFERENCE{ max_audit_log1024 max_learning_entry2048 } 1-CONFIG{ modepermissive grant_logno reject_logyes } 1-CONFIG::file{ modelearning grant_logno reject_logyes } 1-CONFIG::file::getattr{ modedisabled grant_logno reject_logyes } 1-CONFIG::network{ modeenforcing grant_logno reject_logyes }这个轮廓文件定义了两个记录。其中 0 号记录占了 3 行 1 号记录占了 6 行。 1 号记录规定对文件的 getattr 操作 Tomoyo 工作于 disabled 模式 对文件的其他操作 Tomoyo 工作于 learning模式对 network 的所有操作 Tomoyo 工作于 enforcing 模式对其他操作 Tomoyo 工作于permissive 模式。1.轮廓和策略看一下前面举过的例子策略文件定义了系统中所有域的策略。每个域的策略的格式是第一行是域的标识也就是进程的执行历史第二行是域使用的轮廓记录不同的域可以使用不同的轮廓。这种设计又从另一个角度增加了 Tomoyo 的灵活性。2.轮廓和名字空间结合名字空间轮廓的定义可以有些变化它的记录各部分的头部可以标记上名字空间若没有标记则认为属于“kernel”。下面举个例子PROFILE_VERSION20110903 0-COMMENTdisabled 0-PREFERENCE{ max_audit_log1024 max_learning_entry2048 } 0-CONFIG{ modedisabled grant_logyes reject_logyes } /usr/sbin/httpd 0-COMMENT-----Learning Mode----- /usr/sbin/httpd 0-PREFERENCE{ max_audit_log1024 max_learning_entry2048 } /usr/sbin/httpd 0-CONFIG{ modelearning grant_logno reject_logyes }也就是说轮廓记录号和名字空间有关。上例中有两个 0 号记录一个属于“kernel”名字空间另一个属于“/usr/sbin/httpd”名字空间。下面看与之相关的 domain_policy 的内容9.4 伪文件系统像 SELinux 一样 Tomoyo 也利用了伪文件系统作为用户态进程和内核交互的接口不过Tomoyo 没有自己发明新的文件系统而是使用了内核中标准的安全文件系统即 securityfs㊀ 。securityfs 通常挂载在/sys/kernel/security/ Tomoyo 在其下添加了一个子目录“tomoyo”内容见表 9-4。同 SELinux 一样进程不能随意修改自己的域。 Tomoyo 通过策略规定进程通过伪文件接口可以动态改变的域名。举个例子task manual_domain_transition kernel //apache /www.tomoyo00.com这表示进程可以通过伪文件接口“/sys/kernel/security/tomoyo/self_domain”将自己的域改为“kernel //apache /www.tomoyo00.com”。9.5 总结在 Linux 内核 5 个安全模块中 Tomoyo 是很有特色的一个。 Tomoyo 的特色来自其背后的日本开发团队。总体来说作者感觉 Tomoyo 日本开发团队与 Linux 主线开发团队有些“隔绝” Tomoyo 的设计思路和 Linux 主线的安全开发团队有些不一致。当初为了接纳 Tomoyo 进入 Linux主线 Linux 安全团队增加了若干与路径安全相关的 LSM 钩子。但是时至今日 Linux 主线仍然不能包含 Tomoyo 全部的功能。因此 Tomoyo 是 5 个安全模块中唯一一个发布三个分支的安全模块一个分支以内核补丁的方式发布一个分支以内核模块的方式发布一个分支存在于内核主线之中。或许是由于 Tomoyo 和 Linux 主线的“隔绝” Tomoyo 有一些有别于其他安全模块的新颖思路。 Tomoyo 的灵活的细粒度管理足以让它在 Linux 内核 5 个安全模块中占据一席之地。Tomoyo 的另一个特色是易用性。 Tomoyo 呈现给用户的策略是文本格式的而 SELinux 通过伪文件接口呈现给用户的策略是二进制格式的用户需要另外使用工具来分析策略。 Tomoyo精心设计的基于 ncurses 的“准图形化”用户态工具使 Tomoyo 的用户体验是 5 个 Linux 内核安全模块中最好的。9.6 参考资料读者可参考 http://tomoyo.osdn.jp/。习题Tomoyo 的用户态工具具有良好的易用性。 试试使用 Tomoyo 的用户态工具分析某个应用的行为。提示将应用所在的域置为学习模式查看内核学到的策略。比较一下用这种方式得到的应用行为状况与用命令“strace”得到的应用行为状况的异同。第 10 章 AppArmor10.1 简介AppArmor 源于 1998 年 WireX 公司开发的 SubDomain。 WireX 将 SubDomain 集成进一个名为 Immunix 的 Linux 发行版。 随后 WireX 公司的名字也更改为 Immunix。 在 2005 年 Novell收购了 Immunix 公司。收购的目的就是为了 Immunix 背后的 SubDomain。为了突出这个安全产品 Novell 将 SubDomain 更名为 AppArmor意思是“Application Armor”——应用装甲。转眼到了 2007 年 Novell 放弃了 AppArmor裁撤了 AppArmor 的开发团队。这直接导致 AppArmor的开发停滞。直到 2009 年 5 月维护 Ubuntu 开发的 Canonical 公司接手了 AppArmor 的开发和维护工作。在 Canonical 公司的努力下 AppArmor 在 2010 年 7 月终于进入了 Linux 主线。AppArmor 的开发工作开始得相当早却是几个主要安全模块中最后一个被 Linux 主线接受的。同 Tomoyo 一样 AppArmor 也是基于路径的。 AppArmor 的独特之处在于它并不关注全系统的安全它只会为特别标明的进程提供强制访问控制其他的进程都工作在不受控制的状态㊀ 。 AppArmor应用装甲真是物如其名它为某个或某些应用提供安全防护。这样做当然不够安全但是却易于使用。它的推崇者说 AppArmor 是内核几个主要安全模块中最容易学习和使用的。10.2 机制AppArmor 的机制也是“类型增强”。 “类型”又可被称为“域”。谈到域还是两个老问题域内操作许可和域间转换规则。AppArmor 的开发者和维护者是开发 Ubuntu 的 Canonical 公司。所以在 Ubuntu 的内核中有一些还未纳入 Linux 主线的 AppArmor 新特性。作者所分析的是 Linux 3.14-rc4如果读者使用的是 Ubuntu下面的 AppArmor 分析可能和读者所看到的略有不同。10.2.1 操作许可在 AppArmor 代码中下列代码反映了 AppArmor 眼中的操作security/apparmor/include/audit.h enum aa_ops { OP_NULL, OP_SYSCTL, OP_CAPABLE, ㊀ 下面这个链接提供了一种方法来让整个系统处在 AppArmor 的控制之下 http://wiki.apparmor.net/index.php/FullSystemPolicy OP_UNLINK, OP_MKDIR, OP_RMDIR, OP_MKNOD, OP_TRUNC, OP_LINK, OP_SYMLINK, OP_RENAME_SRC, OP_RENAME_DEST, OP_CHMOD, OP_CHOWN, OP_GETATTR, OP_OPEN, OP_FPERM, OP_FLOCK, OP_FMMAP, OP_FMPROT, OP_CREATE, OP_POST_CREATE, OP_BIND, OP_CONNECT, OP_LISTEN, OP_ACCEPT, OP_SENDMSG, OP_RECVMSG, OP_GETSOCKNAME, OP_GETPEERNAME, OP_GETSOCKOPT, OP_SETSOCKOPT, OP_SOCK_SHUTDOWN, OP_PTRACE, OP_EXEC, OP_CHANGE_HAT, OP_CHANGE_PROFILE, OP_CHANGE_ONEXEC, OP_SETPROCATTR, OP_SETRLIMIT, OP_PROF_REPL, OP_PROF_LOAD, OP_PROF_RM, };深入研究 AppArmor 的代码之后作者发现上述代码并不是为了访问控制而是为了在输出日志消息时体现操作类型的。而且上面只是一个框架有些部分还没有完成比如“OP_SYSCTL”只有定义没有使用。用于访问控制的是下面这些代码security/apparmor/include/file.h #define AA_MAY_CREATE 0x0010 #define AA_MAY_DELETE 0x0020 #define AA_MAY_META_WRITE 0x0040 #define AA_MAY_META_READ 0x0080 #define AA_MAY_CHMOD 0x0100 #define AA_MAY_CHOWN 0x0200 #define AA_MAY_LOCK 0x0400 #define AA_EXEC_MMAP 0x0800 #define AA_MAY_LINK 0x1000 #define AA_LINK_SUBSET AA_MAY_LOCK /* overlaid */ #define AA_MAY_ONEXEC 0x40000000 /* exec allows onexec */ #define AA_MAY_CHANGE_PROFILE 0x80000000 #define AA_MAY_CHANGEHAT 0x80000000 /* ctrl auditing only */上面这些代码只是文件部分的操作许可。 AppArmor 不止可以对文件操作进行控制还可以对其他客体对象进行访问控制只不过对其他客体对象的访问控制没有像文件那样有明确的常量定义。下面看一下代码security/apparmor/include/policy.h struct aa_profile { … struct aa_profile __rcu *parent; struct aa_namespace *ns; … struct aa_file_rules file; struct aa_caps caps; struct aa_rlimit rlimits; … char *dirname; struct dentry *dents[AAFS_PROF_SIZEOF]; }在 Linux 3.14-rc4 主线中的 AppArmor 可以对三种客体进行访问控制文件、能力和资源限制rlimit。在代码中这三种客体的访问控制策略分别对应结构 aa_profile 的成员 file、 caps和 rlimits。 对于能力 AppArmor 判断进程所需的能力是否包含在结构 aa_profile 的成员 caps 中对于资源限制 AppArmor 判断进程当前的资源是否小于 aa_profile 的成员 rlimits 中的相关项。下面列出 aa_caps 和 aa_rlimit 的定义security/apparmor/include/capability.h struct aa_caps { kernel_cap_t allow; kernel_cap_t audit; kernel_cap_t quiet; kernel_cap_t kill; kernel_cap_t extended; }; security/apparmor/include/resource.h struct aa_rlimit { unsigned int mask; struct rlimit limits[RLIM_NLIMITS]; }Linux 系统中的客体类型很多 AppArmor 只对其中一小部分施加了强制访问控制。其他部分就要靠 Linux 的自主访问控制了。作者认为不太合乎逻辑的是 AppArmor 将对自身策略的管理也交给了属于自主访问控制的能力机制具有 CAP_MAC_ADMIN 能力的进程可以修改AppArmor 策略尽管 AppArmor 可以对能力进行访问控制。最后强调一点 AppArmor 的开发还在进行中新的 AppArmor 增加了对新型客体如网络的访问控制。