boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo,
cpi.name, cpi.flags)
&& isValidSingletonCall(r.uid, cpi.applicationInfo.uid);
if (singleton) {
userId = UserHandle.USER_SYSTEM;
}
cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo, userId);
checkTime(startTime, "getContentProviderImpl: got app info for user");
String msg;
checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission");
if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, !singleton))
!= null) {
throw new SecurityException(msg);
}
checkTime(startTime, "getContentProviderImpl: after checkContentProviderPermission");
.
.
.
.
/**
* Check if {@link ProcessRecord} has a possible chance at accessing the
* given {@link ProviderInfo}. Final permission checking is always done
* in {@link ContentProvider}.
*/
private final String checkContentProviderPermissionLocked(
ProviderInfo cpi, ProcessRecord r, int userId, boolean checkUser) {
final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
final int callingUid = (r != null) ? r.uid : Binder.getCallingUid();
boolean checkedGrants = false;
if (checkUser) {
// Looking for cross-user grants before enforcing the typical cross-users permissions
int tmpTargetUserId = mUserController.unsafeConvertIncomingUserLocked(userId);
if (tmpTargetUserId != UserHandle.getUserId(callingUid)) {
if (checkAuthorityGrants(callingUid, cpi, tmpTargetUserId, checkUser)) {
return null;
}
checkedGrants = true;
}
userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
ALLOW_NON_FULL, "checkContentProviderPermissionLocked " + cpi.authority, null);
if (userId != tmpTargetUserId) {
// When we actually went to determine the final targer user ID, this ended
// up different than our initial check for the authority. This is because
// they had asked for USER_CURRENT_OR_SELF and we ended up switching to
// SELF. So we need to re-check the grants again.
checkedGrants = false;
}
}
if (checkComponentPermission(cpi.readPermission, callingPid, callingUid,
cpi.applicationInfo.uid, cpi.exported)
== PackageManager.PERMISSION_GRANTED) {
return null;
}
if (checkComponentPermission(cpi.writePermission, callingPid, callingUid,
cpi.applicationInfo.uid, cpi.exported)
== PackageManager.PERMISSION_GRANTED) {
return null;
}
PathPermission[] pps = cpi.pathPermissions;
if (pps != null) {
int i = pps.length;
while (i > 0) {
i--;
PathPermission pp = pps[i];
String pprperm = pp.getReadPermission();
if (pprperm != null && checkComponentPermission(pprperm, callingPid, callingUid,
cpi.applicationInfo.uid, cpi.exported)
== PackageManager.PERMISSION_GRANTED) {
return null;
}
String ppwperm = pp.getWritePermission();
if (ppwperm != null && checkComponentPermission(ppwperm, callingPid, callingUid,
cpi.applicationInfo.uid, cpi.exported)
== PackageManager.PERMISSION_GRANTED) {
return null;
}
}
}
if (!checkedGrants && checkAuthorityGrants(callingUid, cpi, userId, checkUser)) {
return null;
}
String msg;
if (!cpi.exported) {
msg = "Permission Denial: opening provider " + cpi.name
+ " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
+ ", uid=" + callingUid + ") that is not exported from uid "
+ cpi.applicationInfo.uid;
} else {
msg = "Permission Denial: opening provider " + cpi.name
+ " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
+ ", uid=" + callingUid + ") requires "
+ cpi.readPermission + " or " + cpi.writePermission;
}
Slog.w(TAG, msg);
return msg;
}