diff --git a/netbpfload/Android.bp b/netbpfload/Android.bp new file mode 100644 index 0000000000..9c45bdcadc --- /dev/null +++ b/netbpfload/Android.bp @@ -0,0 +1,42 @@ +// +// Copyright (C) 2023 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. +// + +cc_binary { + name: "netbpfload", + + defaults: ["bpf_defaults"], + cflags: [ + "-Wall", + "-Werror", + "-Wthread-safety", + ], + sanitize: { + integer_overflow: true, + }, + + header_libs: ["bpf_headers"], + shared_libs: [ + "libbase", + "libcutils", + "liblog", + ], + srcs: [ + "loader.cpp", + "NetBpfLoad.cpp", + ], + + init_rc: ["netbpfload.rc"], +} diff --git a/netbpfload/NetBpfLoad.cpp b/netbpfload/NetBpfLoad.cpp index 8e47ea87a1..7d9c48e612 100644 --- a/netbpfload/NetBpfLoad.cpp +++ b/netbpfload/NetBpfLoad.cpp @@ -44,12 +44,11 @@ #include #include #include -#include #include -#include -#include + #include "BpfSyscallWrappers.h" #include "bpf/BpfUtils.h" +#include "loader.h" using android::base::EndsWith; using android::bpf::domain; @@ -73,26 +72,6 @@ constexpr unsigned long long kTetheringApexDomainBitmask = domainToBitmask(domain::netd_readonly) | domainToBitmask(domain::netd_shared); -// Programs shipped inside the tethering apex should be limited to networking stuff, -// as KPROBE, PERF_EVENT, TRACEPOINT are dangerous to use from mainline updatable code, -// since they are less stable abi/api and may conflict with platform uses of bpf. -constexpr bpf_prog_type kTetheringApexAllowedProgTypes[] = { - BPF_PROG_TYPE_CGROUP_SKB, - BPF_PROG_TYPE_CGROUP_SOCK, - BPF_PROG_TYPE_CGROUP_SOCKOPT, - BPF_PROG_TYPE_CGROUP_SOCK_ADDR, - BPF_PROG_TYPE_CGROUP_SYSCTL, - BPF_PROG_TYPE_LWT_IN, - BPF_PROG_TYPE_LWT_OUT, - BPF_PROG_TYPE_LWT_SEG6LOCAL, - BPF_PROG_TYPE_LWT_XMIT, - BPF_PROG_TYPE_SCHED_ACT, - BPF_PROG_TYPE_SCHED_CLS, - BPF_PROG_TYPE_SOCKET_FILTER, - BPF_PROG_TYPE_SOCK_OPS, - BPF_PROG_TYPE_XDP, -}; - const android::bpf::Location locations[] = { // S+ Tethering mainline module (network_stack): tether offload @@ -100,8 +79,6 @@ const android::bpf::Location locations[] = { .dir = "/apex/com.android.tethering/etc/bpf/", .prefix = "tethering/", .allowedDomainBitmask = kTetheringApexDomainBitmask, - .allowedProgTypes = kTetheringApexAllowedProgTypes, - .allowedProgTypesLength = arraysize(kTetheringApexAllowedProgTypes), }, // T+ Tethering mainline module (shared with netd & system server) // netutils_wrapper (for iptables xt_bpf) has access to programs @@ -109,8 +86,6 @@ const android::bpf::Location locations[] = { .dir = "/apex/com.android.tethering/etc/bpf/netd_shared/", .prefix = "netd_shared/", .allowedDomainBitmask = kTetheringApexDomainBitmask, - .allowedProgTypes = kTetheringApexAllowedProgTypes, - .allowedProgTypesLength = arraysize(kTetheringApexAllowedProgTypes), }, // T+ Tethering mainline module (shared with netd & system server) // netutils_wrapper has no access, netd has read only access @@ -118,24 +93,18 @@ const android::bpf::Location locations[] = { .dir = "/apex/com.android.tethering/etc/bpf/netd_readonly/", .prefix = "netd_readonly/", .allowedDomainBitmask = kTetheringApexDomainBitmask, - .allowedProgTypes = kTetheringApexAllowedProgTypes, - .allowedProgTypesLength = arraysize(kTetheringApexAllowedProgTypes), }, // T+ Tethering mainline module (shared with system server) { .dir = "/apex/com.android.tethering/etc/bpf/net_shared/", .prefix = "net_shared/", .allowedDomainBitmask = kTetheringApexDomainBitmask, - .allowedProgTypes = kTetheringApexAllowedProgTypes, - .allowedProgTypesLength = arraysize(kTetheringApexAllowedProgTypes), }, // T+ Tethering mainline module (not shared, just network_stack) { .dir = "/apex/com.android.tethering/etc/bpf/net_private/", .prefix = "net_private/", .allowedDomainBitmask = kTetheringApexDomainBitmask, - .allowedProgTypes = kTetheringApexAllowedProgTypes, - .allowedProgTypesLength = arraysize(kTetheringApexAllowedProgTypes), }, }; diff --git a/netbpfload/loader.cpp b/netbpfload/loader.cpp index 3bb758b6b5..82ce6d5fa1 100644 --- a/netbpfload/loader.cpp +++ b/netbpfload/loader.cpp @@ -43,7 +43,7 @@ #include "BpfSyscallWrappers.h" #include "bpf/BpfUtils.h" #include "bpf/bpf_map_def.h" -#include "include/libbpf_android.h" +#include "loader.h" #if BPFLOADER_VERSION < COMPILE_FOR_BPFLOADER_VERSION #error "BPFLOADER_VERSION is less than COMPILE_FOR_BPFLOADER_VERSION" @@ -178,6 +178,10 @@ typedef struct { * * However, be aware that you should not be directly using the SECTION() macro. * Instead use the DEFINE_(BPF|XDP)_(PROG|MAP)... & LICENSE/CRITICAL macros. + * + * Programs shipped inside the tethering apex should be limited to networking stuff, + * as KPROBE, PERF_EVENT, TRACEPOINT are dangerous to use from mainline updatable code, + * since they are less stable abi/api and may conflict with platform uses of bpf. */ sectionType sectionNameTypes[] = { {"bind4/", BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_BIND}, @@ -189,13 +193,10 @@ sectionType sectionNameTypes[] = { {"egress/", BPF_PROG_TYPE_CGROUP_SKB, BPF_CGROUP_INET_EGRESS}, {"getsockopt/", BPF_PROG_TYPE_CGROUP_SOCKOPT, BPF_CGROUP_GETSOCKOPT}, {"ingress/", BPF_PROG_TYPE_CGROUP_SKB, BPF_CGROUP_INET_INGRESS}, - {"kprobe/", BPF_PROG_TYPE_KPROBE, BPF_ATTACH_TYPE_UNSPEC}, - {"kretprobe/", BPF_PROG_TYPE_KPROBE, BPF_ATTACH_TYPE_UNSPEC}, {"lwt_in/", BPF_PROG_TYPE_LWT_IN, BPF_ATTACH_TYPE_UNSPEC}, {"lwt_out/", BPF_PROG_TYPE_LWT_OUT, BPF_ATTACH_TYPE_UNSPEC}, {"lwt_seg6local/", BPF_PROG_TYPE_LWT_SEG6LOCAL, BPF_ATTACH_TYPE_UNSPEC}, {"lwt_xmit/", BPF_PROG_TYPE_LWT_XMIT, BPF_ATTACH_TYPE_UNSPEC}, - {"perf_event/", BPF_PROG_TYPE_PERF_EVENT, BPF_ATTACH_TYPE_UNSPEC}, {"postbind4/", BPF_PROG_TYPE_CGROUP_SOCK, BPF_CGROUP_INET4_POST_BIND}, {"postbind6/", BPF_PROG_TYPE_CGROUP_SOCK, BPF_CGROUP_INET6_POST_BIND}, {"recvmsg4/", BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP4_RECVMSG}, @@ -208,9 +209,6 @@ sectionType sectionNameTypes[] = { {"skfilter/", BPF_PROG_TYPE_SOCKET_FILTER, BPF_ATTACH_TYPE_UNSPEC}, {"sockops/", BPF_PROG_TYPE_SOCK_OPS, BPF_CGROUP_SOCK_OPS}, {"sysctl", BPF_PROG_TYPE_CGROUP_SYSCTL, BPF_CGROUP_SYSCTL}, - {"tracepoint/", BPF_PROG_TYPE_TRACEPOINT, BPF_ATTACH_TYPE_UNSPEC}, - {"uprobe/", BPF_PROG_TYPE_KPROBE, BPF_ATTACH_TYPE_UNSPEC}, - {"uretprobe/", BPF_PROG_TYPE_KPROBE, BPF_ATTACH_TYPE_UNSPEC}, {"xdp/", BPF_PROG_TYPE_XDP, BPF_ATTACH_TYPE_UNSPEC}, }; @@ -393,19 +391,10 @@ static int readSymTab(ifstream& elfFile, int sort, vector& data) { return 0; } -static enum bpf_prog_type getFuseProgType() { - int result = BPF_PROG_TYPE_UNSPEC; - ifstream("/sys/fs/fuse/bpf_prog_type_fuse") >> result; - return static_cast(result); -} - static enum bpf_prog_type getSectionType(string& name) { for (auto& snt : sectionNameTypes) if (StartsWith(name, snt.name)) return snt.type; - // TODO Remove this code when fuse-bpf is upstream and this BPF_PROG_TYPE_FUSE is fixed - if (StartsWith(name, "fuse/")) return getFuseProgType(); - return BPF_PROG_TYPE_UNSPEC; } @@ -415,6 +404,7 @@ static enum bpf_attach_type getExpectedAttachType(string& name) { return BPF_ATTACH_TYPE_UNSPEC; } +/* static string getSectionName(enum bpf_prog_type type) { for (auto& snt : sectionNameTypes) @@ -423,6 +413,7 @@ static string getSectionName(enum bpf_prog_type type) return "UNKNOWN SECTION NAME " + std::to_string(type); } +*/ static int readProgDefs(ifstream& elfFile, vector& pd, size_t sizeOfBpfProgDef) { @@ -502,22 +493,8 @@ static int getSectionSymNames(ifstream& elfFile, const string& sectionName, vect return 0; } -static bool IsAllowed(bpf_prog_type type, const bpf_prog_type* allowed, size_t numAllowed) { - if (allowed == nullptr) return true; - - for (size_t i = 0; i < numAllowed; i++) { - if (allowed[i] == BPF_PROG_TYPE_UNSPEC) { - if (type == getFuseProgType()) return true; - } else if (type == allowed[i]) - return true; - } - - return false; -} - /* Read a section by its index - for ex to get sec hdr strtab blob */ -static int readCodeSections(ifstream& elfFile, vector& cs, size_t sizeOfBpfProgDef, - const bpf_prog_type* allowed, size_t numAllowed) { +static int readCodeSections(ifstream& elfFile, vector& cs, size_t sizeOfBpfProgDef) { vector shTable; int entries, ret = 0; @@ -544,11 +521,6 @@ static int readCodeSections(ifstream& elfFile, vector& cs, size_t s if (ptype == BPF_PROG_TYPE_UNSPEC) continue; - if (!IsAllowed(ptype, allowed, numAllowed)) { - ALOGE("Program type %s not permitted here", getSectionName(ptype).c_str()); - return -1; - } - // This must be done before '/' is replaced with '_'. cs_temp.expected_attach_type = getExpectedAttachType(name); @@ -1210,8 +1182,7 @@ int loadProg(const char* elfPath, bool* isCritical, const Location& location) { return -1; } - ret = readCodeSections(elfFile, cs, sizeOfBpfProgDef, location.allowedProgTypes, - location.allowedProgTypesLength); + ret = readCodeSections(elfFile, cs, sizeOfBpfProgDef); if (ret) { ALOGE("Couldn't read all code sections in %s", elfPath); return ret; diff --git a/netbpfload/loader.h b/netbpfload/loader.h index a47e4da138..6402ceafac 100644 --- a/netbpfload/loader.h +++ b/netbpfload/loader.h @@ -76,8 +76,6 @@ struct Location { const char* const dir = ""; const char* const prefix = ""; unsigned long long allowedDomainBitmask = 0; - const bpf_prog_type* allowedProgTypes = nullptr; - size_t allowedProgTypesLength = 0; }; // BPF loader implementation. Loads an eBPF ELF object