AOSP 5.1 - 如何以真正的根权限执行我的应用程序?
AOSP 5.1 - how can I execute my app with real-root rights?
在我的 AOSP 5.1-build 中,我正在尝试创建一个 MySetupApp.apk
-app,它根据用户执行一些设置操作。
例如。除其他事项外(大多数情况下还需要 root),用户应该能够 select 在我的 MySetupApp.apk
中启动动画。引导动画保存在 /sdcard/
上,apk 应将其移动到正确的系统文件夹 /system/media/bootanimation.zip
这在 adb-shell 上运行良好。以下命令可提供所需的结果(新的引导动画):
adb remount
adb shell cp /sdcard/bootanimation.zip /system/media/
adb shell chmod 777 /system/media/bootanimation.zip
该应用程序 运行正在以系统用户身份运行:
android:sharedUserId="android.uid.system"
我可以在 adb-shell:
上验证
root@astar-yh:/system/bin # ps
system 9634 170 1242144 35536 ffffffff b6e51bf4 S com.mycompany.MySetupApp
我已将应用程序添加到我的 AOSP 构建中:
/android/device/softwinner/common/prebuild/apk/Android.mk
:
include $(CLEAR_VARS)
LOCAL_MODULE := MySetupApp
LOCAL_MODULE_TAGS := optional
LOCAL_CERTIFICATE := platform
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_PRIVILEGED_MODULE := true
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
include $(BUILD_PREBUILT)
因此应用程序安装在 /system/priv-app
中并使用平台密钥签名。
我还调整了 /android/system/extras/su/su.c
:
myuid = getuid();
// added AID_SYSTEM
if (myuid != AID_ROOT && myuid != AID_SHELL && myuid != AID_SYSTEM) {
fprintf(stderr,"su: uid %d not allowed to su\n", myuid);
return 1;
}
// Removed this code-block
/*if(setgid(gid) || setuid(uid)) {
fprintf(stderr,"su: permission denied\n");
return 1;
}*/
这是我的 Java-代码。输出在行后面的注释中:
public void doRootStuff(){
try {
String line;
Process process = Runtime.getRuntime().exec("su");
OutputStream stdin = process.getOutputStream();
InputStream stderr = process.getErrorStream();
InputStream stdout = process.getInputStream();
stdin.write(("getenforce\n").getBytes()); // "Permissive"
stdin.write(("mount -o rw,remount -t ext4 /system\n").getBytes()); //E/[Error]: mount: Operation not permitted
stdin.write(("ls /data/data/\n").getBytes()); // Works! Shows the directory contents
stdin.write(("touch /system/media/test\n").getBytes()); // Does nothing - no error but also no file
stdin.write(("cp -f /sdcard/bootanimation.zip /system/media/bootanimation_test.zip\n").getBytes()); // E/[Error]: cp: /system/media/bootanimation_test.zip: Read-only file system
stdin.write("exit\n".getBytes());
stdin.flush();
stdin.close();
BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
while ((line = br.readLine()) != null) {
Log.d("[Output]", line);
}
br.close();
br = new BufferedReader(new InputStreamReader(stderr));
while ((line = br.readLine()) != null) {
Log.e("[Error]", line);
}
br.close();
process.waitFor();
process.destroy();
} catch (Exception ex) {
Log.e(TAG, ex.toString());
ex.printStackTrace();
}
}
按照建议here,我也编辑了android_filesystem_config.h
,但运气不好
{ 06755, AID_ROOT, AID_ROOT, 0, "system/priv-app/MySetupApp/*" },
在我的应用程序中调用 setuid(0);
也不起作用:
com.mycompany.MySetupApp W/art: Failed to find OatDexFile for DexFile /system/priv-app/MySetupApp/MySetupApp.apk ( canonical path /system/priv-app/MySetupApp/MySetupApp.apk) with checksum 0x73b2ee8d in OatFile /data/dalvik-cache/arm/system@priv-app@MySetupApp@MySetupApp.apk@classes.dex
com.mycompany.MySetupApp W/System.err: android.system.ErrnoException: setuid failed: EPERM (Operation not permitted)
因此无法从 apk 重新挂载系统目录并在其中复制内容!
我该怎么做才能使这项工作正常进行?我应该在我的应用程序或 Android-Sources 中更改什么?
更新
我还尝试将功能转移到脚本 setup_device.sh
中并将其放入 /system/bin/setup_script.sh
。当我在 java 中尝试 运行 时:
Process process = Runtime.getRuntime().exec("su");
stdin.write(("./system/bin/setup_device.sh\n").getBytes());
它说:
E/[Error]: sh: <stdin>[2]: ./system/bin/setup_device.sh: Permission denied
我能够解决我的问题:
1.) 正如问题中提到的,我写了一个简单的脚本,它将引导动画从 /sdcard/
复制到 /system/media/
。将此脚本放入 /system/bin/
setup_device.sh
#!/sbin/busybox sh
BUSYBOX="/sbin/busybox"
echo "Remount /system-partition to rw"
mount -o remount,rw /system
if [ -e /sdcard/bootanimation.zip ] ; then
echo "copy bootanimation"
$BUSYBOX cp -fp "/sdcard/bootanimation.zip" "/system/media/bootanimation.zip"
chmod 777 "/system/media/bootanimation.zip"
chown 0.0 "/system/media/bootanimation.zip"
$BUSYBOX rm "/sdcard/bootanimation.zip"
else
echo "Bootanimation not in /sdcard/-folder"
fi
2.) 在 init.rc
中调用此脚本并在 属性-change
上执行
service setup_device /sbin/busybox sh /system/bin/setup_device.sh
user root
group root
disabled
oneshot
on property:start.setup=1
start setup_device
3.) 在setup.apk中,设置这个属性:
Process proc = Runtime.getRuntime().exec(new String[] { "/system/bin/sh", "-c", "setprop start.setup 1" });
proc.waitFor();
在应用程序设置此 属性 后,setup_device.sh
-脚本将触发并执行具有 root 权限 的代码!
bootanimation.zip
将最终复制到 /system/media/
并且您可以在重新启动设备后立即看到新的引导程序。
陷阱:
- 当您在 init.rc 中声明脚本名称时,请确保不超过 16 个字符的字符限制!也只有用户字母数字字符和
-
或 _
在我的 AOSP 5.1-build 中,我正在尝试创建一个 MySetupApp.apk
-app,它根据用户执行一些设置操作。
例如。除其他事项外(大多数情况下还需要 root),用户应该能够 select 在我的 MySetupApp.apk
中启动动画。引导动画保存在 /sdcard/
上,apk 应将其移动到正确的系统文件夹 /system/media/bootanimation.zip
这在 adb-shell 上运行良好。以下命令可提供所需的结果(新的引导动画):
adb remount
adb shell cp /sdcard/bootanimation.zip /system/media/
adb shell chmod 777 /system/media/bootanimation.zip
该应用程序 运行正在以系统用户身份运行:
android:sharedUserId="android.uid.system"
我可以在 adb-shell:
root@astar-yh:/system/bin # ps
system 9634 170 1242144 35536 ffffffff b6e51bf4 S com.mycompany.MySetupApp
我已将应用程序添加到我的 AOSP 构建中:
/android/device/softwinner/common/prebuild/apk/Android.mk
:
include $(CLEAR_VARS)
LOCAL_MODULE := MySetupApp
LOCAL_MODULE_TAGS := optional
LOCAL_CERTIFICATE := platform
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_PRIVILEGED_MODULE := true
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
include $(BUILD_PREBUILT)
因此应用程序安装在 /system/priv-app
中并使用平台密钥签名。
我还调整了 /android/system/extras/su/su.c
:
myuid = getuid();
// added AID_SYSTEM
if (myuid != AID_ROOT && myuid != AID_SHELL && myuid != AID_SYSTEM) {
fprintf(stderr,"su: uid %d not allowed to su\n", myuid);
return 1;
}
// Removed this code-block
/*if(setgid(gid) || setuid(uid)) {
fprintf(stderr,"su: permission denied\n");
return 1;
}*/
这是我的 Java-代码。输出在行后面的注释中:
public void doRootStuff(){
try {
String line;
Process process = Runtime.getRuntime().exec("su");
OutputStream stdin = process.getOutputStream();
InputStream stderr = process.getErrorStream();
InputStream stdout = process.getInputStream();
stdin.write(("getenforce\n").getBytes()); // "Permissive"
stdin.write(("mount -o rw,remount -t ext4 /system\n").getBytes()); //E/[Error]: mount: Operation not permitted
stdin.write(("ls /data/data/\n").getBytes()); // Works! Shows the directory contents
stdin.write(("touch /system/media/test\n").getBytes()); // Does nothing - no error but also no file
stdin.write(("cp -f /sdcard/bootanimation.zip /system/media/bootanimation_test.zip\n").getBytes()); // E/[Error]: cp: /system/media/bootanimation_test.zip: Read-only file system
stdin.write("exit\n".getBytes());
stdin.flush();
stdin.close();
BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
while ((line = br.readLine()) != null) {
Log.d("[Output]", line);
}
br.close();
br = new BufferedReader(new InputStreamReader(stderr));
while ((line = br.readLine()) != null) {
Log.e("[Error]", line);
}
br.close();
process.waitFor();
process.destroy();
} catch (Exception ex) {
Log.e(TAG, ex.toString());
ex.printStackTrace();
}
}
按照建议here,我也编辑了android_filesystem_config.h
,但运气不好
{ 06755, AID_ROOT, AID_ROOT, 0, "system/priv-app/MySetupApp/*" },
在我的应用程序中调用 setuid(0);
也不起作用:
com.mycompany.MySetupApp W/art: Failed to find OatDexFile for DexFile /system/priv-app/MySetupApp/MySetupApp.apk ( canonical path /system/priv-app/MySetupApp/MySetupApp.apk) with checksum 0x73b2ee8d in OatFile /data/dalvik-cache/arm/system@priv-app@MySetupApp@MySetupApp.apk@classes.dex
com.mycompany.MySetupApp W/System.err: android.system.ErrnoException: setuid failed: EPERM (Operation not permitted)
因此无法从 apk 重新挂载系统目录并在其中复制内容!
我该怎么做才能使这项工作正常进行?我应该在我的应用程序或 Android-Sources 中更改什么?
更新
我还尝试将功能转移到脚本 setup_device.sh
中并将其放入 /system/bin/setup_script.sh
。当我在 java 中尝试 运行 时:
Process process = Runtime.getRuntime().exec("su");
stdin.write(("./system/bin/setup_device.sh\n").getBytes());
它说:
E/[Error]: sh: <stdin>[2]: ./system/bin/setup_device.sh: Permission denied
我能够解决我的问题:
1.) 正如问题中提到的,我写了一个简单的脚本,它将引导动画从 /sdcard/
复制到 /system/media/
。将此脚本放入 /system/bin/
setup_device.sh
#!/sbin/busybox sh
BUSYBOX="/sbin/busybox"
echo "Remount /system-partition to rw"
mount -o remount,rw /system
if [ -e /sdcard/bootanimation.zip ] ; then
echo "copy bootanimation"
$BUSYBOX cp -fp "/sdcard/bootanimation.zip" "/system/media/bootanimation.zip"
chmod 777 "/system/media/bootanimation.zip"
chown 0.0 "/system/media/bootanimation.zip"
$BUSYBOX rm "/sdcard/bootanimation.zip"
else
echo "Bootanimation not in /sdcard/-folder"
fi
2.) 在 init.rc
中调用此脚本并在 属性-change
上执行
service setup_device /sbin/busybox sh /system/bin/setup_device.sh
user root
group root
disabled
oneshot
on property:start.setup=1
start setup_device
3.) 在setup.apk中,设置这个属性:
Process proc = Runtime.getRuntime().exec(new String[] { "/system/bin/sh", "-c", "setprop start.setup 1" });
proc.waitFor();
在应用程序设置此 属性 后,setup_device.sh
-脚本将触发并执行具有 root 权限 的代码!
bootanimation.zip
将最终复制到 /system/media/
并且您可以在重新启动设备后立即看到新的引导程序。
陷阱:
- 当您在 init.rc 中声明脚本名称时,请确保不超过 16 个字符的字符限制!也只有用户字母数字字符和
-
或_