Merge "Fix privacy leaks in LocationManager" into mnc-dev

This commit is contained in:
David Christie
2015-06-22 21:26:47 +00:00
committed by Android (Google) Code Review
2 changed files with 38 additions and 14 deletions

View File

@@ -892,7 +892,6 @@ public class LocationManager {
* @param listener listener object that no longer needs location updates * @param listener listener object that no longer needs location updates
* @throws IllegalArgumentException if listener is null * @throws IllegalArgumentException if listener is null
*/ */
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void removeUpdates(LocationListener listener) { public void removeUpdates(LocationListener listener) {
checkListener(listener); checkListener(listener);
String packageName = mContext.getPackageName(); String packageName = mContext.getPackageName();
@@ -1055,7 +1054,6 @@ public class LocationManager {
* @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION} * @throws SecurityException if {@link android.Manifest.permission#ACCESS_FINE_LOCATION}
* permission is not present * permission is not present
*/ */
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void removeProximityAlert(PendingIntent intent) { public void removeProximityAlert(PendingIntent intent) {
checkPendingIntent(intent); checkPendingIntent(intent);
String packageName = mContext.getPackageName(); String packageName = mContext.getPackageName();
@@ -1083,7 +1081,6 @@ public class LocationManager {
* *
* @hide * @hide
*/ */
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void removeGeofence(Geofence fence, PendingIntent intent) { public void removeGeofence(Geofence fence, PendingIntent intent) {
checkPendingIntent(intent); checkPendingIntent(intent);
checkGeofence(fence); checkGeofence(fence);
@@ -1107,7 +1104,6 @@ public class LocationManager {
* *
* @hide * @hide
*/ */
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void removeAllGeofences(PendingIntent intent) { public void removeAllGeofences(PendingIntent intent) {
checkPendingIntent(intent); checkPendingIntent(intent);
String packageName = mContext.getPackageName(); String packageName = mContext.getPackageName();

View File

@@ -270,6 +270,17 @@ public class LocationManagerService extends ILocationManager.Stub {
}; };
mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null, callback); mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null, callback);
PackageManager.OnPermissionsChangedListener permissionListener
= new PackageManager.OnPermissionsChangedListener() {
@Override
public void onPermissionsChanged(final int uid) {
synchronized (mLock) {
applyAllProviderRequirementsLocked();
}
}
};
mPackageManager.addOnPermissionsChangeListener(permissionListener);
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
updateUserProfiles(mCurrentUserId); updateUserProfiles(mCurrentUserId);
@@ -1133,23 +1144,34 @@ public class LocationManagerService extends ILocationManager.Stub {
return -1; return -1;
} }
boolean reportLocationAccessNoThrow(int uid, String packageName, int allowedResolutionLevel) { boolean reportLocationAccessNoThrow(
int pid, int uid, String packageName, int allowedResolutionLevel) {
int op = resolutionLevelToOp(allowedResolutionLevel); int op = resolutionLevelToOp(allowedResolutionLevel);
if (op >= 0) { if (op >= 0) {
if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) { if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
return false; return false;
} }
} }
if (getAllowedResolutionLevel(pid, uid) < allowedResolutionLevel) {
return false;
}
return true; return true;
} }
boolean checkLocationAccess(int uid, String packageName, int allowedResolutionLevel) { boolean checkLocationAccess(int pid, int uid, String packageName, int allowedResolutionLevel) {
int op = resolutionLevelToOp(allowedResolutionLevel); int op = resolutionLevelToOp(allowedResolutionLevel);
if (op >= 0) { if (op >= 0) {
if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) { if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
return false; return false;
} }
} }
if (getAllowedResolutionLevel(pid, uid) < allowedResolutionLevel) {
return false;
}
return true; return true;
} }
@@ -1347,7 +1369,10 @@ public class LocationManagerService extends ILocationManager.Stub {
if (records != null) { if (records != null) {
for (UpdateRecord record : records) { for (UpdateRecord record : records) {
if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mUid))) { if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mUid))) {
if (checkLocationAccess(record.mReceiver.mUid, record.mReceiver.mPackageName, if (checkLocationAccess(
record.mReceiver.mPid,
record.mReceiver.mUid,
record.mReceiver.mPackageName,
record.mReceiver.mAllowedResolutionLevel)) { record.mReceiver.mAllowedResolutionLevel)) {
LocationRequest locationRequest = record.mRequest; LocationRequest locationRequest = record.mRequest;
providerRequest.locationRequests.add(locationRequest); providerRequest.locationRequests.add(locationRequest);
@@ -1583,7 +1608,7 @@ public class LocationManagerService extends ILocationManager.Stub {
try { try {
// We don't check for MODE_IGNORED here; we will do that when we go to deliver // We don't check for MODE_IGNORED here; we will do that when we go to deliver
// a location. // a location.
checkLocationAccess(uid, packageName, allowedResolutionLevel); checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
synchronized (mLock) { synchronized (mLock) {
Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid, Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
@@ -1711,6 +1736,7 @@ public class LocationManagerService extends ILocationManager.Stub {
request.getProvider()); request.getProvider());
// no need to sanitize this request, as only the provider name is used // no need to sanitize this request, as only the provider name is used
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid(); final int uid = Binder.getCallingUid();
final long identity = Binder.clearCallingIdentity(); final long identity = Binder.clearCallingIdentity();
try { try {
@@ -1720,7 +1746,7 @@ public class LocationManagerService extends ILocationManager.Stub {
return null; return null;
} }
if (!reportLocationAccessNoThrow(uid, packageName, allowedResolutionLevel)) { if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel)) {
if (D) Log.d(TAG, "not returning last loc for no op app: " + if (D) Log.d(TAG, "not returning last loc for no op app: " +
packageName); packageName);
return null; return null;
@@ -1794,7 +1820,6 @@ public class LocationManagerService extends ILocationManager.Stub {
@Override @Override
public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) { public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
checkResolutionLevelIsSufficientForGeofenceUse(getCallerAllowedResolutionLevel());
checkPendingIntent(intent); checkPendingIntent(intent);
checkPackageName(packageName); checkPackageName(packageName);
@@ -1816,10 +1841,11 @@ public class LocationManagerService extends ILocationManager.Stub {
checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
LocationManager.GPS_PROVIDER); LocationManager.GPS_PROVIDER);
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid(); final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
try { try {
if (!checkLocationAccess(uid, packageName, allowedResolutionLevel)) { if (!checkLocationAccess(pid, uid, packageName, allowedResolutionLevel)) {
return false; return false;
} }
} finally { } finally {
@@ -1859,11 +1885,12 @@ public class LocationManagerService extends ILocationManager.Stub {
allowedResolutionLevel, allowedResolutionLevel,
LocationManager.GPS_PROVIDER); LocationManager.GPS_PROVIDER);
int pid = Binder.getCallingPid();
int uid = Binder.getCallingUid(); int uid = Binder.getCallingUid();
long identity = Binder.clearCallingIdentity(); long identity = Binder.clearCallingIdentity();
boolean hasLocationAccess; boolean hasLocationAccess;
try { try {
hasLocationAccess = checkLocationAccess(uid, packageName, allowedResolutionLevel); hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
} finally { } finally {
Binder.restoreCallingIdentity(identity); Binder.restoreCallingIdentity(identity);
} }
@@ -1890,11 +1917,12 @@ public class LocationManagerService extends ILocationManager.Stub {
allowedResolutionLevel, allowedResolutionLevel,
LocationManager.GPS_PROVIDER); LocationManager.GPS_PROVIDER);
int pid = Binder.getCallingPid();
int uid = Binder.getCallingUid(); int uid = Binder.getCallingUid();
long identity = Binder.clearCallingIdentity(); long identity = Binder.clearCallingIdentity();
boolean hasLocationAccess; boolean hasLocationAccess;
try { try {
hasLocationAccess = checkLocationAccess(uid, packageName, allowedResolutionLevel); hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
} finally { } finally {
Binder.restoreCallingIdentity(identity); Binder.restoreCallingIdentity(identity);
} }
@@ -2209,7 +2237,7 @@ public class LocationManagerService extends ILocationManager.Stub {
continue; continue;
} }
if (!reportLocationAccessNoThrow(receiver.mUid, receiver.mPackageName, if (!reportLocationAccessNoThrow(receiver.mPid, receiver.mUid, receiver.mPackageName,
receiver.mAllowedResolutionLevel)) { receiver.mAllowedResolutionLevel)) {
if (D) Log.d(TAG, "skipping loc update for no op app: " + if (D) Log.d(TAG, "skipping loc update for no op app: " +
receiver.mPackageName); receiver.mPackageName);