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

Commit 9fd2b649 authored by Martijn Coenen's avatar Martijn Coenen
Browse files

Use new setupAppDir() API for creating app-specific directories.

Use a more targeted API to create app-specific directories; allows us to
set the UID of app-specific directories correctly on devices that don't
have sdcardfs.

Bug: 146419093
Test: atest FuseDaemonHostTest
Test: boot device without FUSE, verify app dirs are created.
Change-Id: I40d9f95a0bf2e53cc6f80d46d46ef71fb39315be
parent dbc4e9c4
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import android.annotation.Nullable;
import android.content.pm.DataLoaderParams;
import android.content.pm.InstallationFile;
import android.os.IVold;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.ArraySet;
@@ -208,7 +209,8 @@ public final class IncrementalFileStorages {
        if (!hasObb()) {
            return;
        }
        final String mainObbDir = String.format("/storage/emulated/0/Android/obb/%s", mPackageName);
        final String obbDir = "/storage/emulated/0/Android/obb";
        final String packageObbDir = String.format("%s/%s", obbDir, mPackageName);
        final String packageObbDirRoot =
                String.format("/mnt/runtime/%s/emulated/0/Android/obb/", mPackageName);
        final String[] obbDirs = {
@@ -217,12 +219,12 @@ public final class IncrementalFileStorages {
                packageObbDirRoot + "full",
                packageObbDirRoot + "default",
                String.format("/data/media/0/Android/obb/%s", mPackageName),
                mainObbDir,
                packageObbDir,
        };
        try {
            Slog.i(TAG, "Creating obb directory '" + mainObbDir + "'");
            Slog.i(TAG, "Creating obb directory '" + packageObbDir + "'");
            final IVold vold = IVold.Stub.asInterface(ServiceManager.getServiceOrThrow("vold"));
            vold.mkdirs(mainObbDir);
            vold.setupAppDir(packageObbDir, obbDir, Process.ROOT_UID);
            for (String d : obbDirs) {
                mObbStorage.bindPermanent(d);
            }
@@ -230,7 +232,7 @@ public final class IncrementalFileStorages {
            Slog.e(TAG, "vold service is not found.");
            cleanUp();
        } catch (IOException | RemoteException ex) {
            Slog.e(TAG, "Failed to create obb dir at: " + mainObbDir, ex);
            Slog.e(TAG, "Failed to create obb dir at: " + packageObbDir, ex);
            cleanUp();
        }
    }
+35 −17
Original line number Diff line number Diff line
@@ -74,8 +74,6 @@ import android.net.Uri;
import android.os.Binder;
import android.os.DropBoxManager;
import android.os.Environment;
import android.os.Environment.UserEnvironment;
import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -183,6 +181,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
@@ -379,6 +379,14 @@ class StorageManagerService extends IStorageManager.Stub
    @GuardedBy("mAppFuseLock")
    private AppFuseBridge mAppFuseBridge = null;

    /** Matches known application dir paths. The first group contains the generic part of the path,
     * the second group contains the user id (or null if it's a public volume without users), the
     * third group contains the package name, and the fourth group the remainder of the path.
     */
    public static final Pattern KNOWN_APP_DIR_PATHS = Pattern.compile(
            "(?i)(^/storage/[^/]+/(?:([0-9]+)/)?Android/(?:data|media|obb|sandbox)/)([^/]+)(/.*)?");


    private VolumeInfo findVolumeByIdOrThrow(String id) {
        synchronized (mLock) {
            final VolumeInfo vol = mVolumes.get(id);
@@ -3135,7 +3143,6 @@ class StorageManagerService extends IStorageManager.Stub
    public void mkdirs(String callingPkg, String appPath) {
        final int callingUid = Binder.getCallingUid();
        final int userId = UserHandle.getUserId(callingUid);
        final UserEnvironment userEnv = new UserEnvironment(userId);
        final String propertyName = "sys.user." + userId + ".ce_available";

        // Ignore requests to create directories while storage is locked
@@ -3161,25 +3168,36 @@ class StorageManagerService extends IStorageManager.Stub
            throw new IllegalStateException("Failed to resolve " + appPath + ": " + e);
        }

        // Try translating the app path into a vold path, but require that it
        // belong to the calling package.
        if (FileUtils.contains(userEnv.buildExternalStorageAppDataDirs(callingPkg), appFile) ||
                FileUtils.contains(userEnv.buildExternalStorageAppObbDirs(callingPkg), appFile) ||
                FileUtils.contains(userEnv.buildExternalStorageAppMediaDirs(callingPkg), appFile)) {
        appPath = appFile.getAbsolutePath();
        if (!appPath.endsWith("/")) {
            appPath = appPath + "/";
        }

        // Ensure that the path we're asked to create is a known application directory
        // path.
        final Matcher matcher = KNOWN_APP_DIR_PATHS.matcher(appPath);
        if (matcher.matches()) {
            // And that the package dir matches the calling package
            if (!matcher.group(3).equals(callingPkg)) {
                throw new SecurityException("Invalid mkdirs path: " + appFile
                        + " does not contain calling package " + callingPkg);
            }
            // And that the user id part of the path (if any) matches the calling user id,
            // or if for a public volume (no user id), the user matches the current user
            if ((matcher.group(2) != null && !matcher.group(2).equals(Integer.toString(userId)))
                    || (matcher.group(2) == null && userId != mCurrentUserId)) {
                throw new SecurityException("Invalid mkdirs path: " + appFile
                        + " does not match calling user id " + userId);
            }
            try {
                mVold.mkdirs(appPath);
                return;
            } catch (Exception e) {
                mVold.setupAppDir(appPath, matcher.group(1), callingUid);
            } catch (RemoteException e) {
                throw new IllegalStateException("Failed to prepare " + appPath + ": " + e);
            }
        }

        throw new SecurityException("Invalid mkdirs path: " + appFile);
            return;
        }
        throw new SecurityException("Invalid mkdirs path: " + appFile
                + " is not a known app path.");
    }

    @Override