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

Commit 6443454d authored by Songchun Fan's avatar Songchun Fan
Browse files

Revert "Revert "[SettingsProvider] remove in-lock calls to PackageManager.getPackageUid()""

This reverts commit 7a659fca.

Reason for revert: Fixing ag/14096109 to clear callingUid before retrieving applicationInfo

BUG: 183007597
Test: atest android.appsecurity.cts.ExternalStorageHostTest#testExternalStorageReadDefaultUris
Change-Id: I6b1e7f156e8e62e6d463a5986a0ef90bf2ef61ff
parent f5195618
Loading
Loading
Loading
Loading
+58 −70
Original line number Original line Diff line number Diff line
@@ -16,7 +16,6 @@


package com.android.providers.settings;
package com.android.providers.settings;


import static android.os.Process.INVALID_UID;
import static android.os.Process.ROOT_UID;
import static android.os.Process.ROOT_UID;
import static android.os.Process.SHELL_UID;
import static android.os.Process.SHELL_UID;
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.SYSTEM_UID;
@@ -364,6 +363,11 @@ public class SettingsProvider extends ContentProvider {
            mHandler = new Handler(mHandlerThread.getLooper());
            mHandler = new Handler(mHandlerThread.getLooper());
            mSettingsRegistry = new SettingsRegistry();
            mSettingsRegistry = new SettingsRegistry();
        }
        }
        SettingsState.cacheSystemPackageNamesAndSystemSignature(getContext());
        synchronized (mLock) {
            mSettingsRegistry.migrateAllLegacySettingsIfNeededLocked();
            mSettingsRegistry.syncSsaidTableOnStartLocked();
        }
        mHandler.post(() -> {
        mHandler.post(() -> {
            registerBroadcastReceivers();
            registerBroadcastReceivers();
            startWatchingUserRestrictionChanges();
            startWatchingUserRestrictionChanges();
@@ -2499,8 +2503,6 @@ public class SettingsProvider extends ContentProvider {
            mHandler = new MyHandler(getContext().getMainLooper());
            mHandler = new MyHandler(getContext().getMainLooper());
            mGenerationRegistry = new GenerationRegistry(mLock);
            mGenerationRegistry = new GenerationRegistry(mLock);
            mBackupManager = new BackupManager(getContext());
            mBackupManager = new BackupManager(getContext());
            migrateAllLegacySettingsIfNeeded();
            syncSsaidTableOnStart();
        }
        }


        private void generateUserKeyLocked(int userId) {
        private void generateUserKeyLocked(int userId) {
@@ -2587,8 +2589,7 @@ public class SettingsProvider extends ContentProvider {
            return getSettingLocked(SETTINGS_TYPE_SSAID, userId, uid);
            return getSettingLocked(SETTINGS_TYPE_SSAID, userId, uid);
        }
        }


        public void syncSsaidTableOnStart() {
        private void syncSsaidTableOnStartLocked() {
            synchronized (mLock) {
            // Verify that each user's packages and ssaid's are in sync.
            // Verify that each user's packages and ssaid's are in sync.
            for (UserInfo user : mUserManager.getAliveUsers()) {
            for (UserInfo user : mUserManager.getAliveUsers()) {
                // Get all uids for the user's packages.
                // Get all uids for the user's packages.
@@ -2621,7 +2622,6 @@ public class SettingsProvider extends ContentProvider {
                }
                }
            }
            }
        }
        }
        }


        public List<String> getSettingsNamesLocked(int type, int userId) {
        public List<String> getSettingsNamesLocked(int type, int userId) {
            final int key = makeKey(type, userId);
            final int key = makeKey(type, userId);
@@ -2911,7 +2911,7 @@ public class SettingsProvider extends ContentProvider {
                        boolean someSettingChanged = false;
                        boolean someSettingChanged = false;
                        Setting setting = settingsState.getSettingLocked(name);
                        Setting setting = settingsState.getSettingLocked(name);
                        if (!SettingsState.isSystemPackage(getContext(),
                        if (!SettingsState.isSystemPackage(getContext(),
                                setting.getPackageName(), INVALID_UID, userId)) {
                                setting.getPackageName())) {
                            if (prefix != null && !setting.getName().startsWith(prefix)) {
                            if (prefix != null && !setting.getName().startsWith(prefix)) {
                                continue;
                                continue;
                            }
                            }
@@ -2931,7 +2931,7 @@ public class SettingsProvider extends ContentProvider {
                        boolean someSettingChanged = false;
                        boolean someSettingChanged = false;
                        Setting setting = settingsState.getSettingLocked(name);
                        Setting setting = settingsState.getSettingLocked(name);
                        if (!SettingsState.isSystemPackage(getContext(),
                        if (!SettingsState.isSystemPackage(getContext(),
                                setting.getPackageName(), INVALID_UID, userId)) {
                                setting.getPackageName())) {
                            if (prefix != null && !setting.getName().startsWith(prefix)) {
                            if (prefix != null && !setting.getName().startsWith(prefix)) {
                                continue;
                                continue;
                            }
                            }
@@ -3009,8 +3009,7 @@ public class SettingsProvider extends ContentProvider {
            return mSettingsStates.get(key);
            return mSettingsStates.get(key);
        }
        }


        private void migrateAllLegacySettingsIfNeeded() {
        private void migrateAllLegacySettingsIfNeededLocked() {
            synchronized (mLock) {
            final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
            final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
            File globalFile = getSettingsFile(key);
            File globalFile = getSettingsFile(key);
            if (SettingsState.stateFileExists(globalFile)) {
            if (SettingsState.stateFileExists(globalFile)) {
@@ -3044,7 +3043,6 @@ public class SettingsProvider extends ContentProvider {
                Binder.restoreCallingIdentity(identity);
                Binder.restoreCallingIdentity(identity);
            }
            }
        }
        }
        }


        private void migrateLegacySettingsForUserIfNeededLocked(int userId) {
        private void migrateLegacySettingsForUserIfNeededLocked(int userId) {
            // Every user has secure settings and if no file we need to migrate.
            // Every user has secure settings and if no file we need to migrate.
@@ -5036,19 +5034,9 @@ public class SettingsProvider extends ContentProvider {
                // In the upgrade case we pretend the call is made from the app
                // In the upgrade case we pretend the call is made from the app
                // that made the last change to the setting to properly determine
                // that made the last change to the setting to properly determine
                // whether the call has been made by a system component.
                // whether the call has been made by a system component.
                int callingUid = -1;
                try {
                    callingUid = mPackageManager.getPackageUid(setting.getPackageName(), 0, userId);
                } catch (RemoteException e) {
                    /* ignore - handled below */
                }
                if (callingUid < 0) {
                    Slog.e(LOG_TAG, "Unknown package: " + setting.getPackageName());
                    continue;
                }
                try {
                try {
                    final boolean systemSet = SettingsState.isSystemPackage(getContext(),
                    final boolean systemSet = SettingsState.isSystemPackage(
                            setting.getPackageName(), callingUid, userId);
                            getContext(), setting.getPackageName());
                    if (systemSet) {
                    if (systemSet) {
                        settings.insertSettingOverrideableByRestoreLocked(name, setting.getValue(),
                        settings.insertSettingOverrideableByRestoreLocked(name, setting.getValue(),
                                setting.getTag(), true, setting.getPackageName());
                                setting.getTag(), true, setting.getPackageName());
+88 −94
Original line number Original line Diff line number Diff line
@@ -17,14 +17,13 @@
package com.android.providers.settings;
package com.android.providers.settings;


import static android.os.Process.FIRST_APPLICATION_UID;
import static android.os.Process.FIRST_APPLICATION_UID;
import static android.os.Process.INVALID_UID;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.os.Binder;
import android.os.Binder;
import android.os.Build;
import android.os.Build;
import android.os.FileUtils;
import android.os.FileUtils;
@@ -37,10 +36,10 @@ import android.provider.Settings;
import android.providers.settings.SettingsOperationProto;
import android.providers.settings.SettingsOperationProto;
import android.text.TextUtils;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.AtomicFile;
import android.util.Base64;
import android.util.Base64;
import android.util.Slog;
import android.util.Slog;
import android.util.SparseIntArray;
import android.util.TimeUtils;
import android.util.TimeUtils;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
import android.util.TypedXmlSerializer;
@@ -149,13 +148,7 @@ final class SettingsState {


    private static final String NULL_VALUE = "null";
    private static final String NULL_VALUE = "null";


    private static final Object sLock = new Object();
    private static final ArraySet<String> sSystemPackages = new ArraySet<>();

    @GuardedBy("sLock")
    private static final SparseIntArray sSystemUids = new SparseIntArray();

    @GuardedBy("sLock")
    private static Signature sSystemSignature;


    private final Object mWriteLock = new Object();
    private final Object mWriteLock = new Object();


@@ -1048,6 +1041,7 @@ final class SettingsState {


    /**
    /**
     * Uses AtomicFile to check if the file or its backup exists.
     * Uses AtomicFile to check if the file or its backup exists.
     *
     * @param file The file to check for existence
     * @param file The file to check for existence
     * @return whether the original or backup exist
     * @return whether the original or backup exist
     */
     */
@@ -1307,9 +1301,9 @@ final class SettingsState {
            if (NULL_VALUE.equals(value)) {
            if (NULL_VALUE.equals(value)) {
                value = null;
                value = null;
            }
            }

            final boolean callerSystem = !forceNonSystemPackage &&
            final boolean callerSystem = !forceNonSystemPackage &&
                    !isNull() && isSystemPackage(mContext, packageName);
                    !isNull() && (isCalledFromSystem(packageName)
                    || isSystemPackage(mContext, packageName));
            // Settings set by the system are always defaults.
            // Settings set by the system are always defaults.
            if (callerSystem) {
            if (callerSystem) {
                setDefault = true;
                setDefault = true;
@@ -1434,98 +1428,98 @@ final class SettingsState {
        return sb.toString();
        return sb.toString();
    }
    }


    // Check if a specific package belonging to the caller is part of the system package.
    // Cache the list of names of system packages. This is only called once on system boot.
    public static boolean isSystemPackage(Context context, String packageName) {
    public static void cacheSystemPackageNamesAndSystemSignature(@NonNull Context context) {
        final int callingUid = Binder.getCallingUid();
        final PackageManager packageManager = context.getPackageManager();
        final int callingUserId = UserHandle.getUserId(callingUid);
        final long identity = Binder.clearCallingIdentity();
        return isSystemPackage(context, packageName, callingUid, callingUserId);
        try {
            sSystemPackages.add(SYSTEM_PACKAGE_NAME);
            // Cache SetupWizard package name.
            final String setupWizPackageName = packageManager.getSetupWizardPackageName();
            if (setupWizPackageName != null) {
                sSystemPackages.add(setupWizPackageName);
            }
            final List<PackageInfo> packageInfos = packageManager.getInstalledPackages(0);
            final int installedPackagesCount = packageInfos.size();
            for (int i = 0; i < installedPackagesCount; i++) {
                if (shouldAddToSystemPackages(packageInfos.get(i))) {
                    sSystemPackages.add(packageInfos.get(i).packageName);
                }
            }
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
        }

    // Check if a specific package, uid, and user ID are part of the system package.
    public static boolean isSystemPackage(Context context, String packageName, int uid,
            int userId) {
        synchronized (sLock) {
            if (SYSTEM_PACKAGE_NAME.equals(packageName)) {
                return true;
    }
    }


    private static boolean shouldAddToSystemPackages(@NonNull PackageInfo packageInfo) {
        // Shell and Root are not considered a part of the system
        // Shell and Root are not considered a part of the system
            if (SHELL_PACKAGE_NAME.equals(packageName)
        if (isShellOrRoot(packageInfo.packageName)) {
                    || ROOT_PACKAGE_NAME.equals(packageName)) {
            return false;
            return false;
        }
        }

        // Already added
            if (uid != INVALID_UID) {
        if (sSystemPackages.contains(packageInfo.packageName)) {
                // Native services running as a special UID get a pass
            return false;
                final int callingAppId = UserHandle.getAppId(uid);
                if (callingAppId < FIRST_APPLICATION_UID) {
                    sSystemUids.put(callingAppId, callingAppId);
                    return true;
        }
        }
        return isSystemPackage(packageInfo.applicationInfo);
    }
    }


            final long identity = Binder.clearCallingIdentity();
    private static boolean isShellOrRoot(@NonNull String packageName) {
            try {
        return (SHELL_PACKAGE_NAME.equals(packageName)
                try {
                || ROOT_PACKAGE_NAME.equals(packageName));
                    uid = context.getPackageManager().getPackageUidAsUser(packageName, 0, userId);
                } catch (PackageManager.NameNotFoundException e) {
                    return false;
    }
    }


                // If the system or a special system UID (like telephony), done.
    private static boolean isCalledFromSystem(@NonNull String packageName) {
                if (UserHandle.getAppId(uid) < FIRST_APPLICATION_UID) {
        // Shell and Root are not considered a part of the system
                    sSystemUids.put(uid, uid);
        if (isShellOrRoot(packageName)) {
                    return true;
            return false;
        }
        }

        final int callingUid = Binder.getCallingUid();
                // If already known system component, done.
        // Native services running as a special UID get a pass
                if (sSystemUids.indexOfKey(uid) >= 0) {
        final int callingAppId = UserHandle.getAppId(callingUid);
                    return true;
        return (callingAppId < FIRST_APPLICATION_UID);
    }
    }


                // If SetupWizard, done.
    public static boolean isSystemPackage(@NonNull Context context, @NonNull String packageName) {
                String setupWizPackage = context.getPackageManager().getSetupWizardPackageName();
        // Check shell or root before trying to retrieve ApplicationInfo to fail fast
                if (packageName.equals(setupWizPackage)) {
        if (isShellOrRoot(packageName)) {
                    sSystemUids.put(uid, uid);
            return false;
        }
        // If it's a known system package or known to be platform signed
        if (sSystemPackages.contains(packageName)) {
            return true;
            return true;
        }
        }


                // If a persistent system app, done.
        ApplicationInfo aInfo = null;
                PackageInfo packageInfo;
        final long identity = Binder.clearCallingIdentity();
        try {
        try {
                    packageInfo = context.getPackageManager().getPackageInfoAsUser(
            try {
                            packageName, PackageManager.GET_SIGNATURES, userId);
                // Notice that this makes a call to package manager inside the lock
                    if ((packageInfo.applicationInfo.flags
                aInfo = context.getPackageManager().getApplicationInfo(packageName, 0);
                            & ApplicationInfo.FLAG_PERSISTENT) != 0
            } catch (PackageManager.NameNotFoundException ignored) {
                            && (packageInfo.applicationInfo.flags
                            & ApplicationInfo.FLAG_SYSTEM) != 0) {
                        sSystemUids.put(uid, uid);
                        return true;
            }
            }
                } catch (PackageManager.NameNotFoundException e) {
        } finally {
                    return false;
            Binder.restoreCallingIdentity(identity);
        }
        return isSystemPackage(aInfo);
    }
    }


                // Last check if system signed.
    private static boolean isSystemPackage(@Nullable ApplicationInfo aInfo) {
                if (sSystemSignature == null) {
        if (aInfo == null) {
                    try {
                        sSystemSignature = context.getPackageManager().getPackageInfoAsUser(
                                SYSTEM_PACKAGE_NAME, PackageManager.GET_SIGNATURES,
                                UserHandle.USER_SYSTEM).signatures[0];
                    } catch (PackageManager.NameNotFoundException e) {
                        /* impossible */
            return false;
            return false;
        }
        }
        // If the system or a special system UID (like telephony), done.
        if (aInfo.uid < FIRST_APPLICATION_UID) {
            return true;
        }
        }
                if (sSystemSignature.equals(packageInfo.signatures[0])) {
        // If a persistent system app, done.
                    sSystemUids.put(uid, uid);
        if ((aInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0
                && (aInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
            return true;
            return true;
        }
        }
            } finally {
        // Platform signed packages are considered to be from the system
                Binder.restoreCallingIdentity(identity);
        if (aInfo.isSignedWithPlatformKey()) {
            return true;
        }
        }

        return false;
        return false;
    }
    }
}
}
}