blob: 47975dd3fe3bbb8388b06dff26e2e1b0af5cfe4b [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"
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070037
Lorenzo Colitti1411d452017-07-17 22:12:15 +090038using android::base::Join;
Lorenzo Colitti89faa342016-02-26 11:38:47 +090039using android::base::StringAppendF;
Lorenzo Colitti1411d452017-07-17 22:12:15 +090040using android::base::StringPrintf;
Lorenzo Colitti89faa342016-02-26 11:38:47 +090041
Luke Huange64fa382018-07-24 16:38:22 +080042namespace android {
43namespace net {
44
Lorenzo Colitti932c44c2016-04-24 16:58:02 +090045auto FirewallController::execIptablesRestore = ::execIptablesRestore;
46
Xiaohui Chen1cdfa9a2015-06-08 16:28:12 -070047const char* FirewallController::TABLE = "filter";
48
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070049const char* FirewallController::LOCAL_INPUT = "fw_INPUT";
50const char* FirewallController::LOCAL_OUTPUT = "fw_OUTPUT";
51const char* FirewallController::LOCAL_FORWARD = "fw_FORWARD";
52
Lorenzo Colittic8683d72015-09-01 16:53:35 +090053// ICMPv6 types that are required for any form of IPv6 connectivity to work. Note that because the
54// fw_dozable chain is called from both INPUT and OUTPUT, this includes both packets that we need
55// to be able to send (e.g., RS, NS), and packets that we need to receive (e.g., RA, NA).
56const char* FirewallController::ICMPV6_TYPES[] = {
57 "packet-too-big",
58 "router-solicitation",
59 "router-advertisement",
60 "neighbour-solicitation",
61 "neighbour-advertisement",
62 "redirect",
63};
64
waynema53de1ff2021-12-01 11:35:06 +080065FirewallController::FirewallController(void) {
Lorenzo Colitticdd79f12020-07-30 12:03:40 +090066 // If no rules are set, it's in DENYLIST mode
67 mFirewallType = DENYLIST;
Lorenzo Colitti1411d452017-07-17 22:12:15 +090068 mIfaceRules = {};
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070069}
70
71int FirewallController::setupIptablesHooks(void) {
waynema53de1ff2021-12-01 11:35:06 +080072 return flushRules();
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070073}
74
Luke Huange64fa382018-07-24 16:38:22 +080075int FirewallController::setFirewallType(FirewallType ftype) {
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070076 int res = 0;
Xiaohui Chen1cdfa9a2015-06-08 16:28:12 -070077 if (mFirewallType != ftype) {
78 // flush any existing rules
Luke Huange64fa382018-07-24 16:38:22 +080079 resetFirewall();
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070080
Lorenzo Colitticdd79f12020-07-30 12:03:40 +090081 if (ftype == ALLOWLIST) {
Xiaohui Chen1cdfa9a2015-06-08 16:28:12 -070082 // create default rule to drop all traffic
Lorenzo Colittid351bea2017-07-16 22:52:30 +090083 std::string command =
84 "*filter\n"
85 "-A fw_INPUT -j DROP\n"
86 "-A fw_OUTPUT -j REJECT\n"
87 "-A fw_FORWARD -j REJECT\n"
88 "COMMIT\n";
89 res = execIptablesRestore(V4V6, command.c_str());
Xiaohui Chen1cdfa9a2015-06-08 16:28:12 -070090 }
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070091
Lorenzo Colitticdd79f12020-07-30 12:03:40 +090092 // Set this after calling disableFirewall(), since it defaults to ALLOWLIST there
Xiaohui Chen1cdfa9a2015-06-08 16:28:12 -070093 mFirewallType = ftype;
Amith Yamasani390e4ea2015-04-25 19:08:57 -070094 }
Luke Huange64fa382018-07-24 16:38:22 +080095 return res ? -EREMOTEIO : 0;
Jeff Sharkeyd8c64022012-07-13 18:04:07 -070096}
97
Maciej Żenczykowski344bb892021-10-14 20:22:23 -070098int FirewallController::flushRules() {
99 std::string command =
100 "*filter\n"
101 ":fw_INPUT -\n"
102 ":fw_OUTPUT -\n"
103 ":fw_FORWARD -\n"
104 "-6 -A fw_OUTPUT ! -o lo -s ::1 -j DROP\n"
105 "COMMIT\n";
106
107 return (execIptablesRestore(V4V6, command.c_str()) == 0) ? 0 : -EREMOTEIO;
108}
109
Luke Huange64fa382018-07-24 16:38:22 +0800110int FirewallController::resetFirewall(void) {
Lorenzo Colitticdd79f12020-07-30 12:03:40 +0900111 mFirewallType = ALLOWLIST;
Lorenzo Colitti1411d452017-07-17 22:12:15 +0900112 mIfaceRules.clear();
Maciej Żenczykowski344bb892021-10-14 20:22:23 -0700113 return flushRules();
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700114}
115
116int FirewallController::isFirewallEnabled(void) {
117 // TODO: verify that rules are still in place near top
118 return -1;
119}
120
121int FirewallController::setInterfaceRule(const char* iface, FirewallRule rule) {
Lorenzo Colitticdd79f12020-07-30 12:03:40 +0900122 if (mFirewallType == DENYLIST) {
123 // Unsupported in DENYLIST mode
Luke Huange64fa382018-07-24 16:38:22 +0800124 return -EINVAL;
Amith Yamasani390e4ea2015-04-25 19:08:57 -0700125 }
126
JP Abgrall69261cb2014-06-19 18:35:24 -0700127 if (!isIfaceName(iface)) {
128 errno = ENOENT;
Luke Huange64fa382018-07-24 16:38:22 +0800129 return -ENOENT;
JP Abgrall69261cb2014-06-19 18:35:24 -0700130 }
131
Lorenzo Colitti1411d452017-07-17 22:12:15 +0900132 // Only delete rules if we actually added them, because otherwise our iptables-restore
133 // processes will terminate with "no such rule" errors and cause latency penalties while we
134 // spin up new ones.
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700135 const char* op;
Lorenzo Colitti1411d452017-07-17 22:12:15 +0900136 if (rule == ALLOW && mIfaceRules.find(iface) == mIfaceRules.end()) {
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700137 op = "-I";
Lorenzo Colitti1411d452017-07-17 22:12:15 +0900138 mIfaceRules.insert(iface);
139 } else if (rule == DENY && mIfaceRules.find(iface) != mIfaceRules.end()) {
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700140 op = "-D";
Lorenzo Colitti1411d452017-07-17 22:12:15 +0900141 mIfaceRules.erase(iface);
142 } else {
143 return 0;
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700144 }
145
Lorenzo Colitti1411d452017-07-17 22:12:15 +0900146 std::string command = Join(std::vector<std::string> {
147 "*filter",
148 StringPrintf("%s fw_INPUT -i %s -j RETURN", op, iface),
149 StringPrintf("%s fw_OUTPUT -o %s -j RETURN", op, iface),
150 "COMMIT\n"
151 }, "\n");
Luke Huange64fa382018-07-24 16:38:22 +0800152 return (execIptablesRestore(V4V6, command) == 0) ? 0 : -EREMOTEIO;
Jeff Sharkeyd8c64022012-07-13 18:04:07 -0700153}
154
Lorenzo Colittiaff28792017-09-26 17:46:18 +0900155/* static */
156std::string FirewallController::makeCriticalCommands(IptablesTarget target, const char* chainName) {
157 // Allow ICMPv6 packets necessary to make IPv6 connectivity work. http://b/23158230 .
158 std::string commands;
159 if (target == V6) {
160 for (size_t i = 0; i < ARRAY_SIZE(ICMPV6_TYPES); i++) {
161 StringAppendF(&commands, "-A %s -p icmpv6 --icmpv6-type %s -j RETURN\n",
162 chainName, ICMPV6_TYPES[i]);
163 }
164 }
165 return commands;
166}
167
Luke Huange64fa382018-07-24 16:38:22 +0800168} // namespace net
Lorenzo Colitticdd79f12020-07-30 12:03:40 +0900169} // namespace android