blob: b3c6b025eab9b57a1ea6b9700510329f3f2f6aec [file] [log] [blame]
Jeff Sharkeyd8c64022012-07-13 18:04:07 -07001/*
2 * Copyright (C) 2012 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
Lorenzo Colitti1411d452017-07-17 22:12:15 +090017#include <set>
18
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070019#include <errno.h>
Hugo Benichi528d3d02018-06-20 13:35:58 +090020#include <limits.h>
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070021#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
Hugo Benichi528d3d02018-06-20 13:35:58 +090024#include <cstdint>
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070025
26#define LOG_TAG "FirewallController"
27#define LOG_NDEBUG 0
28
Hugo Benichi528d3d02018-06-20 13:35:58 +090029#include <android-base/file.h>
Lorenzo Colitti89faa342016-02-26 11:38:47 +090030#include <android-base/stringprintf.h>
Hugo Benichi528d3d02018-06-20 13:35:58 +090031#include <android-base/strings.h>
Logan Chien3f461482018-04-23 14:31:32 +080032#include <log/log.h>
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070033
Chenbo Feng89c12f12018-03-21 10:29:18 -070034#include "Controllers.h"
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070035#include "FirewallController.h"
Chenbo Feng89c12f12018-03-21 10:29:18 -070036#include "NetdConstants.h"
37#include "bpf/BpfUtils.h"
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070038
Lorenzo Colitti1411d452017-07-17 22:12:15 +090039using android::base::Join;
Lorenzo Colitti89faa342016-02-26 11:38:47 +090040using android::base::StringAppendF;
Lorenzo Colitti1411d452017-07-17 22:12:15 +090041using android::base::StringPrintf;
Lorenzo Colitti89faa342016-02-26 11:38:47 +090042
Luke Huange64fa382018-07-24 16:38:22 +080043namespace android {
44namespace net {
45
Lorenzo Colitti932c44c2016-04-24 16:58:02 +090046auto FirewallController::execIptablesRestore = ::execIptablesRestore;
47
Xiaohui Chen1cdfa9a2015-06-08 16:28:12 -070048const char* FirewallController::TABLE = "filter";
49
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070050const char* FirewallController::LOCAL_INPUT = "fw_INPUT";
51const char* FirewallController::LOCAL_OUTPUT = "fw_OUTPUT";
52const char* FirewallController::LOCAL_FORWARD = "fw_FORWARD";
53
Lorenzo Colittic8683d72015-09-01 16:53:35 +090054// ICMPv6 types that are required for any form of IPv6 connectivity to work. Note that because the
55// fw_dozable chain is called from both INPUT and OUTPUT, this includes both packets that we need
56// to be able to send (e.g., RS, NS), and packets that we need to receive (e.g., RA, NA).
57const char* FirewallController::ICMPV6_TYPES[] = {
58 "packet-too-big",
59 "router-solicitation",
60 "router-advertisement",
61 "neighbour-solicitation",
62 "neighbour-advertisement",
63 "redirect",
64};
65
waynema53de1ff2021-12-01 11:35:06 +080066FirewallController::FirewallController(void) {
Lorenzo Colitticdd79f12020-07-30 12:03:40 +090067 // If no rules are set, it's in DENYLIST mode
68 mFirewallType = DENYLIST;
Lorenzo Colitti1411d452017-07-17 22:12:15 +090069 mIfaceRules = {};
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070070}
71
72int FirewallController::setupIptablesHooks(void) {
waynema53de1ff2021-12-01 11:35:06 +080073 return flushRules();
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070074}
75
Luke Huange64fa382018-07-24 16:38:22 +080076int FirewallController::setFirewallType(FirewallType ftype) {
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070077 int res = 0;
Xiaohui Chen1cdfa9a2015-06-08 16:28:12 -070078 if (mFirewallType != ftype) {
79 // flush any existing rules
Luke Huange64fa382018-07-24 16:38:22 +080080 resetFirewall();
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070081
Lorenzo Colitticdd79f12020-07-30 12:03:40 +090082 if (ftype == ALLOWLIST) {
Xiaohui Chen1cdfa9a2015-06-08 16:28:12 -070083 // create default rule to drop all traffic
Lorenzo Colittid351bea2017-07-16 22:52:30 +090084 std::string command =
85 "*filter\n"
86 "-A fw_INPUT -j DROP\n"
87 "-A fw_OUTPUT -j REJECT\n"
88 "-A fw_FORWARD -j REJECT\n"
89 "COMMIT\n";
90 res = execIptablesRestore(V4V6, command.c_str());
Xiaohui Chen1cdfa9a2015-06-08 16:28:12 -070091 }
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070092
Lorenzo Colitticdd79f12020-07-30 12:03:40 +090093 // Set this after calling disableFirewall(), since it defaults to ALLOWLIST there
Xiaohui Chen1cdfa9a2015-06-08 16:28:12 -070094 mFirewallType = ftype;
Amith Yamasani390e4ea2015-04-25 19:08:57 -070095 }
Luke Huange64fa382018-07-24 16:38:22 +080096 return res ? -EREMOTEIO : 0;
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070097}
98
Maciej Żenczykowski344bb892021-10-14 20:22:23 -070099int FirewallController::flushRules() {
100 std::string command =
101 "*filter\n"
102 ":fw_INPUT -\n"
103 ":fw_OUTPUT -\n"
104 ":fw_FORWARD -\n"
105 "-6 -A fw_OUTPUT ! -o lo -s ::1 -j DROP\n"
106 "COMMIT\n";
107
108 return (execIptablesRestore(V4V6, command.c_str()) == 0) ? 0 : -EREMOTEIO;
109}
110
Luke Huange64fa382018-07-24 16:38:22 +0800111int FirewallController::resetFirewall(void) {
Lorenzo Colitticdd79f12020-07-30 12:03:40 +0900112 mFirewallType = ALLOWLIST;
Lorenzo Colitti1411d452017-07-17 22:12:15 +0900113 mIfaceRules.clear();
Maciej Żenczykowski344bb892021-10-14 20:22:23 -0700114 return flushRules();
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700115}
116
117int FirewallController::isFirewallEnabled(void) {
118 // TODO: verify that rules are still in place near top
119 return -1;
120}
121
122int FirewallController::setInterfaceRule(const char* iface, FirewallRule rule) {
Lorenzo Colitticdd79f12020-07-30 12:03:40 +0900123 if (mFirewallType == DENYLIST) {
124 // Unsupported in DENYLIST mode
Luke Huange64fa382018-07-24 16:38:22 +0800125 return -EINVAL;
Amith Yamasani390e4ea2015-04-25 19:08:57 -0700126 }
127
JP Abgrall69261cb2014-06-19 18:35:24 -0700128 if (!isIfaceName(iface)) {
129 errno = ENOENT;
Luke Huange64fa382018-07-24 16:38:22 +0800130 return -ENOENT;
JP Abgrall69261cb2014-06-19 18:35:24 -0700131 }
132
Lorenzo Colitti1411d452017-07-17 22:12:15 +0900133 // Only delete rules if we actually added them, because otherwise our iptables-restore
134 // processes will terminate with "no such rule" errors and cause latency penalties while we
135 // spin up new ones.
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700136 const char* op;
Lorenzo Colitti1411d452017-07-17 22:12:15 +0900137 if (rule == ALLOW && mIfaceRules.find(iface) == mIfaceRules.end()) {
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700138 op = "-I";
Lorenzo Colitti1411d452017-07-17 22:12:15 +0900139 mIfaceRules.insert(iface);
140 } else if (rule == DENY && mIfaceRules.find(iface) != mIfaceRules.end()) {
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700141 op = "-D";
Lorenzo Colitti1411d452017-07-17 22:12:15 +0900142 mIfaceRules.erase(iface);
143 } else {
144 return 0;
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700145 }
146
Lorenzo Colitti1411d452017-07-17 22:12:15 +0900147 std::string command = Join(std::vector<std::string> {
148 "*filter",
149 StringPrintf("%s fw_INPUT -i %s -j RETURN", op, iface),
150 StringPrintf("%s fw_OUTPUT -o %s -j RETURN", op, iface),
151 "COMMIT\n"
152 }, "\n");
Luke Huange64fa382018-07-24 16:38:22 +0800153 return (execIptablesRestore(V4V6, command) == 0) ? 0 : -EREMOTEIO;
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700154}
155
Lorenzo Colittiaff28792017-09-26 17:46:18 +0900156/* static */
157std::string FirewallController::makeCriticalCommands(IptablesTarget target, const char* chainName) {
158 // Allow ICMPv6 packets necessary to make IPv6 connectivity work. http://b/23158230 .
159 std::string commands;
160 if (target == V6) {
161 for (size_t i = 0; i < ARRAY_SIZE(ICMPV6_TYPES); i++) {
162 StringAppendF(&commands, "-A %s -p icmpv6 --icmpv6-type %s -j RETURN\n",
163 chainName, ICMPV6_TYPES[i]);
164 }
165 }
166 return commands;
167}
168
Luke Huange64fa382018-07-24 16:38:22 +0800169} // namespace net
Lorenzo Colitticdd79f12020-07-30 12:03:40 +0900170} // namespace android