Merge "Only allow Download authority/MTP/installers to write in Android/."

This commit is contained in:
Martijn Coenen
2020-01-09 07:38:22 +00:00
committed by Android (Google) Code Review
7 changed files with 57 additions and 11 deletions

View File

@@ -88,6 +88,12 @@ public class Process {
@UnsupportedAppUsage
public static final int DRM_UID = 1019;
/**
* Defines the GID for the group that allows write access to the internal media storage.
* @hide
*/
public static final int SDCARD_RW_GID = 1015;
/**
* Defines the UID/GID for the group that controls VPN services.
* @hide

View File

@@ -594,6 +594,8 @@ public class ZygoteProcess {
argsForZygote.add("--mount-external-legacy");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_PASS_THROUGH) {
argsForZygote.add("--mount-external-pass-through");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE) {
argsForZygote.add("--mount-external-android-writable");
}
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);

View File

@@ -145,6 +145,11 @@ public final class Zygote {
/** The lower file system should be bind mounted directly on external storage */
public static final int MOUNT_EXTERNAL_PASS_THROUGH = IVold.REMOUNT_MODE_PASS_THROUGH;
/** Use the regular scoped storage filesystem, but Android/ should be writable.
* Used to support the applications hosting DownloadManager and the MTP server.
*/
public static final int MOUNT_EXTERNAL_ANDROID_WRITABLE = IVold.REMOUNT_MODE_ANDROID_WRITABLE;
/** Number of bytes sent to the Zygote over USAP pipes or the pool event FD */
static final int USAP_MANAGEMENT_MESSAGE_BYTES = 8;

View File

@@ -376,6 +376,8 @@ class ZygoteArguments {
mMountExternal = Zygote.MOUNT_EXTERNAL_LEGACY;
} else if (arg.equals("--mount-external-pass-through")) {
mMountExternal = Zygote.MOUNT_EXTERNAL_PASS_THROUGH;
} else if (arg.equals("--mount-external-android-writable")) {
mMountExternal = Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE;
} else if (arg.equals("--query-abi-list")) {
mAbiListQuery = true;
} else if (arg.equals("--get-pid")) {

View File

@@ -319,7 +319,8 @@ enum MountExternalKind {
MOUNT_EXTERNAL_INSTALLER = 5,
MOUNT_EXTERNAL_FULL = 6,
MOUNT_EXTERNAL_PASS_THROUGH = 7,
MOUNT_EXTERNAL_COUNT = 8
MOUNT_EXTERNAL_ANDROID_WRITABLE = 8,
MOUNT_EXTERNAL_COUNT = 9
};
// The order of entries here must be kept in sync with MountExternalKind enum values.
@@ -331,6 +332,8 @@ static const std::array<const std::string, MOUNT_EXTERNAL_COUNT> ExternalStorage
"/mnt/runtime/write", // MOUNT_EXTERNAL_LEGACY
"/mnt/runtime/write", // MOUNT_EXTERNAL_INSTALLER
"/mnt/runtime/full", // MOUNT_EXTERNAL_FULL
"/mnt/runtime/full", // MOUNT_EXTERNAL_PASS_THROUGH (only used w/ FUSE)
"/mnt/runtime/full", // MOUNT_EXTERNAL_ANDROID_WRITABLE (only used w/ FUSE)
};
// Must match values in com.android.internal.os.Zygote.
@@ -755,12 +758,7 @@ static void MountEmulatedStorage(uid_t uid, jint mount_mode,
multiuser_get_uid(user_id, AID_EVERYBODY), fail_fn);
if (isFuse) {
if (mount_mode == MOUNT_EXTERNAL_PASS_THROUGH || mount_mode ==
MOUNT_EXTERNAL_INSTALLER || mount_mode == MOUNT_EXTERNAL_FULL) {
// For now, MediaProvider, installers and "full" get the pass_through mount
// view, which is currently identical to the sdcardfs write view.
//
// TODO(b/146189163): scope down MOUNT_EXTERNAL_INSTALLER
if (mount_mode == MOUNT_EXTERNAL_PASS_THROUGH) {
BindMount(pass_through_source, "/storage", fail_fn);
} else {
BindMount(user_source, "/storage", fail_fn);

View File

@@ -16,6 +16,7 @@
package com.android.server;
import static android.Manifest.permission.ACCESS_MTP;
import static android.Manifest.permission.INSTALL_PACKAGES;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
@@ -111,6 +112,7 @@ import android.os.storage.StorageVolume;
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
import android.provider.DeviceConfig;
import android.provider.Downloads;
import android.provider.MediaStore;
import android.provider.Settings;
import android.sysprop.VoldProperties;
@@ -367,6 +369,8 @@ class StorageManagerService extends IStorageManager.Stub
private volatile int mMediaStoreAuthorityAppId = -1;
private volatile int mDownloadsAuthorityAppId = -1;
private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
private final Installer mInstaller;
@@ -1788,6 +1792,15 @@ class StorageManagerService extends IStorageManager.Stub
mMediaStoreAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
}
provider = mPmInternal.resolveContentProvider(
Downloads.Impl.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
UserHandle.getUserId(UserHandle.USER_SYSTEM));
if (provider != null) {
mDownloadsAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
}
try {
mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback);
mIAppOpsService.startWatchingMode(OP_LEGACY_STORAGE, null, mAppOpsCallback);
@@ -3881,6 +3894,19 @@ class StorageManagerService extends IStorageManager.Stub
return Zygote.MOUNT_EXTERNAL_PASS_THROUGH;
}
if (mIsFuseEnabled && mDownloadsAuthorityAppId == UserHandle.getAppId(uid)) {
// DownloadManager can write in app-private directories on behalf of apps;
// give it write access to Android/
return Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE;
}
final boolean hasMtp = mIPackageManager.checkUidPermission(ACCESS_MTP, uid) ==
PERMISSION_GRANTED;
if (mIsFuseEnabled && hasMtp) {
// The process hosting the MTP server should be able to write in Android/
return Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE;
}
// Determine if caller is holding runtime permission
final boolean hasRead = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE);

View File

@@ -1555,20 +1555,27 @@ public final class ProcessList {
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
int numGids = 3;
if (mountExternal == Zygote.MOUNT_EXTERNAL_INSTALLER
|| mountExternal == Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE) {
numGids++;
}
/*
* Add shared application and profile GIDs so applications can share some
* resources like shared libraries and access user-wide resources
*/
if (ArrayUtils.isEmpty(permGids)) {
gids = new int[3];
gids = new int[numGids];
} else {
gids = new int[permGids.length + 3];
System.arraycopy(permGids, 0, gids, 3, permGids.length);
gids = new int[permGids.length + numGids];
System.arraycopy(permGids, 0, gids, numGids, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));
if (numGids > 3) {
gids[3] = Process.SDCARD_RW_GID;
}
// Replace any invalid GIDs
if (gids[0] == UserHandle.ERR_GID) gids[0] = gids[2];