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

Commit b84e5aad authored by William Loh's avatar William Loh
Browse files

Set app.metadata file permission to 640

This should prevent apps from circumventing the GET_APP_METADATA
permission by reading the file directly if they are aware of the file
path.

Bug: 267823160
Test: atest android.packageinstaller.install.cts.InstallAppMetadataTest
Change-Id: I4aab10b48e62234bc252535ab2e2c8b9c77a7ac3
parent 0085edf0
Loading
Loading
Loading
Loading
+6 −10
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.ParcelableException;
import android.os.PersistableBundle;
import android.os.Process;
@@ -126,9 +127,6 @@ import dalvik.system.VMRuntime;

import libcore.util.EmptyArray;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
@@ -1233,25 +1231,23 @@ public class ApplicationPackageManager extends PackageManager {
    public PersistableBundle getAppMetadata(@NonNull String packageName)
            throws NameNotFoundException {
        PersistableBundle appMetadata = null;
        String path = null;
        ParcelFileDescriptor pfd = null;
        try {
            path = mPM.getAppMetadataPath(packageName, getUserId());
            pfd = mPM.getAppMetadataFd(packageName, getUserId());
        } catch (ParcelableException e) {
            e.maybeRethrow(NameNotFoundException.class);
            throw new RuntimeException(e);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        if (path != null) {
            File file = new File(path);
            try (InputStream inputStream = new FileInputStream(file)) {
        if (pfd != null) {
            try (InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
                appMetadata = PersistableBundle.readFromStream(inputStream);
            } catch (FileNotFoundException e) {
                // ignore and return empty bundle if app metadata does not exist
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        return appMetadata != null ? appMetadata : new PersistableBundle();
    }

+2 −1
Original line number Diff line number Diff line
@@ -159,7 +159,8 @@ interface IPackageManager {
     */
    ParceledListSlice getInstalledPackages(long flags, in int userId);

    String getAppMetadataPath(String packageName, int userId);
    @nullable ParcelFileDescriptor getAppMetadataFd(String packageName,
                int userId);

    /**
     * This implements getPackagesHoldingPermissions via a "last returned row"
+1 −1
Original line number Diff line number Diff line
@@ -83,7 +83,7 @@ interface IIncrementalService {
    /**
     * Creates a file under a storage.
     */
    int makeFile(int storageId, in @utf8InCpp String path, in IncrementalNewFileParams params, in @nullable byte[] content);
    int makeFile(int storageId, in @utf8InCpp String path, int mode, in IncrementalNewFileParams params, in @nullable byte[] content);

    /**
     * Creates a file under a storage. Content of the file is from a range inside another file.
+6 −3
Original line number Diff line number Diff line
@@ -153,7 +153,8 @@ public final class IncrementalFileStorages {
        final String apkName = apk.name;
        final File targetFile = new File(mStageDir, apkName);
        if (!targetFile.exists()) {
            mDefaultStorage.makeFile(apkName, apk.size, null, apk.metadata, apk.signature, null);
            mDefaultStorage.makeFile(apkName, apk.size, 0777, null, apk.metadata,
                    apk.signature, null);
        }
    }

@@ -176,8 +177,10 @@ public final class IncrementalFileStorages {
    /**
     * Creates file in default storage and sets its content.
     */
    public void makeFile(@NonNull String name, @NonNull byte[] content) throws IOException {
        mDefaultStorage.makeFile(name, content.length, UUID.randomUUID(), null, null, content);
    public void makeFile(@NonNull String name, @NonNull byte[] content,
            @NonNull int mode) throws IOException {
        mDefaultStorage.makeFile(name, content.length, mode, UUID.randomUUID(),
                null, null, content);
    }

    /**
+3 −3
Original line number Diff line number Diff line
@@ -173,11 +173,12 @@ public final class IncrementalStorage {
     *
     * @param path             Relative path of the new file.
     * @param size             Size of the new file in bytes.
     * @param mode             File access permission mode.
     * @param metadata         Metadata bytes.
     * @param v4signatureBytes Serialized V4SignatureProto.
     * @param content          Optionally set file content.
     */
    public void makeFile(@NonNull String path, long size, @Nullable UUID id,
    public void makeFile(@NonNull String path, long size, int mode, @Nullable UUID id,
            @Nullable byte[] metadata, @Nullable byte[] v4signatureBytes, @Nullable byte[] content)
            throws IOException {
        try {
@@ -190,7 +191,7 @@ public final class IncrementalStorage {
            params.metadata = (metadata == null ? new byte[0] : metadata);
            params.fileId = idToBytes(id);
            params.signature = v4signatureBytes;
            int res = mService.makeFile(mId, path, params, content);
            int res = mService.makeFile(mId, path, mode, params, content);
            if (res != 0) {
                throw new IOException("makeFile() failed with errno " + -res);
            }
@@ -199,7 +200,6 @@ public final class IncrementalStorage {
        }
    }


    /**
     * Creates a file in Incremental storage. The content of the file is mapped from a range inside
     * a source file in the same storage.
Loading