Loading services/core/java/com/android/server/connectivity/Vpn.java +65 −55 Original line number Original line Diff line number Diff line Loading @@ -23,8 +23,7 @@ import static android.net.RouteInfo.RTN_UNREACHABLE; import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN; import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN; import static android.os.UserHandle.PER_USER_RANGE; import static android.os.UserHandle.PER_USER_RANGE; import static com.android.internal.util.Preconditions.checkArgument; import static java.util.Objects.requireNonNull; import static com.android.internal.util.Preconditions.checkNotNull; import android.Manifest; import android.Manifest; import android.annotation.NonNull; import android.annotation.NonNull; Loading Loading @@ -1096,13 +1095,14 @@ public class Vpn { return Process.myUid(); return Process.myUid(); } } PackageManager pm = mContext.getPackageManager(); PackageManager pm = mContext.getPackageManager(); return Binder.withCleanCallingIdentity(() -> { final long token = Binder.clearCallingIdentity(); try { try { return pm.getPackageUidAsUser(app, userId); return pm.getPackageUidAsUser(app, userId); } catch (NameNotFoundException e) { } catch (NameNotFoundException e) { return -1; return -1; } finally { Binder.restoreCallingIdentity(token); } } }); } } private boolean doesPackageTargetAtLeastQ(String packageName) { private boolean doesPackageTargetAtLeastQ(String packageName) { Loading Loading @@ -1278,15 +1278,16 @@ public class Vpn { // We are user controlled, not driven by NetworkRequest. // We are user controlled, not driven by NetworkRequest. } } }; }; Binder.withCleanCallingIdentity(() -> { final long token = Binder.clearCallingIdentity(); try { try { mNetworkAgent.register(); mNetworkAgent.register(); } catch (final Exception e) { } catch (final Exception e) { // If register() throws, don't keep an unregistered agent. // If register() throws, don't keep an unregistered agent. mNetworkAgent = null; mNetworkAgent = null; throw e; throw e; } finally { Binder.restoreCallingIdentity(token); } } }); mNetworkAgent.setUnderlyingNetworks((mConfig.underlyingNetworks != null) mNetworkAgent.setUnderlyingNetworks((mConfig.underlyingNetworks != null) ? Arrays.asList(mConfig.underlyingNetworks) : null); ? Arrays.asList(mConfig.underlyingNetworks) : null); updateState(DetailedState.CONNECTED, "agentConnect"); updateState(DetailedState.CONNECTED, "agentConnect"); Loading Loading @@ -2024,13 +2025,16 @@ public class Vpn { } } private void enforceNotRestrictedUser() { private void enforceNotRestrictedUser() { Binder.withCleanCallingIdentity(() -> { final long token = Binder.clearCallingIdentity(); try { final UserInfo user = mUserManager.getUserInfo(mUserId); final UserInfo user = mUserManager.getUserInfo(mUserId); if (user.isRestricted()) { if (user.isRestricted()) { throw new SecurityException("Restricted users cannot configure VPNs"); throw new SecurityException("Restricted users cannot configure VPNs"); } } }); } finally { Binder.restoreCallingIdentity(token); } } } /** /** Loading Loading @@ -2823,8 +2827,10 @@ public class Vpn { LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd, VpnProfile profile) { LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd, VpnProfile profile) { super(TAG); super(TAG); checkArgument(racoon != null || mtpd != null, "Arguments to racoon and mtpd " if (racoon == null && mtpd == null) { + "must not both be null"); throw new IllegalArgumentException( "Arguments to racoon and mtpd must not both be null"); } mConfig = config; mConfig = config; mDaemons = new String[] {"racoon", "mtpd"}; mDaemons = new String[] {"racoon", "mtpd"}; // TODO: clear arguments from memory once launched // TODO: clear arguments from memory once launched Loading Loading @@ -3149,8 +3155,8 @@ public class Vpn { */ */ public synchronized boolean provisionVpnProfile( public synchronized boolean provisionVpnProfile( @NonNull String packageName, @NonNull VpnProfile profile) { @NonNull String packageName, @NonNull VpnProfile profile) { checkNotNull(packageName, "No package name provided"); requireNonNull(packageName, "No package name provided"); checkNotNull(profile, "No profile provided"); requireNonNull(profile, "No profile provided"); verifyCallingUidAndPackage(packageName); verifyCallingUidAndPackage(packageName); enforceNotRestrictedUser(); enforceNotRestrictedUser(); Loading @@ -3167,12 +3173,12 @@ public class Vpn { } } // Permissions checked during startVpnProfile() // Permissions checked during startVpnProfile() Binder.withCleanCallingIdentity( final long token = Binder.clearCallingIdentity(); () -> { try { getVpnProfileStore().put( getVpnProfileStore().put(getProfileNameForPackage(packageName), encodedProfile); getProfileNameForPackage(packageName), } finally { encodedProfile); Binder.restoreCallingIdentity(token); }); } // TODO: if package has CONTROL_VPN, grant the ACTIVATE_PLATFORM_VPN appop. // TODO: if package has CONTROL_VPN, grant the ACTIVATE_PLATFORM_VPN appop. // This mirrors the prepareAndAuthorize that is used by VpnService. // This mirrors the prepareAndAuthorize that is used by VpnService. Loading @@ -3192,13 +3198,13 @@ public class Vpn { */ */ public synchronized void deleteVpnProfile( public synchronized void deleteVpnProfile( @NonNull String packageName) { @NonNull String packageName) { checkNotNull(packageName, "No package name provided"); requireNonNull(packageName, "No package name provided"); verifyCallingUidAndPackage(packageName); verifyCallingUidAndPackage(packageName); enforceNotRestrictedUser(); enforceNotRestrictedUser(); Binder.withCleanCallingIdentity( final long token = Binder.clearCallingIdentity(); () -> { try { // If this profile is providing the current VPN, turn it off, disabling // If this profile is providing the current VPN, turn it off, disabling // always-on as well if enabled. // always-on as well if enabled. if (isCurrentIkev2VpnLocked(packageName)) { if (isCurrentIkev2VpnLocked(packageName)) { Loading @@ -3211,7 +3217,9 @@ public class Vpn { } } getVpnProfileStore().remove(getProfileNameForPackage(packageName)); getVpnProfileStore().remove(getProfileNameForPackage(packageName)); }); } finally { Binder.restoreCallingIdentity(token); } } } /** /** Loading Loading @@ -3245,7 +3253,7 @@ public class Vpn { */ */ public synchronized void startVpnProfile( public synchronized void startVpnProfile( @NonNull String packageName) { @NonNull String packageName) { checkNotNull(packageName, "No package name provided"); requireNonNull(packageName, "No package name provided"); enforceNotRestrictedUser(); enforceNotRestrictedUser(); Loading @@ -3254,15 +3262,17 @@ public class Vpn { throw new SecurityException("User consent not granted for package " + packageName); throw new SecurityException("User consent not granted for package " + packageName); } } Binder.withCleanCallingIdentity( final long token = Binder.clearCallingIdentity(); () -> { try { final VpnProfile profile = getVpnProfilePrivileged(packageName); final VpnProfile profile = getVpnProfilePrivileged(packageName); if (profile == null) { if (profile == null) { throw new IllegalArgumentException("No profile found for " + packageName); throw new IllegalArgumentException("No profile found for " + packageName); } } startVpnProfilePrivileged(profile, packageName); startVpnProfilePrivileged(profile, packageName); }); } finally { Binder.restoreCallingIdentity(token); } } } private synchronized void startVpnProfilePrivileged( private synchronized void startVpnProfilePrivileged( Loading Loading @@ -3323,7 +3333,7 @@ public class Vpn { * @param packageName the package name of the app provisioning this profile * @param packageName the package name of the app provisioning this profile */ */ public synchronized void stopVpnProfile(@NonNull String packageName) { public synchronized void stopVpnProfile(@NonNull String packageName) { checkNotNull(packageName, "No package name provided"); requireNonNull(packageName, "No package name provided"); enforceNotRestrictedUser(); enforceNotRestrictedUser(); Loading Loading
services/core/java/com/android/server/connectivity/Vpn.java +65 −55 Original line number Original line Diff line number Diff line Loading @@ -23,8 +23,7 @@ import static android.net.RouteInfo.RTN_UNREACHABLE; import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN; import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN; import static android.os.UserHandle.PER_USER_RANGE; import static android.os.UserHandle.PER_USER_RANGE; import static com.android.internal.util.Preconditions.checkArgument; import static java.util.Objects.requireNonNull; import static com.android.internal.util.Preconditions.checkNotNull; import android.Manifest; import android.Manifest; import android.annotation.NonNull; import android.annotation.NonNull; Loading Loading @@ -1096,13 +1095,14 @@ public class Vpn { return Process.myUid(); return Process.myUid(); } } PackageManager pm = mContext.getPackageManager(); PackageManager pm = mContext.getPackageManager(); return Binder.withCleanCallingIdentity(() -> { final long token = Binder.clearCallingIdentity(); try { try { return pm.getPackageUidAsUser(app, userId); return pm.getPackageUidAsUser(app, userId); } catch (NameNotFoundException e) { } catch (NameNotFoundException e) { return -1; return -1; } finally { Binder.restoreCallingIdentity(token); } } }); } } private boolean doesPackageTargetAtLeastQ(String packageName) { private boolean doesPackageTargetAtLeastQ(String packageName) { Loading Loading @@ -1278,15 +1278,16 @@ public class Vpn { // We are user controlled, not driven by NetworkRequest. // We are user controlled, not driven by NetworkRequest. } } }; }; Binder.withCleanCallingIdentity(() -> { final long token = Binder.clearCallingIdentity(); try { try { mNetworkAgent.register(); mNetworkAgent.register(); } catch (final Exception e) { } catch (final Exception e) { // If register() throws, don't keep an unregistered agent. // If register() throws, don't keep an unregistered agent. mNetworkAgent = null; mNetworkAgent = null; throw e; throw e; } finally { Binder.restoreCallingIdentity(token); } } }); mNetworkAgent.setUnderlyingNetworks((mConfig.underlyingNetworks != null) mNetworkAgent.setUnderlyingNetworks((mConfig.underlyingNetworks != null) ? Arrays.asList(mConfig.underlyingNetworks) : null); ? Arrays.asList(mConfig.underlyingNetworks) : null); updateState(DetailedState.CONNECTED, "agentConnect"); updateState(DetailedState.CONNECTED, "agentConnect"); Loading Loading @@ -2024,13 +2025,16 @@ public class Vpn { } } private void enforceNotRestrictedUser() { private void enforceNotRestrictedUser() { Binder.withCleanCallingIdentity(() -> { final long token = Binder.clearCallingIdentity(); try { final UserInfo user = mUserManager.getUserInfo(mUserId); final UserInfo user = mUserManager.getUserInfo(mUserId); if (user.isRestricted()) { if (user.isRestricted()) { throw new SecurityException("Restricted users cannot configure VPNs"); throw new SecurityException("Restricted users cannot configure VPNs"); } } }); } finally { Binder.restoreCallingIdentity(token); } } } /** /** Loading Loading @@ -2823,8 +2827,10 @@ public class Vpn { LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd, VpnProfile profile) { LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd, VpnProfile profile) { super(TAG); super(TAG); checkArgument(racoon != null || mtpd != null, "Arguments to racoon and mtpd " if (racoon == null && mtpd == null) { + "must not both be null"); throw new IllegalArgumentException( "Arguments to racoon and mtpd must not both be null"); } mConfig = config; mConfig = config; mDaemons = new String[] {"racoon", "mtpd"}; mDaemons = new String[] {"racoon", "mtpd"}; // TODO: clear arguments from memory once launched // TODO: clear arguments from memory once launched Loading Loading @@ -3149,8 +3155,8 @@ public class Vpn { */ */ public synchronized boolean provisionVpnProfile( public synchronized boolean provisionVpnProfile( @NonNull String packageName, @NonNull VpnProfile profile) { @NonNull String packageName, @NonNull VpnProfile profile) { checkNotNull(packageName, "No package name provided"); requireNonNull(packageName, "No package name provided"); checkNotNull(profile, "No profile provided"); requireNonNull(profile, "No profile provided"); verifyCallingUidAndPackage(packageName); verifyCallingUidAndPackage(packageName); enforceNotRestrictedUser(); enforceNotRestrictedUser(); Loading @@ -3167,12 +3173,12 @@ public class Vpn { } } // Permissions checked during startVpnProfile() // Permissions checked during startVpnProfile() Binder.withCleanCallingIdentity( final long token = Binder.clearCallingIdentity(); () -> { try { getVpnProfileStore().put( getVpnProfileStore().put(getProfileNameForPackage(packageName), encodedProfile); getProfileNameForPackage(packageName), } finally { encodedProfile); Binder.restoreCallingIdentity(token); }); } // TODO: if package has CONTROL_VPN, grant the ACTIVATE_PLATFORM_VPN appop. // TODO: if package has CONTROL_VPN, grant the ACTIVATE_PLATFORM_VPN appop. // This mirrors the prepareAndAuthorize that is used by VpnService. // This mirrors the prepareAndAuthorize that is used by VpnService. Loading @@ -3192,13 +3198,13 @@ public class Vpn { */ */ public synchronized void deleteVpnProfile( public synchronized void deleteVpnProfile( @NonNull String packageName) { @NonNull String packageName) { checkNotNull(packageName, "No package name provided"); requireNonNull(packageName, "No package name provided"); verifyCallingUidAndPackage(packageName); verifyCallingUidAndPackage(packageName); enforceNotRestrictedUser(); enforceNotRestrictedUser(); Binder.withCleanCallingIdentity( final long token = Binder.clearCallingIdentity(); () -> { try { // If this profile is providing the current VPN, turn it off, disabling // If this profile is providing the current VPN, turn it off, disabling // always-on as well if enabled. // always-on as well if enabled. if (isCurrentIkev2VpnLocked(packageName)) { if (isCurrentIkev2VpnLocked(packageName)) { Loading @@ -3211,7 +3217,9 @@ public class Vpn { } } getVpnProfileStore().remove(getProfileNameForPackage(packageName)); getVpnProfileStore().remove(getProfileNameForPackage(packageName)); }); } finally { Binder.restoreCallingIdentity(token); } } } /** /** Loading Loading @@ -3245,7 +3253,7 @@ public class Vpn { */ */ public synchronized void startVpnProfile( public synchronized void startVpnProfile( @NonNull String packageName) { @NonNull String packageName) { checkNotNull(packageName, "No package name provided"); requireNonNull(packageName, "No package name provided"); enforceNotRestrictedUser(); enforceNotRestrictedUser(); Loading @@ -3254,15 +3262,17 @@ public class Vpn { throw new SecurityException("User consent not granted for package " + packageName); throw new SecurityException("User consent not granted for package " + packageName); } } Binder.withCleanCallingIdentity( final long token = Binder.clearCallingIdentity(); () -> { try { final VpnProfile profile = getVpnProfilePrivileged(packageName); final VpnProfile profile = getVpnProfilePrivileged(packageName); if (profile == null) { if (profile == null) { throw new IllegalArgumentException("No profile found for " + packageName); throw new IllegalArgumentException("No profile found for " + packageName); } } startVpnProfilePrivileged(profile, packageName); startVpnProfilePrivileged(profile, packageName); }); } finally { Binder.restoreCallingIdentity(token); } } } private synchronized void startVpnProfilePrivileged( private synchronized void startVpnProfilePrivileged( Loading Loading @@ -3323,7 +3333,7 @@ public class Vpn { * @param packageName the package name of the app provisioning this profile * @param packageName the package name of the app provisioning this profile */ */ public synchronized void stopVpnProfile(@NonNull String packageName) { public synchronized void stopVpnProfile(@NonNull String packageName) { checkNotNull(packageName, "No package name provided"); requireNonNull(packageName, "No package name provided"); enforceNotRestrictedUser(); enforceNotRestrictedUser(); Loading