Merge "Log bpf rc file if it differs from the template files." into main
This commit is contained in:
commit
8670809d7f
5 changed files with 243 additions and 0 deletions
161
service/src/com/android/server/BpfLoaderRcUtils.java
Normal file
161
service/src/com/android/server/BpfLoaderRcUtils.java
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.modules.utils.build.SdkLevel;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* BpfRcUtils is responsible for comparing the bpf loader rc file.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public class BpfLoaderRcUtils {
|
||||
public static final String TAG = BpfLoaderRcUtils.class.getSimpleName();
|
||||
|
||||
private static final List<String> BPF_LOADER_RC_S_T = List.of(
|
||||
"service bpfloader /system/bin/bpfloader",
|
||||
"capabilities CHOWN SYS_ADMIN NET_ADMIN",
|
||||
"rlimit memlock 1073741824 1073741824",
|
||||
"oneshot",
|
||||
"reboot_on_failure reboot,bpfloader-failed",
|
||||
"updatable"
|
||||
);
|
||||
|
||||
private static final List<String> BPF_LOADER_RC_U = List.of(
|
||||
"service bpfloader /system/bin/bpfloader",
|
||||
"capabilities CHOWN SYS_ADMIN NET_ADMIN",
|
||||
"group root graphics network_stack net_admin net_bw_acct net_bw_stats net_raw system",
|
||||
"user root",
|
||||
"rlimit memlock 1073741824 1073741824",
|
||||
"oneshot",
|
||||
"reboot_on_failure reboot,bpfloader-failed",
|
||||
"updatable"
|
||||
);
|
||||
|
||||
private static final List<String> BPF_LOADER_RC_UQPR2 = List.of(
|
||||
"service bpfloader /system/bin/netbpfload",
|
||||
"capabilities CHOWN SYS_ADMIN NET_ADMIN",
|
||||
"group root graphics network_stack net_admin net_bw_acct net_bw_stats net_raw system",
|
||||
"user root",
|
||||
"rlimit memlock 1073741824 1073741824",
|
||||
"oneshot",
|
||||
"reboot_on_failure reboot,bpfloader-failed",
|
||||
"updatable"
|
||||
);
|
||||
|
||||
|
||||
private static final String BPF_LOADER_RC_FILE_PATH = "/etc/init/bpfloader.rc";
|
||||
private static final String NET_BPF_LOAD_RC_FILE_PATH = "/etc/init/netbpfload.rc";
|
||||
|
||||
private BpfLoaderRcUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the bpf rc file content from the input stream.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public static List<String> loadExistingBpfRcFile(@NonNull InputStream inputStream) {
|
||||
List<String> contents = new ArrayList<>();
|
||||
boolean bpfSectionFound = false;
|
||||
try (BufferedReader br = new BufferedReader(
|
||||
new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
line = line.trim();
|
||||
if (line.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (line.startsWith("#")) {
|
||||
continue;
|
||||
}
|
||||
// If bpf service section was found and new service or action section start. The
|
||||
// read should stop.
|
||||
if (bpfSectionFound && (line.startsWith("service ") || (line.startsWith("on ")))) {
|
||||
break;
|
||||
}
|
||||
if (line.startsWith("service bpfloader ")) {
|
||||
bpfSectionFound = true;
|
||||
}
|
||||
if (bpfSectionFound) {
|
||||
contents.add(line);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.wtf("read input stream failed.", e);
|
||||
contents.clear();
|
||||
return contents;
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the bpfLoader rc file on the system image matches any of the template files.
|
||||
*/
|
||||
public static boolean checkBpfLoaderRc() {
|
||||
File bpfRcFile = new File(BPF_LOADER_RC_FILE_PATH);
|
||||
if (!bpfRcFile.exists()) {
|
||||
if (SdkLevel.isAtLeastU()) {
|
||||
bpfRcFile = new File(NET_BPF_LOAD_RC_FILE_PATH);
|
||||
}
|
||||
if (!bpfRcFile.exists()) {
|
||||
Log.wtf(TAG,
|
||||
"neither " + BPF_LOADER_RC_FILE_PATH + " nor " + NET_BPF_LOAD_RC_FILE_PATH
|
||||
+ " exist.");
|
||||
return false;
|
||||
}
|
||||
// Check bpf rc file in U QPR2
|
||||
return compareBpfLoaderRc(bpfRcFile, BPF_LOADER_RC_UQPR2);
|
||||
}
|
||||
|
||||
if (SdkLevel.isAtLeastU()) {
|
||||
// Check bpf rc file in U
|
||||
return compareBpfLoaderRc(bpfRcFile, BPF_LOADER_RC_U);
|
||||
}
|
||||
// Check bpf rc file in S/T
|
||||
return compareBpfLoaderRc(bpfRcFile, BPF_LOADER_RC_S_T);
|
||||
}
|
||||
|
||||
private static boolean compareBpfLoaderRc(@NonNull File bpfRcFile,
|
||||
@NonNull List<String> template) {
|
||||
try {
|
||||
List<String> actualContent = loadExistingBpfRcFile(new FileInputStream(bpfRcFile));
|
||||
if (!actualContent.equals(template)) {
|
||||
Log.wtf(TAG, "BPF rc file is not same as the template files " + actualContent);
|
||||
return false;
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.wtf(bpfRcFile.getPath() + " doesn't exist.", e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1876,6 +1876,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
activityManager.registerUidFrozenStateChangedCallback(
|
||||
(Runnable r) -> r.run(), frozenStateChangedCallback);
|
||||
}
|
||||
|
||||
if (mDeps.isFeatureNotChickenedOut(mContext, LOG_BPF_RC)) {
|
||||
mHandler.post(BpfLoaderRcUtils::checkBpfLoaderRc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -3335,6 +3339,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
public static final String ALLOW_SYSUI_CONNECTIVITY_REPORTS =
|
||||
"allow_sysui_connectivity_reports";
|
||||
|
||||
public static final String LOG_BPF_RC = "log_bpf_rc_force_disable";
|
||||
|
||||
private void enforceInternetPermission() {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
android.Manifest.permission.INTERNET,
|
||||
|
|
|
|||
72
tests/unit/java/com/android/server/BpfLoaderRcUtilsTest.kt
Normal file
72
tests/unit/java/com/android/server/BpfLoaderRcUtilsTest.kt
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server
|
||||
|
||||
import android.os.Build
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
|
||||
import com.android.testutils.DevSdkIgnoreRunner
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(DevSdkIgnoreRunner::class)
|
||||
@SmallTest
|
||||
@IgnoreUpTo(Build.VERSION_CODES.S)
|
||||
class BpfLoaderRcUtilsTest {
|
||||
@Test
|
||||
fun testLoadExistingBpfRcFile() {
|
||||
|
||||
val inputString = """
|
||||
service a
|
||||
# test comment
|
||||
service bpfloader /system/bin/bpfloader
|
||||
capabilities CHOWN SYS_ADMIN NET_ADMIN
|
||||
group root graphics network_stack net_admin net_bw_acct net_bw_stats net_raw system
|
||||
user root
|
||||
rlimit memlock 1073741824 1073741824
|
||||
oneshot
|
||||
# comment 漢字
|
||||
reboot_on_failure reboot,bpfloader-failed
|
||||
updatable
|
||||
|
||||
#test comment
|
||||
on b
|
||||
oneshot
|
||||
# test comment
|
||||
""".trimIndent()
|
||||
val expectedResult = listOf(
|
||||
"service bpfloader /system/bin/bpfloader",
|
||||
"capabilities CHOWN SYS_ADMIN NET_ADMIN",
|
||||
"group root graphics network_stack net_admin net_bw_acct net_bw_stats net_raw system",
|
||||
"user root",
|
||||
"rlimit memlock 1073741824 1073741824",
|
||||
"oneshot",
|
||||
"reboot_on_failure reboot,bpfloader-failed",
|
||||
"updatable"
|
||||
)
|
||||
|
||||
assertEquals(expectedResult,
|
||||
BpfLoaderRcUtils.loadExistingBpfRcFile(inputString.byteInputStream()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCheckBpfRcFile() {
|
||||
assertTrue(BpfLoaderRcUtils.checkBpfLoaderRc())
|
||||
}
|
||||
}
|
||||
|
|
@ -161,6 +161,7 @@ import static com.android.server.ConnectivityService.DELAY_DESTROY_FROZEN_SOCKET
|
|||
import static com.android.net.module.util.DeviceConfigUtils.TETHERING_MODULE_NAME;
|
||||
import static com.android.server.ConnectivityService.ALLOW_SYSUI_CONNECTIVITY_REPORTS;
|
||||
import static com.android.server.ConnectivityService.KEY_DESTROY_FROZEN_SOCKETS_VERSION;
|
||||
import static com.android.server.ConnectivityService.LOG_BPF_RC;
|
||||
import static com.android.server.ConnectivityService.MAX_NETWORK_REQUESTS_PER_SYSTEM_UID;
|
||||
import static com.android.server.ConnectivityService.PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED;
|
||||
import static com.android.server.ConnectivityService.PREFERENCE_ORDER_OEM;
|
||||
|
|
@ -2157,6 +2158,8 @@ public class ConnectivityServiceTest {
|
|||
switch (name) {
|
||||
case ALLOW_SYSUI_CONNECTIVITY_REPORTS:
|
||||
return true;
|
||||
case LOG_BPF_RC:
|
||||
return true;
|
||||
default:
|
||||
return super.isFeatureNotChickenedOut(context, name);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ open class CSTest {
|
|||
it[ConnectivityService.KEY_DESTROY_FROZEN_SOCKETS_VERSION] = true
|
||||
it[ConnectivityService.DELAY_DESTROY_FROZEN_SOCKETS_VERSION] = true
|
||||
it[ConnectivityService.ALLOW_SYSUI_CONNECTIVITY_REPORTS] = true
|
||||
it[ConnectivityService.LOG_BPF_RC] = true
|
||||
}
|
||||
fun enableFeature(f: String) = enabledFeatures.set(f, true)
|
||||
fun disableFeature(f: String) = enabledFeatures.set(f, false)
|
||||
|
|
|
|||
Loading…
Reference in a new issue