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 =
|
private static ConcurrentHashMap<Pair<String, Integer>, ParcelFileDescriptor> sFdCache =
|
||||||
new ConcurrentHashMap<>();
|
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 {
|
throws ErrnoException, NullPointerException {
|
||||||
|
// TODO: key should include keySize & valueSize, but really we should match specific types
|
||||||
Pair<String, Integer> key = Pair.create(path, mode);
|
Pair<String, Integer> key = Pair.create(path, mode);
|
||||||
// unlocked fetch is safe: map is concurrent read capable, and only inserted into
|
// unlocked fetch is safe: map is concurrent read capable, and only inserted into
|
||||||
ParcelFileDescriptor fd = sFdCache.get(key);
|
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);
|
fd = sFdCache.get(key);
|
||||||
if (fd != null) return fd;
|
if (fd != null) return fd;
|
||||||
// okay, we really haven't opened this before...
|
// 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);
|
sFdCache.put(key, fd);
|
||||||
return 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,
|
public BpfMap(@NonNull final String path, final int flag, final Class<K> key,
|
||||||
final Class<V> value) throws ErrnoException, NullPointerException {
|
final Class<V> value) throws ErrnoException, NullPointerException {
|
||||||
mMapFd = cachedBpfFdGet(path, flag);
|
|
||||||
mKeyClass = key;
|
mKeyClass = key;
|
||||||
mValueClass = value;
|
mValueClass = value;
|
||||||
mKeySize = Struct.getSize(key);
|
mKeySize = Struct.getSize(key);
|
||||||
mValueSize = Struct.getSize(value);
|
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;
|
throws ErrnoException, NullPointerException;
|
||||||
|
|
||||||
// Note: the following methods appear to not require the object by virtue of taking the
|
// Note: the following methods appear to not require the object by virtue of taking the
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <linux/if_ether.h>
|
#include <linux/if_ether.h>
|
||||||
#include <linux/pfkeyv2.h>
|
#include <linux/pfkeyv2.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
@@ -25,9 +26,10 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
|
|
||||||
#include <android-base/unique_fd.h>
|
|
||||||
#include <log/log.h>
|
#include <log/log.h>
|
||||||
|
|
||||||
|
#include "KernelVersion.h"
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
namespace bpf {
|
namespace bpf {
|
||||||
|
|
||||||
@@ -84,27 +86,5 @@ static inline int setrlimitForTest() {
|
|||||||
return res;
|
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 bpf
|
||||||
} // namespace android
|
} // 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",
|
"com_android_net_module_util_TcUtils.cpp",
|
||||||
],
|
],
|
||||||
header_libs: [
|
header_libs: [
|
||||||
"bpf_syscall_wrappers",
|
"bpf_headers",
|
||||||
"jni_headers",
|
"jni_headers",
|
||||||
],
|
],
|
||||||
shared_libs: [
|
shared_libs: [
|
||||||
|
|||||||
@@ -25,15 +25,34 @@
|
|||||||
#define BPF_FD_JUST_USE_INT
|
#define BPF_FD_JUST_USE_INT
|
||||||
#include "BpfSyscallWrappers.h"
|
#include "BpfSyscallWrappers.h"
|
||||||
|
|
||||||
|
#include "bpf/KernelVersion.h"
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
static jint com_android_net_module_util_BpfMap_nativeBpfFdGet(JNIEnv *env, jclass clazz,
|
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);
|
ScopedUtfChars pathname(env, path);
|
||||||
|
|
||||||
jint fd = bpf::bpfFdGet(pathname.c_str(), static_cast<unsigned>(mode));
|
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;
|
return fd;
|
||||||
}
|
}
|
||||||
@@ -103,7 +122,7 @@ static jboolean com_android_net_module_util_BpfMap_nativeFindMapEntry(JNIEnv *en
|
|||||||
*/
|
*/
|
||||||
static const JNINativeMethod gMethods[] = {
|
static const JNINativeMethod gMethods[] = {
|
||||||
/* name, signature, funcPtr */
|
/* name, signature, funcPtr */
|
||||||
{ "nativeBpfFdGet", "(Ljava/lang/String;I)I",
|
{ "nativeBpfFdGet", "(Ljava/lang/String;III)I",
|
||||||
(void*) com_android_net_module_util_BpfMap_nativeBpfFdGet },
|
(void*) com_android_net_module_util_BpfMap_nativeBpfFdGet },
|
||||||
{ "nativeWriteToMapEntry", "(I[B[BI)V",
|
{ "nativeWriteToMapEntry", "(I[B[BI)V",
|
||||||
(void*) com_android_net_module_util_BpfMap_nativeWriteToMapEntry },
|
(void*) com_android_net_module_util_BpfMap_nativeWriteToMapEntry },
|
||||||
|
|||||||
Reference in New Issue
Block a user