Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22c79505 authored by Mark Chien's avatar Mark Chien Committed by Automerger Merge Worker
Browse files

Merge "Protect invalid entitlement app configuration" into rvc-dev am: 06b2e1cb

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11699076

Change-Id: Iff190a50257352ad815288aa821bb8ca3611580b
parents 994e91f1 06b2e1cb
Loading
Loading
Loading
Loading
+0 −33
Original line number Diff line number Diff line
@@ -19,42 +19,9 @@ import static android.os.UserManager.DISALLOW_CONFIG_TETHERING;

import android.content.Context;
import android.net.ConnectivityManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.telephony.CarrierConfigManager;

import androidx.annotation.VisibleForTesting;

public class TetherUtil {

    @VisibleForTesting
    static boolean isEntitlementCheckRequired(Context context) {
        final CarrierConfigManager configManager = (CarrierConfigManager) context
             .getSystemService(Context.CARRIER_CONFIG_SERVICE);
        if (configManager == null || configManager.getConfig() == null) {
            // return service default
            return true;
        }
        return configManager.getConfig().getBoolean(CarrierConfigManager
             .KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL);
    }

    public static boolean isProvisioningNeeded(Context context) {
        // Keep in sync with other usage of config_mobile_hotspot_provision_app.
        // ConnectivityManager#enforceTetherChangePermission
        String[] provisionApp = context.getResources().getStringArray(
                com.android.internal.R.array.config_mobile_hotspot_provision_app);
        if (SystemProperties.getBoolean("net.tethering.noprovisioning", false)
                || provisionApp == null) {
            return false;
        }
        // Check carrier config for entitlement checks
        if (isEntitlementCheckRequired(context) == false) {
            return false;
        }
        return (provisionApp.length == 2);
    }

    public static boolean isTetherAvailable(Context context) {
        final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
        final boolean tetherConfigDisallowed = RestrictedLockUtilsInternal
+0 −7
Original line number Diff line number Diff line
@@ -59,13 +59,6 @@ public class TetherUtilTest {
                .when(mContext).getSystemService(Context.USER_SERVICE);
    }

    @Test
    public void isEntitlementCheckRequired_noConfigManager_returnTrue() {
        doReturn(null).when(mContext).getSystemService(Context.CARRIER_CONFIG_SERVICE);

        assertThat(TetherUtil.isEntitlementCheckRequired(mContext)).isTrue();
    }

    @Test
    public void isTetherAvailable_supported_configDisallowed_hasUserRestriction_returnTrue() {
        setupIsTetherAvailable(true, true, true);
+24 −4
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.networkstack.tethering;

import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.Manifest.permission.NETWORK_STACK;
import static android.content.pm.PackageManager.GET_ACTIVITIES;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
import static android.hardware.usb.UsbManager.USB_CONNECTED;
@@ -70,6 +71,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager;
import android.net.EthernetManager;
@@ -109,7 +111,6 @@ import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceSpecificException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -782,11 +783,30 @@ public class Tethering {
        }
    }

    private boolean isProvisioningNeededButUnavailable() {
        return isTetherProvisioningRequired() && !doesEntitlementPackageExist();
    }

    boolean isTetherProvisioningRequired() {
        final TetheringConfiguration cfg = mConfig;
        return mEntitlementMgr.isTetherProvisioningRequired(cfg);
    }

    private boolean doesEntitlementPackageExist() {
        // provisioningApp must contain package and class name.
        if (mConfig.provisioningApp.length != 2) {
            return false;
        }

        final PackageManager pm = mContext.getPackageManager();
        try {
            pm.getPackageInfo(mConfig.provisioningApp[0], GET_ACTIVITIES);
        } catch (PackageManager.NameNotFoundException e) {
            return false;
        }
        return true;
    }

    // TODO: Figure out how to update for local hotspot mode interfaces.
    private void sendTetherStateChangedBroadcast() {
        if (!isTetheringSupported()) return;
@@ -2145,14 +2165,14 @@ public class Tethering {
    // gservices could set the secure setting to 1 though to enable it on a build where it
    // had previously been turned off.
    boolean isTetheringSupported() {
        final int defaultVal =
                SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1;
        final int defaultVal = mDeps.isTetheringDenied() ? 0 : 1;
        final boolean tetherSupported = Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.TETHER_SUPPORTED, defaultVal) != 0;
        final boolean tetherEnabledInSettings = tetherSupported
                && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);

        return tetherEnabledInSettings && hasTetherableConfiguration();
        return tetherEnabledInSettings && hasTetherableConfiguration()
                && !isProvisioningNeededButUnavailable();
    }

    void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer, @Nullable String[] args) {
+9 −0
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ import android.net.util.SharedLog;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.SystemProperties;
import android.text.TextUtils;

import androidx.annotation.NonNull;

@@ -150,4 +152,11 @@ public abstract class TetheringDependencies {
     * Get a reference to BluetoothAdapter to be used by tethering.
     */
    public abstract BluetoothAdapter getBluetoothAdapter();

    /**
     * Get SystemProperties which indicate whether tethering is denied.
     */
    public boolean isTetheringDenied() {
        return TextUtils.equals(SystemProperties.get("ro.tether.denied"), "true");
    }
}
+30 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.networkstack.tethering;

import static android.content.pm.PackageManager.GET_ACTIVITIES;
import static android.hardware.usb.UsbManager.USB_CONFIGURED;
import static android.hardware.usb.UsbManager.USB_CONNECTED;
import static android.hardware.usb.UsbManager.USB_FUNCTION_NCM;
@@ -81,6 +82,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager;
@@ -204,6 +206,7 @@ public class TetheringTest {
    @Mock private EthernetManager mEm;
    @Mock private TetheringNotificationUpdater mNotificationUpdater;
    @Mock private BpfCoordinator mBpfCoordinator;
    @Mock private PackageManager mPackageManager;

    private final MockIpServerDependencies mIpServerDependencies =
            spy(new MockIpServerDependencies());
@@ -263,6 +266,11 @@ public class TetheringTest {
            return super.getSystemService(name);
        }

        @Override
        public PackageManager getPackageManager() {
            return mPackageManager;
        }

        @Override
        public String getSystemServiceName(Class<?> serviceClass) {
            if (TelephonyManager.class.equals(serviceClass)) return Context.TELEPHONY_SERVICE;
@@ -425,6 +433,11 @@ public class TetheringTest {
        public TetheringNotificationUpdater getNotificationUpdater(Context ctx, Looper looper) {
            return mNotificationUpdater;
        }

        @Override
        public boolean isTetheringDenied() {
            return false;
        }
    }

    private static UpstreamNetworkState buildMobileUpstreamState(boolean withIPv4,
@@ -1951,6 +1964,23 @@ public class TetheringTest {
        assertEquals(TETHER_ERROR_IFACE_CFG_ERROR, mTethering.getLastTetherError(TEST_ETH_IFNAME));
    }

    @Test
    public void testProvisioningNeededButUnavailable() throws Exception {
        assertTrue(mTethering.isTetheringSupported());
        verify(mPackageManager, never()).getPackageInfo(PROVISIONING_APP_NAME[0], GET_ACTIVITIES);

        setupForRequiredProvisioning();
        assertTrue(mTethering.isTetheringSupported());
        verify(mPackageManager).getPackageInfo(PROVISIONING_APP_NAME[0], GET_ACTIVITIES);
        reset(mPackageManager);

        doThrow(PackageManager.NameNotFoundException.class).when(mPackageManager).getPackageInfo(
                PROVISIONING_APP_NAME[0], GET_ACTIVITIES);
        setupForRequiredProvisioning();
        assertFalse(mTethering.isTetheringSupported());
        verify(mPackageManager).getPackageInfo(PROVISIONING_APP_NAME[0], GET_ACTIVITIES);
    }

    // TODO: Test that a request for hotspot mode doesn't interfere with an
    // already operating tethering mode interface.
}