Merge "Grant package visibility to dependent library" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-03-12 18:51:24 +00:00
committed by Android (Google) Code Review
2 changed files with 164 additions and 0 deletions

View File

@@ -104,6 +104,12 @@ public class AppsFilter implements Watchable, Snappable {
*/
private final SparseSetArray<Integer> mQueriesViaComponent = new SparseSetArray<>();
/**
* A mapping from the set of App IDs that query other App IDs via library name to the
* list of packages that they can see.
*/
private final SparseSetArray<Integer> mQueryableViaUsesLibrary = new SparseSetArray<>();
/**
* Executor for running reasonably short background tasks such as building the initial
* visibility cache.
@@ -239,6 +245,7 @@ public class AppsFilter implements Watchable, Snappable {
Snapshots.copy(mImplicitlyQueryable, orig.mImplicitlyQueryable);
Snapshots.copy(mQueriesViaPackage, orig.mQueriesViaPackage);
Snapshots.copy(mQueriesViaComponent, orig.mQueriesViaComponent);
Snapshots.copy(mQueryableViaUsesLibrary, orig.mQueryableViaUsesLibrary);
mQueriesViaComponentRequireRecompute = orig.mQueriesViaComponentRequireRecompute;
mForceQueryable.addAll(orig.mForceQueryable);
mForceQueryableByDevicePackageNames = orig.mForceQueryableByDevicePackageNames;
@@ -508,6 +515,22 @@ public class AppsFilter implements Watchable, Snappable {
return false;
}
private static boolean canQueryViaUsesLibrary(AndroidPackage querying,
AndroidPackage potentialTarget) {
if (potentialTarget.getLibraryNames().isEmpty()) {
return false;
}
final List<String> libNames = potentialTarget.getLibraryNames();
for (int i = 0, size = libNames.size(); i < size; i++) {
final String libName = libNames.get(i);
if (querying.getUsesLibraries().contains(libName)
|| querying.getUsesOptionalLibraries().contains(libName)) {
return true;
}
}
return false;
}
private static boolean matchesProviders(
Set<String> queriesAuthorities, AndroidPackage potentialTarget) {
for (int p = ArrayUtils.size(potentialTarget.getProviders()) - 1; p >= 0; p--) {
@@ -707,6 +730,9 @@ public class AppsFilter implements Watchable, Snappable {
|| canQueryAsInstaller(existingSetting, newPkg)) {
mQueriesViaPackage.add(existingSetting.appId, newPkgSetting.appId);
}
if (canQueryViaUsesLibrary(existingPkg, newPkg)) {
mQueryableViaUsesLibrary.add(existingSetting.appId, newPkgSetting.appId);
}
}
// now we'll evaluate our new package's ability to see existing packages
if (!mForceQueryable.contains(existingSetting.appId)) {
@@ -718,6 +744,9 @@ public class AppsFilter implements Watchable, Snappable {
|| canQueryAsInstaller(newPkgSetting, existingPkg)) {
mQueriesViaPackage.add(newPkgSetting.appId, existingSetting.appId);
}
if (canQueryViaUsesLibrary(newPkg, existingPkg)) {
mQueryableViaUsesLibrary.add(newPkgSetting.appId, existingSetting.appId);
}
}
// if either package instruments the other, mark both as visible to one another
if (newPkgSetting.pkg != null && existingSetting.pkg != null
@@ -1035,6 +1064,10 @@ public class AppsFilter implements Watchable, Snappable {
for (int i = mQueriesViaPackage.size() - 1; i >= 0; i--) {
mQueriesViaPackage.remove(mQueriesViaPackage.keyAt(i), setting.appId);
}
mQueryableViaUsesLibrary.remove(setting.appId);
for (int i = mQueryableViaUsesLibrary.size() - 1; i >= 0; i--) {
mQueryableViaUsesLibrary.remove(mQueryableViaUsesLibrary.keyAt(i), setting.appId);
}
mForceQueryable.remove(setting.appId);
@@ -1315,6 +1348,18 @@ public class AppsFilter implements Watchable, Snappable {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueryableViaUsesLibrary");
if (mQueryableViaUsesLibrary.contains(callingAppId, targetAppId)) {
if (DEBUG_LOGGING) {
log(callingSetting, targetPkgSetting, "queryable for library users");
}
return false;
}
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
return true;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -1394,6 +1439,8 @@ public class AppsFilter implements Watchable, Snappable {
filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId),
mImplicitlyQueryable, " ", expandPackages);
}
pw.println(" queryable via uses-library:");
dumpQueriesMap(pw, filteringAppId, mQueryableViaUsesLibrary, " ", expandPackages);
}
private static void dumpQueriesMap(PrintWriter pw, @Nullable Integer filteringId,

View File

@@ -31,6 +31,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.SigningDetails;
import android.content.pm.Signature;
import android.content.pm.UserInfo;
import android.content.pm.parsing.ParsingPackage;
@@ -141,6 +142,10 @@ public class AppsFilterTest {
return pkg(packageName).addReceiver(receiver);
}
private static ParsingPackage pkgWithSharedLibrary(String packageName, String libName) {
return pkg(packageName).addLibraryName(libName);
}
private static ParsedActivity createActivity(String packageName, IntentFilter[] filters) {
ParsedActivity activity = new ParsedActivity();
activity.setPackageName(packageName);
@@ -412,6 +417,118 @@ public class AppsFilterTest {
SYSTEM_USER));
}
@Test
public void testNoUsesLibrary_Filters() throws Exception {
final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock,
new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null,
mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
final Signature mockSignature = Mockito.mock(Signature.class);
final SigningDetails mockSigningDetails = new SigningDetails(
new Signature[]{mockSignature},
SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2);
final PackageSetting target = simulateAddPackage(appsFilter,
pkgWithSharedLibrary("com.some.package", "com.some.shared_library"),
DUMMY_TARGET_APPID,
setting -> setting.setSigningDetails(mockSigningDetails)
.setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
final PackageSetting calling = simulateAddPackage(appsFilter,
pkg("com.some.other.package"), DUMMY_CALLING_APPID);
assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
SYSTEM_USER));
}
@Test
public void testUsesLibrary_DoesntFilter() throws Exception {
final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock,
new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null,
mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
final Signature mockSignature = Mockito.mock(Signature.class);
final SigningDetails mockSigningDetails = new SigningDetails(
new Signature[]{mockSignature},
SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2);
final PackageSetting target = simulateAddPackage(appsFilter,
pkgWithSharedLibrary("com.some.package", "com.some.shared_library"),
DUMMY_TARGET_APPID,
setting -> setting.setSigningDetails(mockSigningDetails)
.setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
final PackageSetting calling = simulateAddPackage(appsFilter,
pkg("com.some.other.package").addUsesLibrary("com.some.shared_library"),
DUMMY_CALLING_APPID);
assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
SYSTEM_USER));
}
@Test
public void testUsesOptionalLibrary_DoesntFilter() throws Exception {
final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock,
new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null,
mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
final Signature mockSignature = Mockito.mock(Signature.class);
final SigningDetails mockSigningDetails = new SigningDetails(
new Signature[]{mockSignature},
SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2);
final PackageSetting target = simulateAddPackage(appsFilter,
pkgWithSharedLibrary("com.some.package", "com.some.shared_library"),
DUMMY_TARGET_APPID,
setting -> setting.setSigningDetails(mockSigningDetails)
.setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
final PackageSetting calling = simulateAddPackage(appsFilter,
pkg("com.some.other.package").addUsesOptionalLibrary("com.some.shared_library"),
DUMMY_CALLING_APPID);
assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
SYSTEM_USER));
}
@Test
public void testUsesLibrary_ShareUid_DoesntFilter() throws Exception {
final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock,
new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null,
mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
final Signature mockSignature = Mockito.mock(Signature.class);
final SigningDetails mockSigningDetails = new SigningDetails(
new Signature[]{mockSignature},
SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2);
final PackageSetting target = simulateAddPackage(appsFilter,
pkgWithSharedLibrary("com.some.package", "com.some.shared_library"),
DUMMY_TARGET_APPID,
setting -> setting.setSigningDetails(mockSigningDetails)
.setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
final PackageSetting calling = simulateAddPackage(appsFilter,
pkg("com.some.other.package_a").setSharedUserId("com.some.uid"),
DUMMY_CALLING_APPID);
simulateAddPackage(appsFilter, pkg("com.some.other.package_b")
.setSharedUserId("com.some.uid").addUsesLibrary("com.some.shared_library"),
DUMMY_CALLING_APPID);
// Although package_a doesn't use library, it should be granted visibility. It's because
// package_a shares userId with package_b, and package_b uses that shared library.
assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
SYSTEM_USER));
}
@Test
public void testForceQueryable_SystemDoesntFilter() throws Exception {
final AppsFilter appsFilter =