我的自定义SELinux策略似乎被Android系统忽略了。

10

我在基于Sony Open Devices树的Android 7.1.2上遇到了一些问题,无法正确运行自定义SELinux策略。

我的问题是审计日志不断告诉我缺少文件访问规则,而我实际上已经添加了这些规则。我还将audit2allow创建的规则复制到我的策略文件中,但即使是这些规则也不能正常工作。

那么,让我们深入了解细节:

我创建了一个名为vendor_app的自定义域。该域根据应用程序的签名进行分配。我已经在mac_permissions.xml中添加了一个条目来分配seinfo字段vendor。在seapp_contexts中,我将vendor_app域分配如下:

user=_app seinfo=vendor domain=vendor_app type=app_data_file levelFrom=user

我的应用在供应商应用上下文中正确启动:

# ps -Z | grep permissiontest
u:r:vendor_app:s0:c512,c768    u0_a109   4110  508   1620732 79584 SyS_epoll_ 0000000000 S com.vendor.android.permissiontest

现在让我们来谈谈完全不起作用的部分。在 vendor_app 上下文中运行的应用程序应该获得 /persist/vendor 中文件的读写权限。为了创建必要的规则,我将一个名为 vendor.te 的文件添加到设备目录中的 sepolicy 文件夹中,其内容如下:

type vendor_app, domain;
type vendor_file, file_type, data_file_type;
# permissive vendor_app;

app_domain(vendor_app)
net_domain(vendor_app)
bluetooth_domain(vendor_app)

allow vendor_app persist_file:dir r_dir_perms;
allow vendor_app vendor_file:dir create_dir_perms;
allow vendor_app vendor_file:file create_file_perms;

allow vendor_app audioserver_service:service_manager find;
allow vendor_app cameraserver_service:service_manager find;
allow vendor_app drmserver_service:service_manager find;
allow vendor_app mediaserver_service:service_manager find;
allow vendor_app mediaextractor_service:service_manager find;
allow vendor_app mediacodec_service:service_manager find;
allow vendor_app mediadrmserver_service:service_manager find;
allow vendor_app persistent_data_block_service:service_manager find;
allow vendor_app radio_service:service_manager find;
allow vendor_app surfaceflinger_service:service_manager find;
allow vendor_app app_api_service:service_manager find;
allow vendor_app system_api_service:service_manager find;
allow vendor_app vr_manager_service:service_manager find;

我已经在file_contexts配置文件中添加了一个条目:

###################################
# persist files
#
/persist(/.*)?                                                      u:object_r:persist_file:s0
/persist/vendor(/.*)?                                               u:object_r:vendor_file:s0

在/persist分区上,我创建了一些目录结构,以便有适当权限的文件夹可以在其中添加一些文件。
# ls -Zal /persist/vendor/                                            
total 56
drwxrwxrwx  5 persist   persist   u:object_r:vendor_file:s0  4096 2017-08-03 22:27 .
drwxrwx--x 16 system    system    u:object_r:persist_file:s0 4096 2017-08-01 16:24 ..
drwxrwxrwx  2 profile   profile   u:object_r:vendor_file:s0  4096 2017-08-04 13:34 profile
drwxrwxrwx  2 provision provision u:object_r:vendor_file:s0  4096 2017-08-04 13:34 provisioning
drwxrwxrwx  2 updater   updater   u:object_r:vendor_file:s0  4096 2017-08-04 13:34 updater

我知道服务的“find”规则是起作用的,因为我能够在强制执行模式下启动我的应用程序,并且没有任何关于此的投诉。根据关于“persist_file:dir”的规则,我也可以访问{search}的/persist目录。
当我尝试将新文件(如/persist/vendor/updater/test)写入/persist目录时,auditd会返回错误消息:
08-04 16:34:29.269  4108  4108 W .permissiontest: type=1400 audit(0.0:27): avc: denied { write } for name="updater" dev="mmcblk0p44" ino=55 scontext=u:r:vendor_app:s0:c512,c768 tcontext=u:object_r:vendor_file:s0 tclass=dir permissive=0

当然,audit2allow 会将该错误转换为以下规则:

#============= vendor_app ==============
allow vendor_app vendor_file:dir write;

作为create_dir_perms的成员,write实际上应该在那里。我还尝试将audit2allow生成的代码行添加到我的vendor.te中,但没有成功。
请注意,写入更新程序还涉及对persist_file和vendor_file进行搜索,这两个似乎都没有任何问题。
有人有什么建议吗,如何正确调试或甚至解决此问题?我已经钻研了两天,它让我疯狂。
编辑:啊,/persist当然可以被挂载为可写:
# mount | grep persist
/dev/block/bootdevice/by-name/persist on /persist type ext4 (rw,seclabel,nosuid,nodev,relatime,nodelalloc,errors=panic,data=ordered)

编辑2:

正如Paul Ratazzi所要求的那样,我已经扫描了sepolicy文件和实际加载到内核中的版本,以查看我的规则是否存在。

$ sesearch -A -s vendor_app -t vendor_file policy 
allow vendor_app vendor_file:dir { rename search setattr read lock create reparent getattr write ioctl rmdir remove_name open add_name };
allow vendor_app vendor_file:file { rename setattr read lock create getattr write ioctl unlink open append };

因此,它们实际上已经正确部署到设备中。

1
如果您还没有这样做,请尝试从正在运行的设备中提取'/sepolicy',将其加载到'apol'中,并检查所有规则是否实际上被编译为策略二进制文件并按照您的预期显示。这可能有助于将问题缩小到构建与运行时问题之间的差异。 - Paul Ratazzi
感谢您的提示。事实上,据我所知,Apol与Android的SELinux策略不兼容,因为Google使用的是自定义版本(v30)的策略文件,而这些文件不受setools支持。但是他们提供了自己的工具来解析和搜索策略文件。这些工具显示规则已经存在于设备上。我将编辑帖子并将输出放在那里。 - nexus
1个回答

8
好的,在进一步查找后,我终于找到了答案。为了可能帮助那些遇到相同问题的人节省时间和精力,以下是解决方案:
除了 MAC(强制访问控制) SElinux 之外,Android 还具有 MLS(多级安全)
虽然 MAC 在 Android SELinux 概念 中有所描述,但关于 MLS 的信息只是简单提及并隐含地说明:
在 SELinux 中,标签采用以下格式:user:role:type:mls_level,其中 type 是访问决策的主要组成部分,可以通过其他组成标签的部分进行修改。
因此,我的 Android 应用程序运行在一个 MLS 级别上(由 c512,c768 表示),该级别可以读取 /persist 上的文件,但无法写入。因此,我的应用程序需要获得一个 MLS 级别才能正确访问这些文件。
我通过更改自定义标签来实现这一点(暂时)。
type vendor_app, domain, mlstrustedsubject;

这使我的应用程序更加可靠。这解决了问题,但是给我的应用程序授予了大量访问权限。因此,更好的选择是将目标的安全级别降低到授予我的应用程序读写访问权限的级别。
因此,这基本上是目前的解决方案(尽管还没有完全完成)。

你能否将应用程序的安全级别降低而不使用mlstrustedobject? - Krishna Balan
我认为我已经从seapp_contexts中删除了“levelFrom=user”,但是最终我成功地消除了mlstrustedobject。 - nexus
感谢您的回答。我花了一晚上的时间试图弄清楚为什么我的i2c_device:chr_file写入被拒绝了。没有任何错误,但它就是会被拒绝,尽管已经明确允许了。结果证明需要mlstrustedsubject。 - Rick Sanchez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接