Merge "Zygote: Preserve capabilities in WrapperInit"
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user