From 47c7440d8fae832ef643743bfd304e89e253a43f Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 6 Jan 2017 10:25:02 +0900 Subject: [PATCH 1/2] Restore the net.dnsX system properties. In order to avoid app breakage, we are putting back the system properties and using selinux to disallow access from apps targeting the O SDK or above. This CL is cherry-picked from internal commit 443b6c40495aaf62114424053bb2f432abf8faa5, but with a different commit description. Bug: 33308258 Bug: 33807046 Bug: 34028616 Bug: 34115651 Test: system properties are readable as root and shell Change-Id: I8d51e8e0a620d581c4251fb2f3c1d0a813b929be --- .../android/server/ConnectivityService.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index d23347fd99..3eb800d1fc 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -4564,9 +4564,28 @@ public class ConnectivityService extends IConnectivityManager.Stub } catch (Exception e) { loge("Exception in setDnsConfigurationForNetwork: " + e); } + final NetworkAgentInfo defaultNai = getDefaultNetwork(); + if (defaultNai != null && defaultNai.network.netId == netId) { + setDefaultDnsSystemProperties(dnses); + } flushVmDnsCache(); } + private void setDefaultDnsSystemProperties(Collection dnses) { + int last = 0; + for (InetAddress dns : dnses) { + ++last; + String key = "net.dns" + last; + String value = dns.getHostAddress(); + SystemProperties.set(key, value); + } + for (int i = last + 1; i <= mNumDnsEntries; ++i) { + String key = "net.dns" + i; + SystemProperties.set(key, ""); + } + mNumDnsEntries = last; + } + private String getNetworkPermission(NetworkCapabilities nc) { // TODO: make these permission strings AIDL constants instead. if (!nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) { @@ -4783,6 +4802,7 @@ public class ConnectivityService extends IConnectivityManager.Stub notifyLockdownVpn(newNetwork); handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy()); updateTcpBufferSizes(newNetwork); + setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers()); } private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) { From cd447b2cdc898a3458a1fbec979af457210d226b Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 21 Mar 2017 18:54:11 +0900 Subject: [PATCH 2/2] Make ConnectivityServiceTest pass on wifi-only devices. Test: ConnectivityServiceTest passes on ryu on internal master Test: ConnectivityServiceTest passes on bullhead Change-Id: If94102c7df0257ea9e69e72b07a685ae3c2c4022 --- .../android/server/ConnectivityService.java | 30 ++++++------ .../server/ConnectivityServiceTest.java | 46 +++++++++++++++++-- 2 files changed, 60 insertions(+), 16 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 3eb800d1fc..ff079adc7c 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -96,7 +96,6 @@ import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.SystemClock; -import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -208,6 +207,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS private final int mReleasePendingIntentDelayMs; + private MockableSystemProperties mSystemProperties; + private Tethering mTethering; private final PermissionMonitor mPermissionMonitor; @@ -691,6 +692,8 @@ public class ConnectivityService extends IConnectivityManager.Stub IpConnectivityLog logger) { if (DBG) log("ConnectivityService starting up"); + mSystemProperties = getSystemProperties(); + mMetricsLog = logger; mDefaultRequest = createInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST); NetworkRequestInfo defaultNRI = new NetworkRequestInfo(null, mDefaultRequest, new Binder()); @@ -708,7 +711,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000); - mLingerDelayMs = SystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS); + mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS); mContext = checkNotNull(context, "missing Context"); mNetd = checkNotNull(netManager, "missing INetworkManagementService"); @@ -735,7 +738,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1]; // TODO: What is the "correct" way to do determine if this is a wifi only device? - boolean wifiOnly = SystemProperties.getBoolean("ro.radio.noril", false); + boolean wifiOnly = mSystemProperties.getBoolean("ro.radio.noril", false); log("wifiOnly=" + wifiOnly); String[] naStrings = context.getResources().getStringArray( com.android.internal.R.array.networkAttributes); @@ -788,8 +791,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - mTestMode = SystemProperties.get("cm.test.mode").equals("true") - && SystemProperties.get("ro.build.type").equals("eng"); + mTestMode = mSystemProperties.get("cm.test.mode").equals("true") + && mSystemProperties.get("ro.build.type").equals("eng"); mTethering = new Tethering(mContext, mNetd, statsService, mPolicyManager, IoThread.get().getLooper(), new MockableSystemProperties()); @@ -1823,8 +1826,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // Overridden for testing purposes to avoid writing to SystemProperties. @VisibleForTesting - protected int getDefaultTcpRwnd() { - return SystemProperties.getInt(DEFAULT_TCP_RWND_KEY, 0); + protected MockableSystemProperties getSystemProperties() { + return new MockableSystemProperties(); } private void updateTcpBufferSizes(NetworkAgentInfo nai) { @@ -1862,10 +1865,11 @@ public class ConnectivityService extends IConnectivityManager.Stub } Integer rwndValue = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.TCP_DEFAULT_INIT_RWND, getDefaultTcpRwnd()); + Settings.Global.TCP_DEFAULT_INIT_RWND, + mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)); final String sysctlKey = "sys.sysctl.tcp_def_init_rwnd"; if (rwndValue != 0) { - SystemProperties.set(sysctlKey, rwndValue.toString()); + mSystemProperties.set(sysctlKey, rwndValue.toString()); } } @@ -1889,7 +1893,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public int getRestoreDefaultNetworkDelay(int networkType) { - String restoreDefaultNetworkDelayStr = SystemProperties.get( + String restoreDefaultNetworkDelayStr = mSystemProperties.get( NETWORK_RESTORE_DELAY_PROP_NAME); if(restoreDefaultNetworkDelayStr != null && restoreDefaultNetworkDelayStr.length() != 0) { @@ -3078,7 +3082,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public boolean isTetheringSupported() { enforceTetherAccessPermission(); - int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1); + int defaultVal = (mSystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1); boolean tetherEnabledInSettings = (Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.TETHER_SUPPORTED, defaultVal) != 0) && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING); @@ -4577,11 +4581,11 @@ public class ConnectivityService extends IConnectivityManager.Stub ++last; String key = "net.dns" + last; String value = dns.getHostAddress(); - SystemProperties.set(key, value); + mSystemProperties.set(key, value); } for (int i = last + 1; i <= mNumDnsEntries; ++i) { String key = "net.dns" + i; - SystemProperties.set(key, ""); + mSystemProperties.set(key, ""); } mNumDnsEntries = last; } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index b03338205f..519e7ab944 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -23,7 +23,12 @@ import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.NetworkCapabilities.*; +import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; import android.app.NotificationManager; import android.app.PendingIntent; @@ -33,6 +38,7 @@ import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.IntentFilter; +import android.content.res.Resources; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; import android.net.ConnectivityManager.PacketKeepalive; @@ -76,11 +82,16 @@ import android.util.LogPrinter; import com.android.internal.util.WakeupMessage; import com.android.internal.util.test.BroadcastInterceptingContext; import com.android.internal.util.test.FakeSettingsProvider; +import com.android.server.connectivity.MockableSystemProperties; import com.android.server.connectivity.NetworkAgentInfo; import com.android.server.connectivity.NetworkMonitor; import com.android.server.connectivity.NetworkMonitor.CaptivePortalProbeResult; import com.android.server.net.NetworkPinner; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; + import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; @@ -133,8 +144,19 @@ public class ConnectivityServiceTest extends AndroidTestCase { private class MockContext extends BroadcastInterceptingContext { private final MockContentResolver mContentResolver; + @Spy private Resources mResources; + MockContext(Context base) { super(base); + + mResources = spy(base.getResources()); + when(mResources.getStringArray(com.android.internal.R.array.networkAttributes)). + thenReturn(new String[] { + "wifi,1,1,1,-1,true", + "mobile,0,0,0,-1,true", + "mobile_mms,2,0,2,60000,true", + }); + mContentResolver = new MockContentResolver(); mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); } @@ -150,6 +172,11 @@ public class ConnectivityServiceTest extends AndroidTestCase { public ContentResolver getContentResolver() { return mContentResolver; } + + @Override + public Resources getResources() { + return mResources; + } } /** @@ -614,6 +641,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { private class WrappedConnectivityService extends ConnectivityService { public WrappedMultinetworkPolicyTracker wrappedMultinetworkPolicyTracker; private WrappedNetworkMonitor mLastCreatedNetworkMonitor; + private MockableSystemProperties mSystemProperties; public WrappedConnectivityService(Context context, INetworkManagementService netManager, INetworkStatsService statsService, INetworkPolicyManager policyManager, @@ -623,9 +651,13 @@ public class ConnectivityServiceTest extends AndroidTestCase { } @Override - protected int getDefaultTcpRwnd() { - // Prevent wrapped ConnectivityService from trying to write to SystemProperties. - return 0; + protected MockableSystemProperties getSystemProperties() { + // Minimal approach to overriding system properties: let most calls fall through to real + // device values, and only override ones values that are important to this test. + mSystemProperties = spy(new MockableSystemProperties()); + when(mSystemProperties.getInt("net.tcp.default_init_rwnd", 0)).thenReturn(0); + when(mSystemProperties.getBoolean("ro.radio.noril", false)).thenReturn(false); + return mSystemProperties; } @Override @@ -795,6 +827,14 @@ public class ConnectivityServiceTest extends AndroidTestCase { return cv; } + public void testNetworkTypes() { + // Ensure that our mocks for the networkAttributes config variable work as expected. If they + // don't, then tests that depend on CONNECTIVITY_ACTION broadcasts for these network types + // will fail. Failing here is much easier to debug. + assertTrue(mCm.isNetworkSupported(TYPE_WIFI)); + assertTrue(mCm.isNetworkSupported(TYPE_MOBILE)); + } + @SmallTest public void testLingering() throws Exception { verifyNoNetwork();