动机

ioctl为设备控制提供了必要的操作。典型的设备驱动支持由命令参数来区分的一套操作集,可以通过ioctl系统调用来访问。SELinux为很多系统操作提供了一一对应的访问控制,例如chown,kill,setuid,ipc_lock等。另一方面,我们使用ioctl permission这一权限,对文件描述符上的ioctl操作进行授权,这意味着,主体要么在授权后可以访问全部的ioctl操作集,要么不能执行任何ioctl。在某些情况下,这可以接受。但是,经常有些驱动提供了庞大的操作集,除必要的功能外,还包含了很多危险的能力,或者对系统敏感信息的访问。

example 1:对隐私敏感信息的访问

拥有socket权限的应用需要ioctl权限以执行控制操作。然而,对ioctl的访问也使得应用能够访问MAC地址、WIFI essid、L2加密信息等等,这些信息可用于唯一标识用户和危害隐私。

example 2:最小特权原则,减少内核攻击面

某个图形驱动,提供了34个ioctl操作,但是测试中发现实际只使用到11个。Media 驱动经常处于开发状态,并且因含有大量bug而臭名昭著。通过限制应用的ioctl操作子集,将可以大大降低bug被利用的风险。


实现

设计约束

设计策略

支持现存策略与定向白名单。这意味着兼容现存的selinux策略,仅为特定客体增加白名单即可。
即使是系统管理员或者策略编写者,也不一定能知道系统中的使用ioctl命令。所以,如果为了使用定向白名单支持的ioctl操作粒度访问控制,就要求了解所有的ioctl命令,这显然不合理。
因此,现存的使用ioctl permission的策略将照用不误。
定向白名单功能,将仅在allow规则中指定的source-target-class 三元组中生效。
例如:init将可以继续访问某个驱动提供的所有ioctl 命令,但是我么可以仅容许浏览器访问该驱动ioctl操作集的某个子集。

性能

很多ioctl调用对性能敏感,某些driver有着庞大的ioctl操作集(socket支持上百个ioctl命令)。
一条过滤后的ioctl命令(也就是通过了定向白名单机制检测)与一条未过滤ioctl命令的执行时间相似,并且与ioctl命令集大小无关。

命令空间:

ioctl命令码由一个32bit整数标识,包含四个字段:
* number:命令序列号,8bits
* type: 该驱动的魔数,8bits
* size: 该命令需要的参数大小,典型值为14bit(与CPU架构相关)
* direction:数据传输方向,典型值为2bit

策略格式

allow|auditallow|dontaudit : { ioctl_cmd_codes }

examples:

allow system_server ion_device:chr_file { 0x4901 0x4905-0x4906 };
allow keystore tee_device:chr_file { 0x9707-0x9708 0x970a 0x970f };
allow netmgrd netmgrd:udp_socket { 0x8913 0x8933 0x89f2-0x89f3 0x89f5 0x89f8-0x89f9 };
allow surfaceflinger graphics_device:chr_file { 0x4600 0x4602 0x4611 0x6d87-0x6d89 0x6da0 0x6da2 0x6da4 0x6da6 };
allow sensors sensors:socket { 0xc302 0xc304 };

相关代码

security: lsm_audit: add ioctl specific auditing
SELinux: per-command whitelisting of ioctls

include/linux/lsm_audit.h           |   7 +
security/lsm_audit.c                |  15 ++
security/selinux/avc.c              | 428 ++++++++++++++++++++++++++++++++++--
security/selinux/hooks.c            |  40 +++-
security/selinux/include/avc.h      |   5 +
security/selinux/include/security.h |  34 ++-
security/selinux/ss/avtab.c         |  91 ++++++--
security/selinux/ss/avtab.h         |  25 ++-
security/selinux/ss/conditional.c   |  32 ++-
security/selinux/ss/conditional.h   |   6 +-
security/selinux/ss/policydb.c      |   5 +
security/selinux/ss/services.c      | 202 +++++++++++++++--
security/selinux/ss/services.h      |   6 +
13 files changed, 832 insertions(+), 64 deletions(-)

FAQ

  1. 如何启用定向白名单机制?

    1. 首先,你需要更新安全策略版本为30. 你可以修改external/sepolicy/Android.mk:
      POLICYVERS ?= 26
      你也可以在make 命令行或者 BoardConfig.mk中覆盖这个值

    2. 在应用层,当然,你还需要一个支持该机制的lisepol和checkpolicy,这些代码已经合并到AOSP master分支以及上游selinux长裤

    3. 在内核层,kernel/common的android-3.4、android-3.10以及android-3.18 包含了相关代码。

  2. ioctl permission 还有用吗?
    当然,对于某个三元组source-target-class,如果你希望在command这一粒度来控制ioctl,
    你首先需要授予该三元组 ioctl permission,然后在定向白名单中为期增加allow规则。
    如果你没有编写该三元组对应的定向白名单,那么该三元组就会拥有所有的ioctl命令权限。

参考文献

  1. http://marc.info/?l=selinux&m=142861645215267&w=2
Logo

更多推荐