android 系统似乎忽略了我的自定义 selinux 策略

My custom selinux policies seem to be ignored by android system

我在基于 Android 7.1.2(更准确地说是基于索尼开放设备树)的 AOSP 上正确获取自定义 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

我的应用程序在 vendor_app 上下文中正确启动:

# 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 上下文中的应用程序 运行 应 read/write 访问 /persist/vendor[=83= 中的文件].为了创建必要的规则,我在设备目录的 sepolicy 文件夹中添加了一个名为 vendor.te 的文件,内容如下:

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-rules 正在工作,因为我能够在强制模式下启动我的应用程序并且没有收到任何关于它的投诉。我还可以根据有关 persist_file:dir.[= 的规则访问 { search } 的 /persist 目录20=]

一旦我尝试将 /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;

由于 writecreate_dir_perms 的成员,它实际上应该在那里。我还尝试将 audit2allow 创建的行添加到我的 vendor.te 但没有成功。

请注意,写入更新程序还涉及 search on persist_filesearch 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 };

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

好吧,经过更多的挖掘,看来我终于找到了答案。为了可能在一些伤脑筋的日子里让某人 运行 陷入同样的​​问题,这里是解决方案:

除了MAC (Mandatory Access Control) SElinux on android also MLS (Multi-Level Security)

虽然 MAC 在 Android SELinux concepts 中以某种方式描述,但仅非常简短和隐含地提到了有关 MLS 的信息:

In SELinux, a label takes the form: user:role:type:mls_level, where the type is the primary component of the access decisions, which may be modified by the other sections components which make up the label.

所以,我的 Android 应用程序运行在 MLS 级别(由 c512、c768 表示),可以读取 /persist 上的文件但不能写入文件。所以需要发生的是我的应用程序获得 MLS 级别以正确访问这些文件。

我(现在)通过将我的自定义标签更改为

将其存档
type vendor_app, domain, mlstrustedsubject;

这让我的应用值得信赖。这解决了问题,但授予了对我的应用程序的大量访问权限。因此,更好的选择是将目的地的安全级别设置为授予对我的应用程序的读写访问权限的级别。

所以这基本上是这个问题到目前为止的解决方案(虽然还没有完成)。