Merge "verify java map key/value struct size matches file descriptor"
This commit is contained in:
@@ -67,8 +67,10 @@ public class BpfMap<K extends Struct, V extends Struct> implements IBpfMap<K, V>
|
||||
private static ConcurrentHashMap<Pair<String, Integer>, ParcelFileDescriptor> sFdCache =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
private static ParcelFileDescriptor cachedBpfFdGet(String path, int mode)
|
||||
private static ParcelFileDescriptor cachedBpfFdGet(String path, int mode,
|
||||
int keySize, int valueSize)
|
||||
throws ErrnoException, NullPointerException {
|
||||
// TODO: key should include keySize & valueSize, but really we should match specific types
|
||||
Pair<String, Integer> key = Pair.create(path, mode);
|
||||
// unlocked fetch is safe: map is concurrent read capable, and only inserted into
|
||||
ParcelFileDescriptor fd = sFdCache.get(key);
|
||||
@@ -79,7 +81,7 @@ public class BpfMap<K extends Struct, V extends Struct> implements IBpfMap<K, V>
|
||||
fd = sFdCache.get(key);
|
||||
if (fd != null) return fd;
|
||||
// okay, we really haven't opened this before...
|
||||
fd = ParcelFileDescriptor.adoptFd(nativeBpfFdGet(path, mode));
|
||||
fd = ParcelFileDescriptor.adoptFd(nativeBpfFdGet(path, mode, keySize, valueSize));
|
||||
sFdCache.put(key, fd);
|
||||
return fd;
|
||||
}
|
||||
@@ -94,11 +96,11 @@ public class BpfMap<K extends Struct, V extends Struct> implements IBpfMap<K, V>
|
||||
*/
|
||||
public BpfMap(@NonNull final String path, final int flag, final Class<K> key,
|
||||
final Class<V> value) throws ErrnoException, NullPointerException {
|
||||
mMapFd = cachedBpfFdGet(path, flag);
|
||||
mKeyClass = key;
|
||||
mValueClass = value;
|
||||
mKeySize = Struct.getSize(key);
|
||||
mValueSize = Struct.getSize(value);
|
||||
mMapFd = cachedBpfFdGet(path, flag, mKeySize, mValueSize);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -295,7 +297,7 @@ public class BpfMap<K extends Struct, V extends Struct> implements IBpfMap<K, V>
|
||||
}
|
||||
}
|
||||
|
||||
private static native int nativeBpfFdGet(String path, int mode)
|
||||
private static native int nativeBpfFdGet(String path, int mode, int keySize, int valueSize)
|
||||
throws ErrnoException, NullPointerException;
|
||||
|
||||
// Note: the following methods appear to not require the object by virtue of taking the
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <errno.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/pfkeyv2.h>
|
||||
#include <net/if.h>
|
||||
@@ -25,9 +26,10 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <log/log.h>
|
||||
|
||||
#include "KernelVersion.h"
|
||||
|
||||
namespace android {
|
||||
namespace bpf {
|
||||
|
||||
@@ -84,27 +86,5 @@ static inline int setrlimitForTest() {
|
||||
return res;
|
||||
}
|
||||
|
||||
#define KVER(a, b, c) (((a) << 24) + ((b) << 16) + (c))
|
||||
|
||||
static inline unsigned uncachedKernelVersion() {
|
||||
struct utsname buf;
|
||||
if (uname(&buf)) return 0;
|
||||
|
||||
unsigned kver_major = 0;
|
||||
unsigned kver_minor = 0;
|
||||
unsigned kver_sub = 0;
|
||||
(void)sscanf(buf.release, "%u.%u.%u", &kver_major, &kver_minor, &kver_sub);
|
||||
return KVER(kver_major, kver_minor, kver_sub);
|
||||
}
|
||||
|
||||
static inline unsigned kernelVersion() {
|
||||
static unsigned kver = uncachedKernelVersion();
|
||||
return kver;
|
||||
}
|
||||
|
||||
static inline bool isAtLeastKernelVersion(unsigned major, unsigned minor, unsigned sub) {
|
||||
return kernelVersion() >= KVER(major, minor, sub);
|
||||
}
|
||||
|
||||
} // namespace bpf
|
||||
} // namespace android
|
||||
|
||||
49
staticlibs/native/bpf_headers/include/bpf/KernelVersion.h
Normal file
49
staticlibs/native/bpf_headers/include/bpf/KernelVersion.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
namespace android {
|
||||
namespace bpf {
|
||||
|
||||
#define KVER(a, b, c) (((a) << 24) + ((b) << 16) + (c))
|
||||
|
||||
static inline unsigned uncachedKernelVersion() {
|
||||
struct utsname buf;
|
||||
if (uname(&buf)) return 0;
|
||||
|
||||
unsigned kver_major = 0;
|
||||
unsigned kver_minor = 0;
|
||||
unsigned kver_sub = 0;
|
||||
(void)sscanf(buf.release, "%u.%u.%u", &kver_major, &kver_minor, &kver_sub);
|
||||
return KVER(kver_major, kver_minor, kver_sub);
|
||||
}
|
||||
|
||||
static inline unsigned kernelVersion() {
|
||||
static unsigned kver = uncachedKernelVersion();
|
||||
return kver;
|
||||
}
|
||||
|
||||
static inline bool isAtLeastKernelVersion(unsigned major, unsigned minor, unsigned sub) {
|
||||
return kernelVersion() >= KVER(major, minor, sub);
|
||||
}
|
||||
|
||||
} // namespace bpf
|
||||
} // namespace android
|
||||
@@ -23,7 +23,7 @@ cc_library_static {
|
||||
"com_android_net_module_util_TcUtils.cpp",
|
||||
],
|
||||
header_libs: [
|
||||
"bpf_syscall_wrappers",
|
||||
"bpf_headers",
|
||||
"jni_headers",
|
||||
],
|
||||
shared_libs: [
|
||||
|
||||
@@ -25,15 +25,34 @@
|
||||
#define BPF_FD_JUST_USE_INT
|
||||
#include "BpfSyscallWrappers.h"
|
||||
|
||||
#include "bpf/KernelVersion.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
static jint com_android_net_module_util_BpfMap_nativeBpfFdGet(JNIEnv *env, jclass clazz,
|
||||
jstring path, jint mode) {
|
||||
jstring path, jint mode, jint keySize, jint valueSize) {
|
||||
ScopedUtfChars pathname(env, path);
|
||||
|
||||
jint fd = bpf::bpfFdGet(pathname.c_str(), static_cast<unsigned>(mode));
|
||||
|
||||
if (fd < 0) jniThrowErrnoException(env, "nativeBpfFdGet", errno);
|
||||
if (fd < 0) {
|
||||
jniThrowErrnoException(env, "nativeBpfFdGet", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bpf::isAtLeastKernelVersion(4, 14, 0)) {
|
||||
// These likely fail with -1 and set errno to EINVAL on <4.14
|
||||
if (bpf::bpfGetFdKeySize(fd) != keySize) {
|
||||
close(fd);
|
||||
jniThrowErrnoException(env, "nativeBpfFdGet KeySize", EBADFD);
|
||||
return -1;
|
||||
}
|
||||
if (bpf::bpfGetFdValueSize(fd) != valueSize) {
|
||||
close(fd);
|
||||
jniThrowErrnoException(env, "nativeBpfFdGet ValueSize", EBADFD);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
@@ -103,7 +122,7 @@ static jboolean com_android_net_module_util_BpfMap_nativeFindMapEntry(JNIEnv *en
|
||||
*/
|
||||
static const JNINativeMethod gMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{ "nativeBpfFdGet", "(Ljava/lang/String;I)I",
|
||||
{ "nativeBpfFdGet", "(Ljava/lang/String;III)I",
|
||||
(void*) com_android_net_module_util_BpfMap_nativeBpfFdGet },
|
||||
{ "nativeWriteToMapEntry", "(I[B[BI)V",
|
||||
(void*) com_android_net_module_util_BpfMap_nativeWriteToMapEntry },
|
||||
|
||||
Reference in New Issue
Block a user