make mapRetrieveWO take exclusive lock

Test: TreeHugger
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: I4929bbc3490350fc4c57e909109d2ec36eb0359c
diff --git a/netd/BpfHandler.cpp b/netd/BpfHandler.cpp
index 06873fa..f884beb 100644
--- a/netd/BpfHandler.cpp
+++ b/netd/BpfHandler.cpp
@@ -204,7 +204,7 @@
     const char * const m1 = BPF_NETD_PATH "map_netd_lock_array_test_map";
     const char * const m2 = BPF_NETD_PATH "map_netd_lock_hash_test_map";
 
-    unique_fd fd0(bpf::mapRetrieveExclusiveRW(m1)); if (!fd0.ok()) abort();
+    unique_fd fd0(bpf::mapRetrieveExclusiveRW(m1)); if (!fd0.ok()) abort();  // grabs exclusive lock
 
     unique_fd fd1(bpf::mapRetrieveExclusiveRW(m2)); if (!fd1.ok()) abort();  // no conflict with fd0
     unique_fd fd2(bpf::mapRetrieveExclusiveRW(m2)); if ( fd2.ok()) abort();  // busy due to fd1
@@ -215,6 +215,9 @@
     unique_fd fd6(bpf::mapRetrieveRW(m2));          if (!fd6.ok()) abort();  // now ok
     unique_fd fd7(bpf::mapRetrieveRO(m2));          if (!fd7.ok()) abort();  // no lock taken
     unique_fd fd8(bpf::mapRetrieveExclusiveRW(m2)); if ( fd8.ok()) abort();  // busy due to fd6
+
+    fd0.reset();  // releases exclusive lock
+    unique_fd fd9(bpf::mapRetrieveWO(m1));          if (!fd9.ok()) abort();  // grabs exclusive lock
 }
 
 Status BpfHandler::initMaps() {
diff --git a/staticlibs/native/bpf_syscall_wrappers/include/BpfSyscallWrappers.h b/staticlibs/native/bpf_syscall_wrappers/include/BpfSyscallWrappers.h
index c710941..eed4fd6 100644
--- a/staticlibs/native/bpf_syscall_wrappers/include/BpfSyscallWrappers.h
+++ b/staticlibs/native/bpf_syscall_wrappers/include/BpfSyscallWrappers.h
@@ -175,10 +175,9 @@
 }
 
 // WARNING: it's impossible to grab a shared (ie. read) lock on a write-only fd,
-// so only use this if you don't care about locking, ie. never use
-// mapRetrieveExclusiveRW() on the same map (ie. pathname).
+// so we instead choose to grab an exclusive (ie. write) lock.
 inline int mapRetrieveWO(const char* pathname) {
-    return bpfFdGet(pathname, BPF_F_WRONLY);
+    return bpfLock(bpfFdGet(pathname, BPF_F_WRONLY), F_WRLCK);
 }
 
 inline int retrieveProgram(const char* pathname) {