Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 54 additions & 7 deletions bpf/include/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#define _COMMON_H_

#include "../../config/kmesh_marcos_def.h"
#include <linux/in.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
Expand All @@ -16,8 +17,60 @@

#include "errno.h"

struct bpf_mem_ptr {
void *ptr;
__u32 size;
};

#if ENHANCED_KERNEL
#if KERNEL_KFUNC
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extract a kfunc.h

extern int bpf_parse_header_msg_func(void *src, int src__sz) __ksym;
extern int bpf_km_header_strnstr_func(void *ctx, int ctx__sz, const char *key, int key__sz, const char *subptr) __ksym;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The signature for bpf_km_header_strnstr_func is missing the subptr__sz parameter. This causes the kfunc implementation to use a hardcoded and likely incorrect size, which can lead to memory safety issues. The signature should include int subptr__sz.

extern int bpf_km_header_strnstr_func(void *ctx, int ctx__sz, const char *key, int key__sz, const char *subptr, int subptr__sz) __ksym;

extern int bpf_km_header_strncmp_func(const char *key, int key__sz, const char *target, int target__sz, int opt) __ksym;
extern int bpf_setsockopt_func(void *bpf_mem, int bpf_mem__sz, int optname, const char *optval, int optval__sz) __ksym;
extern int bpf_getsockopt_func(void *bpf_mem, int bpf_mem__sz, int optname, char *optval, int optval__sz) __ksym;

#define bpf_km_header_strncmp bpf_km_header_strncmp_func

int bpf_km_header_strnstr(void *ctx, const char *key, int key__sz, const char *subptr, int subptr__sz)
{
struct bpf_mem_ptr msg_tmp = {.ptr = ctx, .size = sizeof(struct bpf_sock_addr)};
return bpf_km_header_strnstr_func(&msg_tmp, sizeof(struct bpf_mem_ptr), key, key__sz, subptr);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The call to bpf_km_header_strnstr_func is missing the subptr__sz argument, which is required for correctness and memory safety. This is related to the incorrect extern declaration on line 28.

    return bpf_km_header_strnstr_func(&msg_tmp, sizeof(struct bpf_mem_ptr), key, key__sz, subptr, subptr__sz);

}

int bpf_parse_header_msg(struct bpf_sock_addr *ctx)
{
struct bpf_mem_ptr msg_tmp = {.ptr = ctx, .size = sizeof(struct bpf_sock_addr)};
return bpf_parse_header_msg_func(&msg_tmp, sizeof(struct bpf_mem_ptr));
}

// Due to the limitation of bpf verifier, optval and optval__sz are required to correspond.
// The strnlen function cannot be used here, so the string is redefined.
int bpf_km_setsockopt(struct bpf_sock_addr *ctx, int level, int optname, const char *optval, int optval__sz)
{
const char kmesh_module_name[] = "kmesh_defer";
if (level != IPPROTO_TCP || optval__sz != sizeof(kmesh_module_name))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need check for this function

return -1;

struct bpf_mem_ptr msg_tmp = {.ptr = ctx, .size = sizeof(struct bpf_sock_addr)};
return bpf_setsockopt_func(
&msg_tmp, sizeof(struct bpf_mem_ptr), optname, (void *)kmesh_module_name, sizeof(kmesh_module_name));
}
Comment on lines +49 to +58

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The function bpf_km_setsockopt has a generic name, but its implementation is highly specific to setting the TCP_ULP option to "kmesh_defer". This is misleading and harms maintainability. Consider renaming the function to reflect its specific purpose, for example, bpf_km_set_tcp_ulp_kmesh_defer.


int bpf_km_getsockopt(struct bpf_sock_addr *ctx, int level, int optname, char *optval, int optval__sz)
{
if (level != IPPROTO_TCP) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need check for this function

return -1;
}
struct bpf_mem_ptr msg_tmp = {.ptr = ctx, .size = sizeof(struct bpf_sock_addr)};
return bpf_getsockopt_func(&msg_tmp, sizeof(struct bpf_mem_ptr), optname, (void *)optval, optval__sz);
}

#else
#include <bpf_helper_defs_ext.h>
#define bpf_km_setsockopt bpf_setsockopt
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pls define macros in bpf_helper_defs_ext.h

#define bpf_km_getsockopt bpf_getsockopt
#endif
#endif

#define bpf_unused __attribute__((__unused__))
Expand Down Expand Up @@ -113,14 +166,8 @@ static inline bool is_ipv4_mapped_addr(__u32 ip6[4])
(dst)[3] = (src)[3]; \
} while (0)

#if OE_23_03
#define bpf__strncmp bpf_strncmp
#define GET_SKOPS_REMOTE_PORT(sk_ops) (__u16)((sk_ops)->remote_port)
#else
#define GET_SKOPS_REMOTE_PORT(sk_ops) (__u16)((sk_ops)->remote_port >> 16)
#endif

#define GET_SKOPS_LOCAL_PORT(sk_ops) (__u16)((sk_ops)->local_port)
#define GET_SKOPS_LOCAL_PORT(sk_ops) (__u16)((sk_ops)->local_port)

#define MAX_BUF_LEN 100
#define MAX_IP4_LEN 16
Expand Down
7 changes: 3 additions & 4 deletions bpf/kmesh/ads/cgroup_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@
#if KMESH_ENABLE_HTTP

static const char kmesh_module_name[] = "kmesh_defer";
static char kmesh_module_name_get[KMESH_MODULE_NAME_LEN] = "";
static inline int sock4_traffic_control(struct bpf_sock_addr *ctx)
{
int ret;

char kmesh_module_name_get[KMESH_MODULE_NAME_LEN] = "";
Listener__Listener *listener = NULL;

if (ctx->protocol != IPPROTO_TCP)
Expand All @@ -42,9 +41,9 @@ static inline int sock4_traffic_control(struct bpf_sock_addr *ctx)
BPF_LOG(DEBUG, KMESH, "bpf find listener addr=[%s:%u]\n", ip2str(&ip, 1), bpf_ntohs(ctx->user_port));

#if ENHANCED_KERNEL
ret = bpf_getsockopt(ctx, IPPROTO_TCP, TCP_ULP, (void *)kmesh_module_name_get, KMESH_MODULE_NAME_LEN);
ret = bpf_km_getsockopt(ctx, IPPROTO_TCP, TCP_ULP, kmesh_module_name_get, KMESH_MODULE_NAME_LEN);
if (CHECK_MODULE_NAME_NULL(ret) || bpf__strncmp(kmesh_module_name_get, KMESH_MODULE_NAME_LEN, kmesh_module_name)) {
ret = bpf_setsockopt(ctx, IPPROTO_TCP, TCP_ULP, (void *)kmesh_module_name, sizeof(kmesh_module_name));
ret = bpf_km_setsockopt(ctx, IPPROTO_TCP, TCP_ULP, kmesh_module_name, sizeof(kmesh_module_name));
if (ret)
BPF_LOG(ERR, KMESH, "bpf set sockopt failed! ret %d\n", ret);
return 0;
Expand Down
11 changes: 0 additions & 11 deletions bpf/kmesh/ads/include/ctx/sock_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,6 @@ typedef struct bpf_sock_ops ctx_buff_t;
name.ipv4 = (ctx)->remote_ip4; \
name.port = (ctx)->remote_port

#if OE_23_03
#define SET_CTX_ADDRESS(ctx, address) \
(ctx)->remote_ip4 = (address)->ipv4; \
(ctx)->remote_port = (address)->port

#define MARK_REJECTED(ctx) \
BPF_LOG(DEBUG, KMESH, "mark reject\n"); \
(ctx)->remote_ip4 = 0; \
(ctx)->remote_port = 0
#else
#define SET_CTX_ADDRESS(ctx, address) \
(ctx)->replylong[2] = (address)->ipv4; \
(ctx)->replylong[3] = (address)->port
Expand All @@ -40,6 +30,5 @@ typedef struct bpf_sock_ops ctx_buff_t;
BPF_LOG(DEBUG, KMESH, "mark reject\n"); \
(ctx)->replylong[2] = 0; \
(ctx)->replylong[3] = 0
#endif

#endif //__BPF_CTX_SOCK_OPS_H
5 changes: 0 additions & 5 deletions bpf/kmesh/ads/include/kmesh_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,6 @@
val; \
})

struct bpf_mem_ptr {
void *ptr;
__u32 size;
};

static inline int bpf__strncmp(const char *dst, int n, const char *src)
{
if (dst == NULL || src == NULL)
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ if [ -z "$1" -o "$1" == "-b" -o "$1" == "--build" ]; then
exit
fi

if [ "$1" == "-d" -o "$1" == "--docker" ]; then
prepare
make kmesh-bpf
make all-binary
install
exit
fi

if [ "$1" == "-i" -o "$1" == "--install" ]; then
make install
install
Expand Down
27 changes: 5 additions & 22 deletions config/kmesh_marcos_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,6 @@
*/
#define MDA_GID_UID_FILTER 1

/*
* openEuler-23.03 is an innovative version of openEuler, in the early time, we
* developed kmesh based on openEuler-23.03, and the implementation of kmesh
* was related to the openEuler-23.03 kernel. Now, the general implementation
* of kmesh differs from the previous openEuler-23.03 version, so we need to
* use this macro to distinguish these differences.
* The main differences between the general implementation of kmesh and the
* openEuler-23.03 version are as follows:
* 1. Use replylong parameter instead of directly modifying the remote IP and Port;
* 2. Use bpf__strncmp instead of bpf_strncmp for string comparison;
* 3. Fix Port shift bug on openEuler-23.03.In the kernel network protocol
* stack, the port is stored in u16, but in the bpf network module, the port
* is stored in u32. Therefore, after the endian conversion, the 16-bit port
* needs to be obtained from the 32-bit data structure.
* You need to find the position of the valid 16 bits. Generally, after the
* port is extended from 16 bits to 32 bits, the port is in the upper 16
* bits after the endian conversion. Therefore, you need to offset the port
* before using the u16 RX port. In some specific kernels, the port stored
* in sockops is in the lower 16 bits and does not need to be offset.
*/
#define OE_23_03 0

/*
* in kernel 6.x version, add the new iter type ITER_UBUF, and we need add code
* for the corresponding scenarios.
Expand All @@ -68,3 +46,8 @@
* is enabled accordingly.
* */
#define LIBBPF_HIGHER_0_6_0_VERSION 0

/*
* Determine whether the current kernel version supports the use of kfunc.
*/
#define KERNEL_KFUNC 0
2 changes: 1 addition & 1 deletion hack/utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function get_arch() {
function build_kmesh() {
local container_id=$1
docker exec $container_id git config --global --add safe.directory /kmesh
docker exec -e VERSION=$VERSION $container_id sh /kmesh/build.sh
docker exec -e VERSION=$VERSION $container_id sh /kmesh/build.sh -d
docker exec -e VERSION=$VERSION $container_id sh /kmesh/build.sh -i
docker exec $container_id sh -c "$(declare -f copy_to_host); copy_to_host"
}
Expand Down
4 changes: 3 additions & 1 deletion kernel/ko_src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ CURRENT_PATH := $(shell pwd)
DIRS := $(shell find $(CURRENT_PATH) -maxdepth 1 -type d)
BASE_DIRS := $(basename $(patsubst $(CURRENT_PATH)/%, %, $(DIRS)))
BASE_DIRS := $(filter-out $(CURRENT_PATH), $(BASE_DIRS))
CONFIG_FILE := ../../config/kmesh_marcos_def.h
ENHANCED_KERNEL := $(shell grep -q "#define ENHANCED_KERNEL 1" $(CONFIG_FILE) && echo yes || echo no)

ifeq ($(ENHANCED_KERNEL), enhanced)
ifeq ($(ENHANCED_KERNEL), yes)
all:
@for dir in ${BASE_DIRS}; do \
make -C $(CURRENT_PATH)/$$dir; \
Expand Down
2 changes: 1 addition & 1 deletion kernel/ko_src/kmesh/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
obj-m := kmesh.o
kmesh-objs = kmesh_main.o defer_connect.o \
kmesh_parse_protocol_data.o \
kmesh_parse_http_1_1.o
kmesh_parse_http_1_1.o kmesh_func.o

KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
Expand Down
62 changes: 33 additions & 29 deletions kernel/ko_src/kmesh/defer_connect.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/* Copyright Authors of Kmesh */

#include "../../../config/kmesh_marcos_def.h"
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kmod.h>
Expand All @@ -21,9 +20,24 @@
#include "defer_connect.h"

static struct proto *kmesh_defer_proto = NULL;
#define KMESH_DELAY_ERROR -1000

#define BPF_CGROUP_RUN_PROG_INET4_CONNECT_KMESH(sk, uaddr, t_ctx) \
#ifdef KERNEL_KFUNC
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a difference introduced by the kernel version. It is inappropriate to use KERNEL_KFUNC to distinguish this difference.

#define BPF_CGROUP_RUN_PROG_INET4_CONNECT_KMESH(sk, uaddr, uaddrlen, t_ctx) \
({ \
int __ret = -1; \
if (t_ctx == NULL) { \
__ret = -EINVAL; \
} else { \
__ret = __cgroup_bpf_run_filter_sock_addr(sk, uaddr, uaddrlen, CGROUP_INET4_CONNECT, t_ctx, NULL); \
} \
__ret; \
})

#define SET_FDEFER_CONNECT_ON(sk) (inet_set_bit(DEFER_CONNECT, sk))
#define SET_FDEFER_CONNECT_OFF(sk) (inet_clear_bit(DEFER_CONNECT, sk))
#define IS_DEFER_CONNECT(sk) (inet_test_bit(DEFER_CONNECT, sk))
#else
#define BPF_CGROUP_RUN_PROG_INET4_CONNECT_KMESH(sk, uaddr, uaddrlen, t_ctx) \
({ \
int __ret = -1; \
if (t_ctx == NULL) { \
Expand All @@ -34,6 +48,11 @@ static struct proto *kmesh_defer_proto = NULL;
__ret; \
})

#define SET_FDEFER_CONNECT_ON(sk) (inet_sk(sk)->defer_connect = 1)
#define SET_FDEFER_CONNECT_OFF(sk) (inet_sk(sk)->defer_connect = 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SET_DEFER_CONNECT_ON
SET_DEFER_CONNECT_OFF

#define IS_DEFER_CONNECT(sk) (inet_sk(sk)->defer_connect == 1)
#endif

static int defer_connect(struct sock *sk, struct msghdr *msg, size_t size)
{
struct bpf_mem_ptr tmpMem = {0};
Expand All @@ -43,6 +62,7 @@ static int defer_connect(struct sock *sk, struct msghdr *msg, size_t size)
const struct iovec *iov;
struct bpf_sock_addr_kern sock_addr;
struct sockaddr_in uaddr;
int uaddrlen = sizeof(struct sockaddr_in);
void __user *ubase;
int err;
u32 dport, daddr;
Expand All @@ -54,7 +74,11 @@ static int defer_connect(struct sock *sk, struct msghdr *msg, size_t size)
ubase = iov->iov_base;
kbuf_size = iov->iov_len;
} else if (iter_is_iovec(&msg->msg_iter)) {
#ifdef KERNEL_KFUNC
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the previous comment.

iov = msg->msg_iter.__iov;
#else
iov = msg->msg_iter.iov;
#endif
ubase = iov->iov_base;
kbuf_size = iov->iov_len;
#if ITER_TYPE_IS_UBUF
Expand All @@ -79,31 +103,11 @@ static int defer_connect(struct sock *sk, struct msghdr *msg, size_t size)
tmpMem.size = kbuf_size;
tmpMem.ptr = kbuf;

#if OE_23_03
tcp_call_bpf_3arg(
sk,
BPF_SOCK_OPS_TCP_DEFER_CONNECT_CB,
((u64)(&tmpMem) & U32_MAX),
(((u64)(&tmpMem) >> 32) & U32_MAX),
kbuf_size);
daddr = sk->sk_daddr;
dport = sk->sk_dport;

// daddr == 0 && dport == 0 are special flags meaning the circuit breaker is open
// Should reject connection here
if (daddr == 0 && dport == 0) {
tcp_set_state(sk, TCP_CLOSE);
sk->sk_route_caps = 0;
inet_sk(sk)->inet_dport = 0;
err = -1;
goto out;
}
#else
uaddr.sin_family = AF_INET;
uaddr.sin_addr.s_addr = daddr;
uaddr.sin_port = dport;
err = BPF_CGROUP_RUN_PROG_INET4_CONNECT_KMESH(sk, (struct sockaddr *)&uaddr, &tmpMem);
#endif
err = BPF_CGROUP_RUN_PROG_INET4_CONNECT_KMESH(sk, (struct sockaddr *)&uaddr, &uaddrlen, &tmpMem);

connect:
err = sk->sk_prot->connect(sk, (struct sockaddr *)&uaddr, sizeof(struct sockaddr_in));
if (unlikely(err)) {
Expand All @@ -113,7 +117,7 @@ static int defer_connect(struct sock *sk, struct msghdr *msg, size_t size)
inet_sk(sk)->inet_dport = 0;
goto out;
}
inet_sk(sk)->defer_connect = 0;
SET_FDEFER_CONNECT_OFF(sk);

if ((((__u32)1 << sk->sk_state) & ~(__u32)(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) && !tcp_passive_fastopen(sk)) {
sk_stream_wait_connect(sk, &timeo);
Expand All @@ -128,7 +132,7 @@ static int defer_connect_and_sendmsg(struct sock *sk, struct msghdr *msg, size_t
struct socket *sock;
int err = 0;

if (unlikely(inet_sk(sk)->defer_connect == 1)) {
if (unlikely(IS_DEFER_CONNECT(sk))) {
lock_sock(sk);

err = defer_connect(sk, msg, size);
Expand Down Expand Up @@ -163,9 +167,9 @@ static int defer_tcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_l
* of defer_connect should be 1 and the normal connect function
* needs to be used.
*/
if (inet_sk(sk)->defer_connect)
if (IS_DEFER_CONNECT(sk))
return tcp_v4_connect(sk, uaddr, addr_len);
inet_sk(sk)->defer_connect = 1;
SET_FDEFER_CONNECT_ON(sk);
sk->sk_dport = ((struct sockaddr_in *)uaddr)->sin_port;
sk_daddr_set(sk, ((struct sockaddr_in *)uaddr)->sin_addr.s_addr);
sk->sk_socket->state = SS_CONNECTING;
Expand Down
Loading
Loading