Merge "NetBpfLoad: change condition for when we execute platform bpfloader" into main am: ea076326b1

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/3132975

Change-Id: I40af902564f6d8b4bea21006f05fff3013b2b30b
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Treehugger Robot 2024-06-14 14:45:04 +00:00 • committed by Automerger Merge Worker
commit ece1e792ec
4 changed files with 45 additions and 41 deletions

View file

@ -254,7 +254,7 @@ static bool isTV() {
}
static int doLoad(char** argv, char * const envp[]) {
const bool runningAsRoot = !getuid();
const bool runningAsRoot = !getuid(); // true iff U QPR3 or V+
const int device_api_level = android_get_device_api_level();
const bool isAtLeastT = (device_api_level >= __ANDROID_API_T__);
const bool isAtLeastU = (device_api_level >= __ANDROID_API_U__);
@ -456,17 +456,25 @@ static int doLoad(char** argv, char * const envp[]) {
return 1;
}
if (isAtLeastV) {
ALOGI("done, transferring control to platform bpfloader.");
// leave a flag that we're done
if (createSysFsBpfSubDir("netd_shared/mainline_done")) return 1;
const char * args[] = { platformBpfLoader, NULL, };
execve(args[0], (char**)args, envp);
ALOGE("FATAL: execve('%s'): %d[%s]", platformBpfLoader, errno, strerror(errno));
return 1;
// platform bpfloader will only succeed when run as root
if (!runningAsRoot) {
// unreachable on U QPR3+ which always runs netbpfload as root
ALOGI("mainline done, no need to transfer control to platform bpf loader.");
return 0;
}
ALOGI("mainline done!");
return 0;
// unreachable before U QPR3
ALOGI("done, transferring control to platform bpfloader.");
// platform BpfLoader *needs* to run as root
const char * args[] = { platformBpfLoader, NULL, };
execve(args[0], (char**)args, envp);
ALOGE("FATAL: execve('%s'): %d[%s]", platformBpfLoader, errno, strerror(errno));
return 1;
}
} // namespace bpf

View file

@ -1,12 +1,4 @@
service mdnsd_netbpfload /system/bin/bpfloader
capabilities CHOWN SYS_ADMIN NET_ADMIN
group root graphics network_stack net_admin net_bw_acct net_bw_stats net_raw system
user root
rlimit memlock 1073741824 1073741824
oneshot
reboot_on_failure reboot,bpfloader-failed
service bpfloader /apex/com.android.tethering/bin/netbpfload
service mdnsd_netbpfload /apex/com.android.tethering/bin/netbpfload
capabilities CHOWN SYS_ADMIN NET_ADMIN
group system root graphics network_stack net_admin net_bw_acct net_bw_stats net_raw
user system

View file

@ -34,6 +34,7 @@ namespace android {
namespace net {
using base::unique_fd;
using base::WaitForProperty;
using bpf::getSocketCookie;
using bpf::retrieveProgram;
using netdutils::Status;
@ -140,39 +141,47 @@ BpfHandler::BpfHandler()
BpfHandler::BpfHandler(uint32_t perUidLimit, uint32_t totalLimit)
: mPerUidStatsEntriesLimit(perUidLimit), mTotalUidStatsEntriesLimit(totalLimit) {}
static bool mainlineNetBpfLoadDone() {
return !access("/sys/fs/bpf/netd_shared/mainline_done", F_OK);
}
// copied with minor changes from waitForProgsLoaded()
// p/m/C's staticlibs/native/bpf_headers/include/bpf/WaitForProgsLoaded.h
static inline void waitForNetProgsLoaded() {
// infinite loop until success with 5/10/20/40/60/60/60... delay
for (int delay = 5;; delay *= 2) {
if (delay > 60) delay = 60;
if (base::WaitForProperty("init.svc.bpfloader", "stopped", std::chrono::seconds(delay))
&& !access("/sys/fs/bpf/netd_shared", F_OK))
if (WaitForProperty("init.svc.mdnsd_netbpfload", "stopped", std::chrono::seconds(delay))
&& mainlineNetBpfLoadDone())
return;
ALOGW("Waited %ds for init.svc.bpfloader=stopped, still waiting...", delay);
ALOGW("Waited %ds for init.svc.mdnsd_netbpfload=stopped, still waiting...", delay);
}
}
Status BpfHandler::init(const char* cg2_path) {
// Note: netd *can* be restarted, so this might get called a second time after boot is complete
// at which point we don't need to (and shouldn't) wait for (more importantly start) loading bpf
if (base::GetProperty("bpf.progs_loaded", "") != "1") {
// Make sure BPF programs are loaded before doing anything
ALOGI("Waiting for BPF programs");
// TODO: use !modules::sdklevel::IsAtLeastV() once api finalized
if (android_get_device_api_level() < __ANDROID_API_V__) {
waitForNetProgsLoaded();
ALOGI("Networking BPF programs are loaded");
if (!base::SetProperty("ctl.start", "mdnsd_netbpfload")) {
ALOGE("Failed to set property ctl.start=mdnsd_netbpfload, see dmesg for reason.");
abort();
}
ALOGI("Waiting for remaining BPF programs");
}
// AOSP platform netd & mainline don't need this (at least prior to U QPR3),
// but there could be platform provided (xt_)bpf programs that oem/vendor
// modified netd (which calls us during init) depends on...
ALOGI("Waiting for platform BPF programs");
android::bpf::waitForProgsLoaded();
}
if (!mainlineNetBpfLoadDone()) {
// we're on < U QPR3 & it's the first time netd is starting up (unless crashlooping)
if (!base::SetProperty("ctl.start", "mdnsd_netbpfload")) {
ALOGE("Failed to set property ctl.start=mdnsd_netbpfload, see dmesg for reason.");
abort();
}
ALOGI("Waiting for Networking BPF programs");
waitForNetProgsLoaded();
ALOGI("Networking BPF programs are loaded");
}
ALOGI("BPF programs are loaded");
RETURN_IF_NOT_OK(initPrograms(cg2_path));

View file

@ -114,12 +114,7 @@ static void verifyClatPerms() {
V("/sys/fs/bpf", S_IFDIR|S_ISVTX|0777, ROOT, ROOT, "fs_bpf", DIR);
// TODO: use modules::sdklevel::IsAtLeastV() once api finalized
if (android_get_device_api_level() >= __ANDROID_API_V__) {
V("/sys/fs/bpf/net_shared", S_IFDIR|01777, ROOT, ROOT, "fs_bpf_net_shared", DIR);
} else {
V("/sys/fs/bpf/net_shared", S_IFDIR|01777, SYSTEM, SYSTEM, "fs_bpf_net_shared", DIR);
}
V("/sys/fs/bpf/net_shared", S_IFDIR|01777, ROOT, ROOT, "fs_bpf_net_shared", DIR);
// pre-U we do not have selinux privs to getattr on bpf maps/progs
// so while the below *should* be as listed, we have no way to actually verify