DO NOT MERGE Allow cross user usage event queries

For multipackage requests, caller must be system uid or hold
interact_across_users if not requesting fate for the same user.

For single package requests, caller must be system uid or the
same package and hold interact_across_users if not requesting data
for the current user.

In both cases the caller must have the usagestats permission.

Test: couldn't find automated tests for this file; manual
Bug: 79142791
Change-Id: I8d650f8e875e0e4578cb48c9ba42e821342852a0
This commit is contained in:
Julia Reynolds
2018-05-21 14:11:43 -04:00
parent 6433ac13bd
commit 20e682910d
2 changed files with 73 additions and 5 deletions

View File

@@ -36,6 +36,8 @@ interface IUsageStatsManager {
String callingPackage);
UsageEvents queryEvents(long beginTime, long endTime, String callingPackage);
UsageEvents queryEventsForPackage(long beginTime, long endTime, String callingPackage);
UsageEvents queryEventsForUser(long beginTime, long endTime, int userId, String callingPackage);
UsageEvents queryEventsForPackageForUser(long beginTime, long endTime, int userId, String pkg, String callingPackage);
void setAppInactive(String packageName, boolean inactive, int userId);
boolean isAppInactive(String packageName, int userId);
void whitelistAppTemporarily(String packageName, long duration, int userId);

View File

@@ -699,6 +699,29 @@ public class UsageStatsService extends SystemService implements
== PackageManager.PERMISSION_GRANTED;
}
private void checkCallerIsSystemOrSameApp(String pkg) {
if (isCallingUidSystem()) {
return;
}
checkCallerIsSameApp(pkg);
}
private void checkCallerIsSameApp(String pkg) {
final int callingUid = Binder.getCallingUid();
final int callingUserId = UserHandle.getUserId(callingUid);
if (mPackageManagerInternal.getPackageUid(pkg, PackageManager.MATCH_ANY_USER,
callingUserId) != callingUid) {
throw new SecurityException("Calling uid " + pkg + " cannot query events"
+ "for package " + pkg);
}
}
private boolean isCallingUidSystem() {
final int uid = Binder.getCallingUid();
return uid == Process.SYSTEM_UID;
}
@Override
public ParceledListSlice<UsageStats> queryUsageStats(int bucketType, long beginTime,
long endTime, String callingPackage) {
@@ -792,11 +815,7 @@ public class UsageStatsService extends SystemService implements
final int callingUid = Binder.getCallingUid();
final int callingUserId = UserHandle.getUserId(callingUid);
if (mPackageManagerInternal.getPackageUid(callingPackage, PackageManager.MATCH_ANY_USER,
callingUserId) != callingUid) {
throw new SecurityException("Calling uid " + callingPackage + " cannot query events"
+ "for package " + callingPackage);
}
checkCallerIsSameApp(callingPackage);
final long token = Binder.clearCallingIdentity();
try {
return UsageStatsService.this.queryEventsForPackage(callingUserId, beginTime,
@@ -806,6 +825,53 @@ public class UsageStatsService extends SystemService implements
}
}
@Override
public UsageEvents queryEventsForUser(long beginTime, long endTime, int userId,
String callingPackage) {
if (!hasPermission(callingPackage)) {
return null;
}
if (userId != UserHandle.getCallingUserId()) {
getContext().enforceCallingPermission(
Manifest.permission.INTERACT_ACROSS_USERS_FULL,
"No permission to query usage stats for this user");
}
final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
Binder.getCallingUid(), UserHandle.getCallingUserId());
final long token = Binder.clearCallingIdentity();
try {
return UsageStatsService.this.queryEvents(userId, beginTime, endTime,
obfuscateInstantApps);
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override
public UsageEvents queryEventsForPackageForUser(long beginTime, long endTime,
int userId, String pkg, String callingPackage) {
if (!hasPermission(callingPackage)) {
return null;
}
if (userId != UserHandle.getCallingUserId()) {
getContext().enforceCallingPermission(
Manifest.permission.INTERACT_ACROSS_USERS_FULL,
"No permission to query usage stats for this user");
}
checkCallerIsSystemOrSameApp(pkg);
final long token = Binder.clearCallingIdentity();
try {
return UsageStatsService.this.queryEventsForPackage(userId, beginTime,
endTime, callingPackage);
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override
public boolean isAppInactive(String packageName, int userId) {
try {