bpfloader: move BpfLoader.cpp into Loader.cpp

Prep work to make legacy BpfLoader usable as a library from rust.

Note: fixups to make this actually build will be in the next commit.

Generated via:
  cd //system/bpf/loader
  echo >> Loader.cpp
  cat BpfLoader.cpp >> Loader.cpp
  rm BpfLoader.cpp

Test: will not build, requires followup
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: Id3a942bd0d217f3b689f165666b73e1f2834d33f
diff --git a/loader/BpfLoader.cpp b/loader/BpfLoader.cpp
deleted file mode 100644
index 3f13291..0000000
--- a/loader/BpfLoader.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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 LOG_TAG "BpfLoader"
-
-#include <arpa/inet.h>
-#include <dirent.h>
-#include <elf.h>
-#include <error.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <linux/bpf.h>
-#include <linux/unistd.h>
-#include <net/if.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sys/mman.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <android-base/logging.h>
-#include <android-base/macros.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <android-base/unique_fd.h>
-#include <libbpf_android.h>
-#include <log/log.h>
-#include "BpfSyscallWrappers.h"
-#include "bpf/BpfUtils.h"
-
-using android::base::EndsWith;
-using std::string;
-
-// Networking-related program types are limited to the Tethering Apex
-// to prevent things from breaking due to conflicts on mainline updates
-// (exception made for socket filters, ie. xt_bpf for potential use in iptables,
-// or for attaching to sockets directly)
-constexpr bpf_prog_type kPlatformAllowedProgTypes[] = {
-        BPF_PROG_TYPE_KPROBE,
-        BPF_PROG_TYPE_PERF_EVENT,
-        BPF_PROG_TYPE_SOCKET_FILTER,
-        BPF_PROG_TYPE_TRACEPOINT,
-        BPF_PROG_TYPE_UNSPEC,  // Will be replaced with fuse bpf program type
-};
-
-constexpr bpf_prog_type kUprobestatsAllowedProgTypes[] = {
-        BPF_PROG_TYPE_KPROBE,
-};
-
-// see b/162057235. For arbitrary program types, the concern is that due to the lack of
-// SELinux access controls over BPF program attachpoints, we have no way to control the
-// attachment of programs to shared resources (or to detect when a shared resource
-// has one BPF program replace another that is attached there)
-constexpr bpf_prog_type kVendorAllowedProgTypes[] = {
-        BPF_PROG_TYPE_SOCKET_FILTER,
-};
-
-const android::bpf::Location locations[] = {
-        // Core operating system
-        {
-                .dir = "/system/etc/bpf/",
-                .prefix = "",
-                .allowedProgTypes = kPlatformAllowedProgTypes,
-                .allowedProgTypesLength = arraysize(kPlatformAllowedProgTypes),
-        },
-        // uprobestats
-        {
-                .dir = "/system/etc/bpf/uprobestats/",
-                .prefix = "uprobestats/",
-                .allowedProgTypes = kUprobestatsAllowedProgTypes,
-                .allowedProgTypesLength = arraysize(kUprobestatsAllowedProgTypes),
-        },
-        // Vendor operating system
-        {
-                .dir = "/vendor/etc/bpf/",
-                .prefix = "vendor/",
-                .allowedProgTypes = kVendorAllowedProgTypes,
-                .allowedProgTypesLength = arraysize(kVendorAllowedProgTypes),
-        },
-};
-
-int loadAllElfObjects(const android::bpf::Location& location) {
-    int retVal = 0;
-    DIR* dir;
-    struct dirent* ent;
-
-    if ((dir = opendir(location.dir)) != NULL) {
-        while ((ent = readdir(dir)) != NULL) {
-            string s = ent->d_name;
-            if (!EndsWith(s, ".o")) continue;
-
-            string progPath(location.dir);
-            progPath += s;
-
-            bool critical;
-            int ret = android::bpf::loadProg(progPath.c_str(), &critical, location);
-            if (ret) {
-                if (critical) retVal = ret;
-                ALOGE("Failed to load object: %s, ret: %s", progPath.c_str(), std::strerror(-ret));
-            } else {
-                ALOGV("Loaded object: %s", progPath.c_str());
-            }
-        }
-        closedir(dir);
-    }
-    return retVal;
-}
-
-int createSysFsBpfSubDir(const char* const prefix) {
-    if (*prefix) {
-        mode_t prevUmask = umask(0);
-
-        string s = "/sys/fs/bpf/";
-        s += prefix;
-
-        errno = 0;
-        int ret = mkdir(s.c_str(), S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO);
-        if (ret && errno != EEXIST) {
-            const int err = errno;
-            ALOGE("Failed to create directory: %s, ret: %s", s.c_str(), std::strerror(err));
-            return -err;
-        }
-
-        umask(prevUmask);
-    }
-    return 0;
-}
-
-int main(int __unused argc, char** argv, char * const envp[]) {
-    android::base::InitLogging(argv, &android::base::KernelLogger);
-
-    // Load all ELF objects, create programs and maps, and pin them
-    for (const auto& location : locations) {
-        if (createSysFsBpfSubDir(location.prefix) || loadAllElfObjects(location)) {
-            ALOGE("=== CRITICAL FAILURE LOADING BPF PROGRAMS FROM %s ===", location.dir);
-            ALOGE("If this triggers reliably, you're probably missing kernel options or patches.");
-            ALOGE("If this triggers randomly, you might be hitting some memory allocation "
-                  "problems or startup script race.");
-            ALOGE("--- DO NOT EXPECT SYSTEM TO BOOT SUCCESSFULLY ---");
-            sleep(20);
-            return 120;
-        }
-    }
-
-    const char * args[] = { "/apex/com.android.tethering/bin/netbpfload", "done", NULL, };
-    execve(args[0], (char**)args, envp);
-    ALOGE("FATAL: execve(): %d[%s]", errno, strerror(errno));
-    return 121;
-}
diff --git a/loader/Loader.cpp b/loader/Loader.cpp
index 6ec7458..919b4b3 100644
--- a/loader/Loader.cpp
+++ b/loader/Loader.cpp
@@ -879,3 +879,171 @@
 
 }  // namespace bpf
 }  // namespace android
+
+/*
+ * 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 LOG_TAG "BpfLoader"
+
+#include <arpa/inet.h>
+#include <dirent.h>
+#include <elf.h>
+#include <error.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <linux/bpf.h>
+#include <linux/unistd.h>
+#include <net/if.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+#include <libbpf_android.h>
+#include <log/log.h>
+#include "BpfSyscallWrappers.h"
+#include "bpf/BpfUtils.h"
+
+using android::base::EndsWith;
+using std::string;
+
+// Networking-related program types are limited to the Tethering Apex
+// to prevent things from breaking due to conflicts on mainline updates
+// (exception made for socket filters, ie. xt_bpf for potential use in iptables,
+// or for attaching to sockets directly)
+constexpr bpf_prog_type kPlatformAllowedProgTypes[] = {
+        BPF_PROG_TYPE_KPROBE,
+        BPF_PROG_TYPE_PERF_EVENT,
+        BPF_PROG_TYPE_SOCKET_FILTER,
+        BPF_PROG_TYPE_TRACEPOINT,
+        BPF_PROG_TYPE_UNSPEC,  // Will be replaced with fuse bpf program type
+};
+
+constexpr bpf_prog_type kUprobestatsAllowedProgTypes[] = {
+        BPF_PROG_TYPE_KPROBE,
+};
+
+// see b/162057235. For arbitrary program types, the concern is that due to the lack of
+// SELinux access controls over BPF program attachpoints, we have no way to control the
+// attachment of programs to shared resources (or to detect when a shared resource
+// has one BPF program replace another that is attached there)
+constexpr bpf_prog_type kVendorAllowedProgTypes[] = {
+        BPF_PROG_TYPE_SOCKET_FILTER,
+};
+
+const android::bpf::Location locations[] = {
+        // Core operating system
+        {
+                .dir = "/system/etc/bpf/",
+                .prefix = "",
+                .allowedProgTypes = kPlatformAllowedProgTypes,
+                .allowedProgTypesLength = arraysize(kPlatformAllowedProgTypes),
+        },
+        // uprobestats
+        {
+                .dir = "/system/etc/bpf/uprobestats/",
+                .prefix = "uprobestats/",
+                .allowedProgTypes = kUprobestatsAllowedProgTypes,
+                .allowedProgTypesLength = arraysize(kUprobestatsAllowedProgTypes),
+        },
+        // Vendor operating system
+        {
+                .dir = "/vendor/etc/bpf/",
+                .prefix = "vendor/",
+                .allowedProgTypes = kVendorAllowedProgTypes,
+                .allowedProgTypesLength = arraysize(kVendorAllowedProgTypes),
+        },
+};
+
+int loadAllElfObjects(const android::bpf::Location& location) {
+    int retVal = 0;
+    DIR* dir;
+    struct dirent* ent;
+
+    if ((dir = opendir(location.dir)) != NULL) {
+        while ((ent = readdir(dir)) != NULL) {
+            string s = ent->d_name;
+            if (!EndsWith(s, ".o")) continue;
+
+            string progPath(location.dir);
+            progPath += s;
+
+            bool critical;
+            int ret = android::bpf::loadProg(progPath.c_str(), &critical, location);
+            if (ret) {
+                if (critical) retVal = ret;
+                ALOGE("Failed to load object: %s, ret: %s", progPath.c_str(), std::strerror(-ret));
+            } else {
+                ALOGV("Loaded object: %s", progPath.c_str());
+            }
+        }
+        closedir(dir);
+    }
+    return retVal;
+}
+
+int createSysFsBpfSubDir(const char* const prefix) {
+    if (*prefix) {
+        mode_t prevUmask = umask(0);
+
+        string s = "/sys/fs/bpf/";
+        s += prefix;
+
+        errno = 0;
+        int ret = mkdir(s.c_str(), S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO);
+        if (ret && errno != EEXIST) {
+            const int err = errno;
+            ALOGE("Failed to create directory: %s, ret: %s", s.c_str(), std::strerror(err));
+            return -err;
+        }
+
+        umask(prevUmask);
+    }
+    return 0;
+}
+
+int main(int __unused argc, char** argv, char * const envp[]) {
+    android::base::InitLogging(argv, &android::base::KernelLogger);
+
+    // Load all ELF objects, create programs and maps, and pin them
+    for (const auto& location : locations) {
+        if (createSysFsBpfSubDir(location.prefix) || loadAllElfObjects(location)) {
+            ALOGE("=== CRITICAL FAILURE LOADING BPF PROGRAMS FROM %s ===", location.dir);
+            ALOGE("If this triggers reliably, you're probably missing kernel options or patches.");
+            ALOGE("If this triggers randomly, you might be hitting some memory allocation "
+                  "problems or startup script race.");
+            ALOGE("--- DO NOT EXPECT SYSTEM TO BOOT SUCCESSFULLY ---");
+            sleep(20);
+            return 120;
+        }
+    }
+
+    const char * args[] = { "/apex/com.android.tethering/bin/netbpfload", "done", NULL, };
+    execve(args[0], (char**)args, envp);
+    ALOGE("FATAL: execve(): %d[%s]", errno, strerror(errno));
+    return 121;
+}