Merge "Allow some apps to get full access to external storage."
This commit is contained in:
committed by
Android (Google) Code Review
commit
6d7e402a50
@@ -384,7 +384,10 @@ public class ZygoteProcess {
|
||||
argsForZygote.add("--mount-external-read");
|
||||
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
|
||||
argsForZygote.add("--mount-external-write");
|
||||
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_FULL) {
|
||||
argsForZygote.add("--mount-external-full");
|
||||
}
|
||||
|
||||
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
|
||||
|
||||
// --setgroups is a comma-separated list
|
||||
|
||||
@@ -81,6 +81,8 @@ public final class Zygote {
|
||||
public static final int MOUNT_EXTERNAL_READ = IVold.REMOUNT_MODE_READ;
|
||||
/** Read-write external storage should be mounted. */
|
||||
public static final int MOUNT_EXTERNAL_WRITE = IVold.REMOUNT_MODE_WRITE;
|
||||
/** Read-write external storage should be mounted instead of package sandbox */
|
||||
public static final int MOUNT_EXTERNAL_FULL = IVold.REMOUNT_MODE_FULL;
|
||||
|
||||
private static final ZygoteHooks VM_HOOKS = new ZygoteHooks();
|
||||
|
||||
|
||||
@@ -644,7 +644,9 @@ class ZygoteConnection {
|
||||
mountExternal = Zygote.MOUNT_EXTERNAL_READ;
|
||||
} else if (arg.equals("--mount-external-write")) {
|
||||
mountExternal = Zygote.MOUNT_EXTERNAL_WRITE;
|
||||
} else if (arg.equals("--query-abi-list")) {
|
||||
} else if (arg.equals("--mount-external-full")) {
|
||||
mountExternal = Zygote.MOUNT_EXTERNAL_FULL;
|
||||
} else if (arg.equals("--query-abi-list")) {
|
||||
abiListQuery = true;
|
||||
} else if (arg.equals("--get-pid")) {
|
||||
pidQuery = true;
|
||||
|
||||
@@ -93,6 +93,7 @@ enum MountExternalKind {
|
||||
MOUNT_EXTERNAL_DEFAULT = 1,
|
||||
MOUNT_EXTERNAL_READ = 2,
|
||||
MOUNT_EXTERNAL_WRITE = 3,
|
||||
MOUNT_EXTERNAL_FULL = 4,
|
||||
};
|
||||
|
||||
static void RuntimeAbort(JNIEnv* env, int line, const char* msg) {
|
||||
@@ -416,7 +417,7 @@ static bool MountEmulatedStorage(uid_t uid, jint mount_mode,
|
||||
storageSource = "/mnt/runtime/read";
|
||||
} else if (mount_mode == MOUNT_EXTERNAL_WRITE) {
|
||||
storageSource = "/mnt/runtime/write";
|
||||
} else if (!force_mount_namespace) {
|
||||
} else if (mount_mode != MOUNT_EXTERNAL_FULL && !force_mount_namespace) {
|
||||
// Sane default of no storage visible
|
||||
return true;
|
||||
}
|
||||
@@ -433,19 +434,44 @@ static bool MountEmulatedStorage(uid_t uid, jint mount_mode,
|
||||
}
|
||||
|
||||
if (GetBoolProperty(kIsolatedStorage, false)) {
|
||||
if (package_name == nullptr) {
|
||||
return true;
|
||||
}
|
||||
if (mount_mode == MOUNT_EXTERNAL_FULL) {
|
||||
storageSource = "/mnt/runtime/write";
|
||||
if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage",
|
||||
NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) {
|
||||
*error_msg = CREATE_ERROR("Failed to mount %s to /storage: %s",
|
||||
storageSource.string(),
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string pkgSandboxDir("/mnt/user");
|
||||
if (!createPkgSandbox(uid, package_name, pkgSandboxDir, error_msg)) {
|
||||
return false;
|
||||
}
|
||||
if (TEMP_FAILURE_RETRY(mount(pkgSandboxDir.c_str(), "/storage",
|
||||
nullptr, MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
|
||||
*error_msg = CREATE_ERROR("Failed to mount %s to /storage: %s",
|
||||
pkgSandboxDir.c_str(), strerror(errno));
|
||||
return false;
|
||||
// Mount user-specific symlink helper into place
|
||||
userid_t user_id = multiuser_get_user_id(uid);
|
||||
const String8 userSource(String8::format("/mnt/user/%d", user_id));
|
||||
if (fs_prepare_dir(userSource.string(), 0751, 0, 0) == -1) {
|
||||
*error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", userSource.string());
|
||||
return false;
|
||||
}
|
||||
if (TEMP_FAILURE_RETRY(mount(userSource.string(), "/storage/self",
|
||||
NULL, MS_BIND, NULL)) == -1) {
|
||||
*error_msg = CREATE_ERROR("Failed to mount %s to /storage/self: %s",
|
||||
userSource.string(),
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (package_name == nullptr) {
|
||||
return true;
|
||||
}
|
||||
std::string pkgSandboxDir("/mnt/user");
|
||||
if (!createPkgSandbox(uid, package_name, pkgSandboxDir, error_msg)) {
|
||||
return false;
|
||||
}
|
||||
if (TEMP_FAILURE_RETRY(mount(pkgSandboxDir.c_str(), "/storage",
|
||||
nullptr, MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
|
||||
*error_msg = CREATE_ERROR("Failed to mount %s to /storage: %s",
|
||||
pkgSandboxDir.c_str(), strerror(errno));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage",
|
||||
|
||||
@@ -45,8 +45,10 @@ import android.os.ServiceManager;
|
||||
import android.os.ShellCallback;
|
||||
import android.os.ShellCommand;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.os.storage.StorageManagerInternal;
|
||||
import android.provider.Settings;
|
||||
import android.util.ArrayMap;
|
||||
@@ -657,33 +659,35 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
});
|
||||
|
||||
StorageManagerInternal storageManagerInternal = LocalServices.getService(
|
||||
StorageManagerInternal.class);
|
||||
storageManagerInternal.addExternalStoragePolicy(
|
||||
new StorageManagerInternal.ExternalStorageMountPolicy() {
|
||||
@Override
|
||||
public int getMountMode(int uid, String packageName) {
|
||||
if (Process.isIsolated(uid)) {
|
||||
return Zygote.MOUNT_EXTERNAL_NONE;
|
||||
if (!SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
|
||||
StorageManagerInternal storageManagerInternal = LocalServices.getService(
|
||||
StorageManagerInternal.class);
|
||||
storageManagerInternal.addExternalStoragePolicy(
|
||||
new StorageManagerInternal.ExternalStorageMountPolicy() {
|
||||
@Override
|
||||
public int getMountMode(int uid, String packageName) {
|
||||
if (Process.isIsolated(uid)) {
|
||||
return Zygote.MOUNT_EXTERNAL_NONE;
|
||||
}
|
||||
if (noteOperation(AppOpsManager.OP_READ_EXTERNAL_STORAGE, uid,
|
||||
packageName) != AppOpsManager.MODE_ALLOWED) {
|
||||
return Zygote.MOUNT_EXTERNAL_NONE;
|
||||
}
|
||||
if (noteOperation(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, uid,
|
||||
packageName) != AppOpsManager.MODE_ALLOWED) {
|
||||
return Zygote.MOUNT_EXTERNAL_READ;
|
||||
}
|
||||
return Zygote.MOUNT_EXTERNAL_WRITE;
|
||||
}
|
||||
if (noteOperation(AppOpsManager.OP_READ_EXTERNAL_STORAGE, uid,
|
||||
packageName) != AppOpsManager.MODE_ALLOWED) {
|
||||
return Zygote.MOUNT_EXTERNAL_NONE;
|
||||
}
|
||||
if (noteOperation(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, uid,
|
||||
packageName) != AppOpsManager.MODE_ALLOWED) {
|
||||
return Zygote.MOUNT_EXTERNAL_READ;
|
||||
}
|
||||
return Zygote.MOUNT_EXTERNAL_WRITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasExternalStorage(int uid, String packageName) {
|
||||
final int mountMode = getMountMode(uid, packageName);
|
||||
return mountMode == Zygote.MOUNT_EXTERNAL_READ
|
||||
|| mountMode == Zygote.MOUNT_EXTERNAL_WRITE;
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public boolean hasExternalStorage(int uid, String packageName) {
|
||||
final int mountMode = getMountMode(uid, packageName);
|
||||
return mountMode == Zygote.MOUNT_EXTERNAL_READ
|
||||
|| mountMode == Zygote.MOUNT_EXTERNAL_WRITE;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void packageRemoved(int uid, String packageName) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
|
||||
import static android.Manifest.permission.REQUEST_DELETE_PACKAGES;
|
||||
import static android.Manifest.permission.SET_HARMFUL_APP_WARNINGS;
|
||||
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
|
||||
import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
|
||||
import static android.content.Intent.ACTION_MAIN;
|
||||
import static android.content.Intent.CATEGORY_DEFAULT;
|
||||
import static android.content.Intent.CATEGORY_HOME;
|
||||
@@ -20034,6 +20035,11 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
if (Process.isIsolated(uid)) {
|
||||
return Zygote.MOUNT_EXTERNAL_NONE;
|
||||
}
|
||||
if (SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
|
||||
return checkUidPermission(WRITE_MEDIA_STORAGE, uid) == PERMISSION_GRANTED
|
||||
? Zygote.MOUNT_EXTERNAL_FULL
|
||||
: Zygote.MOUNT_EXTERNAL_WRITE;
|
||||
}
|
||||
if (checkUidPermission(READ_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) {
|
||||
return Zygote.MOUNT_EXTERNAL_DEFAULT;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user