diff options
| author | 2017-03-21 18:45:00 +0000 | |
|---|---|---|
| committer | 2017-03-21 18:45:02 +0000 | |
| commit | 1ae7af10ff4204b3dcb7b4412eab3412ee4d892b (patch) | |
| tree | 04136b1863d38183d7911e3872f0f5237a2af34b | |
| parent | 7f14b8f09590f69a85090a3f944255b6c55a35b8 (diff) | |
| parent | 220aba254bf8f85927acd321ce484d5eba289b48 (diff) | |
Merge "Zygote: Preserve capabilities in WrapperInit"
| -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); + } + } + } + } } |