| Maciej Żenczykowski | 438e4a8 | 2022-12-08 16:35:25 +0000 | [diff] [blame] | 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 |  | 
 | 17 | #include <string> | 
 | 18 |  | 
 | 19 | #include <fcntl.h> | 
 | 20 | #include <inttypes.h> | 
 | 21 | #include <limits.h> | 
 | 22 | #include <linux/inet_diag.h> | 
 | 23 | #include <linux/sock_diag.h> | 
 | 24 | #include <net/if.h> | 
 | 25 | #include <sys/socket.h> | 
 | 26 | #include <sys/types.h> | 
 | 27 | #include <unistd.h> | 
 | 28 |  | 
 | 29 | #include <gtest/gtest.h> | 
 | 30 |  | 
 | 31 | #include <cutils/qtaguid.h> | 
 | 32 | #include <processgroup/processgroup.h> | 
 | 33 |  | 
 | 34 | #include <android-base/stringprintf.h> | 
 | 35 | #include <android-base/strings.h> | 
 | 36 | #include <netdutils/NetNativeTestBase.h> | 
 | 37 |  | 
 | 38 | #include "bpf/BpfMap.h" | 
 | 39 | #include "bpf/BpfUtils.h" | 
| Maciej Żenczykowski | 3b67343 | 2022-12-18 20:26:12 +0000 | [diff] [blame] | 40 | #include "netd.h" | 
| Maciej Żenczykowski | 438e4a8 | 2022-12-08 16:35:25 +0000 | [diff] [blame] | 41 |  | 
 | 42 | using android::base::Result; | 
 | 43 |  | 
 | 44 | namespace android { | 
 | 45 | namespace bpf { | 
 | 46 |  | 
 | 47 | // Use the upper limit of uid to avoid conflict with real app uids. We can't use UID_MAX because | 
 | 48 | // it's -1, which is INVALID_UID. | 
 | 49 | constexpr uid_t TEST_UID = UID_MAX - 1; | 
 | 50 | constexpr uint32_t TEST_TAG = 42; | 
 | 51 |  | 
 | 52 | class BpfBasicTest : public NetNativeTestBase { | 
 | 53 |   protected: | 
 | 54 |     BpfBasicTest() {} | 
 | 55 | }; | 
 | 56 |  | 
 | 57 | TEST_F(BpfBasicTest, TestCgroupMounted) { | 
 | 58 |     std::string cg2_path; | 
 | 59 |     ASSERT_EQ(true, CgroupGetControllerPath(CGROUPV2_CONTROLLER_NAME, &cg2_path)); | 
 | 60 |     ASSERT_EQ(0, access(cg2_path.c_str(), R_OK)); | 
 | 61 |     ASSERT_EQ(0, access((cg2_path + "/cgroup.controllers").c_str(), R_OK)); | 
 | 62 | } | 
 | 63 |  | 
| Maciej Żenczykowski | 438e4a8 | 2022-12-08 16:35:25 +0000 | [diff] [blame] | 64 | TEST_F(BpfBasicTest, TestTagSocket) { | 
 | 65 |     BpfMap<uint64_t, UidTagValue> cookieTagMap(COOKIE_TAG_MAP_PATH); | 
 | 66 |     ASSERT_TRUE(cookieTagMap.isValid()); | 
 | 67 |     int sock = socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0); | 
 | 68 |     ASSERT_LE(0, sock); | 
 | 69 |     uint64_t cookie = getSocketCookie(sock); | 
 | 70 |     ASSERT_NE(NONEXISTENT_COOKIE, cookie); | 
 | 71 |     ASSERT_EQ(0, qtaguid_tagSocket(sock, TEST_TAG, TEST_UID)); | 
 | 72 |     Result<UidTagValue> tagResult = cookieTagMap.readValue(cookie); | 
 | 73 |     ASSERT_RESULT_OK(tagResult); | 
 | 74 |     ASSERT_EQ(TEST_UID, tagResult.value().uid); | 
 | 75 |     ASSERT_EQ(TEST_TAG, tagResult.value().tag); | 
 | 76 |     ASSERT_EQ(0, qtaguid_untagSocket(sock)); | 
 | 77 |     tagResult = cookieTagMap.readValue(cookie); | 
 | 78 |     ASSERT_FALSE(tagResult.ok()); | 
 | 79 |     ASSERT_EQ(ENOENT, tagResult.error().code()); | 
 | 80 | } | 
 | 81 |  | 
 | 82 | TEST_F(BpfBasicTest, TestCloseSocketWithoutUntag) { | 
 | 83 |     BpfMap<uint64_t, UidTagValue> cookieTagMap(COOKIE_TAG_MAP_PATH); | 
 | 84 |     ASSERT_TRUE(cookieTagMap.isValid()); | 
 | 85 |     int sock = socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0); | 
 | 86 |     ASSERT_LE(0, sock); | 
 | 87 |     uint64_t cookie = getSocketCookie(sock); | 
 | 88 |     ASSERT_NE(NONEXISTENT_COOKIE, cookie); | 
 | 89 |     ASSERT_EQ(0, qtaguid_tagSocket(sock, TEST_TAG, TEST_UID)); | 
 | 90 |     Result<UidTagValue> tagResult = cookieTagMap.readValue(cookie); | 
 | 91 |     ASSERT_RESULT_OK(tagResult); | 
 | 92 |     ASSERT_EQ(TEST_UID, tagResult.value().uid); | 
 | 93 |     ASSERT_EQ(TEST_TAG, tagResult.value().tag); | 
 | 94 |     ASSERT_EQ(0, close(sock)); | 
 | 95 |     // Check map periodically until sk destroy handler have done its job. | 
| Maciej Żenczykowski | 3bf75ef | 2023-05-15 18:48:18 +0000 | [diff] [blame] | 96 |     for (int i = 0; i < 1000; i++) { | 
| Maciej Żenczykowski | 438e4a8 | 2022-12-08 16:35:25 +0000 | [diff] [blame] | 97 |         usleep(5000);  // 5ms | 
 | 98 |         tagResult = cookieTagMap.readValue(cookie); | 
 | 99 |         if (!tagResult.ok()) { | 
 | 100 |             ASSERT_EQ(ENOENT, tagResult.error().code()); | 
 | 101 |             return; | 
 | 102 |         } | 
 | 103 |     } | 
| Maciej Żenczykowski | 3bf75ef | 2023-05-15 18:48:18 +0000 | [diff] [blame] | 104 |     FAIL() << "socket tag still exist after 5s"; | 
| Maciej Żenczykowski | 438e4a8 | 2022-12-08 16:35:25 +0000 | [diff] [blame] | 105 | } | 
 | 106 |  | 
 | 107 | } | 
 | 108 | } |