summaryrefslogtreecommitdiff
path: root/core/java/com
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2017-03-13 14:36:09 -0700
committerAndreas Gampe <agampe@google.com>2017-03-21 08:39:26 -0700
commit220aba254bf8f85927acd321ce484d5eba289b48 (patch)
tree35d6dfb112c9e398f93f4a7f49d87302bced20d3 /core/java/com
parent2d3fb48b392f69b6d986e39c1dc950deeeecc0a1 (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.java59
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);
+ }
+ }
+ }
+ }
}