Merge "Allow some apps to get full access to external storage."

This commit is contained in:
Sudheer Shanka
2018-08-24 04:00:25 +00:00
committed by Android (Google) Code Review
6 changed files with 82 additions and 39 deletions

View File

@@ -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

View File

@@ -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();

View File

@@ -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;

View File

@@ -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",

View File

@@ -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) {

View File

@@ -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;
}