Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 74a9bbae authored by Zim's avatar Zim
Browse files

Support a mount mode to bypass FUSE on /storage

When Zygote forks a process with the MOUNT_MODE_PASS_THROUGH
flag, bind mount the pass_through path into /storage for the
process, allowing the process to bypass FUSE.

Bug: 140064376
Test: cat /proc/<pid of app with pass_through flag>/mountinfo shows
the lower fs bind mounted directly on /storage

Change-Id: Ia212c2c71ecfdc1629739ca8af171f332ccfca72
parent 9a3e5410
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -576,6 +576,8 @@ public class ZygoteProcess {
            argsForZygote.add("--mount-external-installer");
            argsForZygote.add("--mount-external-installer");
        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_LEGACY) {
        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_LEGACY) {
            argsForZygote.add("--mount-external-legacy");
            argsForZygote.add("--mount-external-legacy");
        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_PASS_THROUGH) {
            argsForZygote.add("--mount-external-pass-through");
        }
        }


        argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
        argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
+3 −0
Original line number Original line Diff line number Diff line
@@ -135,6 +135,9 @@ public final class Zygote {
    /** Read-write external storage should be mounted instead of package sandbox */
    /** Read-write external storage should be mounted instead of package sandbox */
    public static final int MOUNT_EXTERNAL_FULL = IVold.REMOUNT_MODE_FULL;
    public static final int MOUNT_EXTERNAL_FULL = IVold.REMOUNT_MODE_FULL;


    /** 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;

    /** Number of bytes sent to the Zygote over USAP pipes or the pool event FD */
    /** Number of bytes sent to the Zygote over USAP pipes or the pool event FD */
    static final int USAP_MANAGEMENT_MESSAGE_BYTES = 8;
    static final int USAP_MANAGEMENT_MESSAGE_BYTES = 8;


+2 −0
Original line number Original line Diff line number Diff line
@@ -362,6 +362,8 @@ class ZygoteArguments {
                mMountExternal = Zygote.MOUNT_EXTERNAL_INSTALLER;
                mMountExternal = Zygote.MOUNT_EXTERNAL_INSTALLER;
            }  else if (arg.equals("--mount-external-legacy")) {
            }  else if (arg.equals("--mount-external-legacy")) {
                mMountExternal = Zygote.MOUNT_EXTERNAL_LEGACY;
                mMountExternal = Zygote.MOUNT_EXTERNAL_LEGACY;
            } else if (arg.equals("--mount-external-pass-through")) {
                mMountExternal = Zygote.MOUNT_EXTERNAL_PASS_THROUGH;
            } else if (arg.equals("--query-abi-list")) {
            } else if (arg.equals("--query-abi-list")) {
                mAbiListQuery = true;
                mAbiListQuery = true;
            } else if (arg.equals("--get-pid")) {
            } else if (arg.equals("--get-pid")) {
+5 −5
Original line number Original line Diff line number Diff line
@@ -303,7 +303,8 @@ enum MountExternalKind {
  MOUNT_EXTERNAL_LEGACY = 4,
  MOUNT_EXTERNAL_LEGACY = 4,
  MOUNT_EXTERNAL_INSTALLER = 5,
  MOUNT_EXTERNAL_INSTALLER = 5,
  MOUNT_EXTERNAL_FULL = 6,
  MOUNT_EXTERNAL_FULL = 6,
  MOUNT_EXTERNAL_COUNT = 7
  MOUNT_EXTERNAL_PASS_THROUGH = 7,
  MOUNT_EXTERNAL_COUNT = 8
};
};


// The order of entries here must be kept in sync with MountExternalKind enum values.
// The order of entries here must be kept in sync with MountExternalKind enum values.
@@ -708,15 +709,14 @@ static void MountEmulatedStorage(uid_t uid, jint mount_mode,


  const userid_t user_id = multiuser_get_user_id(uid);
  const userid_t user_id = multiuser_get_user_id(uid);
  const std::string user_source = StringPrintf("/mnt/user/%d", user_id);
  const std::string user_source = StringPrintf("/mnt/user/%d", user_id);
  const std::string pass_through_source = StringPrintf("/mnt/pass_through/%d", user_id);
  bool isFuse = GetBoolProperty(kPropFuse, false);
  bool isFuse = GetBoolProperty(kPropFuse, false);


  CreateDir(user_source, 0751, AID_ROOT, AID_ROOT, fail_fn);
  CreateDir(user_source, 0751, AID_ROOT, AID_ROOT, fail_fn);


  if (isFuse) {
  if (isFuse) {
    // TODO(b/135341433): Bind mount the appropriate storage view for the app given its permissions
    BindMount(mount_mode == MOUNT_EXTERNAL_PASS_THROUGH ? pass_through_source : user_source,
    // media and media_location permission access. This should prevent the kernel from incorrectly
              "/storage", fail_fn);
    // sharing a cache across permission buckets
    BindMount(user_source, "/storage", fail_fn);
  } else {
  } else {
    const std::string& storage_source = ExternalStorageViews[mount_mode];
    const std::string& storage_source = ExternalStorageViews[mount_mode];
    BindMount(storage_source, "/storage", fail_fn);
    BindMount(storage_source, "/storage", fail_fn);
+20 −0
Original line number Original line Diff line number Diff line
@@ -196,6 +196,9 @@ class StorageManagerService extends IStorageManager.Stub
    private static final String ZRAM_ENABLED_PROPERTY =
    private static final String ZRAM_ENABLED_PROPERTY =
            "persist.sys.zram_enabled";
            "persist.sys.zram_enabled";


    private static final boolean IS_FUSE_ENABLED =
            SystemProperties.getBoolean("persist.sys.fuse", false);

    private static final boolean ENABLE_ISOLATED_STORAGE = StorageManager.hasIsolatedStorage();
    private static final boolean ENABLE_ISOLATED_STORAGE = StorageManager.hasIsolatedStorage();


    /**
    /**
@@ -346,6 +349,9 @@ class StorageManagerService extends IStorageManager.Stub
    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private String mMoveTargetUuid;
    private String mMoveTargetUuid;


    @Nullable
    private volatile String mMediaStoreAuthorityPackageName = null;

    private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;
    private volatile int mCurrentUserId = UserHandle.USER_SYSTEM;


    /** Holding lock for AppFuse business */
    /** Holding lock for AppFuse business */
@@ -1661,6 +1667,15 @@ class StorageManagerService extends IStorageManager.Stub
                ServiceManager.getService("package"));
                ServiceManager.getService("package"));
        mIAppOpsService = IAppOpsService.Stub.asInterface(
        mIAppOpsService = IAppOpsService.Stub.asInterface(
                ServiceManager.getService(Context.APP_OPS_SERVICE));
                ServiceManager.getService(Context.APP_OPS_SERVICE));

        ProviderInfo provider = mPmInternal.resolveContentProvider(
                MediaStore.AUTHORITY, PackageManager.MATCH_DIRECT_BOOT_AWARE
                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                UserHandle.getUserId(UserHandle.USER_SYSTEM));
        if (provider != null) {
            mMediaStoreAuthorityPackageName = provider.packageName;
        }

        try {
        try {
            mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback);
            mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback);
            mIAppOpsService.startWatchingMode(OP_LEGACY_STORAGE, null, mAppOpsCallback);
            mIAppOpsService.startWatchingMode(OP_LEGACY_STORAGE, null, mAppOpsCallback);
@@ -3672,6 +3687,11 @@ class StorageManagerService extends IStorageManager.Stub
                return Zygote.MOUNT_EXTERNAL_NONE;
                return Zygote.MOUNT_EXTERNAL_NONE;
            }
            }


            if (IS_FUSE_ENABLED && packageName.equals(mMediaStoreAuthorityPackageName)) {
                // Determine if caller requires pass_through mount
                return Zygote.MOUNT_EXTERNAL_PASS_THROUGH;
            }

            // Determine if caller is holding runtime permission
            // Determine if caller is holding runtime permission
            final boolean hasRead = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
            final boolean hasRead = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
                    uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE);
                    uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE);