集成这一基本级别的功能并全面分析结果后,您可以添加自己的政策设置,以便涵盖自己对 Android 操作系统进行的自定义。当然,这些政策仍必须要满足 Android 兼容性计划的要求,并且不会移除默认的 SELinux 设置。
制造商不得移除现有的安全设置,否则可能会破坏 Android SELinux 实现及其管控的应用。这包括可能需要进行改进以符合政策并正常运行的第三方应用。应用必须无需进行任何修改即可继续在启用了 SELinux 的设备上正常运行。
当开始着手自定义 SELinux 时,制造商应记得做以下事情:
init
服务衍生的所有进程分配域不要做以下事情:
如需查看具体要求,请参阅 Android 兼容性定义文档中的“内核安全功能”部分。
SELinux 采用白名单方法,这意味着只能授予政策中明确允许的访问权限。由于 Android 的默认 SELinux 政策已经支持 Android 开放源代码项目,因此原始设备制造商 (OEM) 无需以任何方式修改 SELinux 设置。如果他们要自定义 SELinux 设置,则应格外谨慎,以免破坏现有应用。以下是我们建议的做法:
/device/manufacturer/device-name/sepolicy
目录中的 *.te 文件(te 是 SELinux 政策源代码文件使用的扩展名)内,然后使用 BOARD_SEPOLICY
变量将它们纳入到您的版本中。
集成工作完成后,原始设备制造商 (OEM) 的 Android 开发过程还应包含一个确保向前兼容 SELinux 的步骤。在理想的软件开发过程中,仅当软件模型发生变化时,SELinux 政策才需要进行更改,而当实际实现发生变化时,SELinux 政策将不需要进行更改。
当设备制造商开始自定义 SELinux 时,他们应首先审核自己向 Android 添加的内容。如果他们添加了执行新功能的组件,在开启强制模式之前,他们需要先确认该组件是否符合 Android 采用的安全政策,以及原始设备制造商 (OEM) 制定的所有相关政策。
为了防止出现不必要的问题,过度宽泛和过度兼容要好于过度限制和不兼容,后者会导致设备功能损坏。不过,如果制造商进行的更改能够惠及其他人,则应将这些更改作为补丁程序提供给默认 SELinux 政策。如果相应补丁程序已应用于默认安全政策,制造商将不再需要针对每个新的 Android 版本进行此项更改。
首先请注意,SELinux 基于 M4 计算机语言,因此支持多种有助于节省时间的宏。
在以下示例中,所有域都被授予从 /dev/null
读取数据或向其写入数据的权限以及从 /dev/zero
读取数据的权限。
# Allow read / write access to /dev/null allow domain null_device:chr_file { getattr open read ioctl lock append write}; # Allow read-only access to /dev/zero allow domain zero_device:chr_file { getattr open read ioctl lock };
可以使用 SELinux *_file_perms
宏编写相同的声明(代码非常简短):
# Allow read / write access to /dev/null allow domain null_device:chr_file rw_file_perms; # Allow read-only access to /dev/zero allow domain zero_device:chr_file r_file_perms;
以下是一个完整的 DHCP 政策示例,我们将在下文中对其进行分析:
type dhcp, domain; permissive dhcp; type dhcp_exec, exec_type, file_type; type dhcp_data_file, file_type, data_file_type; init_daemon_domain(dhcp) net_domain(dhcp) allow dhcp self:capability { setgid setuid net_admin net_raw net_bind_service }; allow dhcp self:packet_socket create_socket_perms; allow dhcp self:netlink_route_socket { create_socket_perms nlmsg_write }; allow dhcp shell_exec:file rx_file_perms; allow dhcp system_file:file rx_file_perms; # For /proc/sys/net/ipv4/conf/*/promote_secondaries allow dhcp proc_net:file write; allow dhcp system_prop:property_service set ; unix_socket_connect(dhcp, property, init) type_transition dhcp system_data_file:{ dir file } dhcp_data_file; allow dhcp dhcp_data_file:dir create_dir_perms; allow dhcp dhcp_data_file:file create_file_perms; allow dhcp netd:fd use; allow dhcp netd:fifo_file rw_file_perms; allow dhcp netd:{ dgram_socket_class_set unix_stream_socket } { read write }; allow dhcp netd:{ netlink_kobject_uevent_socket netlink_route_socket netlink_nflog_socket } { read write };
下面我们来分析一下该示例:
在第一行(即类型声明)中,该政策声明 DHCP 守护进程将沿用基本的安全政策 (domain
)。从前面的声明示例中,我们知道 DHCP 可以从 /dev/null.
读取数据以及向其写入数据。
在第二行中,DHCP 被声明为宽容域。
在 init_daemon_domain(dhcp)
这一行中,该政策声明 DHCP 是从 init
衍生而来的,并且可以与其进行通信。
在 net_domain(dhcp)
这一行中,该政策允许 DHCP 使用 net
域中的常用网络功能,例如读取和写入 TCP 数据包、通过套接字进行通信,以及执行 DNS 请求。
在 allow dhcp proc_net:file write;
这一行中,该政策声明 DHCP 可以向 /proc
中的特定文件写入数据。这一行显示了 SELinux 的详细文件标签。它使用 proc_net
标签来限定 DHCP 仅对 /proc/sys/net
中的文件具有写入权限。
该示例的最后一部分以 allow dhcp netd:fd use;
开头,描述了允许应用之间如何进行交互。该政策声明 DHCP 和 netd 之间可通过文件描述符、FIFO 文件、数据报套接字以及 UNIX 信息流套接字进行通信。DHCP 只能从数据报套接字和 UNIX 信息流套接字中读取数据以及向它们写入数据,但不能创建或打开此类套接字。
类 |
权限 |
文件 |
ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton |
目录 |
add_name remove_name reparent search rmdir open audit_access execmod |
套接字 |
ioctl read write create getattr setattr lock relabelfrom relabelto append bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind |
文件系统 |
mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget |
进程 |
fork transition sigchld sigkill sigstop signull signal ptrace getsched setsched getsession getpgid setpgid getcap setcap share getattr setexec setfscreate noatsecure siginh setrlimit rlimitinh dyntransition setcurrent execmem execstack execheap setkeycreate setsockcreate |
安全 |
compute_av compute_create compute_member check_context load_policy compute_relabel compute_user setenforce setbool setsecparam setcheckreqprot read_policy |
功能 |
chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write audit_control setfcap |
更多 |
还有更多 |
SELinux neverallow
规则用于禁止在任何情况下都不应该发生的行为。通过兼容性测试,现在各种合作伙伴设备上都会强制执行 SELinux neverallow
规则。
以下准则旨在协助制造商在自定义过程中避免与 neverallow
规则相关的错误。此处使用的规则编号与 Android 5.1 中使用的编号一致,并且会因版本而异。
规则 48:neverallow { domain -debuggerd -vold -dumpstate
-system_server } self:capability sys_ptrace;
请参阅 ptrace
的帮助页面。sys_ptrace
功能用于授予对任何进程执行 ptrace
命令的权限。拥有该权限后,可以对其他进程进行广泛的控制。应该只有该规则中列出的指定系统组件享有该权限。如果需要该功能,则通常表明存在的某些内容不适用于面向用户的版本或存在不需要的功能。请移除不必要的组件。
规则 76:neverallow { domain -appdomain -dumpstate -shell -system_server -zygote } { file_type -system_file -exec_type }:file execute;
该规则旨在防止执行系统中的任意代码。具体来说就是,该规则声明仅执行 /system
中的代码,以便通过验证启动等机制实现安全保证。通常情况下,当遇到与这个 neverallow
规则相关的问题时,最好的解决办法是将违规代码移到 /system
分区。