blob: 6e35d07efde138586f92c47ba5531d933a709bef [file] [log] [blame]
Ken Chenc52cbe02022-07-29 03:30:25 +08001/*
2 * Copyright (C) 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 */
17
18#include "firewall.h"
19
20#include <android-base/result.h>
21#include <gtest/gtest.h>
22
23Firewall::Firewall() {
24 std::lock_guard guard(mMutex);
25 auto result = mConfigurationMap.init(CONFIGURATION_MAP_PATH);
26 EXPECT_RESULT_OK(result) << "init mConfigurationMap failed";
27
28 result = mUidOwnerMap.init(UID_OWNER_MAP_PATH);
29 EXPECT_RESULT_OK(result) << "init mUidOwnerMap failed";
Ken Chen5b144a12023-10-26 14:00:23 +080030
31 result = mDataSaverEnabledMap.init(DATA_SAVER_ENABLED_MAP_PATH);
32 EXPECT_RESULT_OK(result) << "init mDataSaverEnabledMap failed";
Ken Chenc52cbe02022-07-29 03:30:25 +080033}
34
35Firewall* Firewall::getInstance() {
36 static Firewall instance;
37 return &instance;
38}
39
40Result<void> Firewall::toggleStandbyMatch(bool enable) {
41 std::lock_guard guard(mMutex);
42 uint32_t key = UID_RULES_CONFIGURATION_KEY;
43 auto oldConfiguration = mConfigurationMap.readValue(key);
44 if (!oldConfiguration.ok()) {
45 return Errorf("Cannot read the old configuration: {}", oldConfiguration.error().message());
46 }
47
48 BpfConfig newConfiguration = enable ? (oldConfiguration.value() | STANDBY_MATCH)
49 : (oldConfiguration.value() & (~STANDBY_MATCH));
50 auto res = mConfigurationMap.writeValue(key, newConfiguration, BPF_EXIST);
51 if (!res.ok()) return Errorf("Failed to toggle STANDBY_MATCH: {}", res.error().message());
52
53 return {};
54}
55
56Result<void> Firewall::addRule(uint32_t uid, UidOwnerMatchType match, uint32_t iif) {
57 // iif should be non-zero if and only if match == MATCH_IIF
58 if (match == IIF_MATCH && iif == 0) {
59 return Errorf("Interface match {} must have nonzero interface index", match);
60 } else if (match != IIF_MATCH && iif != 0) {
61 return Errorf("Non-interface match {} must have zero interface index", match);
62 }
63
64 std::lock_guard guard(mMutex);
65 auto oldMatch = mUidOwnerMap.readValue(uid);
66 if (oldMatch.ok()) {
67 UidOwnerValue newMatch = {
68 .iif = iif ? iif : oldMatch.value().iif,
69 .rule = static_cast<uint8_t>(oldMatch.value().rule | match),
70 };
71 auto res = mUidOwnerMap.writeValue(uid, newMatch, BPF_ANY);
72 if (!res.ok()) return Errorf("Failed to update rule: {}", res.error().message());
73 } else {
74 UidOwnerValue newMatch = {
75 .iif = iif,
76 .rule = static_cast<uint8_t>(match),
77 };
78 auto res = mUidOwnerMap.writeValue(uid, newMatch, BPF_ANY);
79 if (!res.ok()) return Errorf("Failed to add rule: {}", res.error().message());
80 }
81 return {};
82}
83
84Result<void> Firewall::removeRule(uint32_t uid, UidOwnerMatchType match) {
85 std::lock_guard guard(mMutex);
86 auto oldMatch = mUidOwnerMap.readValue(uid);
87 if (!oldMatch.ok()) return Errorf("uid: %u does not exist in map", uid);
88
89 UidOwnerValue newMatch = {
90 .iif = (match == IIF_MATCH) ? 0 : oldMatch.value().iif,
91 .rule = static_cast<uint8_t>(oldMatch.value().rule & ~match),
92 };
93 if (newMatch.rule == 0) {
94 auto res = mUidOwnerMap.deleteValue(uid);
95 if (!res.ok()) return Errorf("Failed to remove rule: {}", res.error().message());
96 } else {
97 auto res = mUidOwnerMap.writeValue(uid, newMatch, BPF_ANY);
98 if (!res.ok()) return Errorf("Failed to update rule: {}", res.error().message());
99 }
100 return {};
101}
102
103Result<void> Firewall::addUidInterfaceRules(const std::string& ifName,
104 const std::vector<int32_t>& uids) {
105 unsigned int iif = if_nametoindex(ifName.c_str());
106 if (!iif) return Errorf("Failed to get interface index: {}", ifName);
107
108 for (auto uid : uids) {
109 auto res = addRule(uid, IIF_MATCH, iif);
110 if (!res.ok()) return res;
111 }
112 return {};
113}
114
115Result<void> Firewall::removeUidInterfaceRules(const std::vector<int32_t>& uids) {
116 for (auto uid : uids) {
117 auto res = removeRule(uid, IIF_MATCH);
118 if (!res.ok()) return res;
119 }
120 return {};
121}
Ken Chen5b144a12023-10-26 14:00:23 +0800122
123Result<bool> Firewall::getDataSaverSetting() {
124 std::lock_guard guard(mMutex);
125 auto dataSaverSetting = mDataSaverEnabledMap.readValue(DATA_SAVER_ENABLED_KEY);
126 if (!dataSaverSetting.ok()) {
127 return Errorf("Cannot read the data saver setting: {}", dataSaverSetting.error().message());
128 }
129 return dataSaverSetting;
130}
131
132Result<void> Firewall::setDataSaver(bool enabled) {
133 std::lock_guard guard(mMutex);
134 auto res = mDataSaverEnabledMap.writeValue(DATA_SAVER_ENABLED_KEY, enabled, BPF_EXIST);
135 if (!res.ok()) return Errorf("Failed to set data saver: {}", res.error().message());
136
137 return {};
138}