mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-26 23:45:19 +07:00
c3bbf176fb
Add a test that calls setsockopt on the listener socket which triggers BPF program. This BPF program writes to the sk storage and sets clone flag. Make sure that sk storage is cloned for a newly accepted connection. We have two cloned maps in the tests to make sure we hit both cases in bpf_sk_storage_clone: first element (sk_storage_alloc) and non-first element(s) (selem_link_map). Cc: Martin KaFai Lau <kafai@fb.com> Cc: Yonghong Song <yhs@fb.com> Acked-by: Martin KaFai Lau <kafai@fb.com> Acked-by: Yonghong Song <yhs@fb.com> Signed-off-by: Stanislav Fomichev <sdf@google.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
98 lines
2.3 KiB
C
98 lines
2.3 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#include <linux/bpf.h>
|
|
#include "bpf_helpers.h"
|
|
|
|
char _license[] SEC("license") = "GPL";
|
|
__u32 _version SEC("version") = 1;
|
|
|
|
#define SOL_CUSTOM 0xdeadbeef
|
|
#define CUSTOM_INHERIT1 0
|
|
#define CUSTOM_INHERIT2 1
|
|
#define CUSTOM_LISTENER 2
|
|
|
|
struct sockopt_inherit {
|
|
__u8 val;
|
|
};
|
|
|
|
struct {
|
|
__uint(type, BPF_MAP_TYPE_SK_STORAGE);
|
|
__uint(map_flags, BPF_F_NO_PREALLOC | BPF_F_CLONE);
|
|
__type(key, int);
|
|
__type(value, struct sockopt_inherit);
|
|
} cloned1_map SEC(".maps");
|
|
|
|
struct {
|
|
__uint(type, BPF_MAP_TYPE_SK_STORAGE);
|
|
__uint(map_flags, BPF_F_NO_PREALLOC | BPF_F_CLONE);
|
|
__type(key, int);
|
|
__type(value, struct sockopt_inherit);
|
|
} cloned2_map SEC(".maps");
|
|
|
|
struct {
|
|
__uint(type, BPF_MAP_TYPE_SK_STORAGE);
|
|
__uint(map_flags, BPF_F_NO_PREALLOC);
|
|
__type(key, int);
|
|
__type(value, struct sockopt_inherit);
|
|
} listener_only_map SEC(".maps");
|
|
|
|
static __inline struct sockopt_inherit *get_storage(struct bpf_sockopt *ctx)
|
|
{
|
|
if (ctx->optname == CUSTOM_INHERIT1)
|
|
return bpf_sk_storage_get(&cloned1_map, ctx->sk, 0,
|
|
BPF_SK_STORAGE_GET_F_CREATE);
|
|
else if (ctx->optname == CUSTOM_INHERIT2)
|
|
return bpf_sk_storage_get(&cloned2_map, ctx->sk, 0,
|
|
BPF_SK_STORAGE_GET_F_CREATE);
|
|
else
|
|
return bpf_sk_storage_get(&listener_only_map, ctx->sk, 0,
|
|
BPF_SK_STORAGE_GET_F_CREATE);
|
|
}
|
|
|
|
SEC("cgroup/getsockopt")
|
|
int _getsockopt(struct bpf_sockopt *ctx)
|
|
{
|
|
__u8 *optval_end = ctx->optval_end;
|
|
struct sockopt_inherit *storage;
|
|
__u8 *optval = ctx->optval;
|
|
|
|
if (ctx->level != SOL_CUSTOM)
|
|
return 1; /* only interested in SOL_CUSTOM */
|
|
|
|
if (optval + 1 > optval_end)
|
|
return 0; /* EPERM, bounds check */
|
|
|
|
storage = get_storage(ctx);
|
|
if (!storage)
|
|
return 0; /* EPERM, couldn't get sk storage */
|
|
|
|
ctx->retval = 0; /* Reset system call return value to zero */
|
|
|
|
optval[0] = storage->val;
|
|
ctx->optlen = 1;
|
|
|
|
return 1;
|
|
}
|
|
|
|
SEC("cgroup/setsockopt")
|
|
int _setsockopt(struct bpf_sockopt *ctx)
|
|
{
|
|
__u8 *optval_end = ctx->optval_end;
|
|
struct sockopt_inherit *storage;
|
|
__u8 *optval = ctx->optval;
|
|
|
|
if (ctx->level != SOL_CUSTOM)
|
|
return 1; /* only interested in SOL_CUSTOM */
|
|
|
|
if (optval + 1 > optval_end)
|
|
return 0; /* EPERM, bounds check */
|
|
|
|
storage = get_storage(ctx);
|
|
if (!storage)
|
|
return 0; /* EPERM, couldn't get sk storage */
|
|
|
|
storage->val = optval[0];
|
|
ctx->optlen = -1;
|
|
|
|
return 1;
|
|
}
|