diff options
| author | Andreas Gampe <agampe@google.com> | 2017-03-13 14:36:09 -0700 |
|---|---|---|
| committer | Andreas Gampe <agampe@google.com> | 2017-03-21 08:39:26 -0700 |
| commit | 220aba254bf8f85927acd321ce484d5eba289b48 (patch) | |
| tree | 35d6dfb112c9e398f93f4a7f49d87302bced20d3 /core/java/com | |
| parent | 2d3fb48b392f69b6d986e39c1dc950deeeecc0a1 (diff) | |
Zygote: Preserve capabilities in WrapperInit
Preserve the capabilities a zygote fork has across the sh exec in
WrapperInit. Use ambient capabilities.
Test: m
Test: adb shell setprop wrap.com.android.bluetooth logwrapper && adb shell kill `pid com.android.bluetooth`
Merged-In: I3526d6a31aaadf082365c9ce31da0950e17677eb
Change-Id: I3526d6a31aaadf082365c9ce31da0950e17677eb
Diffstat (limited to 'core/java/com')
| -rw-r--r-- | core/java/com/android/internal/os/WrapperInit.java | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java index c329fd1b5e09..aced75d6a0ba 100644 --- a/core/java/com/android/internal/os/WrapperInit.java +++ b/core/java/com/android/internal/os/WrapperInit.java @@ -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; @@ -119,6 +124,7 @@ public class WrapperInit { command.append(' '); command.append(targetSdkVersion); Zygote.appendQuotedShellArgs(command, args); + preserveCapabilities(); Zygote.execShell(command.toString()); } @@ -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); + } + } + } + } } |
