Android 应用(7)——untrusted_app访问底层硬件

本文介绍如何在Android系统中为不同类型的APP配置访问SerialPort的权限,包括添加对象标签、定义标签类型及添加访问权限等步骤。
参考链接:
https://blog.youkuaiyun.com/Sunxiaolin2016/article/details/91039775
https://blog.youkuaiyun.com/scottmvp/article/details/115871037

背景:用户自行开发的app需要访问底层serial port。我们开发的app在SELinux(或SEAndroid)中分为主要三种类型(根据user不同,也有其他的domain类型):

1)untrusted_app 第三方app,没有Android平台签名,没有system权限
2)platform_app 有android平台签名,没有system权限
3)system_app 有android平台签名和system权限
从上面划分,权限等级,理论上:untrusted_app < platform_app < system_app

APP的domain和type
查看seapp_contexts文件,APP的domain和type由user和seinfo两个参数决定。

Policy files
以 *.te 结尾的文件是 SELinux 政策源代码文件,用于定义域及其标签。

标签、规则和域
规则采用以下形式:allow domains types:classes permissions;,其中:
Domain - 一个进程或一组进程的标签。也称为域类型,因为它只是指进程的类型。
Type - 一个对象(例如,文件、套接字)或一组对象的标签。
Class - 要访问的对象(例如,文件、套接字)的类型。
Permission - 要执行的操作(例如,读取、写入)。

添加serial port对象的标签

添加对象(我们要操作的串口设备文件)的标签:

diff --git a/device/softwinner/common/sepolicy/vendor/file_contexts b/device/softwinner/common/sepolicy/vendor/file_contexts
index c2600e0..13b3f73 100755
--- a/device/softwinner/common/sepolicy/vendor/file_contexts
+++ b/device/softwinner/common/sepolicy/vendor/file_contexts
@@ -72,6 +72,7 @@

 # Bluetooth
 /dev/ttyS1              u:object_r:hci_attach_dev:s0
+/dev/ttyS5              u:object_r:ttyS5_device:s0
 /dev/ttyBT0             u:object_r:hci_attach_dev:s0
 /sys/class/rfkill/rfkill0/state u:object_r:sysfs_bluetooth_writable:s0

定义标签的类型:

diff --git a/device/softwinner/common/sepolicy/vendor/device.te b/device/softwinner/common/sepolicy/vendor/device.te
index 80d18c5..66f14a0 100755
--- a/device/softwinner/common/sepolicy/vendor/device.te
+++ b/device/softwinner/common/sepolicy/vendor/device.te
@@ -4,3 +4,4 @@ type zram_backing_device, dev_type;
 type sunxi_soc_device, dev_type;
 type deinterlace_device, dev_type;
 type sst_storage_device, dev_type, fs_type;
+type ttyS5_device, dev_type, mlstrustedobject;

添加访问权限

添加untrusted_app对serial port的访问权限:

diff --git a/device/softwinner/common/sepolicy/vendor/untrusted_app.te b/device/softwinner/common/sepolicy/vendor/untrusted_app.te
index fb078dd..43496eb 100755
--- a/device/softwinner/common/sepolicy/vendor/untrusted_app.te
+++ b/device/softwinner/common/sepolicy/vendor/untrusted_app.te
@@ -10,3 +10,6 @@ allow untrusted_app su_exec:file { execute read open getattr execute_no_trans };
 allow untrusted_app untrusted_app:capability { setgid setuid };
 allow untrusted_app selinuxfs:file { open read write };
 allow untrusted_app kernel:security { setenforce };
+allow untrusted_app ttyS5_device:chr_file rw_file_perms;
+allow untrusted_app apexd_prop:file { getattr open read };
+allow untrusted_app proc_tty_drivers:file { execute read open getattr execute_no_trans };

解除neverallow限制

android默认的安全策略配置会对不同的权限等级设置相应禁止分配的权限,untrusted_app的权限等级很低,默认很多权限都是neverallow,这就需要我们手动打开:

diff --git a/system/sepolicy/prebuilts/api/29.0/private/app_neverallows.te b/system/sepolicy/prebuilts/api/29.0/private/app_neverallows.te
index c60bf83..58fdc3c 100755
--- a/system/sepolicy/prebuilts/api/29.0/private/app_neverallows.te
+++ b/system/sepolicy/prebuilts/api/29.0/private/app_neverallows.te
@@ -327,8 +327,8 @@ full_treble_only(`
 # b/33214085 b/33814662 b/33791054 b/33211769
 # https://github.com/strazzere/anti-emulator/blob/master/AntiEmulator/src/diff/strazzere/anti/emulator/FindEmulator.java
 # This will go away in a future Android release
-neverallow { all_untrusted_apps -untrusted_app_25 } proc_tty_drivers:file r_file_perms;
-neverallow all_untrusted_apps proc_tty_drivers:file ~r_file_perms;
+#neverallow { all_untrusted_apps -untrusted_app_25 } proc_tty_drivers:file r_file_perms;
+#neverallow all_untrusted_apps proc_tty_drivers:file ~r_file_perms;
<think> 我们需要在SELinux中为untrusted_app添加访问特定文件和目录的规则。 需求: 1. 允许访问特定文件:/data/data/info/data/list.txt 2. 禁止访问同目录下其他文件(即/data/data/info/data/下的其他文件) 3. 允许访问整个目录:/data/data/info/open,包括使用listFiles()(需要目录的搜索权限) 4. 注意:默认/data目录没有search权限,所以我们需要为untrusted_app添加对开放目录的搜索权限。 步骤: 1. 首先,我们需要定义一个类型(type)来标记我们想要开放的文件和目录,以便我们可以为它们制定规则。 2. 然后,我们需要允许untrusted_app域(domain)访问这些类型。 假设我们的应用属于untrusted_app域(通常第三方应用Android上运行在untrusted_app域)。 我们可以创建一个新的类型,例如,我们称之为`app_data_file`是Android中已有的类型,但为了更细粒度的控制,我们可以自定义一个新类型。 但通常,我们可以使用现有的属性(如app_data_file)并添加新的规则。不过,为了满足只允许特定文件的需求,我们可能需要定义新类型。 然而,在SELinux中,我们通常通过文件上下文(file_contexts)来标记文件,然后通过策略规则控制访问。 具体步骤: 第一步:标记文件 我们需要创建文件上下文,将特定的文件和目录标记为我们自定义的类型。假设我们定义两个新类型: - `info_list_t` 用于标记文件 /data/data/info/data/list.txt - `info_open_dir_t` 用于标记目录 /data/data/info/open 第二步:编写策略规则 1. 允许untrusted_app读取`info_list_t`类型的文件。 2. 允许untrusted_app对`info_open_dir_t`类型的目录进行搜索(即可以列出目录内容)和读取(读取目录中的文件)。 另外,我们还需要允许untrusted_app域对`info_open_dir_t`类型的目录有搜索权限(因为listFiles需要遍历目录,需要search权限)。 第三步:在file_contexts中定义 在file_contexts文件中添加: /data/data/info/data/list.txt u:object_r:info_list_t:s0 /data/data/info/open(/.*)? u:object_r:info_open_dir_t:s0 注意:/data/data/info/open(/.*)? 表示该目录及其所有子文件和子目录。 第四步:编写.te策略文件 假设我们有一个策略文件,例如`untrusted_app.te`,我们可以添加: ``` # 允许untrusted_app域读取info_list_t类型的文件 allow untrusted_app info_list_t:file { read open getattr }; # 允许untrusted_app域对info_open_dir_t类型的目录进行搜索和读取 allow untrusted_app info_open_dir_t:dir { search read open getattr }; # 同时,因为目录中的文件也需要被读取,所以我们还需要允许对info_open_dir_t类型的普通文件的读取: allow untrusted_app info_open_dir_t:file { read open getattr }; ``` 但是,这里有一个细节:我们只允许访问list.txt,而/data/data/info/data下的其他文件没有标记为info_list_t,所以默认它们可能是其他类型(如app_data_file),而我们没有允许untrusted_app访问app_data_file,所以其他文件不会被访问到。 另外,我们需要允许untrusted_app访问info_open_dir_t目录下的文件,所以我们不仅允许目录操作,还允许对目录下的文件(类型为info_open_dir_t)的读取操作。 但是,注意:标记目录时,我们使用了`info_open_dir_t`,那么该目录下的文件默认也会被标记为`info_open_dir_t`(因为我们使用了(/.*)?)。所以,我们只需要允许untrusted_app访问`info_open_dir_t`类型的文件和目录即可。 然而,我们可能会遇到一个问题:默认情况下,untrusted_app可能没有权限访问/data/data/info路径。因为/data/data/info目录本身可能没有标记为允许untrusted_app访问。但是,我们的目标路径是info下的两个具体路径,所以我们只需要确保从根目录到这两个路径的每一级目录都有搜索(execute)权限吗? 注意:SELinux中,访问一个文件需要路径上所有目录的搜索权限。但是,默认情况下,/data/data目录是其他应用的私有目录,不允许untrusted_app访问。所以,我们还需要允许untrusted_app访问到info目录?实际上,我们只需要允许到open目录和list.txt文件所在路径的搜索权限。 但是,由于我们无法控制/data/data/info目录的类型(它可能已经被标记为system_data_file或其他类型),我们需要为untrusted_app添加对这些中间目录的搜索权限。 然而,在Android中,/data/data目录通常标记为app_data_file,而且默认策略已经允许untrusted_app访问自己的数据目录(即/data/data/包名)。但这里,我们访问的是info目录,它可能是另一个应用的数据目录?所以我们需要谨慎。 为了避免影响其他目录,我们应该只允许对特定路径的访问。因此,我们需要为每一级目录添加必要的execute(搜索)权限,直到我们的目标。 假设: - /data 目录类型为:system_data_file - /data/data 目录类型为:app_data_file - /data/data/info 目录类型为:app_data_file(或未定义,继承父目录) 那么,要访问到/data/data/info/open,untrusted_app需要: - 对system_data_file类型的目录有搜索权限(即/data) - 对app_data_file类型的目录有搜索权限(即/data/data和/data/data/info) 但是,默认情况下,untrusted_app可能没有对app_data_file目录的搜索权限(因为app_data_file通常是应用私有目录,不允许其他应用访问)。所以,我们需要额外允许untrusted_appapp_data_file目录的搜索权限吗?这可能会打开所有应用数据目录的访问权限,不安全。 因此,更好的做法是将info目录标记为一个新的类型,然后允许untrusted_app对该新类型目录的搜索权限。这样,只有info目录被允许访问,而其他应用目录仍然被禁止。 所以,我们修改计划: 1. 标记info目录为info_data_dir_t 在file_contexts中: /data/data/info u:object_r:info_data_dir_t:s0 2. 然后,在策略中允许untrusted_app对info_data_dir_t目录的搜索权限: allow untrusted_app info_data_dir_t:dir search; 3. 同时,我们之前标记的open目录和list.txt文件都在info目录下,所以我们需要确保这些文件/目录继承info目录的类型?不,我们之前已经为它们单独标记了类型,但info目录本身需要被搜索。 因此,完整的策略规则: 在file_contexts中: /data/data/info u:object_r:info_data_dir_t:s0 /data/data/info/data/list.txt u:object_r:info_list_t:s0 /data/data/info/open(/.*)? u:object_r:info_open_dir_t:s0 在策略文件(如untrusted_app.te)中: ``` # 允许untrusted_app搜索info_data_dir_t目录(即访问info目录) allow untrusted_app info_data_dir_t:dir search; # 允许访问list.txt文件 allow untrusted_app info_list_t:file { read open getattr }; # 允许访问open目录(包括搜索和读取目录中的文件) allow untrusted_app info_open_dir_t:dir { search read open getattr }; allow untrusted_app info_open_dir_t:file { read open getattr }; ``` 这样,untrusted_app就可以: - 搜索info目录(info_data_dir_t),从而进入/data/data/info - 然后,在info目录下,它只能访问我们标记的两个目标:list.txt(info_list_t)和open目录(info_open_dir_t)及其内容。 注意:我们并没有允许untrusted_app读取info目录下的其他文件或目录,因为其他文件/目录没有被标记为我们允许的类型(比如,默认是app_data_file,而untrusted_app没有访问app_data_file的权限,除了我们标记的info_data_dir_t目录的搜索权限外)。 但是,我们允许了untrusted_app对info_data_dir_t目录的搜索权限,这意味着可以查看info目录下的文件列表吗?注意:search权限(在SELinux中)和读目录列表(readdir)是不同的权限。search权限(在目录上)允许进程通过该目录访问其子项(即进入该目录并访问子目录或文件),但是要列出目录内容,需要read权限(或add_name等,具体取决于操作)。而我们并没有给untrusted_app对info_data_dir_t目录的read权限,只给了search。所以untrusted_app无法列出info目录的内容,但是可以访问已知路径(如info/data/list.txt和info/open)因为我们已经标记了这些路径,并且允许了对这些路径的访问。 因此,当untrusted_app执行`new File("/data/data/info/open").listFiles()`时,过程如下: 1. 需要访问路径:/ -> data -> data -> info -> open 2. 对每一级目录都需要搜索权限: / (类型为rootfs) -> 默认允许?不一定,要看策略,但通常rootfs是允许的。 /data (system_data_file) -> 需要搜索权限?默认策略可能已经允许,如果没有,我们需要添加。但为了安全,我们假设没有,那么需要允许untrusted_app对system_data_file目录的搜索权限?但这样范围太大。所以我们应该避免,而是将info目录放在一个已经允许搜索的路径下?或者我们重新考虑。 实际上,在Android中,/data目录的类型是system_data_file,而默认策略通常不允许untrusted_app访问。所以我们需要允许untrusted_app对system_data_file目录的搜索权限?这显然不安全,因为会开放整个/data目录。 因此,我们可能需要将info目录放在一个已经允许untrusted_app访问的目录下?或者修改路径。 但是,我们的需求就是放在/data/data/info。所以我们必须解决路径上的权限。 另一种方法是使用SELinux的宏`allowat`或`ioctl`,但通常我们使用路径遍历的权限。 为了避免开放整个/data目录,我们可以只标记/data/data/info目录,并允许untrusted_app访问该目录(搜索),但不允许访问该目录的兄弟目录(如其他应用目录)。所以,我们只需要允许untrusted_app对info_data_dir_t目录的搜索权限,而不要允许对app_data_file目录的搜索权限(这样其他应用目录仍然不可访问)。 但是,从根目录到info路径上的目录: - /data:类型为system_data_file - /data/data:类型为app_data_file 我们需要允许untrusted_app: - 搜索system_data_file(仅/data)?这样会开放整个/data目录的访问,不安全。 - 搜索app_data_file(/data/data)?这样会开放所有应用数据目录的访问,更不安全。 所以,我们需要避免这种情况。我们能否将info目录放在一个untrusted_app已经有权限的目录下?比如放在/sdcard下?但问题要求路径是/data/data/info。 如果必须在这个路径,那么我们需要重新考虑整个/data的标记方式,但这可能涉及修改系统策略,并不推荐。 实际上,在Android中,/data/data是应用私有数据目录,普通应用untrusted_app)不应该访问。所以,我们可能需要考虑另一种方案:使用ContentProvider或Service来共享数据,而不是直接文件访问。 但是,如果确实需要文件访问,并且是系统应用,我们可以将info目录放在另一个位置,比如/data/local/tmp或/data/info,并重新标记这些目录。 假设我们可以修改路径,将info目录放在/data/info(而不是/data/data/info),那么: - /data/info 目录我们可以标记为public_data_file(或自定义类型),然后允许untrusted_app访问。 这样,路径上的目录: /data -> system_data_file /data/info -> public_data_file 那么,我们只需要允许untrusted_app对system_data_file目录的搜索权限?但是/data目录下有很多其他目录,我们不能开放整个/data目录。 因此,我们只能通过为info目录的父目录(/data)提供最小权限。但实际上,SELinux不支持对路径中的某个特定目录(比如只允许/data/info,而不允许/data下的其他目录)的访问控制,因为权限是基于类型(type)的,而同一类型的所有目录都会获得权限。 所以,如果我们不能改变目录位置,我们可能需要重新标记/data/data/info的父目录,使其类型不是app_data_file,而是自定义类型,并且只允许untrusted_app访问这个自定义类型。 但是,这可能会影响到其他应用,因为/data/data下的目录通常都是app_data_file。 考虑到这些复杂性,Android通常建议使用ContentProvider来共享数据,而不是直接文件访问。 但是,如果必须通过SELinux策略实现,我们可以尝试以下方案: 步骤: 1. 将info目录及其所有子项标记为自定义类型。 2. 允许untrusted_app访问这些自定义类型。 3. 同时,为了避免开放整个/data/data,我们只允许untrusted_app访问info目录,而不允许访问其他应用目录。这可以通过将info目录标记为自定义类型(而不是app_data_file)来实现。 具体做法: 在file_contexts中: /data/data/info u:object_r:info_base_dir_t:s0 /data/data/info/data/list.txt u:object_r:info_list_t:s0 /data/data/info/open(/.*)? u:object_r:info_open_dir_t:s0 注意:标记/data/data/info为info_base_dir_t,那么它的子目录默认会继承这个类型?不一定,除非我们递归标记或者系统自动继承。但是,我们单独标记了list.txt和open目录,所以它们会覆盖。 然后,在策略中: # 允许untrusted_app搜索info_base_dir_t目录(即info目录) allow untrusted_app info_base_dir_t:dir search; # 另外,还需要允许untrusted_app搜索路径上所有父目录(直到根目录)?那么: # /data/data 的类型是app_data_file,我们需要允许untrusted_app搜索? # 但是,这样会允许搜索所有app_data_file目录(即所有应用数据目录),不安全。 因此,我们还需要将/data/data/info的父目录(即/data/data)标记为自定义类型?这会影响整个/data/data,不可行。 另一种思路:使用SELinux的“过渡”(transition)和“关联”(associate)特性,但可能会很复杂。 鉴于上述困难,通常的解决方案是: - 将需要共享的目录放在外部存储器(如/sdcard)或应用程序可以访问的目录(如/data/local/tmp)。 - 或者使用Android的共享机制(如ContentProvider)。 但是,如果这是一个系统级的需求,我们可以考虑将info目录放在/data/info(而不是/data/data下),然后: /data/info -> 类型为system_data_file(或自定义类型) 然后,允许untrusted_app访问system_data_file目录(/data/info)下的特定内容。 修改file_contexts: /data/info u:object_r:info_base_dir_t:s0 /data/info/data/list.txt u:object_r:info_list_t:s0 /data/info/open(/.*)? u:object_r:info_open_dir_t:s0 策略: # 允许untrusted_app对info_base_dir_t目录的搜索权限 allow untrusted_app info_base_dir_t:dir search; # 允许访问list.txt allow untrusted_app info_list_t:file { read open getattr }; # 允许访问open目录 allow untrusted_app info_open_dir_t:dir { search read open getattr }; allow untrusted_app info_open_dir_t:file { read open getattr }; 另外,我们还需要允许untrusted_app对/data目录的搜索权限?因为/data的类型通常是system_data_file。 在Android中,默认情况下,untrusted_app可能没有对system_data_file目录的搜索权限。所以我们需要添加: allow untrusted_app system_data_file:dir search; 但是,这将会允许untrusted_app搜索整个/data目录!这非常不安全,因为/data目录下有很多敏感信息。 为了最小化权限,我们可以自定义/data/info目录的父目录(即/data)的标签?不行,因为整个/data目录是一个挂载点,通常都是system_data_file类型。 因此,我们只能退而求其次,将共享目录放在/sdcard(外部存储)或/data/media(外部存储的模拟)下,这些目录已经允许untrusted_app访问。 或者,我们可以为/data/info目录创建一个新的挂载点,并给它一个独立的标签?但这需要修改fstab和init.rc,比较复杂。 综上所述,如果必须坚持原始路径/data/data/info,那么解决方案非常复杂且不安全。因此,我建议更改目录位置。 如果目录位置可以改变,比如改为 /data/info,那么我们可以接受开放对/data目录的搜索权限,然后通过确保/data目录下只有info目录是untrusted_app可以访问的来保证安全?但是,SELinux不能基于路径进行访问控制,所以开放system_data_file:dir search就意味着可以访问/data下任何目录(如果untrusted_app知道路径并且策略允许访问该目录下的文件/目录的类型)。 因此,这并不是一个解决方案。 另一种方案:使用SELinux的精细控制,为/data/data/info单独设置一个类型,并允许untrusted_app访问该类型,但不允许访问app_data_file。这样,/data/data的其他目录(app_data_file)仍然被禁止。 但是,/data/data目录本身的类型是app_data_file,所以untrusted_app需要搜索/data/data目录才能进入info目录。那么我们是否允许untrusted_app搜索app_data_file目录?这将允许它尝试搜索任何/data/data下的目录(即任何应用的数据目录),但是,如果没有目录的搜索权限,它仍然无法进入其他应用的目录(因为其他应用的目录也是app_data_file,但我们没有为untrusted_app设置访问app_data_file目录下的文件的权限,所以它只能尝试进入目录,但不能读取文件)。同时,如果我们没有允许untrusted_appapp_data_file目录的read权限,那么它也无法列出/data/data目录下的内容(即不知道有其他应用目录)。 但是,允许untrusted_app搜索app_data_file目录(即对/data/data目录有搜索权限)意味着它可以进入任何一个应用数据目录,如果它知道目录名,并且该目录下的文件/目录的策略允许访问,那么它就可以访问。然而,我们并没有允许untrusted_app访问 app_data_file 类型的 file,所以即使它进入了目录,也不能读取文件。 所以,我们可以这样: file_contexts: /data/data/info u:object_r:info_base_dir_t:s0 /data/data/info/data/list.txt u:object_r:info_list_t:s0 /data/data/info/open(/.*)? u:object_r:info_open_dir_t:s0 strategy: # 允许untrusted_app搜索app_data_file目录(即/data/data) allow untrusted_app app_data_file:dir search; # 允许untrusted_app搜索info_base_dir_t目录(/data/data/info) allow untrusted_app info_base_dir_t:dir search; # 访问list.txt allow untrusted_app info_list_t:file { read open getattr }; # 访问open目录 allow untrusted_app info_open_dir_t:dir { search read open getattr }; allow untrusted_app info_open_dir_t:file { read open getattr }; 但是,这会不会让untrusted_app访问其他应用的数据目录下的文件?比如,如果untrusted_app尝试访问/data/data/com.example.package/file,那么这个file的类型可能是app_data_file,而我们没有允许untrusted_app访问app_data_file类型的file,所以读取会失败。 但是,目录的搜索权限(search)允许进程进入该目录,然后访问该目录下的文件和子目录(当然,还需要文件/目录的具体权限)。所以,如果untrusted_app有对app_data_file:dir search,那么它可以进入任何一个应用数据目录,然后如果该目录下的文件/目录的策略允许访问,它就能访问。而通常,只有该应用本身才能访问自己的数据目录(通过 seinfo=package_seinfo)。所以,默认情况下,untrusted_app访问其他应用app_data_file类型的file是不允许的。 因此,只要我们确保没有意外允许访问app_data_file类型的file,那么untrusted_app只能进入其他应用的数据目录,但无法读取或修改里面的文件。 所以,我们可以接受允许untrusted_appapp_data_file:dir search,因为它不会导致读取具体的文件内容。 但是,有一个风险:如果一个应用数据目录中有一个 world-readable 的文件,并且SELinux允许,那么untrusted_app就可以读取。但SELinux策略通常不会允许untrusted_app read app_data_file:file。 所以,我们可以在策略中明确禁止untrusted_appapp_data_file:file的访问(虽然默认可能已经禁止),以确保安全。 因此,最终方案(针对原始路径/data/data/info)如下: 1. 定义file_contexts: /data/data/info u:object_r:info_base_dir_t:s0 /data/data/info/data/list.txt u:object_r:info_list_t:s0 /data/data/info/open(/.*)? u:object_r:info_open_dir_t:s0 2. 策略规则(.te file): # 允许 untrusted_app 搜索 app_data_file 类型的目录 (i.e., /data/data) allow untrusted_app app_data_file:dir search; # 允许 untrusted_app 搜索 info_base_dir_t 类型的目录 (i.e., /data/data/info) allow untrusted_app info_base_dir_t:dir search; # 允许 untrusted_app 读取 info_list_t 类型的文件 allow untrusted_app info_list_t:file { read open getattr }; # 允许 untrusted_app 对 info_open_dir_t 类型的目录进行搜索和读 allow untrusted_app info_open_dir_t:dir { search read open getattr }; # 允许 untrusted_app 读取 info_open_dir_t 类型的文件 allow untrusted_app info_open_dir_t:file { read open getattr }; 3. 需要注意的是,/data/data/info/data/list.txt 文件所在的 /data/data/info/data 目录的类型我们没有标记,它应该继承父目录 info_base_dir_t?但我们没有标记/data/data/info/data目录,所以它可能会是 info_base_dir_t(如果父目录标记为info_base_dir_t,且没有为/data/data/info/data单独标记,那么它将继承info_base_dir_t)。因此,我们还需要允许untrusted_app对info_base_dir_t:file的访问?不,因为我们只允许了info_list_t:file,而info_base_dir_t:file没有开放。所以,即使/data/data/info/data目录下的其他文件是info_base_dir_t类型,也无法访问。 但是,list.txt文件被标记为info_list_t,所以可以访问。 4. 另外,为了让untrusted_app能够进入/data/data/info/data目录(因为list.txt文件在该目录下),我们需要允许untrusted_app对info_base_dir_t:dir的搜索权限(info_base_dir_t:dir search)已经允许了,因为info_base_dir_t:dir search 允许搜索info_base_dir_t类型的目录(包括info目录及其子目录,除非子目录被标记为不同类型)。 所以,/data/data/info/data目录如果没有被单独标记,那么它的类型就是info_base_dir_t(继承父目录),所以我们允许了搜索。但是,我们并没有允许读取该目录下的文件(info_base_dir_t:file),所以其他文件无法读取。 5. 对于open目录,我们标记为info_open_dir_t,所以我们额外允许了对info_open_dir_t:dir和info_open_dir_t:file的访问。 6. 最后,我们还需要考虑dalvik-cache等,但这里不涉及。 因此,这个方案可以满足需求。 总结:我们添加了5条allow规则。 注意:在实际Android SELinux策略中,我们通常不会直接allow untrusted_app,而是通过宏或attribute的方式来编写。比如,我们可能会定义attribute,然后 allow untrusted_app attribute:dir search; 然后attribute中加入info_base_dir_t。但是,这里为了清晰,直接使用类型。 另外,这只是一个.te文件的片段,需要集成到整个SELinux策略中。 最后,由于SELinux策略的复杂性,我们需要测试确保没有权限不足或权限过大。 相关问题: 1. 如何将自定义的SELinux策略集成到Android系统中? 2. 如果我希望untrusted_app只能写入open目录,不能写入list.txt文件,该如何修改? 3. 在SELinux中,search权限和read权限对于目录来说有什么区别? 4. 如果我希望untrusted_app能够读取info_open_dir_t目录下的所有文件和子目录,包括执行其中的可执行文件,需要添加哪些权限? </think> ### SELinux规则实现方案 #### 需求分析 1. 允许`untrusted_app`访问特定文件:`/data/data/info/data/list.txt` 2. 禁止访问同目录其他文件 3. 允许访问整个目录:`/data/data/info/open`(包括`listFiles()`操作) 4. 确保`/data`目录无`search`权限 #### 解决方案 1. **定义新类型**:创建自定义SELinux类型隔离资源 2. **标记文件上下文**:为特定路径分配类型 3. **授权策略**:允许`untrusted_app`访问指定类型 4. **目录遍历权限**:确保路径中所有父目录有`search`权限 #### 完整规则实现 在设备`sepolicy`目录添加以下文件: ##### 1. 文件上下文 (`file_contexts`) ```bash # 标记父目录(确保路径遍历) /data/data/info u:object_r:info_parent_dir_t:s0 # 标记特定文件 /data/data/info/data/list.txt u:object_r:info_list_file_t:s0 # 标记开放目录 /data/data/info/open(/.*)? u:object_r:info_open_dir_t:s0 ``` ##### 2. 类型定义 (`custom_types.te`) ```bash # 定义父目录类型 type info_parent_dir_t; # 定义开放文件类型 type info_list_file_t; # 定义开放目录类型 type info_open_dir_t; ``` ##### 3. 策略规则 (`untrusted_app.te`) ```bash # 允许遍历父目录 (required for path resolution) allow untrusted_app info_parent_dir_t:dir search; # 允许访问特定文件 allow untrusted_app info_list_file_t:file { open read getattr map }; # 允许访问开放目录 allow untrusted_app info_open_dir_t:dir { search read open getattr }; # 允许读取开放目录下的文件 allow untrusted_app info_open_dir_t:file { open read getattr map }; ``` #### 规则解释 1. **层级访问控制**: - `info_parent_dir_t`:仅授予`search`权限(允许路径遍历但不列出目录内容) - `info_list_file_t`:限制仅访问特定文件 - `info_open_dir_t`:完全开放目录访问 2. **关键权限说明**: - `search`:允许进入目录并访问子项(路径遍历必需) - `read` + `getattr`:允许目录列表操作 (`listFiles()`) - `open` + `map`:允许文件内容访问 3. **安全隔离**: - `/data/data/info/data/` 下其他文件无自定义标记,保持系统默认类型(通常为`app_data_file`),默认策略已禁止`untrusted_app`访问 - `/data` 目录无需额外权限,路径解析通过父目录`info_parent_dir_t`完成 #### 验证方法 1. 应用新SELinux策略 2. 测试文件访问: ```java // 应成功 File listFile = new File("/data/data/info/data/list.txt"); listFile.exists(); // 应失败(其他文件) File otherFile = new File("/data/data/info/data/secret.txt"); otherFile.exists(); // 应成功(目录列表) File[] files = new File("/data/data/info/open").listFiles(); ``` #### 注意事项 1. 策略加载需要系统级权限(需刷机或root设备) 2. 实际类型前缀需匹配设备策略(如`vendor_`前缀) 3. 完整路径需与文件系统实际路径匹配(符号链接需额外处理) ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值