diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/content/pm/IPackageManager.aidl | 1 | ||||
-rw-r--r-- | core/java/android/os/Process.java | 11 | ||||
-rw-r--r-- | core/java/android/os/storage/IMountService.java | 26 | ||||
-rw-r--r-- | core/java/android/os/storage/StorageManager.java | 9 | ||||
-rw-r--r-- | core/java/com/android/internal/os/Zygote.java | 6 | ||||
-rw-r--r-- | core/java/com/android/internal/os/ZygoteConnection.java | 4 | ||||
-rw-r--r-- | core/jni/com_android_internal_os_Zygote.cpp | 71 |
7 files changed, 97 insertions, 31 deletions
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index cb68d74..c9853df 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -504,4 +504,5 @@ interface IPackageManager { void grantDefaultPermissions(int userId); void setCarrierAppPackagesProvider(in IPackagesProvider provider); + int getMountExternalMode(int uid); } diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index f9c50f3..7234e98 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -643,6 +643,10 @@ public class Process { } if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) { argsForZygote.add("--mount-external-default"); + } else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) { + argsForZygote.add("--mount-external-read"); + } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) { + argsForZygote.add("--mount-external-write"); } argsForZygote.add("--target-sdk-version=" + targetSdkVersion); @@ -802,7 +806,12 @@ public class Process { * @hide */ public static final boolean isIsolated() { - int uid = UserHandle.getAppId(myUid()); + return isIsolated(myUid()); + } + + /** {@hide} */ + public static final boolean isIsolated(int uid) { + uid = UserHandle.getAppId(uid); return uid >= FIRST_ISOLATED_UID && uid <= LAST_ISOLATED_UID; } diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index e55ae99..84a879c 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -1177,6 +1177,21 @@ public interface IMountService extends IInterface { _data.recycle(); } } + + @Override + public void remountUid(int uid) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeInt(uid); + mRemote.transact(Stub.TRANSACTION_remountUid, _data, _reply, 0); + _reply.readException(); + } finally { + _reply.recycle(); + _data.recycle(); + } + } } private static final String DESCRIPTOR = "IMountService"; @@ -1292,6 +1307,8 @@ public interface IMountService extends IInterface { static final int TRANSACTION_benchmark = IBinder.FIRST_CALL_TRANSACTION + 59; static final int TRANSACTION_setDebugFlags = IBinder.FIRST_CALL_TRANSACTION + 60; + static final int TRANSACTION_remountUid = IBinder.FIRST_CALL_TRANSACTION + 61; + /** * Cast an IBinder object into an IMountService interface, generating a * proxy if needed. @@ -1845,6 +1862,13 @@ public interface IMountService extends IInterface { reply.writeNoException(); return true; } + case TRANSACTION_remountUid: { + data.enforceInterface(DESCRIPTOR); + int uid = data.readInt(); + remountUid(uid); + reply.writeNoException(); + return true; + } } return super.onTransact(code, data, reply, flags); } @@ -2154,4 +2178,6 @@ public interface IMountService extends IInterface { public String getPrimaryStorageUuid() throws RemoteException; public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback) throws RemoteException; + + public void remountUid(int uid) throws RemoteException; } diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 9b26f24..aab68e9 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -871,6 +871,15 @@ public class StorageManager { } /** {@hide} */ + public void remountUid(int uid) { + try { + mMountService.remountUid(uid); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + /** {@hide} */ private static final int DEFAULT_THRESHOLD_PERCENTAGE = 10; private static final long DEFAULT_THRESHOLD_MAX_BYTES = 500 * MB_IN_BYTES; private static final long DEFAULT_FULL_THRESHOLD_BYTES = MB_IN_BYTES; diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index c97fdf4..197004c 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -46,8 +46,12 @@ public final class Zygote { /** No external storage should be mounted. */ public static final int MOUNT_EXTERNAL_NONE = 0; - /** Default user-specific external storage should be mounted. */ + /** Default external storage should be mounted. */ public static final int MOUNT_EXTERNAL_DEFAULT = 1; + /** Read-only external storage should be mounted. */ + public static final int MOUNT_EXTERNAL_READ = 2; + /** Read-write external storage should be mounted. */ + public static final int MOUNT_EXTERNAL_WRITE = 3; private static final ZygoteHooks VM_HOOKS = new ZygoteHooks(); diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index fa870b9..3e86fac 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -519,6 +519,10 @@ class ZygoteConnection { niceName = arg.substring(arg.indexOf('=') + 1); } else if (arg.equals("--mount-external-default")) { mountExternal = Zygote.MOUNT_EXTERNAL_DEFAULT; + } else if (arg.equals("--mount-external-read")) { + mountExternal = Zygote.MOUNT_EXTERNAL_READ; + } else if (arg.equals("--mount-external-write")) { + mountExternal = Zygote.MOUNT_EXTERNAL_WRITE; } else if (arg.equals("--query-abi-list")) { abiListQuery = true; } else if (arg.startsWith("--instruction-set=")) { diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 76db5d3..f7cfe0e 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -66,6 +66,8 @@ static jmethodID gCallPostForkChildHooks; enum MountExternalKind { MOUNT_EXTERNAL_NONE = 0, MOUNT_EXTERNAL_DEFAULT = 1, + MOUNT_EXTERNAL_READ = 2, + MOUNT_EXTERNAL_WRITE = 3, }; static void RuntimeAbort(JNIEnv* env) { @@ -249,38 +251,49 @@ static void SetSchedulerPolicy(JNIEnv* env) { // Create a private mount namespace and bind mount appropriate emulated // storage for the given user. -static bool MountEmulatedStorage(uid_t uid, jint mount_mode, bool force_mount_namespace) { - if (mount_mode == MOUNT_EXTERNAL_NONE && !force_mount_namespace) { - return true; - } - - // Create a second private mount namespace for our process - if (unshare(CLONE_NEWNS) == -1) { - ALOGW("Failed to unshare(): %s", strerror(errno)); - return false; - } +static bool MountEmulatedStorage(uid_t uid, jint mount_mode, + bool force_mount_namespace) { + // See storage config details at http://source.android.com/tech/storage/ - if (mount_mode == MOUNT_EXTERNAL_NONE) { - return true; - } - - // See storage config details at http://source.android.com/tech/storage/ - userid_t user_id = multiuser_get_user_id(uid); - - // Bind mount user-specific storage into place - const String8 source(String8::format("/mnt/user/%d", user_id)); - const String8 target(String8::format("/storage/self")); + // Create a second private mount namespace for our process + if (unshare(CLONE_NEWNS) == -1) { + ALOGW("Failed to unshare(): %s", strerror(errno)); + return false; + } - if (fs_prepare_dir(source.string(), 0755, 0, 0) == -1) { - return false; - } + // Unmount storage provided by root namespace and mount requested view + umount2("/storage", MNT_FORCE); + + String8 storageSource; + if (mount_mode == MOUNT_EXTERNAL_DEFAULT) { + storageSource = "/mnt/runtime_default"; + } else if (mount_mode == MOUNT_EXTERNAL_READ) { + storageSource = "/mnt/runtime_read"; + } else if (mount_mode == MOUNT_EXTERNAL_WRITE) { + storageSource = "/mnt/runtime_write"; + } else { + // Sane default of no storage visible + return true; + } + if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage", + NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) { + ALOGW("Failed to mount %s to /storage: %s", storageSource.string(), strerror(errno)); + return false; + } - if (TEMP_FAILURE_RETRY(mount(source.string(), target.string(), NULL, MS_BIND, NULL)) == -1) { - ALOGW("Failed to mount %s to %s: %s", source.string(), target.string(), strerror(errno)); - return false; - } + // Mount user-specific symlink helpers 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) { + return false; + } + if (TEMP_FAILURE_RETRY(mount(userSource.string(), "/storage/self", + NULL, MS_BIND, NULL)) == -1) { + ALOGW("Failed to mount %s to /storage/self: %s", userSource.string(), strerror(errno)); + return false; + } - return true; + return true; } static bool NeedsNoRandomizeWorkaround() { @@ -543,7 +556,7 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer( pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, rlimits, permittedCapabilities, effectiveCapabilities, - MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL, + MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL, NULL, NULL); if (pid > 0) { // The zygote process checks whether the child process has died or not. |