Loading core/java/com/android/internal/os/WrapperInit.java +59 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,11 @@ package com.android.internal.os; import android.os.Process; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; import android.system.StructCapUserData; import android.system.StructCapUserHeader; import android.util.Slog; import com.android.internal.os.Zygote.MethodAndArgsCaller; import dalvik.system.VMRuntime; Loading Loading @@ -119,6 +124,7 @@ public class WrapperInit { command.append(' '); command.append(targetSdkVersion); Zygote.appendQuotedShellArgs(command, args); preserveCapabilities(); Zygote.execShell(command.toString()); } Loading Loading @@ -156,4 +162,57 @@ public class WrapperInit { RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); } /** * Copy current capabilities to ambient capabilities. This is required for apps using * capabilities, as execv will re-evaluate the capability set, and the set of sh is * empty. Ambient capabilities have to be set to inherit them effectively. * * Note: This is BEST EFFORT ONLY. In case capabilities can't be raised, this function * will silently return. In THIS CASE ONLY, as this is a development feature, it * is better to return and try to run anyways, instead of blocking the wrapped app. * This is acceptable here as failure will leave the wrapped app with strictly less * capabilities, which may make it crash, but not exceed its allowances. */ private static void preserveCapabilities() { StructCapUserHeader header = new StructCapUserHeader( OsConstants._LINUX_CAPABILITY_VERSION_3, 0); StructCapUserData[] data; try { data = Os.capget(header); } catch (ErrnoException e) { Slog.e(RuntimeInit.TAG, "RuntimeInit: Failed capget", e); return; } if (data[0].permitted != data[0].inheritable || data[1].permitted != data[1].inheritable) { data[0] = new StructCapUserData(data[0].effective, data[0].permitted, data[0].permitted); data[1] = new StructCapUserData(data[1].effective, data[1].permitted, data[1].permitted); try { Os.capset(header, data); } catch (ErrnoException e) { Slog.e(RuntimeInit.TAG, "RuntimeInit: Failed capset", e); return; } } for (int i = 0; i < 64; i++) { int dataIndex = OsConstants.CAP_TO_INDEX(i); int capMask = OsConstants.CAP_TO_MASK(i); if ((data[dataIndex].inheritable & capMask) != 0) { try { Os.prctl(OsConstants.PR_CAP_AMBIENT, OsConstants.PR_CAP_AMBIENT_RAISE, i, 0, 0); } catch (ErrnoException ex) { // Only log here. Try to run the wrapped application even without this // ambient capability. It may crash after fork, but at least we'll try. Slog.e(RuntimeInit.TAG, "RuntimeInit: Failed to raise ambient capability " + i, ex); } } } } } Loading
core/java/com/android/internal/os/WrapperInit.java +59 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,11 @@ package com.android.internal.os; import android.os.Process; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; import android.system.StructCapUserData; import android.system.StructCapUserHeader; import android.util.Slog; import com.android.internal.os.Zygote.MethodAndArgsCaller; import dalvik.system.VMRuntime; Loading Loading @@ -119,6 +124,7 @@ public class WrapperInit { command.append(' '); command.append(targetSdkVersion); Zygote.appendQuotedShellArgs(command, args); preserveCapabilities(); Zygote.execShell(command.toString()); } Loading Loading @@ -156,4 +162,57 @@ public class WrapperInit { RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); } /** * Copy current capabilities to ambient capabilities. This is required for apps using * capabilities, as execv will re-evaluate the capability set, and the set of sh is * empty. Ambient capabilities have to be set to inherit them effectively. * * Note: This is BEST EFFORT ONLY. In case capabilities can't be raised, this function * will silently return. In THIS CASE ONLY, as this is a development feature, it * is better to return and try to run anyways, instead of blocking the wrapped app. * This is acceptable here as failure will leave the wrapped app with strictly less * capabilities, which may make it crash, but not exceed its allowances. */ private static void preserveCapabilities() { StructCapUserHeader header = new StructCapUserHeader( OsConstants._LINUX_CAPABILITY_VERSION_3, 0); StructCapUserData[] data; try { data = Os.capget(header); } catch (ErrnoException e) { Slog.e(RuntimeInit.TAG, "RuntimeInit: Failed capget", e); return; } if (data[0].permitted != data[0].inheritable || data[1].permitted != data[1].inheritable) { data[0] = new StructCapUserData(data[0].effective, data[0].permitted, data[0].permitted); data[1] = new StructCapUserData(data[1].effective, data[1].permitted, data[1].permitted); try { Os.capset(header, data); } catch (ErrnoException e) { Slog.e(RuntimeInit.TAG, "RuntimeInit: Failed capset", e); return; } } for (int i = 0; i < 64; i++) { int dataIndex = OsConstants.CAP_TO_INDEX(i); int capMask = OsConstants.CAP_TO_MASK(i); if ((data[dataIndex].inheritable & capMask) != 0) { try { Os.prctl(OsConstants.PR_CAP_AMBIENT, OsConstants.PR_CAP_AMBIENT_RAISE, i, 0, 0); } catch (ErrnoException ex) { // Only log here. Try to run the wrapped application even without this // ambient capability. It may crash after fork, but at least we'll try. Slog.e(RuntimeInit.TAG, "RuntimeInit: Failed to raise ambient capability " + i, ex); } } } } }