Android U user+root实现方案

背景

由于项目(MTK平台)上要实现user+root的版本,供特殊用户使用。Android T上的方案无效,经历了各种搜索查看资料,和bsp大佬一起通宵奋战,整出了方案。梳理记录下,有需要的同学可以参考。

Root代码实现原理

系统判断是否有root权限的地方在system/packages/modules/adb/daemon/main.cpp里面,

should_drop_privileges()函数返回false,表明可以root。

复制代码
auth_required 是否需要adb鉴权(adb弹框确认),false时默认授权adb鉴权权限,不需要弹框确认。

userdebug 版本可以root是因为ro.secure = 0,代码路径build/core/main.mk 在should_drop_privileges()里面有判断

java 复制代码
else # !user_variant
   # Turn on checkjni for non-user builds.
   ADDITIONAL_SYSTEM_PROPERTIES += ro.kernel.android.checkjni=1
   # Set device insecure for non-user builds.
   ADDITIONAL_SYSTEM_PROPERTIES += ro.secure=0
java 复制代码
static bool should_drop_privileges() {
    // The properties that affect `adb root` and `adb unroot` are ro.secure and
    // ro.debuggable. In this context the names don't make the expected behavior
    // particularly obvious.
    //
    // ro.debuggable:
    //   Allowed to become root, but not necessarily the default. Set to 1 on
    //   eng and userdebug builds.
    //
    // ro.secure:
    //   Drop privileges by default. Set to 1 on userdebug and user builds.
    bool ro_secure = android::base::GetBoolProperty("ro.secure", true);
    bool ro_debuggable = __android_log_is_debuggable();

    // Drop privileges if ro.secure is set...
    bool drop = ro_secure;

    // ... except "adb root" lets you keep privileges in a debuggable build.
    std::string prop = android::base::GetProperty("service.adb.root", "");
    bool adb_root = (prop == "1");
    bool adb_unroot = (prop == "0");
    if (ro_debuggable && adb_root) {
        drop = false;
    }
    // ... and "adb unroot" lets you explicitly drop privileges.
    if (adb_unroot) {
        drop = true;
    }

    return drop;
}

实现中遇到的问题

1,selinux问题(主要解决问题);

2,缺少su 和remount执行的bin文件;

具体实现方案和步骤

1),特殊版本标识,CUSTOM_ROOT_VERSION=yes,编译版本时需要export下该环境变量

2),添加flag,路径build/core/soong_config.mk

Go 复制代码
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -58,6 +58,9 @@
 
 $(call add_json_bool, Debuggable,                        $(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
 $(call add_json_bool, Eng,                               $(filter eng,$(TARGET_BUILD_VARIANT)))
+$(call add_json_bool, ROOTVersion,                         $(filter yes,$(CUSTOM_ROOT_VERSION)))
 $(call add_json_str,  DeviceName,                        $(TARGET_DEVICE))

3),添加root版本的数据声明,设置root相关的flag需要

Go 复制代码
--- a/android/variable.go
+++ b/android/variable.go
@@ -151,6 +151,14 @@
 			}
 		}

+		ROOTVersion struct {
+			Cflags          []string
+			Cppflags        []string
+			Init_rc         []string
+		}

 		Pdk struct {
 			Enabled *bool `android:"arch_variant"`
 		} `android:"arch_variant"`
@@ -315,6 +323,9 @@
 	UseRBED8                         *bool    `json:",omitempty"`
 	Debuggable                       *bool    `json:",omitempty"`
 	Eng                              *bool    `json:",omitempty"`
+	ROOTVersion                        *bool    `json:",omitempty"`
 	Treble_linker_namespaces         *bool    `json:",omitempty"`

4),添加su 和 remount 模块,在产品的mk文件中添加

PRODUCT_PACKAGES +=remount

PRODUCT_PACKAGES +=su

5),在文件系统模块fs_mgr中添加ROOTVersion相应的flag,property_service中设置ro.secure和ro.debuggable的值

Go 复制代码
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -118,6 +118,14 @@
                 "-DALLOW_ADBD_DISABLE_VERITY=1",
             ],
         },
+        ROOTVersion: {
+            cppflags: [
+                "-UALLOW_ADBD_DISABLE_VERITY",
+                "-DALLOW_ADBD_DISABLE_VERITY=1",
+            ],
+        },
     },
     header_libs: [
         "libfiemap_headers",
@@ -248,6 +256,17 @@
                 "clean_scratch_files.rc",
             ],
         },
+        ROOTVersion: {
+            cppflags: [
+                "-UALLOW_ADBD_DISABLE_VERITY",
+                "-DALLOW_ADBD_DISABLE_VERITY=1",
+            ],
+            init_rc: [
+                "clean_scratch_files.rc",
+            ],
+        },
     },
     symlinks: [
         "clean_scratch_files",

--- a/init/Android.bp
+++ b/init/Android.bp
@@ -149,6 +149,13 @@
                 "-DSHUTDOWN_ZERO_TIMEOUT=1",
             ],
         },
+        ROOTVersion: {
+            cppflags: [
+                "-DROOT_VERSION",
+            ],
+        },
         uml: {
             cppflags: ["-DUSER_MODE_LINUX"],
         },

--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -1328,6 +1328,19 @@
         }
     }
 
+    bool adbAuthorized = false;
+#ifdef ROOT_VERSION
+    adbAuthorized = true;
+#endif
+    if (adbAuthorized) {
+        InitPropertySet("ro.adb.secure", "0");
+        InitPropertySet("ro.debuggable", "1");
+    }
+
     for (const auto& [name, value] : properties) {

6)adb模块添加权限的判断,和5)中设置属性的值有重复,此处是为了确保生效。有时间的同学可以验证下去掉这一步看是否生效。

should_drop_privileges()函数最后添加

java 复制代码
#ifdef CUSTON_ROOT_VERSION
   return false;
#endif

drop_privileges()函数最后添加

java 复制代码
#ifdef CUSTON_ROOT_VERSION
   auth_required=false;
#endif

7),最重要的一步,更换sepolicy文件为debug版本的

(1)添加sepolicy,src文件是debug版本的,修改路径system/sepolicy/android.bp
Go 复制代码
--- a/Android.bp
+++ b/Android.bp
     },
 }
 
+se_policy_cil {
+    name: "userdebug_plat_sepolicy_root.cil",
+    src: ":userdebug_plat_sepolicy.conf",
+    additional_cil_files: [":sepolicy_technical_debt{.plat_private}"],
+    dist: {
+        targets: ["droidcore"],
+    },
+}
+
 // A copy of the userdebug_plat_policy in GSI.
(2),同路径下mk文件加入编译
Go 复制代码
--- a/Android.mk
+++ b/Android.mk

 LOCAL_REQUIRED_MODULES += \
     userdebug_plat_sepolicy.cil \

+ifeq ($(strip $(CUSTOM_ROOT_VERSION)),yes)
+LOCAL_REQUIRED_MODULES += \
+    userdebug_plat_sepolicy_root.cil
+endif
(3)代码中加载sepolicy地方GetUserdebugPlatformPolicyFile()也使用上面生成的sepolicy文件,代码路径system/core/init/selinux.cpp
cpp 复制代码
 std::optional<const char*> GetUserdebugPlatformPolicyFile() {
+#ifdef DF_VERSION
+    return "/system/etc/selinux/userdebug_plat_sepolicy_root.cil";
+#endif

至此,Android U版本user+root+remount方案修改完成。

相关推荐
叽哥7 分钟前
Kotlin学习第 1 课:Kotlin 入门准备:搭建学习环境与认知基础
android·java·kotlin
风往哪边走25 分钟前
创建自定义语音录制View
android·前端
用户20187928316725 分钟前
事件分发之“官僚主义”?或“绕圈”的艺术
android
用户20187928316726 分钟前
Android事件分发为何喜欢“兜圈子”?不做个“敞亮人”!
android
Kapaseker2 小时前
你一定会喜欢的 Compose 形变动画
android
QuZhengRong3 小时前
【数据库】Navicat 导入 Excel 数据乱码问题的解决方法
android·数据库·excel
zhangphil4 小时前
Android Coil3视频封面抽取封面帧存Disk缓存,Kotlin(2)
android·kotlin
程序员码歌10 小时前
【零代码AI编程实战】AI灯塔导航-总结篇
android·前端·后端
书弋江山12 小时前
flutter 跨平台编码库 protobuf 工具使用
android·flutter
来来走走14 小时前
Flutter开发 webview_flutter的基本使用
android·flutter