From 2f50623b0edd32c55003bad2c3fecd3e303dcf58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Sat, 15 Jun 2024 06:11:00 -0700 Subject: [PATCH] BpfMap: enforce BPF_F_RDWR_EXCLUSIVE doesn't use cached fd. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This prevents creation of 2 SingleWriterBpfMap objects accessing the same map. Note: we never close/flush the cache, so this also prevents the creation of 2 such maps even if they don't simultaneously exist... Test: TreeHugger, atest BpfMapTest fails Signed-off-by: Maciej Żenczykowski Change-Id: I2754657cdd54a07fcab3bd43b3530ac690bcba18 --- .../device/com/android/net/module/util/BpfMap.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/staticlibs/device/com/android/net/module/util/BpfMap.java b/staticlibs/device/com/android/net/module/util/BpfMap.java index dafff20404..0fbc25de7b 100644 --- a/staticlibs/device/com/android/net/module/util/BpfMap.java +++ b/staticlibs/device/com/android/net/module/util/BpfMap.java @@ -15,6 +15,7 @@ */ package com.android.net.module.util; +import static android.system.OsConstants.EBUSY; import static android.system.OsConstants.EEXIST; import static android.system.OsConstants.ENOENT; @@ -72,6 +73,12 @@ public class BpfMap implements IBpfMap private static ConcurrentHashMap, ParcelFileDescriptor> sFdCache = new ConcurrentHashMap<>(); + private static ParcelFileDescriptor checkModeExclusivity(ParcelFileDescriptor fd, int mode) + throws ErrnoException { + if (mode == BPF_F_RDWR_EXCLUSIVE) throw new ErrnoException("cachedBpfFdGet", EBUSY); + return fd; + } + private static ParcelFileDescriptor cachedBpfFdGet(String path, int mode, int keySize, int valueSize) throws ErrnoException, NullPointerException { @@ -82,12 +89,12 @@ public class BpfMap implements IBpfMap var key = Pair.create(path, (mode << 26) ^ (keySize << 16) ^ valueSize); // unlocked fetch is safe: map is concurrent read capable, and only inserted into ParcelFileDescriptor fd = sFdCache.get(key); - if (fd != null) return fd; + if (fd != null) return checkModeExclusivity(fd, mode); // ok, no cached fd present, need to grab a lock synchronized (BpfMap.class) { // need to redo the check fd = sFdCache.get(key); - if (fd != null) return fd; + if (fd != null) return checkModeExclusivity(fd, mode); // okay, we really haven't opened this before... fd = ParcelFileDescriptor.adoptFd(nativeBpfFdGet(path, mode, keySize, valueSize)); sFdCache.put(key, fd);