文件 DAC 配置

早期版本的 Android 使用不可扩展的系统配置文件,导致设备制造商无法通过添加具名二进制文件来指定所有权、访问模式或可执行权限的自主访问控制 (DAC)。设置这种限制的原因是为了支持 Linux 内核 3.14 及更高版本,这些版本通过 CAP_SUSPEND_BLOCK 功能启用唤醒锁定;要保持此唤醒锁定(从而在文件系统中设置此功能),需要合作伙伴提供的 GPS 守护进程。

从 Android 6.0 开始,fs_config 和相关结构定义 (system/core/include/private/android_filesystem_config.h) 位于 system/core/libcutils/fs_config.c 中,可以由安装在 /system/etc/fs_config_dirs/system/etc/fs_config_files 中的二进制文件进行更新或替换。为明确起见,Android 针对目录和文件采用单独的匹配和解析规则(可以使用其它全局表达式),并在两个不同的表格中处理目录和文件。system/core/libcutils/fs_config.c 中的结构定义不仅允许运行时读取目录和文件,而且主机在构建时也可以使用相同的文件来构建文件系统映像,比方说 ${OUT}/system/etc/fs_config_dirs${OUT}/system/etc/fs_config_files

生成替换文件

您可以使用 build/tools/fs_config 中的 fs_config_generate 工具生成相应的二进制文件 /system/etc/fs_config_dirs/system/etc/fs_config_files。该工具使用 libcutils 库函数 (fs_config_generate()) 管理放入缓冲区内的 DAC 需求,并为头文件定义规则来规定 DAC 规则的用法。

要使用此工具,请在 device/vendor/device/android_filesystem_config.h 中创建头文件作为替换。该文件必须使用 system/core/include/private/android_filesystem_config.h 中定义的 structure fs_path_config 格式,并对目录和文件符号进行以下结构初始化:

  • 对于目录,请使用 android_device_dirs[]
  • 对于文件,请使用 android_device_files[]

在不使用 android_device_dirs[]android_device_files[] 时,您可以定义 NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRSNO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES(请参见下面的示例)。

您还可以使用单板配置中的 TARGET_ANDROID_FILESYSTEM_CONFIG_H 指定强制基本名称为 android_filesystem_config.h 的替换文件。

包含的文件

PRODUCT_PACKAGES 必须包含 fs_config_dirs 和/或 fs_config_files,才能分别将它们安装到 /system/etc/fs_config_dirs/system/etc/fs_config_files

构建系统会在 BoardConfig.mk 所在的 $(TARGET_DEVICE_DIR) 中搜索自定义 android_filesystem_config.h。如果此文件位于其他位置,请设置单板配置变量 TARGET_ANDROID_FILESYSTEM_CONFIG_H 来指向该位置。

配置

要在 Android 6.0 及更高版本中配置文件系统,请按以下步骤操作:

  1. 创建 $(TARGET_DEVICE_DIR)/android_filesystem_config.h 文件。
  2. fs_config_dirs 和/或 fs_config_files 添加到单板配置文件(例如 $(TARGET_DEVICE_DIR)/device.mk)中的 PRODUCT_PACKAGES

迁移问题

将系统配置从 Android 5.0 及更早版本中迁出会造成干扰。在规划此类迁移时,请注意以下事项:

  • Android 6.0 会移除部分头文件、结构和内嵌定义。
  • Android 6.0 需要引用 libcutils,而不是直接从 system/core/include/private/android_filesystem_config.h 运行。依赖于 system/code/include/private_filesystem_config.h 的文件/目录结构或者 fs_config 的设备制造商私有可执行文件必须添加 libcutils 库依赖关系。
  • Android 6.0 需要使用 system/core/include/private/android_filesystem_config.h 的设备制造商私有分支副本,该副本应包含有关现有目标的附加内容,以便移至 device/vendor/device/android_filesystem_config.h
  • 由于 Android 保留将 SELinux 强制访问控制 (MAC) 应用于目标系统中配置文件的权利,因此包含使用 fs_config() 的自定义目标可执行文件的实现必须确保具有访问权限。

示例

此示例展示了用于替换 system/bin/glgps 守护进程以在 device/vendor/device 目录中添加唤醒锁定支持的补丁。请注意以下几点:

  • 每个结构条目都包含模式、uid、gid、功能和名称。 已自动包含 system/core/include/private/android_filesystem_config.h 来提供清单 #defines(AID_ROOTAID_SHELLCAP_BLOCK_SUSPEND)。
  • android_device_files[] 区段包含在未指定时禁止访问 system/etc/fs_config_dirs 的操作,其作用是在缺少目录替换内容时提供额外 DAC 保护。但此保护的强度较弱;如果有人拥有超过 /system 的控制权,那么他通常可以执行任何操作。
diff --git a/android_filesystem_config.h b/android_filesystem_config.h
new file mode 100644
index 0000000..874195f
--- /dev/null
+++ b/android_filesystem_config.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+/* This file is used to define the properties of the filesystem
+** images generated by build tools (eg: mkbootfs) and
+** by the device side of adb.
+*/
+
+#define NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS
+/* static const struct fs_path_config android_device_dirs[] = { }; */
+
+/* Rules for files.
+** These rules are applied based on "first match", so they
+** should start with the most specific path and work their
+** way up to the root. Prefixes ending in * denotes wildcard
+** and will allow partial matches.
+*/
+static const struct fs_path_config android_device_files[] = {
+  { 00755, AID_ROOT, AID_SHELL, (1ULL << CAP_BLOCK_SUSPEND),
"system/bin/glgps" },
+#ifdef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS
+  { 00000, AID_ROOT, AID_ROOT, 0, "system/etc/fs_config_dirs" },
+#endif
+};

diff --git a/device.mk b/device.mk
index 0c71d21..235c1a7 100644
--- a/device.mk
+++ b/device.mk
@@ -18,7 +18,8 @@ PRODUCT_PACKAGES := \
     libwpa_client \
     hostapd \
     wpa_supplicant \
-    wpa_supplicant.conf
+    wpa_supplicant.conf \
+    fs_config_files

 ifeq ($(TARGET_PREBUILT_KERNEL),)
 ifeq ($(USE_SVELTE_KERNEL), true)