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

Commit 0f522bfe authored by Martijn Coenen's avatar Martijn Coenen
Browse files

Add (hidden) fixupAppDir() API.

On devices without sdcardfs, filesystem permissions aren't magically
fixed up. This is problematic mostly in application-private directories,
which are owned by the application itself; if another process with
elevated permissions creates a file in these directories, the UID will
be wrong, and the owning package won't be able to access the files.

Allow processes that modify application-private directories (eg
DownloadManager) to ask the framework to fix up permissions on their
behalf.

Bug: 151986170
Test: WIP
Change-Id: Ic30f708d25d7702ec3a4569ee6ddf100732d89d1
parent b4decfc1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -194,4 +194,5 @@ interface IStorageManager {
    boolean needsCheckpoint() = 86;
    void abortChanges(in String message, boolean retry) = 87;
    void clearUserKeyAuth(int userId, int serialNumber, in byte[] token, in byte[] secret) = 88;
    void fixupAppDir(in String path) = 89;
}
+30 −0
Original line number Diff line number Diff line
@@ -2470,6 +2470,36 @@ public class StorageManager {
        }
    }

    /**
     * Asks StorageManager to fixup the permissions of an application-private directory.
     *
     * On devices without sdcardfs, filesystem permissions aren't magically fixed up. This
     * is problematic mostly in application-private directories, which are owned by the
     * application itself; if another process with elevated permissions creates a file
     * in these directories, the UID will be wrong, and the owning package won't be able
     * to access the files.
     *
     * This API can be used to recursively fix up the permissions on the passed in path.
     * The default platform user of this API is the DownloadProvider, which can download
     * things in application-private directories on their behalf.
     *
     * This API doesn't require any special permissions, because it merely changes the
     * permissions of a directory to what they should anyway be.
     *
     * @param path the path for which we should fix up the permissions
     *
     * @hide
     */
    public void fixupAppDir(@NonNull File path) {
        try {
            mStorageManager.fixupAppDir(path.getCanonicalPath());
        } catch (IOException e) {
            Log.e(TAG, "Failed to get canonical path for " + path.getPath(), e);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /** {@hide} */
    private static void setCacheBehavior(File path, String name, boolean enabled)
            throws IOException {
+20 −0
Original line number Diff line number Diff line
@@ -156,6 +156,7 @@ import com.android.internal.util.Preconditions;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.SystemService.TargetUser;
import com.android.server.pm.Installer;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.storage.AppFuseBridge;
import com.android.server.storage.StorageSessionController;
import com.android.server.storage.StorageSessionController.ExternalStorageServiceException;
@@ -3196,6 +3197,25 @@ class StorageManagerService extends IStorageManager.Stub
        }
    }

    @Override
    public void fixupAppDir(String path) {
        final Matcher matcher = KNOWN_APP_DIR_PATHS.matcher(path);
        if (matcher.matches()) {
            AndroidPackage pkg = mPmInternal.getPackage(matcher.group(3));
            if (pkg != null) {
                try {
                    mVold.fixupAppDir(path + "/", pkg.getUid());
                } catch (RemoteException | ServiceSpecificException e) {
                    Log.e(TAG, "Failed to fixup app dir for " + pkg.getPackageName(), e);
                }
            } else {
                Log.e(TAG, "Can't find package belonging to " + path);
            }
        } else {
            Log.e(TAG, "Path " + path + " is not a valid application-specific directory");
        }
    }

    /** Not thread safe */
    class AppFuseMountScope extends AppFuseBridge.MountScope {
        private boolean mMounted = false;