From 2dd1bc3476aa4ae0dab2b27b3c04cb4c780f89e0 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 17 Apr 2017 13:51:47 +0900 Subject: Add a whitelist of commands to the NetUtils wrappers. Currently, the whitelist only logs unexpected commands. In the future, it could log these to netd for later recovery/analysis using dumpsys, or return failure. Tested by ensuring that "adb logcat -s NetUtilsWrapper" never logs anything. Bug: 36463595 Test: boot marlin, swap SIMs, make cell/wifi calls, use mobile data, hotspot, toggle airplane mode Test: new unit test passes Change-Id: I4edae4e1b30ceac7f6c8582ff719c8468b8ca0b9 --- netutils_wrappers/Android.mk | 18 ++++++- netutils_wrappers/NetUtilsWrapper-1.0.cpp | 67 +++++++++++++++++++++++++- netutils_wrappers/NetUtilsWrapper.h | 20 ++++++++ netutils_wrappers/NetUtilsWrapperTest-1.0.cpp | 68 +++++++++++++++++++++++++++ netutils_wrappers/main.cpp | 21 +++++++++ 5 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 netutils_wrappers/NetUtilsWrapper.h create mode 100644 netutils_wrappers/NetUtilsWrapperTest-1.0.cpp create mode 100644 netutils_wrappers/main.cpp (limited to 'netutils_wrappers') diff --git a/netutils_wrappers/Android.mk b/netutils_wrappers/Android.mk index f06f67f4..69204544 100644 --- a/netutils_wrappers/Android.mk +++ b/netutils_wrappers/Android.mk @@ -14,6 +14,7 @@ LOCAL_PATH := $(call my-dir) +### ### Wrapper binary. ### include $(CLEAR_VARS) @@ -21,8 +22,8 @@ include $(CLEAR_VARS) LOCAL_CFLAGS := -Wall -Werror LOCAL_CLANG := true LOCAL_MODULE := netutils-wrapper-1.0 -LOCAL_SHARED_LIBRARIES := libc -LOCAL_SRC_FILES := NetUtilsWrapper-1.0.cpp +LOCAL_SHARED_LIBRARIES := libc libbase liblog +LOCAL_SRC_FILES := NetUtilsWrapper-1.0.cpp main.cpp LOCAL_MODULE_CLASS := EXECUTABLES LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_OUT)/bin; \ @@ -34,3 +35,16 @@ LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_OUT)/bin; \ include $(BUILD_EXECUTABLE) +### +### Wrapper unit tests. +### +include $(CLEAR_VARS) + +LOCAL_CFLAGS := -Wall -Werror +LOCAL_CLANG := true +LOCAL_MODULE := netutils_wrapper_test +LOCAL_SHARED_LIBRARIES := libc libbase liblog +LOCAL_SRC_FILES := NetUtilsWrapper-1.0.cpp NetUtilsWrapperTest-1.0.cpp +LOCAL_MODULE_CLASS := NATIVE_TESTS + +include $(BUILD_NATIVE_TEST) diff --git a/netutils_wrappers/NetUtilsWrapper-1.0.cpp b/netutils_wrappers/NetUtilsWrapper-1.0.cpp index 22d5831d..36b65fab 100644 --- a/netutils_wrappers/NetUtilsWrapper-1.0.cpp +++ b/netutils_wrappers/NetUtilsWrapper-1.0.cpp @@ -14,14 +14,29 @@ * limitations under the License. */ +#include +#include + #include #include #include #include #include +#include + +#define LOG_TAG "NetUtilsWrapper" +#include + +#include "NetUtilsWrapper.h" + #define SYSTEM_DIRNAME "/system/bin/" +#define OEM_IFACE "[^ ]*oem[0-9]+" +#define RMNET_IFACE "(r_)?rmnet_(data)?[0-9]+" +#define VENDOR_IFACE "(" OEM_IFACE "|" RMNET_IFACE ")" +#define VENDOR_CHAIN "(oem_.*|nm_.*|qcom_.*)" + // List of net utils wrapped by this program // The list MUST be in descending order of string length const char *netcmds[] = { @@ -33,8 +48,57 @@ const char *netcmds[] = { NULL, }; +// List of regular expressions of expected commands. +const char *EXPECTED_REGEXPS[] = { +#define CMD "^" SYSTEM_DIRNAME + // Create, delete, and manage OEM networks. + CMD "ndc network (create|destroy) oem[0-9]+( |$)", + CMD "ndc network interface (add|remove) oem[0-9]+ " VENDOR_IFACE, + CMD "ndc network route (add|remove) oem[0-9]+ ", + CMD "ndc ipfwd (enable|disable) ", + CMD "ndc ipfwd (add|remove) .*" VENDOR_IFACE, + + // Manage vendor iptables rules. + CMD "ip(6)?tables -w.* (-A|-D|-F|-I|-N|-X) " VENDOR_CHAIN, + CMD "ip(6)?tables -w.* (-i|-o) " VENDOR_IFACE, + + // Manage IPsec state. + CMD "ip xfrm .*", + + // Manage vendor interfaces. + CMD "tc .* dev " VENDOR_IFACE, + CMD "ip( -4| -6)? (addr|address) (add|del|delete|flush).* dev " VENDOR_IFACE, + + // Other activities observed on current devices. In future releases, these should be supported + // in a way that is less likely to interfere with general Android networking behaviour. + CMD "tc qdisc del dev root", + CMD "ip( -4| -6)? rule .* goto 13000 prio 11999", + CMD "ip( -4| -6)? rule .* prio 25000", + CMD "ip(6)?tables -w .* -j " VENDOR_CHAIN, + CMD "iptables -w -t mangle -[AD] PREROUTING -m socket --nowildcard --restore-skmark -j ACCEPT", + CMD "ndc network interface (add|remove) oem[0-9]+$", // Invalid command: no interface removed. +#undef CMD +}; + +bool checkExpectedCommand(int argc, char **argv) { + std::vector allArgs(argc); + for (int i = 0; i < argc; i++) { + allArgs[i] = argv[i]; + } + std::string fullCmd = android::base::Join(allArgs, ' '); + for (size_t i = 0; i < ARRAY_SIZE(EXPECTED_REGEXPS); i++) { + const std::regex expectedRegexp(EXPECTED_REGEXPS[i], std::regex_constants::extended); + if (std::regex_search(fullCmd, expectedRegexp)) { + return true; + } + } + ALOGI("Unexpected command: %s", fullCmd.c_str()); + return false; +} + + // This is the only gateway for vendor programs to reach net utils. -int main(int /* argc */, char **argv) { +int doMain(int argc, char **argv) { char *progname = argv[0]; char *basename = NULL; @@ -54,6 +118,7 @@ int main(int /* argc */, char **argv) { exit(EXIT_FAILURE); } argv[0] = cmd; + checkExpectedCommand(argc, argv); execv(cmd, argv); } } diff --git a/netutils_wrappers/NetUtilsWrapper.h b/netutils_wrappers/NetUtilsWrapper.h new file mode 100644 index 00000000..127addc0 --- /dev/null +++ b/netutils_wrappers/NetUtilsWrapper.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define ARRAY_SIZE(x) (sizeof((x)) / (sizeof(((x)[0])))) + +int doMain(int argc, char *argv[]); +bool checkExpectedCommand(int argc, char **argv); diff --git a/netutils_wrappers/NetUtilsWrapperTest-1.0.cpp b/netutils_wrappers/NetUtilsWrapperTest-1.0.cpp new file mode 100644 index 00000000..a32cc3b7 --- /dev/null +++ b/netutils_wrappers/NetUtilsWrapperTest-1.0.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +#include + +#include "NetUtilsWrapper.h" + +#define MAX_ARGS 128 +#define VALID true +#define INVALID false + +struct Command { + bool valid; + std::string cmdString; +}; + +std::vector COMMANDS = { + {INVALID, "tc qdisc del dev root"}, + {VALID, "/system/bin/tc qdisc del dev root"}, + {VALID, "/system/bin/ip -6 addr add dev r_rmnet_data6 2001:db8::/64"}, + {INVALID, "/system/bin/ip -6 addr add dev wlan2 2001:db8::/64"}, + {VALID, "/system/bin/ip6tables -w -A INPUT -j qcom_foo"}, + {INVALID, "/system/bin/ip6tables -w -A INPUT -j routectrl_MANGLE_INPUT"}, + {VALID, "/system/bin/ip6tables -w -A INPUT -i rmnet_data9 -j routectrl_MANGLE_INPUT"}, + {VALID, "/system/bin/ip6tables -w -F nm_pre_ip4"}, + {INVALID, "/system/bin/ip6tables -w -F INPUT"}, + {VALID, "/system/bin/ndc network interface add oem10"}, + {VALID, "/system/bin/ndc network interface add oem10 v_oem9"}, + {VALID, "/system/bin/ndc network interface add oem10 oem9"}, + {INVALID, "/system/bin/ndc network interface add 100 v_oem9"}, + {VALID, "/system/bin/ndc network interface add oem10 r_rmnet_data0"}, + {VALID, "/system/bin/ip xfrm state"}, +}; + +TEST(NetUtilsWrapperTest10, TestCommands) { + // Overwritten by each test case. + char *argv[MAX_ARGS]; + + for (const Command& cmd : COMMANDS) { + std::vector pieces = android::base::Split(cmd.cmdString, " "); + ASSERT_LE(pieces.size(), ARRAY_SIZE(argv)); + for (size_t i = 0; i < pieces.size(); i++) { + argv[i] = const_cast(pieces[i].c_str()); + } + EXPECT_EQ(cmd.valid, checkExpectedCommand(pieces.size(), argv)) << + "Expected command to be " << + (cmd.valid ? "valid" : "invalid") << ", but was " << + (cmd.valid ? "invalid" : "valid") << ": '" << cmd.cmdString << "'"; + } +} diff --git a/netutils_wrappers/main.cpp b/netutils_wrappers/main.cpp new file mode 100644 index 00000000..e2072a37 --- /dev/null +++ b/netutils_wrappers/main.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "NetUtilsWrapper.h" + +int main(int argc, char *argv[]) { + return doMain(argc, argv); +} -- cgit v1.2.3