blob: 5e3df5711b80f83c3cd139de99727725a3b2dd08 [file] [log] [blame]
Lorenzo Colitti3b38b122022-01-12 16:06:07 +09001/*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * bpf_existence_test.cpp - checks that the device runs expected BPF programs
17 */
18
19#include <cstdint>
20#include <string>
21#include <vector>
22
23#include <android-base/strings.h>
24#include <android-base/properties.h>
25#include <android-modules-utils/sdk_level.h>
26
27#include <gtest/gtest.h>
28
29using std::find;
30using std::string;
31using std::vector;
32
33using android::modules::sdklevel::IsAtLeastR;
34using android::modules::sdklevel::IsAtLeastS;
35using android::modules::sdklevel::IsAtLeastT;
36
37class BpfExistenceTest : public ::testing::Test {
38};
39
40static const vector<string> INTRODUCED_R = {
41 "/sys/fs/bpf/prog_offload_schedcls_ingress_tether_ether",
42 "/sys/fs/bpf/prog_offload_schedcls_ingress_tether_rawip",
43};
44
45static const vector<string> INTRODUCED_S = {
46 "/sys/fs/bpf/tethering/prog_offload_schedcls_tether_downstream4_ether",
47 "/sys/fs/bpf/tethering/prog_offload_schedcls_tether_downstream4_rawip",
48 "/sys/fs/bpf/tethering/prog_offload_schedcls_tether_downstream6_ether",
49 "/sys/fs/bpf/tethering/prog_offload_schedcls_tether_downstream6_rawip",
50 "/sys/fs/bpf/tethering/prog_offload_schedcls_tether_upstream4_ether",
51 "/sys/fs/bpf/tethering/prog_offload_schedcls_tether_upstream4_rawip",
52 "/sys/fs/bpf/tethering/prog_offload_schedcls_tether_upstream6_ether",
53 "/sys/fs/bpf/tethering/prog_offload_schedcls_tether_upstream6_rawip",
54};
55
56static const vector<string> REMOVED_S = {
57 "/sys/fs/bpf/prog_offload_schedcls_ingress_tether_ether",
58 "/sys/fs/bpf/prog_offload_schedcls_ingress_tether_rawip",
59};
60
61static const vector<string> INTRODUCED_T = {
62};
63
64static const vector<string> REMOVED_T = {
65};
66
67void addAll(vector<string>* a, const vector<string>& b) {
68 a->insert(a->end(), b.begin(), b.end());
69}
70
71void removeAll(vector<string>* a, const vector<string> b) {
72 for (const auto& toRemove : b) {
73 auto iter = find(a->begin(), a->end(), toRemove);
74 while (iter != a->end()) {
75 a->erase(iter);
76 iter = find(a->begin(), a->end(), toRemove);
77 }
78 }
79}
80
81void getFileLists(vector<string>* expected, vector<string>* unexpected) {
82 unexpected->clear();
83 expected->clear();
84
85 addAll(unexpected, INTRODUCED_R);
86 addAll(unexpected, INTRODUCED_S);
87 addAll(unexpected, INTRODUCED_T);
88
89 if (IsAtLeastR()) {
90 addAll(expected, INTRODUCED_R);
91 removeAll(unexpected, INTRODUCED_R);
92 // Nothing removed in R.
93 }
94
95 if (IsAtLeastS()) {
96 addAll(expected, INTRODUCED_S);
97 removeAll(expected, REMOVED_S);
98
99 addAll(unexpected, REMOVED_S);
100 removeAll(unexpected, INTRODUCED_S);
101 }
102
103 // Nothing added or removed in SCv2.
104
105 if (IsAtLeastT()) {
106 addAll(expected, INTRODUCED_T);
107 removeAll(expected, REMOVED_T);
108
109 addAll(unexpected, REMOVED_T);
110 removeAll(unexpected, INTRODUCED_T);
111 }
112}
113
114void checkFiles() {
115 vector<string> mustExist;
116 vector<string> mustNotExist;
117
118 getFileLists(&mustExist, &mustNotExist);
119
120 for (const auto& file : mustExist) {
121 EXPECT_EQ(0, access(file.c_str(), R_OK)) << file << " does not exist";
122 }
123 for (const auto& file : mustNotExist) {
124 int ret = access(file.c_str(), R_OK);
125 int err = errno;
126 EXPECT_EQ(-1, ret) << file << " unexpectedly exists";
127 if (ret == -1) {
128 EXPECT_EQ(ENOENT, err) << " accessing " << file << " failed with errno " << err;
129 }
130 }
131}
132
133TEST_F(BpfExistenceTest, TestPrograms) {
134 // Pre-flight check to ensure test has been updated.
135 uint64_t buildVersionSdk = android::base::GetUintProperty<uint64_t>("ro.build.version.sdk", 0);
136 ASSERT_NE(0, buildVersionSdk) << "Unable to determine device SDK version";
137 if (buildVersionSdk > 33 && buildVersionSdk != 10000) {
138 FAIL() << "Unknown OS version " << buildVersionSdk << ", please update this test";
139 }
140
141 // Only unconfined root is guaranteed to be able to access everything in /sys/fs/bpf.
142 ASSERT_EQ(0, getuid()) << "This test must run as root.";
143
144 checkFiles();
145}