Loading services/core/java/com/android/server/connectivity/Vpn.java +74 −14 Original line number Diff line number Diff line Loading @@ -126,6 +126,7 @@ import com.android.server.net.BaseNetworkObserver; import libcore.io.IoUtils; import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; Loading Loading @@ -195,6 +196,7 @@ public class Vpn { private final Context mContext; private final ConnectivityManager mConnectivityManager; private final AppOpsManager mAppOpsManager; // The context is for specific user which is created from mUserId private final Context mUserIdContext; @VisibleForTesting final Dependencies mDeps; Loading Loading @@ -407,6 +409,46 @@ public class Vpn { public boolean isInterfacePresent(final Vpn vpn, final String iface) { return vpn.jniCheck(iface) != 0; } /** * @see ParcelFileDescriptor#adoptFd(int) */ public ParcelFileDescriptor adoptFd(Vpn vpn, int mtu) { return ParcelFileDescriptor.adoptFd(jniCreate(vpn, mtu)); } /** * Call native method to create the VPN interface and return the FileDescriptor of /dev/tun. */ public int jniCreate(Vpn vpn, int mtu) { return vpn.jniCreate(mtu); } /** * Call native method to get the interface name of VPN. */ public String jniGetName(Vpn vpn, int fd) { return vpn.jniGetName(fd); } /** * Call native method to set the VPN addresses and return the number of addresses. */ public int jniSetAddresses(Vpn vpn, String interfaze, String addresses) { return vpn.jniSetAddresses(interfaze, addresses); } /** * @see IoUtils#setBlocking(FileDescriptor, boolean) */ public void setBlocking(FileDescriptor fd, boolean blocking) { try { IoUtils.setBlocking(fd, blocking); } catch (IOException e) { throw new IllegalStateException( "Cannot set tunnel's fd as blocking=" + blocking, e); } } } public Vpn(Looper looper, Context context, INetworkManagementService netService, INetd netd, Loading @@ -431,6 +473,7 @@ public class Vpn { mVpnProfileStore = vpnProfileStore; mContext = context; mConnectivityManager = mContext.getSystemService(ConnectivityManager.class); mAppOpsManager = mContext.getSystemService(AppOpsManager.class); mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */); mDeps = deps; mNms = netService; Loading Loading @@ -826,7 +869,6 @@ public class Vpn { VpnProfile profile = getVpnProfilePrivileged(alwaysOnPackage); if (profile != null) { startVpnProfilePrivileged(profile, alwaysOnPackage); // If the above startVpnProfilePrivileged() call returns, the Ikev2VpnProfile was // correctly parsed, and the VPN has started running in a different thread. The only // other possibility is that the above call threw an exception, which will be Loading Loading @@ -974,9 +1016,15 @@ public class Vpn { } catch (Exception e) { // ignore } mAppOpsManager.finishOp( AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, mOwnerUID, mPackage, null); mContext.unbindService(mConnection); cleanupVpnStateLocked(); } else if (mVpnRunner != null) { if (!VpnConfig.LEGACY_VPN.equals(mPackage)) { mAppOpsManager.finishOp( AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, null); } // cleanupVpnStateLocked() is called from mVpnRunner.exit() mVpnRunner.exit(); } Loading Loading @@ -1041,10 +1089,8 @@ public class Vpn { return false; } final AppOpsManager appOpMgr = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); for (final String appOpStr : toChange) { appOpMgr.setMode( mAppOpsManager.setMode( appOpStr, uid, packageName, Loading Loading @@ -1366,9 +1412,9 @@ public class Vpn { Set<Range<Integer>> oldUsers = mNetworkCapabilities.getUids(); // Configure the interface. Abort if any of these steps fails. ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu)); final ParcelFileDescriptor tun = mDeps.adoptFd(this, config.mtu); try { String interfaze = jniGetName(tun.getFd()); final String interfaze = mDeps.jniGetName(this, tun.getFd()); // TEMP use the old jni calls until there is support for netd address setting StringBuilder builder = new StringBuilder(); Loading @@ -1376,7 +1422,7 @@ public class Vpn { builder.append(" "); builder.append(address); } if (jniSetAddresses(interfaze, builder.toString()) < 1) { if (mDeps.jniSetAddresses(this, interfaze, builder.toString()) < 1) { throw new IllegalArgumentException("At least one address must be specified"); } Connection connection = new Connection(); Loading Loading @@ -1422,11 +1468,11 @@ public class Vpn { jniReset(oldInterface); } try { IoUtils.setBlocking(tun.getFileDescriptor(), config.blocking); } catch (IOException e) { throw new IllegalStateException( "Cannot set tunnel's fd as blocking=" + config.blocking, e); mDeps.setBlocking(tun.getFileDescriptor(), config.blocking); // Record that the VPN connection is established by an app which uses VpnService API. if (oldNetworkAgent != mNetworkAgent) { mAppOpsManager.startOp( AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, mOwnerUID, mPackage, null, null); } } catch (RuntimeException e) { IoUtils.closeQuietly(tun); Loading Loading @@ -1781,9 +1827,17 @@ public class Vpn { synchronized (Vpn.this) { if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) { if (mConnection != null) { mAppOpsManager.finishOp( AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, mOwnerUID, mPackage, null); mContext.unbindService(mConnection); cleanupVpnStateLocked(); } else if (mVpnRunner != null) { if (!VpnConfig.LEGACY_VPN.equals(mPackage)) { mAppOpsManager.finishOp( AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, null); } // cleanupVpnStateLocked() is called from mVpnRunner.exit() mVpnRunner.exit(); } Loading Loading @@ -3254,8 +3308,7 @@ public class Vpn { * * @param packageName the package name of the app provisioning this profile */ public synchronized void startVpnProfile( @NonNull String packageName) { public synchronized void startVpnProfile(@NonNull String packageName) { requireNonNull(packageName, "No package name provided"); enforceNotRestrictedUser(); Loading Loading @@ -3318,6 +3371,13 @@ public class Vpn { Log.d(TAG, "Unknown VPN profile type: " + profile.type); break; } // Record that the VPN connection is established by an app which uses VpnManager API. if (!VpnConfig.LEGACY_VPN.equals(packageName)) { mAppOpsManager.startOp( AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, null, null); } } catch (GeneralSecurityException e) { // Reset mConfig mConfig = null; Loading Loading
services/core/java/com/android/server/connectivity/Vpn.java +74 −14 Original line number Diff line number Diff line Loading @@ -126,6 +126,7 @@ import com.android.server.net.BaseNetworkObserver; import libcore.io.IoUtils; import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; Loading Loading @@ -195,6 +196,7 @@ public class Vpn { private final Context mContext; private final ConnectivityManager mConnectivityManager; private final AppOpsManager mAppOpsManager; // The context is for specific user which is created from mUserId private final Context mUserIdContext; @VisibleForTesting final Dependencies mDeps; Loading Loading @@ -407,6 +409,46 @@ public class Vpn { public boolean isInterfacePresent(final Vpn vpn, final String iface) { return vpn.jniCheck(iface) != 0; } /** * @see ParcelFileDescriptor#adoptFd(int) */ public ParcelFileDescriptor adoptFd(Vpn vpn, int mtu) { return ParcelFileDescriptor.adoptFd(jniCreate(vpn, mtu)); } /** * Call native method to create the VPN interface and return the FileDescriptor of /dev/tun. */ public int jniCreate(Vpn vpn, int mtu) { return vpn.jniCreate(mtu); } /** * Call native method to get the interface name of VPN. */ public String jniGetName(Vpn vpn, int fd) { return vpn.jniGetName(fd); } /** * Call native method to set the VPN addresses and return the number of addresses. */ public int jniSetAddresses(Vpn vpn, String interfaze, String addresses) { return vpn.jniSetAddresses(interfaze, addresses); } /** * @see IoUtils#setBlocking(FileDescriptor, boolean) */ public void setBlocking(FileDescriptor fd, boolean blocking) { try { IoUtils.setBlocking(fd, blocking); } catch (IOException e) { throw new IllegalStateException( "Cannot set tunnel's fd as blocking=" + blocking, e); } } } public Vpn(Looper looper, Context context, INetworkManagementService netService, INetd netd, Loading @@ -431,6 +473,7 @@ public class Vpn { mVpnProfileStore = vpnProfileStore; mContext = context; mConnectivityManager = mContext.getSystemService(ConnectivityManager.class); mAppOpsManager = mContext.getSystemService(AppOpsManager.class); mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */); mDeps = deps; mNms = netService; Loading Loading @@ -826,7 +869,6 @@ public class Vpn { VpnProfile profile = getVpnProfilePrivileged(alwaysOnPackage); if (profile != null) { startVpnProfilePrivileged(profile, alwaysOnPackage); // If the above startVpnProfilePrivileged() call returns, the Ikev2VpnProfile was // correctly parsed, and the VPN has started running in a different thread. The only // other possibility is that the above call threw an exception, which will be Loading Loading @@ -974,9 +1016,15 @@ public class Vpn { } catch (Exception e) { // ignore } mAppOpsManager.finishOp( AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, mOwnerUID, mPackage, null); mContext.unbindService(mConnection); cleanupVpnStateLocked(); } else if (mVpnRunner != null) { if (!VpnConfig.LEGACY_VPN.equals(mPackage)) { mAppOpsManager.finishOp( AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, null); } // cleanupVpnStateLocked() is called from mVpnRunner.exit() mVpnRunner.exit(); } Loading Loading @@ -1041,10 +1089,8 @@ public class Vpn { return false; } final AppOpsManager appOpMgr = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); for (final String appOpStr : toChange) { appOpMgr.setMode( mAppOpsManager.setMode( appOpStr, uid, packageName, Loading Loading @@ -1366,9 +1412,9 @@ public class Vpn { Set<Range<Integer>> oldUsers = mNetworkCapabilities.getUids(); // Configure the interface. Abort if any of these steps fails. ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu)); final ParcelFileDescriptor tun = mDeps.adoptFd(this, config.mtu); try { String interfaze = jniGetName(tun.getFd()); final String interfaze = mDeps.jniGetName(this, tun.getFd()); // TEMP use the old jni calls until there is support for netd address setting StringBuilder builder = new StringBuilder(); Loading @@ -1376,7 +1422,7 @@ public class Vpn { builder.append(" "); builder.append(address); } if (jniSetAddresses(interfaze, builder.toString()) < 1) { if (mDeps.jniSetAddresses(this, interfaze, builder.toString()) < 1) { throw new IllegalArgumentException("At least one address must be specified"); } Connection connection = new Connection(); Loading Loading @@ -1422,11 +1468,11 @@ public class Vpn { jniReset(oldInterface); } try { IoUtils.setBlocking(tun.getFileDescriptor(), config.blocking); } catch (IOException e) { throw new IllegalStateException( "Cannot set tunnel's fd as blocking=" + config.blocking, e); mDeps.setBlocking(tun.getFileDescriptor(), config.blocking); // Record that the VPN connection is established by an app which uses VpnService API. if (oldNetworkAgent != mNetworkAgent) { mAppOpsManager.startOp( AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, mOwnerUID, mPackage, null, null); } } catch (RuntimeException e) { IoUtils.closeQuietly(tun); Loading Loading @@ -1781,9 +1827,17 @@ public class Vpn { synchronized (Vpn.this) { if (interfaze.equals(mInterface) && jniCheck(interfaze) == 0) { if (mConnection != null) { mAppOpsManager.finishOp( AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE, mOwnerUID, mPackage, null); mContext.unbindService(mConnection); cleanupVpnStateLocked(); } else if (mVpnRunner != null) { if (!VpnConfig.LEGACY_VPN.equals(mPackage)) { mAppOpsManager.finishOp( AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, null); } // cleanupVpnStateLocked() is called from mVpnRunner.exit() mVpnRunner.exit(); } Loading Loading @@ -3254,8 +3308,7 @@ public class Vpn { * * @param packageName the package name of the app provisioning this profile */ public synchronized void startVpnProfile( @NonNull String packageName) { public synchronized void startVpnProfile(@NonNull String packageName) { requireNonNull(packageName, "No package name provided"); enforceNotRestrictedUser(); Loading Loading @@ -3318,6 +3371,13 @@ public class Vpn { Log.d(TAG, "Unknown VPN profile type: " + profile.type); break; } // Record that the VPN connection is established by an app which uses VpnManager API. if (!VpnConfig.LEGACY_VPN.equals(packageName)) { mAppOpsManager.startOp( AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER, mOwnerUID, mPackage, null, null); } } catch (GeneralSecurityException e) { // Reset mConfig mConfig = null; Loading