Merge "ConnectivityService: synchronize access on mLockdownEnabled"

This commit is contained in:
Hugo Benichi
2018-01-16 00:20:52 +00:00
committed by Gerrit Code Review

View File

@@ -225,7 +225,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
@GuardedBy("mVpns") @GuardedBy("mVpns")
private final SparseArray<Vpn> mVpns = new SparseArray<Vpn>(); private final SparseArray<Vpn> mVpns = new SparseArray<Vpn>();
// TODO: investigate if mLockdownEnabled can be removed and replaced everywhere by
// a direct call to LockdownVpnTracker.isEnabled().
@GuardedBy("mVpns")
private boolean mLockdownEnabled; private boolean mLockdownEnabled;
@GuardedBy("mVpns")
private LockdownVpnTracker mLockdownTracker; private LockdownVpnTracker mLockdownTracker;
final private Context mContext; final private Context mContext;
@@ -974,9 +978,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
private Network[] getVpnUnderlyingNetworks(int uid) { private Network[] getVpnUnderlyingNetworks(int uid) {
if (!mLockdownEnabled) { synchronized (mVpns) {
int user = UserHandle.getUserId(uid); if (!mLockdownEnabled) {
synchronized (mVpns) { int user = UserHandle.getUserId(uid);
Vpn vpn = mVpns.get(user); Vpn vpn = mVpns.get(user);
if (vpn != null && vpn.appliesToUid(uid)) { if (vpn != null && vpn.appliesToUid(uid)) {
return vpn.getUnderlyingNetworks(); return vpn.getUnderlyingNetworks();
@@ -1064,8 +1068,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, ignoreBlocked)) { if (isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, ignoreBlocked)) {
state.networkInfo.setDetailedState(DetailedState.BLOCKED, null, null); state.networkInfo.setDetailedState(DetailedState.BLOCKED, null, null);
} }
if (mLockdownTracker != null) { synchronized (mVpns) {
mLockdownTracker.augmentNetworkInfo(state.networkInfo); if (mLockdownTracker != null) {
mLockdownTracker.augmentNetworkInfo(state.networkInfo);
}
} }
} }
@@ -1230,8 +1236,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
result.put(nai.network, nc); result.put(nai.network, nc);
} }
if (!mLockdownEnabled) { synchronized (mVpns) {
synchronized (mVpns) { if (!mLockdownEnabled) {
Vpn vpn = mVpns.get(userId); Vpn vpn = mVpns.get(userId);
if (vpn != null) { if (vpn != null) {
Network[] networks = vpn.getUnderlyingNetworks(); Network[] networks = vpn.getUnderlyingNetworks();
@@ -1557,9 +1563,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
private Intent makeGeneralIntent(NetworkInfo info, String bcastType) { private Intent makeGeneralIntent(NetworkInfo info, String bcastType) {
if (mLockdownTracker != null) { synchronized (mVpns) {
info = new NetworkInfo(info); if (mLockdownTracker != null) {
mLockdownTracker.augmentNetworkInfo(info); info = new NetworkInfo(info);
mLockdownTracker.augmentNetworkInfo(info);
}
} }
Intent intent = new Intent(bcastType); Intent intent = new Intent(bcastType);
@@ -3408,9 +3416,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage, public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage,
int userId) { int userId) {
enforceCrossUserPermission(userId); enforceCrossUserPermission(userId);
throwIfLockdownEnabled();
synchronized (mVpns) { synchronized (mVpns) {
throwIfLockdownEnabled();
Vpn vpn = mVpns.get(userId); Vpn vpn = mVpns.get(userId);
if (vpn != null) { if (vpn != null) {
return vpn.prepare(oldPackage, newPackage); return vpn.prepare(oldPackage, newPackage);
@@ -3454,9 +3462,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/ */
@Override @Override
public ParcelFileDescriptor establishVpn(VpnConfig config) { public ParcelFileDescriptor establishVpn(VpnConfig config) {
throwIfLockdownEnabled();
int user = UserHandle.getUserId(Binder.getCallingUid()); int user = UserHandle.getUserId(Binder.getCallingUid());
synchronized (mVpns) { synchronized (mVpns) {
throwIfLockdownEnabled();
return mVpns.get(user).establish(config); return mVpns.get(user).establish(config);
} }
} }
@@ -3467,13 +3475,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/ */
@Override @Override
public void startLegacyVpn(VpnProfile profile) { public void startLegacyVpn(VpnProfile profile) {
throwIfLockdownEnabled(); int user = UserHandle.getUserId(Binder.getCallingUid());
final LinkProperties egress = getActiveLinkProperties(); final LinkProperties egress = getActiveLinkProperties();
if (egress == null) { if (egress == null) {
throw new IllegalStateException("Missing active network connection"); throw new IllegalStateException("Missing active network connection");
} }
int user = UserHandle.getUserId(Binder.getCallingUid());
synchronized (mVpns) { synchronized (mVpns) {
throwIfLockdownEnabled();
mVpns.get(user).startLegacyVpn(profile, mKeyStore, egress); mVpns.get(user).startLegacyVpn(profile, mKeyStore, egress);
} }
} }
@@ -3499,11 +3507,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
@Override @Override
public VpnInfo[] getAllVpnInfo() { public VpnInfo[] getAllVpnInfo() {
enforceConnectivityInternalPermission(); enforceConnectivityInternalPermission();
if (mLockdownEnabled) {
return new VpnInfo[0];
}
synchronized (mVpns) { synchronized (mVpns) {
if (mLockdownEnabled) {
return new VpnInfo[0];
}
List<VpnInfo> infoList = new ArrayList<>(); List<VpnInfo> infoList = new ArrayList<>();
for (int i = 0; i < mVpns.size(); i++) { for (int i = 0; i < mVpns.size(); i++) {
VpnInfo info = createVpnInfo(mVpns.valueAt(i)); VpnInfo info = createVpnInfo(mVpns.valueAt(i));
@@ -3568,33 +3576,33 @@ public class ConnectivityService extends IConnectivityManager.Stub
return false; return false;
} }
// Tear down existing lockdown if profile was removed synchronized (mVpns) {
mLockdownEnabled = LockdownVpnTracker.isEnabled(); // Tear down existing lockdown if profile was removed
if (mLockdownEnabled) { mLockdownEnabled = LockdownVpnTracker.isEnabled();
byte[] profileTag = mKeyStore.get(Credentials.LOCKDOWN_VPN); if (mLockdownEnabled) {
if (profileTag == null) { byte[] profileTag = mKeyStore.get(Credentials.LOCKDOWN_VPN);
Slog.e(TAG, "Lockdown VPN configured but cannot be read from keystore"); if (profileTag == null) {
return false; Slog.e(TAG, "Lockdown VPN configured but cannot be read from keystore");
} return false;
String profileName = new String(profileTag); }
final VpnProfile profile = VpnProfile.decode( String profileName = new String(profileTag);
profileName, mKeyStore.get(Credentials.VPN + profileName)); final VpnProfile profile = VpnProfile.decode(
if (profile == null) { profileName, mKeyStore.get(Credentials.VPN + profileName));
Slog.e(TAG, "Lockdown VPN configured invalid profile " + profileName); if (profile == null) {
setLockdownTracker(null); Slog.e(TAG, "Lockdown VPN configured invalid profile " + profileName);
return true; setLockdownTracker(null);
} return true;
int user = UserHandle.getUserId(Binder.getCallingUid()); }
synchronized (mVpns) { int user = UserHandle.getUserId(Binder.getCallingUid());
Vpn vpn = mVpns.get(user); Vpn vpn = mVpns.get(user);
if (vpn == null) { if (vpn == null) {
Slog.w(TAG, "VPN for user " + user + " not ready yet. Skipping lockdown"); Slog.w(TAG, "VPN for user " + user + " not ready yet. Skipping lockdown");
return false; return false;
} }
setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, vpn, profile)); setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, vpn, profile));
} else {
setLockdownTracker(null);
} }
} else {
setLockdownTracker(null);
} }
return true; return true;
@@ -3604,6 +3612,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
* Internally set new {@link LockdownVpnTracker}, shutting down any existing * Internally set new {@link LockdownVpnTracker}, shutting down any existing
* {@link LockdownVpnTracker}. Can be {@code null} to disable lockdown. * {@link LockdownVpnTracker}. Can be {@code null} to disable lockdown.
*/ */
@GuardedBy("mVpns")
private void setLockdownTracker(LockdownVpnTracker tracker) { private void setLockdownTracker(LockdownVpnTracker tracker) {
// Shutdown any existing tracker // Shutdown any existing tracker
final LockdownVpnTracker existing = mLockdownTracker; final LockdownVpnTracker existing = mLockdownTracker;
@@ -3618,6 +3627,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
} }
@GuardedBy("mVpns")
private void throwIfLockdownEnabled() { private void throwIfLockdownEnabled() {
if (mLockdownEnabled) { if (mLockdownEnabled) {
throw new IllegalStateException("Unavailable in lockdown mode"); throw new IllegalStateException("Unavailable in lockdown mode");
@@ -3665,12 +3675,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
enforceConnectivityInternalPermission(); enforceConnectivityInternalPermission();
enforceCrossUserPermission(userId); enforceCrossUserPermission(userId);
// Can't set always-on VPN if legacy VPN is already in lockdown mode.
if (LockdownVpnTracker.isEnabled()) {
return false;
}
synchronized (mVpns) { synchronized (mVpns) {
// Can't set always-on VPN if legacy VPN is already in lockdown mode.
if (LockdownVpnTracker.isEnabled()) {
return false;
}
Vpn vpn = mVpns.get(userId); Vpn vpn = mVpns.get(userId);
if (vpn == null) { if (vpn == null) {
Slog.w(TAG, "User " + userId + " has no Vpn configuration"); Slog.w(TAG, "User " + userId + " has no Vpn configuration");
@@ -3846,9 +3856,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
userVpn = new Vpn(mHandler.getLooper(), mContext, mNetd, userId); userVpn = new Vpn(mHandler.getLooper(), mContext, mNetd, userId);
mVpns.put(userId, userVpn); mVpns.put(userId, userVpn);
} if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) { updateLockdownVpn();
updateLockdownVpn(); }
} }
} }
@@ -3885,11 +3895,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
private void onUserUnlocked(int userId) { private void onUserUnlocked(int userId) {
// User present may be sent because of an unlock, which might mean an unlocked keystore. synchronized (mVpns) {
if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) { // User present may be sent because of an unlock, which might mean an unlocked keystore.
updateLockdownVpn(); if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
} else { updateLockdownVpn();
startAlwaysOnVpn(userId); } else {
startAlwaysOnVpn(userId);
}
} }
} }
@@ -5177,11 +5189,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
private void notifyLockdownVpn(NetworkAgentInfo nai) { private void notifyLockdownVpn(NetworkAgentInfo nai) {
if (mLockdownTracker != null) { synchronized (mVpns) {
if (nai != null && nai.isVPN()) { if (mLockdownTracker != null) {
mLockdownTracker.onVpnStateChanged(nai.networkInfo); if (nai != null && nai.isVPN()) {
} else { mLockdownTracker.onVpnStateChanged(nai.networkInfo);
mLockdownTracker.onNetworkInfoChanged(); } else {
mLockdownTracker.onNetworkInfoChanged();
}
} }
} }
} }
@@ -5411,28 +5425,28 @@ public class ConnectivityService extends IConnectivityManager.Stub
@Override @Override
public boolean addVpnAddress(String address, int prefixLength) { public boolean addVpnAddress(String address, int prefixLength) {
throwIfLockdownEnabled();
int user = UserHandle.getUserId(Binder.getCallingUid()); int user = UserHandle.getUserId(Binder.getCallingUid());
synchronized (mVpns) { synchronized (mVpns) {
throwIfLockdownEnabled();
return mVpns.get(user).addAddress(address, prefixLength); return mVpns.get(user).addAddress(address, prefixLength);
} }
} }
@Override @Override
public boolean removeVpnAddress(String address, int prefixLength) { public boolean removeVpnAddress(String address, int prefixLength) {
throwIfLockdownEnabled();
int user = UserHandle.getUserId(Binder.getCallingUid()); int user = UserHandle.getUserId(Binder.getCallingUid());
synchronized (mVpns) { synchronized (mVpns) {
throwIfLockdownEnabled();
return mVpns.get(user).removeAddress(address, prefixLength); return mVpns.get(user).removeAddress(address, prefixLength);
} }
} }
@Override @Override
public boolean setUnderlyingNetworksForVpn(Network[] networks) { public boolean setUnderlyingNetworksForVpn(Network[] networks) {
throwIfLockdownEnabled();
int user = UserHandle.getUserId(Binder.getCallingUid()); int user = UserHandle.getUserId(Binder.getCallingUid());
boolean success; final boolean success;
synchronized (mVpns) { synchronized (mVpns) {
throwIfLockdownEnabled();
success = mVpns.get(user).setUnderlyingNetworks(networks); success = mVpns.get(user).setUnderlyingNetworks(networks);
} }
if (success) { if (success) {
@@ -5492,31 +5506,31 @@ public class ConnectivityService extends IConnectivityManager.Stub
setAlwaysOnVpnPackage(userId, null, false); setAlwaysOnVpnPackage(userId, null, false);
setVpnPackageAuthorization(alwaysOnPackage, userId, false); setVpnPackageAuthorization(alwaysOnPackage, userId, false);
} }
}
// Turn Always-on VPN off // Turn Always-on VPN off
if (mLockdownEnabled && userId == UserHandle.USER_SYSTEM) { if (mLockdownEnabled && userId == UserHandle.USER_SYSTEM) {
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
try { try {
mKeyStore.delete(Credentials.LOCKDOWN_VPN); mKeyStore.delete(Credentials.LOCKDOWN_VPN);
mLockdownEnabled = false; mLockdownEnabled = false;
setLockdownTracker(null); setLockdownTracker(null);
} finally { } finally {
Binder.restoreCallingIdentity(ident); Binder.restoreCallingIdentity(ident);
}
} }
}
// Turn VPN off // Turn VPN off
VpnConfig vpnConfig = getVpnConfig(userId); VpnConfig vpnConfig = getVpnConfig(userId);
if (vpnConfig != null) { if (vpnConfig != null) {
if (vpnConfig.legacy) { if (vpnConfig.legacy) {
prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, userId); prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, userId);
} else { } else {
// Prevent this app (packagename = vpnConfig.user) from initiating VPN connections // Prevent this app (packagename = vpnConfig.user) from initiating
// in the future without user intervention. // VPN connections in the future without user intervention.
setVpnPackageAuthorization(vpnConfig.user, userId, false); setVpnPackageAuthorization(vpnConfig.user, userId, false);
prepareVpn(null, VpnConfig.LEGACY_VPN, userId); prepareVpn(null, VpnConfig.LEGACY_VPN, userId);
}
} }
} }
} }