Do not set referrerUri on SessionInfo for non-owners
This change leaves the referrerUri field null when the caller leading to
its production is not the owner of the session.
Bug: 142125338
Test: atest SessionReferrerUriTest
Merged-In: I84679ea0636aa2097e25e23813c48134c9cc1d75
Change-Id: I84679ea0636aa2097e25e23813c48134c9cc1d75
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index a15caa0..44842c6 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -2082,6 +2082,7 @@
/**
* Get the value set in {@link SessionParams#setOriginatingUri(Uri)}.
+ * Note: This value will only be non-null for the owner of the session.
*/
public @Nullable Uri getOriginatingUri() {
return originatingUri;
@@ -2096,6 +2097,7 @@
/**
* Get the value set in {@link SessionParams#setReferrerUri(Uri)}
+ * Note: This value will only be non-null for the owner of the session.
*/
public @Nullable Uri getReferrerUri() {
return referrerUri;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 0329e2c..0321da6 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -762,26 +762,30 @@
public SessionInfo getSessionInfo(int sessionId) {
synchronized (mSessions) {
final PackageInstallerSession session = mSessions.get(sessionId);
- return session != null ? session.generateInfo() : null;
+
+ return session != null
+ ? session.generateInfoForCaller(true /*withIcon*/, Binder.getCallingUid())
+ : null;
}
}
@Override
public ParceledListSlice<SessionInfo> getStagedSessions() {
- return mStagingManager.getSessions();
+ return mStagingManager.getSessions(Binder.getCallingUid());
}
@Override
public ParceledListSlice<SessionInfo> getAllSessions(int userId) {
+ final int callingUid = Binder.getCallingUid();
mPermissionManager.enforceCrossUserPermission(
- Binder.getCallingUid(), userId, true, false, "getAllSessions");
+ callingUid, userId, true, false, "getAllSessions");
final List<SessionInfo> result = new ArrayList<>();
synchronized (mSessions) {
for (int i = 0; i < mSessions.size(); i++) {
final PackageInstallerSession session = mSessions.valueAt(i);
if (session.userId == userId && !session.hasParentSessionId()) {
- result.add(session.generateInfo(false));
+ result.add(session.generateInfoForCaller(false, callingUid));
}
}
}
@@ -799,7 +803,8 @@
for (int i = 0; i < mSessions.size(); i++) {
final PackageInstallerSession session = mSessions.valueAt(i);
- SessionInfo info = session.generateInfo(false);
+ SessionInfo info =
+ session.generateInfoForCaller(false /*withIcon*/, Process.SYSTEM_UID);
if (Objects.equals(info.getInstallerPackageName(), installerPackageName)
&& session.userId == userId && !session.hasParentSessionId()) {
result.add(info);
@@ -1243,7 +1248,10 @@
session.markUpdated();
writeSessionsAsync();
if (mOkToSendBroadcasts) {
- mPm.sendSessionUpdatedBroadcast(session.generateInfo(false),
+ // we don't scrub the data here as this is sent only to the installer several
+ // privileged system packages
+ mPm.sendSessionUpdatedBroadcast(
+ session.generateInfoForCaller(false/*icon*/, Process.SYSTEM_UID),
session.userId);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 6f9a918..c9e24a6 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -457,11 +457,41 @@
stagedSessionErrorMessage != null ? stagedSessionErrorMessage : "";
}
- public SessionInfo generateInfo() {
- return generateInfo(true);
+ /**
+ * Returns {@code true} if the {@link SessionInfo} object should be produced with potentially
+ * sensitive data scrubbed from its fields.
+ *
+ * @param callingUid the uid of the caller; the recipient of the {@link SessionInfo} that may
+ * need to be scrubbed
+ */
+ private boolean shouldScrubData(int callingUid) {
+ return !(callingUid < Process.FIRST_APPLICATION_UID || getInstallerUid() == callingUid);
}
- public SessionInfo generateInfo(boolean includeIcon) {
+ /**
+ * Generates a {@link SessionInfo} object for the provided uid. This may result in some fields
+ * that may contain sensitive info being filtered.
+ *
+ * @param includeIcon true if the icon should be included in the object
+ * @param callingUid the uid of the caller; the recipient of the {@link SessionInfo} that may
+ * need to be scrubbed
+ * @see #shouldScrubData(int)
+ */
+ public SessionInfo generateInfoForCaller(boolean includeIcon, int callingUid) {
+ return generateInfoInternal(includeIcon, shouldScrubData(callingUid));
+ }
+
+ /**
+ * Generates a {@link SessionInfo} object to ensure proper hiding of sensitive fields.
+ *
+ * @param includeIcon true if the icon should be included in the object
+ * @see #generateInfoForCaller(boolean, int)
+ */
+ public SessionInfo generateInfoScrubbed(boolean includeIcon) {
+ return generateInfoInternal(includeIcon, true /*scrubData*/);
+ }
+
+ private SessionInfo generateInfoInternal(boolean includeIcon, boolean scrubData) {
final SessionInfo info = new SessionInfo();
synchronized (mLock) {
info.sessionId = sessionId;
@@ -484,9 +514,13 @@
info.appLabel = params.appLabel;
info.installLocation = params.installLocation;
- info.originatingUri = params.originatingUri;
+ if (!scrubData) {
+ info.originatingUri = params.originatingUri;
+ }
info.originatingUid = params.originatingUid;
- info.referrerUri = params.referrerUri;
+ if (!scrubData) {
+ info.referrerUri = params.referrerUri;
+ }
info.grantedRuntimePermissions = params.grantedRuntimePermissions;
info.whitelistedRestrictedPermissions = params.whitelistedRestrictedPermissions;
info.installFlags = params.installFlags;
@@ -2188,7 +2222,7 @@
// Send broadcast to default launcher only if it's a new install
final boolean isNewInstall = extras == null || !extras.getBoolean(Intent.EXTRA_REPLACING);
if (success && isNewInstall && mPm.mInstallerService.okToSendBroadcasts()) {
- mPm.sendSessionCommitBroadcast(generateInfo(), userId);
+ mPm.sendSessionCommitBroadcast(generateInfoScrubbed(true /*icon*/), userId);
}
mCallback.onSessionFinished(this, success);
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 9c87c74..b6de395 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -94,11 +94,12 @@
}
}
- ParceledListSlice<PackageInstaller.SessionInfo> getSessions() {
+ ParceledListSlice<PackageInstaller.SessionInfo> getSessions(int callingUid) {
final List<PackageInstaller.SessionInfo> result = new ArrayList<>();
synchronized (mStagedSessions) {
for (int i = 0; i < mStagedSessions.size(); i++) {
- result.add(mStagedSessions.valueAt(i).generateInfo(false));
+ final PackageInstallerSession stagedSession = mStagedSessions.valueAt(i);
+ result.add(stagedSession.generateInfoForCaller(false /*icon*/, callingUid));
}
}
return new ParceledListSlice<>(result);