From 0ef16918087a8294cc46583b951d59b18b7ce926 Mon Sep 17 00:00:00 2001 From: Aseem Kumar Date: Mon, 17 May 2021 09:25:03 +0000 Subject: Prevent apps from spamming addAccountExplicitly. See comment here for the discussion on solution https://b.corp.google.com/issues/169762606#comment14 Change-Id: If212df3a3b7be1de0fb26b8e88b2fcbb8077c253 Bug: 169762606 (cherry picked from commit 11053c17b397db67b20e96ce769508766cef7db9) Change-Id: I6494366a5695daedc3f4f0046da9e130a5363f5f Merged-In: If212df3a3b7be1de0fb26b8e88b2fcbb8077c253 (cherry picked from commit 5beff34b5738ee050d04ff5786e8c883bb5585f8) Merged-In:I6494366a5695daedc3f4f0046da9e130a5363f5f --- core/java/android/accounts/Account.java | 7 +++++++ .../java/com/android/server/accounts/AccountManagerService.java | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java index 3f90f36fb2a1..1546ae14862d 100644 --- a/core/java/android/accounts/Account.java +++ b/core/java/android/accounts/Account.java @@ -28,6 +28,7 @@ import android.util.ArraySet; import android.util.Log; import com.android.internal.annotations.GuardedBy; +import java.util.Objects; import java.util.Set; /** @@ -80,6 +81,12 @@ public class Account implements Parcelable { if (TextUtils.isEmpty(type)) { throw new IllegalArgumentException("the type must not be empty: " + type); } + if (name.length() > 200) { + throw new IllegalArgumentException("account name is longer than 200 characters"); + } + if (type.length() > 200) { + throw new IllegalArgumentException("account type is longer than 200 characters"); + } this.name = name; this.type = type; this.accessId = accessId; diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index ce0b68418f06..08b708e6f875 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -1790,6 +1790,11 @@ public class AccountManagerService + ", skipping since the account already exists"); return false; } + if (accounts.accountsDb.findAllDeAccounts().size() > 100) { + Log.w(TAG, "insertAccountIntoDatabase: " + account + + ", skipping since more than 50 accounts on device exist"); + return false; + } long accountId = accounts.accountsDb.insertCeAccount(account, password); if (accountId < 0) { Log.w(TAG, "insertAccountIntoDatabase: " + account -- cgit v1.2.3 From ffa177d3e0d7e25d88e39aa279ad2c7a11ee9b38 Mon Sep 17 00:00:00 2001 From: Songchun Fan Date: Thu, 14 Oct 2021 10:40:25 -0700 Subject: Revert "Revert "[pm] remove old stage dirs on low storage"" This reverts commit b45ebca772a77bf3fd269d0dcfc1a7af7c73861d. Reason for revert: adding the fix for system to abandon sessions BUG: 67862680 Test: manual Change-Id: I2b735e4860dce6eb6d5d8ddc158e8b3165910dc7 Merged-In: I91170ba399b3a596320b3bd9c8188912e5c4f1be (cherry picked from commit bd25f7062391fa1e8965f2bee8ee5f7c963324b0) Merged-In:I2b735e4860dce6eb6d5d8ddc158e8b3165910dc7 --- .../android/server/pm/PackageInstallerService.java | 45 ++++++++++++++++++++-- .../android/server/pm/PackageInstallerSession.java | 15 +++++++- .../android/server/pm/PackageManagerService.java | 3 ++ 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 000627cc884e..5df53551b84f 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -125,6 +125,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub { private static final long MAX_ACTIVE_SESSIONS = 1024; /** Upper bound on number of historical sessions for a UID */ private static final long MAX_HISTORICAL_SESSIONS = 1048576; + /** Destroy sessions older than this on storage free request */ + private static final long MAX_SESSION_AGE_ON_LOW_STORAGE_MILLIS = 8 * DateUtils.HOUR_IN_MILLIS; private final Context mContext; private final PackageManagerService mPm; @@ -228,23 +230,58 @@ public class PackageInstallerService extends IPackageInstaller.Stub { @GuardedBy("mSessions") private void reconcileStagesLocked(String volumeUuid, boolean isEphemeral) { - final File stagingDir = buildStagingDir(volumeUuid, isEphemeral); - final ArraySet unclaimedStages = newArraySet( - stagingDir.listFiles(sStageFilter)); + final ArraySet unclaimedStages = getStagingDirsOnVolume(volumeUuid, isEphemeral); // Ignore stages claimed by active sessions for (int i = 0; i < mSessions.size(); i++) { final PackageInstallerSession session = mSessions.valueAt(i); unclaimedStages.remove(session.stageDir); } + removeStagingDirs(unclaimedStages); + } + private ArraySet getStagingDirsOnVolume(String volumeUuid, boolean isEphemeral) { + final File stagingDir = buildStagingDir(volumeUuid, isEphemeral); + final ArraySet stagingDirs = newArraySet( + stagingDir.listFiles(sStageFilter)); + return stagingDirs; + } + + private void removeStagingDirs(ArraySet stagingDirsToRemove) { // Clean up orphaned staging directories - for (File stage : unclaimedStages) { + for (File stage : stagingDirsToRemove) { Slog.w(TAG, "Deleting orphan stage " + stage); synchronized (mPm.mInstallLock) { mPm.removeCodePathLI(stage); + } + } + } + + /** + * Called to free up some storage space from obsolete installation files + */ + public void freeStageDirs(String volumeUuid, boolean internalVolume) { + final ArraySet unclaimedStagingDirsOnVolume = getStagingDirsOnVolume(volumeUuid, internalVolume); + final long currentTimeMillis = System.currentTimeMillis(); + synchronized (mSessions) { + for (int i = 0; i < mSessions.size(); i++) { + final PackageInstallerSession session = mSessions.valueAt(i); + if (!unclaimedStagingDirsOnVolume.contains(session.stageDir)) { + // Only handles sessions stored on the target volume + continue; + } + final long age = currentTimeMillis - session.createdMillis; + if (age >= MAX_SESSION_AGE_ON_LOW_STORAGE_MILLIS) { + // Aggressively close old sessions because we are running low on storage + // Their staging dirs will be removed too + session.abandon(); + } else { + // Session is new enough, so it deserves to be kept even on low storage + unclaimedStagingDirsOnVolume.remove(session.stageDir); + } } } + removeStagingDirs(unclaimedStagingDirsOnVolume); } public void onPrivateVolumeMounted(String volumeUuid) { diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 4c44b7b8027f..edada326ee12 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -793,6 +793,19 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } + /** + * Check if the caller is the owner of this session. Otherwise throw a + * {@link SecurityException}. + */ + @GuardedBy("mLock") + private void assertCallerIsOwnerOrRootOrSystemLocked() { + final int callingUid = Binder.getCallingUid(); + if (callingUid != Process.ROOT_UID && callingUid != mInstallerUid + && callingUid != Process.SYSTEM_UID) { + throw new SecurityException("Session does not belong to uid " + callingUid); + } + } + /** * If anybody is reading or writing data of the session, throw an {@link SecurityException}. */ @@ -1564,7 +1577,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @Override public void abandon() { synchronized (mLock) { - assertCallerIsOwnerOrRootLocked(); + assertCallerIsOwnerOrRootOrSystemLocked(); if (mRelinquished) { Slog.d(TAG, "Ignoring abandon after commit relinquished control"); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 2433df96ddd6..5306b7a9e8c5 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -4694,6 +4694,9 @@ public class PackageManagerService extends IPackageManager.Stub InstantAppRegistry.DEFAULT_UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) { return; } + + // 11. Clear temp install session files + mInstallerService.freeStageDirs(volumeUuid, internalVolume); } else { try { mInstaller.freeCache(volumeUuid, bytes, 0, 0); -- cgit v1.2.3 From 4e9ea675434412180e95d24ac178c6130c616b18 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Thu, 23 Apr 2020 11:11:06 -0600 Subject: Force-set a ClipData to prevent later migration. migrateExtraStreamToClipData() will only offer to promote Uri values if a ClipData isn't already defined, so we ensure that a ClipData value is always defined. This blocks later promotion and granting. Bug: 200683077 Bug: 123700107 Test: manual Change-Id: I99c1411e8b4eb01eb27ac4306e3bf6cc88cb4273 (cherry picked from commit 6ebf410b818c6a525130d5fcb72381217fec8e7a) (cherry picked from commit 3cf2b049867977916d29f1674f71e89b49ea1f69) Merged-In:I99c1411e8b4eb01eb27ac4306e3bf6cc88cb4273 --- .../java/com/android/server/accounts/AccountManagerService.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 08b708e6f875..9e8464728b9b 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -46,6 +46,7 @@ import android.app.admin.DeviceAdminInfo; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; import android.content.BroadcastReceiver; +import android.content.ClipData; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -4759,6 +4760,11 @@ public class AccountManagerService * supplied entries in the system Settings app. */ protected boolean checkKeyIntent(int authUid, Intent intent) { + // Explicitly set an empty ClipData to ensure that we don't offer to + // promote any Uris contained inside for granting purposes + if (intent.getClipData() == null) { + intent.setClipData(ClipData.newPlainText(null, null)); + } intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION -- cgit v1.2.3