bpf_base_test.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /*
  2. * Copyright (C) 2018 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. #include <string>
  17. #include <fcntl.h>
  18. #include <inttypes.h>
  19. #include <limits.h>
  20. #include <linux/inet_diag.h>
  21. #include <linux/sock_diag.h>
  22. #include <net/if.h>
  23. #include <sys/socket.h>
  24. #include <sys/types.h>
  25. #include <unistd.h>
  26. #include <gtest/gtest.h>
  27. #include <cutils/qtaguid.h>
  28. #include <processgroup/processgroup.h>
  29. #include <android-base/stringprintf.h>
  30. #include <android-base/strings.h>
  31. #include "bpf/BpfMap.h"
  32. #include "bpf/BpfUtils.h"
  33. #include "netdbpf/bpf_shared.h"
  34. using android::netdutils::StatusOr;
  35. namespace android {
  36. namespace bpf {
  37. // Use the upper limit of uid to avoid conflict with real app uids. We can't use UID_MAX because
  38. // it's -1, which is INVALID_UID.
  39. constexpr uid_t TEST_UID = UID_MAX - 1;
  40. constexpr uint32_t TEST_TAG = 42;
  41. constexpr int TEST_COUNTERSET = 1;
  42. constexpr int DEFAULT_COUNTERSET = 0;
  43. #define SKIP_IF_EXTENDED_BPF_NOT_SUPPORTED \
  44. do { \
  45. if (android::bpf::getBpfSupportLevel() != android::bpf::BpfLevel::EXTENDED) { \
  46. GTEST_LOG_(INFO) << "This test is skipped since extended bpf feature" \
  47. << "not supported\n"; \
  48. return; \
  49. } \
  50. } while (0)
  51. class BpfBasicTest : public testing::Test {
  52. protected:
  53. BpfBasicTest() {}
  54. };
  55. TEST_F(BpfBasicTest, TestCgroupMounted) {
  56. SKIP_IF_BPF_NOT_SUPPORTED;
  57. std::string cg2_path;
  58. ASSERT_EQ(true, CgroupGetControllerPath(CGROUPV2_CONTROLLER_NAME, &cg2_path));
  59. ASSERT_EQ(0, access(cg2_path.c_str(), R_OK));
  60. ASSERT_EQ(0, access((cg2_path + "/cgroup.controllers").c_str(), R_OK));
  61. }
  62. TEST_F(BpfBasicTest, TestTrafficControllerSetUp) {
  63. SKIP_IF_BPF_NOT_SUPPORTED;
  64. ASSERT_EQ(0, access(BPF_EGRESS_PROG_PATH, R_OK));
  65. ASSERT_EQ(0, access(BPF_INGRESS_PROG_PATH, R_OK));
  66. ASSERT_EQ(0, access(XT_BPF_INGRESS_PROG_PATH, R_OK));
  67. ASSERT_EQ(0, access(XT_BPF_EGRESS_PROG_PATH, R_OK));
  68. ASSERT_EQ(0, access(COOKIE_TAG_MAP_PATH, R_OK));
  69. ASSERT_EQ(0, access(UID_COUNTERSET_MAP_PATH, R_OK));
  70. ASSERT_EQ(0, access(STATS_MAP_A_PATH, R_OK));
  71. ASSERT_EQ(0, access(STATS_MAP_B_PATH, R_OK));
  72. ASSERT_EQ(0, access(IFACE_INDEX_NAME_MAP_PATH, R_OK));
  73. ASSERT_EQ(0, access(IFACE_STATS_MAP_PATH, R_OK));
  74. ASSERT_EQ(0, access(CONFIGURATION_MAP_PATH, R_OK));
  75. ASSERT_EQ(0, access(UID_OWNER_MAP_PATH, R_OK));
  76. }
  77. TEST_F(BpfBasicTest, TestSocketFilterSetUp) {
  78. SKIP_IF_EXTENDED_BPF_NOT_SUPPORTED;
  79. ASSERT_EQ(0, access(CGROUP_SOCKET_PROG_PATH, R_OK));
  80. ASSERT_EQ(0, access(UID_PERMISSION_MAP_PATH, R_OK));
  81. }
  82. TEST_F(BpfBasicTest, TestTagSocket) {
  83. SKIP_IF_BPF_NOT_SUPPORTED;
  84. BpfMap<uint64_t, UidTag> cookieTagMap(mapRetrieve(COOKIE_TAG_MAP_PATH, 0));
  85. ASSERT_LE(0, cookieTagMap.getMap());
  86. int sock = socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0);
  87. ASSERT_LE(0, sock);
  88. uint64_t cookie = getSocketCookie(sock);
  89. ASSERT_NE(NONEXISTENT_COOKIE, cookie);
  90. ASSERT_EQ(0, qtaguid_tagSocket(sock, TEST_TAG, TEST_UID));
  91. StatusOr<UidTag> tagResult = cookieTagMap.readValue(cookie);
  92. ASSERT_TRUE(isOk(tagResult));
  93. ASSERT_EQ(TEST_UID, tagResult.value().uid);
  94. ASSERT_EQ(TEST_TAG, tagResult.value().tag);
  95. ASSERT_EQ(0, qtaguid_untagSocket(sock));
  96. tagResult = cookieTagMap.readValue(cookie);
  97. ASSERT_FALSE(isOk(tagResult));
  98. ASSERT_EQ(ENOENT, tagResult.status().code());
  99. }
  100. TEST_F(BpfBasicTest, TestCloseSocketWithoutUntag) {
  101. SKIP_IF_BPF_NOT_SUPPORTED;
  102. BpfMap<uint64_t, UidTag> cookieTagMap(mapRetrieve(COOKIE_TAG_MAP_PATH, 0));
  103. ASSERT_LE(0, cookieTagMap.getMap());
  104. int sock = socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0);
  105. ASSERT_LE(0, sock);
  106. uint64_t cookie = getSocketCookie(sock);
  107. ASSERT_NE(NONEXISTENT_COOKIE, cookie);
  108. ASSERT_EQ(0, qtaguid_tagSocket(sock, TEST_TAG, TEST_UID));
  109. StatusOr<UidTag> tagResult = cookieTagMap.readValue(cookie);
  110. ASSERT_TRUE(isOk(tagResult));
  111. ASSERT_EQ(TEST_UID, tagResult.value().uid);
  112. ASSERT_EQ(TEST_TAG, tagResult.value().tag);
  113. ASSERT_EQ(0, close(sock));
  114. // Check map periodically until sk destroy handler have done its job.
  115. for (int i = 0; i < 10; i++) {
  116. usleep(5000); // 5ms
  117. tagResult = cookieTagMap.readValue(cookie);
  118. if (!isOk(tagResult)) {
  119. ASSERT_EQ(ENOENT, tagResult.status().code());
  120. return;
  121. }
  122. }
  123. FAIL() << "socket tag still exist after 50ms";
  124. }
  125. TEST_F(BpfBasicTest, TestChangeCounterSet) {
  126. SKIP_IF_BPF_NOT_SUPPORTED;
  127. BpfMap<uint32_t, uint8_t> uidCounterSetMap(mapRetrieve(UID_COUNTERSET_MAP_PATH, 0));
  128. ASSERT_LE(0, uidCounterSetMap.getMap());
  129. ASSERT_EQ(0, qtaguid_setCounterSet(TEST_COUNTERSET, TEST_UID));
  130. uid_t uid = TEST_UID;
  131. StatusOr<uint8_t> counterSetResult = uidCounterSetMap.readValue(uid);
  132. ASSERT_TRUE(isOk(counterSetResult));
  133. ASSERT_EQ(TEST_COUNTERSET, counterSetResult.value());
  134. ASSERT_EQ(0, qtaguid_setCounterSet(DEFAULT_COUNTERSET, TEST_UID));
  135. counterSetResult = uidCounterSetMap.readValue(uid);
  136. ASSERT_FALSE(isOk(counterSetResult));
  137. ASSERT_EQ(ENOENT, counterSetResult.status().code());
  138. }
  139. TEST_F(BpfBasicTest, TestDeleteTagData) {
  140. SKIP_IF_BPF_NOT_SUPPORTED;
  141. BpfMap<StatsKey, StatsValue> statsMapA(mapRetrieve(STATS_MAP_A_PATH, 0));
  142. ASSERT_LE(0, statsMapA.getMap());
  143. BpfMap<StatsKey, StatsValue> statsMapB(mapRetrieve(STATS_MAP_B_PATH, 0));
  144. ASSERT_LE(0, statsMapB.getMap());
  145. BpfMap<uint32_t, StatsValue> appUidStatsMap(mapRetrieve(APP_UID_STATS_MAP_PATH, 0));
  146. ASSERT_LE(0, appUidStatsMap.getMap());
  147. StatsKey key = {.uid = TEST_UID, .tag = TEST_TAG, .counterSet = TEST_COUNTERSET,
  148. .ifaceIndex = 1};
  149. StatsValue statsMapValue = {.rxPackets = 1, .rxBytes = 100};
  150. EXPECT_TRUE(isOk(statsMapB.writeValue(key, statsMapValue, BPF_ANY)));
  151. key.tag = 0;
  152. EXPECT_TRUE(isOk(statsMapA.writeValue(key, statsMapValue, BPF_ANY)));
  153. EXPECT_TRUE(isOk(appUidStatsMap.writeValue(TEST_UID, statsMapValue, BPF_ANY)));
  154. ASSERT_EQ(0, qtaguid_deleteTagData(0, TEST_UID));
  155. StatusOr<StatsValue> statsResult = statsMapA.readValue(key);
  156. ASSERT_FALSE(isOk(statsResult));
  157. ASSERT_EQ(ENOENT, statsResult.status().code());
  158. statsResult = appUidStatsMap.readValue(TEST_UID);
  159. ASSERT_FALSE(isOk(statsResult));
  160. ASSERT_EQ(ENOENT, statsResult.status().code());
  161. key.tag = TEST_TAG;
  162. statsResult = statsMapB.readValue(key);
  163. ASSERT_FALSE(isOk(statsResult));
  164. ASSERT_EQ(ENOENT, statsResult.status().code());
  165. }
  166. }
  167. }