Skip to content

Commit 84085f8

Browse files
author
Alexei Starovoitov
committed
Merge branch 'enable-bpf_skc-cast-for-networking-progs'
Martin KaFai Lau says: ==================== This set allows networking prog type to directly read fields from the in-kernel socket type, e.g. "struct tcp_sock". Patch 2 has the details on the use case. v3: - Pass arg_btf_id instead of fn into check_reg_type() in Patch 1 (Lorenz) - Move arg_btf_id from func_proto to struct bpf_reg_types in Patch 2 (Lorenz) - Remove test_sock_fields from .gitignore in Patch 8 (Andrii) - Add tests to have better coverage on the modified helpers (Alexei) Patch 13 is added. - Use "void *sk" as the helper argument in UAPI bpf.h v3: - ARG_PTR_TO_SOCK_COMMON_OR_NULL was attempted in v2. The _OR_NULL was needed because the PTR_TO_BTF_ID could be NULL but note that a could be NULL PTR_TO_BTF_ID is not a scalar NULL to the verifier. "_OR_NULL" implicitly gives an expectation that the helper can take a scalar NULL which does not make sense in most (except one) helpers. Passing scalar NULL should be rejected at the verification time. Thus, this patch uses ARG_PTR_TO_BTF_ID_SOCK_COMMON to specify that the helper can take both the btf-id ptr or the legacy PTR_TO_SOCK_COMMON but not scalar NULL. It requires the func_proto to explicitly specify the arg_btf_id such that there is a very clear expectation that the helper can handle a NULL PTR_TO_BTF_ID. v2: - Add ARG_PTR_TO_SOCK_COMMON_OR_NULL (Lorenz) ==================== Signed-off-by: Alexei Starovoitov <[email protected]>
2 parents 182bf3f + 9a856ca commit 84085f8

File tree

20 files changed

+1093
-716
lines changed

20 files changed

+1093
-716
lines changed

include/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ enum bpf_arg_type {
292292
ARG_PTR_TO_ALLOC_MEM, /* pointer to dynamically allocated memory */
293293
ARG_PTR_TO_ALLOC_MEM_OR_NULL, /* pointer to dynamically allocated memory or NULL */
294294
ARG_CONST_ALLOC_SIZE_OR_ZERO, /* number of allocated bytes requested */
295+
ARG_PTR_TO_BTF_ID_SOCK_COMMON, /* pointer to in-kernel sock_common or bpf-mirrored bpf_sock */
295296
__BPF_ARG_TYPE_MAX,
296297
};
297298

include/net/bpf_sk_storage.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ void bpf_sk_storage_free(struct sock *sk);
2020

2121
extern const struct bpf_func_proto bpf_sk_storage_get_proto;
2222
extern const struct bpf_func_proto bpf_sk_storage_delete_proto;
23-
extern const struct bpf_func_proto sk_storage_get_btf_proto;
24-
extern const struct bpf_func_proto sk_storage_delete_btf_proto;
2523

2624
struct bpf_local_storage_elem;
2725
struct bpf_sk_storage_diag;

include/uapi/linux/bpf.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2512,7 +2512,7 @@ union bpf_attr {
25122512
* result is from *reuse*\ **->socks**\ [] using the hash of the
25132513
* tuple.
25142514
*
2515-
* long bpf_sk_release(struct bpf_sock *sock)
2515+
* long bpf_sk_release(void *sock)
25162516
* Description
25172517
* Release the reference held by *sock*. *sock* must be a
25182518
* non-**NULL** pointer that was returned from
@@ -2692,7 +2692,7 @@ union bpf_attr {
26922692
* result is from *reuse*\ **->socks**\ [] using the hash of the
26932693
* tuple.
26942694
*
2695-
* long bpf_tcp_check_syncookie(struct bpf_sock *sk, void *iph, u32 iph_len, struct tcphdr *th, u32 th_len)
2695+
* long bpf_tcp_check_syncookie(void *sk, void *iph, u32 iph_len, struct tcphdr *th, u32 th_len)
26962696
* Description
26972697
* Check whether *iph* and *th* contain a valid SYN cookie ACK for
26982698
* the listening socket in *sk*.
@@ -2861,6 +2861,7 @@ union bpf_attr {
28612861
* 0 on success.
28622862
*
28632863
* **-ENOENT** if the bpf-local-storage cannot be found.
2864+
* **-EINVAL** if sk is not a fullsock (e.g. a request_sock).
28642865
*
28652866
* long bpf_send_signal(u32 sig)
28662867
* Description
@@ -2877,7 +2878,7 @@ union bpf_attr {
28772878
*
28782879
* **-EAGAIN** if bpf program can try again.
28792880
*
2880-
* s64 bpf_tcp_gen_syncookie(struct bpf_sock *sk, void *iph, u32 iph_len, struct tcphdr *th, u32 th_len)
2881+
* s64 bpf_tcp_gen_syncookie(void *sk, void *iph, u32 iph_len, struct tcphdr *th, u32 th_len)
28812882
* Description
28822883
* Try to issue a SYN cookie for the packet with corresponding
28832884
* IP/TCP headers, *iph* and *th*, on the listening socket in *sk*.
@@ -3106,7 +3107,7 @@ union bpf_attr {
31063107
* Return
31073108
* The id is returned or 0 in case the id could not be retrieved.
31083109
*
3109-
* long bpf_sk_assign(struct sk_buff *skb, struct bpf_sock *sk, u64 flags)
3110+
* long bpf_sk_assign(struct sk_buff *skb, void *sk, u64 flags)
31103111
* Description
31113112
* Helper is overloaded depending on BPF program type. This
31123113
* description applies to **BPF_PROG_TYPE_SCHED_CLS** and
@@ -3234,11 +3235,11 @@ union bpf_attr {
32343235
*
32353236
* **-EOVERFLOW** if an overflow happened: The same object will be tried again.
32363237
*
3237-
* u64 bpf_sk_cgroup_id(struct bpf_sock *sk)
3238+
* u64 bpf_sk_cgroup_id(void *sk)
32383239
* Description
32393240
* Return the cgroup v2 id of the socket *sk*.
32403241
*
3241-
* *sk* must be a non-**NULL** pointer to a full socket, e.g. one
3242+
* *sk* must be a non-**NULL** pointer to a socket, e.g. one
32423243
* returned from **bpf_sk_lookup_xxx**\ (),
32433244
* **bpf_sk_fullsock**\ (), etc. The format of returned id is
32443245
* same as in **bpf_skb_cgroup_id**\ ().
@@ -3248,7 +3249,7 @@ union bpf_attr {
32483249
* Return
32493250
* The id is returned or 0 in case the id could not be retrieved.
32503251
*
3251-
* u64 bpf_sk_ancestor_cgroup_id(struct bpf_sock *sk, int ancestor_level)
3252+
* u64 bpf_sk_ancestor_cgroup_id(void *sk, int ancestor_level)
32523253
* Description
32533254
* Return id of cgroup v2 that is ancestor of cgroup associated
32543255
* with the *sk* at the *ancestor_level*. The root cgroup is at

kernel/bpf/bpf_lsm.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ bpf_lsm_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
5656
case BPF_FUNC_inode_storage_delete:
5757
return &bpf_inode_storage_delete_proto;
5858
case BPF_FUNC_sk_storage_get:
59-
return &sk_storage_get_btf_proto;
59+
return &bpf_sk_storage_get_proto;
6060
case BPF_FUNC_sk_storage_delete:
61-
return &sk_storage_delete_btf_proto;
61+
return &bpf_sk_storage_delete_proto;
6262
default:
6363
return tracing_prog_func_proto(func_id, prog);
6464
}

kernel/bpf/verifier.c

Lines changed: 63 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,12 @@ static bool is_acquire_function(enum bpf_func_id func_id,
486486
static bool is_ptr_cast_function(enum bpf_func_id func_id)
487487
{
488488
return func_id == BPF_FUNC_tcp_sock ||
489-
func_id == BPF_FUNC_sk_fullsock;
489+
func_id == BPF_FUNC_sk_fullsock ||
490+
func_id == BPF_FUNC_skc_to_tcp_sock ||
491+
func_id == BPF_FUNC_skc_to_tcp6_sock ||
492+
func_id == BPF_FUNC_skc_to_udp6_sock ||
493+
func_id == BPF_FUNC_skc_to_tcp_timewait_sock ||
494+
func_id == BPF_FUNC_skc_to_tcp_request_sock;
490495
}
491496

492497
/* string representation of 'enum bpf_reg_type' */
@@ -3953,6 +3958,7 @@ static int resolve_map_arg_type(struct bpf_verifier_env *env,
39533958

39543959
struct bpf_reg_types {
39553960
const enum bpf_reg_type types[10];
3961+
u32 *btf_id;
39563962
};
39573963

39583964
static const struct bpf_reg_types map_key_value_types = {
@@ -3973,6 +3979,17 @@ static const struct bpf_reg_types sock_types = {
39733979
},
39743980
};
39753981

3982+
static const struct bpf_reg_types btf_id_sock_common_types = {
3983+
.types = {
3984+
PTR_TO_SOCK_COMMON,
3985+
PTR_TO_SOCKET,
3986+
PTR_TO_TCP_SOCK,
3987+
PTR_TO_XDP_SOCK,
3988+
PTR_TO_BTF_ID,
3989+
},
3990+
.btf_id = &btf_sock_ids[BTF_SOCK_TYPE_SOCK_COMMON],
3991+
};
3992+
39763993
static const struct bpf_reg_types mem_types = {
39773994
.types = {
39783995
PTR_TO_STACK,
@@ -4014,6 +4031,7 @@ static const struct bpf_reg_types *compatible_reg_types[__BPF_ARG_TYPE_MAX] = {
40144031
[ARG_PTR_TO_CTX] = &context_types,
40154032
[ARG_PTR_TO_CTX_OR_NULL] = &context_types,
40164033
[ARG_PTR_TO_SOCK_COMMON] = &sock_types,
4034+
[ARG_PTR_TO_BTF_ID_SOCK_COMMON] = &btf_id_sock_common_types,
40174035
[ARG_PTR_TO_SOCKET] = &fullsock_types,
40184036
[ARG_PTR_TO_SOCKET_OR_NULL] = &fullsock_types,
40194037
[ARG_PTR_TO_BTF_ID] = &btf_ptr_types,
@@ -4028,26 +4046,61 @@ static const struct bpf_reg_types *compatible_reg_types[__BPF_ARG_TYPE_MAX] = {
40284046
};
40294047

40304048
static int check_reg_type(struct bpf_verifier_env *env, u32 regno,
4031-
const struct bpf_reg_types *compatible)
4049+
enum bpf_arg_type arg_type,
4050+
const u32 *arg_btf_id)
40324051
{
40334052
struct bpf_reg_state *regs = cur_regs(env), *reg = &regs[regno];
40344053
enum bpf_reg_type expected, type = reg->type;
4054+
const struct bpf_reg_types *compatible;
40354055
int i, j;
40364056

4057+
compatible = compatible_reg_types[arg_type];
4058+
if (!compatible) {
4059+
verbose(env, "verifier internal error: unsupported arg type %d\n", arg_type);
4060+
return -EFAULT;
4061+
}
4062+
40374063
for (i = 0; i < ARRAY_SIZE(compatible->types); i++) {
40384064
expected = compatible->types[i];
40394065
if (expected == NOT_INIT)
40404066
break;
40414067

40424068
if (type == expected)
4043-
return 0;
4069+
goto found;
40444070
}
40454071

40464072
verbose(env, "R%d type=%s expected=", regno, reg_type_str[type]);
40474073
for (j = 0; j + 1 < i; j++)
40484074
verbose(env, "%s, ", reg_type_str[compatible->types[j]]);
40494075
verbose(env, "%s\n", reg_type_str[compatible->types[j]]);
40504076
return -EACCES;
4077+
4078+
found:
4079+
if (type == PTR_TO_BTF_ID) {
4080+
if (!arg_btf_id) {
4081+
if (!compatible->btf_id) {
4082+
verbose(env, "verifier internal error: missing arg compatible BTF ID\n");
4083+
return -EFAULT;
4084+
}
4085+
arg_btf_id = compatible->btf_id;
4086+
}
4087+
4088+
if (!btf_struct_ids_match(&env->log, reg->off, reg->btf_id,
4089+
*arg_btf_id)) {
4090+
verbose(env, "R%d is of type %s but %s is expected\n",
4091+
regno, kernel_type_name(reg->btf_id),
4092+
kernel_type_name(*arg_btf_id));
4093+
return -EACCES;
4094+
}
4095+
4096+
if (!tnum_is_const(reg->var_off) || reg->var_off.value) {
4097+
verbose(env, "R%d is a pointer to in-kernel struct with non-zero offset\n",
4098+
regno);
4099+
return -EACCES;
4100+
}
4101+
}
4102+
4103+
return 0;
40514104
}
40524105

40534106
static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
@@ -4057,7 +4110,6 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
40574110
u32 regno = BPF_REG_1 + arg;
40584111
struct bpf_reg_state *regs = cur_regs(env), *reg = &regs[regno];
40594112
enum bpf_arg_type arg_type = fn->arg_type[arg];
4060-
const struct bpf_reg_types *compatible;
40614113
enum bpf_reg_type type = reg->type;
40624114
int err = 0;
40634115

@@ -4097,35 +4149,11 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
40974149
*/
40984150
goto skip_type_check;
40994151

4100-
compatible = compatible_reg_types[arg_type];
4101-
if (!compatible) {
4102-
verbose(env, "verifier internal error: unsupported arg type %d\n", arg_type);
4103-
return -EFAULT;
4104-
}
4105-
4106-
err = check_reg_type(env, regno, compatible);
4152+
err = check_reg_type(env, regno, arg_type, fn->arg_btf_id[arg]);
41074153
if (err)
41084154
return err;
41094155

4110-
if (type == PTR_TO_BTF_ID) {
4111-
const u32 *btf_id = fn->arg_btf_id[arg];
4112-
4113-
if (!btf_id) {
4114-
verbose(env, "verifier internal error: missing BTF ID\n");
4115-
return -EFAULT;
4116-
}
4117-
4118-
if (!btf_struct_ids_match(&env->log, reg->off, reg->btf_id, *btf_id)) {
4119-
verbose(env, "R%d is of type %s but %s is expected\n",
4120-
regno, kernel_type_name(reg->btf_id), kernel_type_name(*btf_id));
4121-
return -EACCES;
4122-
}
4123-
if (!tnum_is_const(reg->var_off) || reg->var_off.value) {
4124-
verbose(env, "R%d is a pointer to in-kernel struct with non-zero offset\n",
4125-
regno);
4126-
return -EACCES;
4127-
}
4128-
} else if (type == PTR_TO_CTX) {
4156+
if (type == PTR_TO_CTX) {
41294157
err = check_ctx_reg(env, reg, regno);
41304158
if (err < 0)
41314159
return err;
@@ -4573,10 +4601,14 @@ static bool check_btf_id_ok(const struct bpf_func_proto *fn)
45734601
{
45744602
int i;
45754603

4576-
for (i = 0; i < ARRAY_SIZE(fn->arg_type); i++)
4604+
for (i = 0; i < ARRAY_SIZE(fn->arg_type); i++) {
45774605
if (fn->arg_type[i] == ARG_PTR_TO_BTF_ID && !fn->arg_btf_id[i])
45784606
return false;
45794607

4608+
if (fn->arg_type[i] != ARG_PTR_TO_BTF_ID && fn->arg_btf_id[i])
4609+
return false;
4610+
}
4611+
45804612
return true;
45814613
}
45824614

net/core/bpf_sk_storage.c

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ BPF_CALL_4(bpf_sk_storage_get, struct bpf_map *, map, struct sock *, sk,
269269
{
270270
struct bpf_local_storage_data *sdata;
271271

272-
if (flags > BPF_SK_STORAGE_GET_F_CREATE)
272+
if (!sk || !sk_fullsock(sk) || flags > BPF_SK_STORAGE_GET_F_CREATE)
273273
return (unsigned long)NULL;
274274

275275
sdata = sk_storage_lookup(sk, map, true);
@@ -299,6 +299,9 @@ BPF_CALL_4(bpf_sk_storage_get, struct bpf_map *, map, struct sock *, sk,
299299

300300
BPF_CALL_2(bpf_sk_storage_delete, struct bpf_map *, map, struct sock *, sk)
301301
{
302+
if (!sk || !sk_fullsock(sk))
303+
return -EINVAL;
304+
302305
if (refcount_inc_not_zero(&sk->sk_refcnt)) {
303306
int err;
304307

@@ -355,7 +358,7 @@ const struct bpf_func_proto bpf_sk_storage_get_proto = {
355358
.gpl_only = false,
356359
.ret_type = RET_PTR_TO_MAP_VALUE_OR_NULL,
357360
.arg1_type = ARG_CONST_MAP_PTR,
358-
.arg2_type = ARG_PTR_TO_SOCKET,
361+
.arg2_type = ARG_PTR_TO_BTF_ID_SOCK_COMMON,
359362
.arg3_type = ARG_PTR_TO_MAP_VALUE_OR_NULL,
360363
.arg4_type = ARG_ANYTHING,
361364
};
@@ -375,27 +378,7 @@ const struct bpf_func_proto bpf_sk_storage_delete_proto = {
375378
.gpl_only = false,
376379
.ret_type = RET_INTEGER,
377380
.arg1_type = ARG_CONST_MAP_PTR,
378-
.arg2_type = ARG_PTR_TO_SOCKET,
379-
};
380-
381-
const struct bpf_func_proto sk_storage_get_btf_proto = {
382-
.func = bpf_sk_storage_get,
383-
.gpl_only = false,
384-
.ret_type = RET_PTR_TO_MAP_VALUE_OR_NULL,
385-
.arg1_type = ARG_CONST_MAP_PTR,
386-
.arg2_type = ARG_PTR_TO_BTF_ID,
387-
.arg2_btf_id = &btf_sock_ids[BTF_SOCK_TYPE_SOCK],
388-
.arg3_type = ARG_PTR_TO_MAP_VALUE_OR_NULL,
389-
.arg4_type = ARG_ANYTHING,
390-
};
391-
392-
const struct bpf_func_proto sk_storage_delete_btf_proto = {
393-
.func = bpf_sk_storage_delete,
394-
.gpl_only = false,
395-
.ret_type = RET_INTEGER,
396-
.arg1_type = ARG_CONST_MAP_PTR,
397-
.arg2_type = ARG_PTR_TO_BTF_ID,
398-
.arg2_btf_id = &btf_sock_ids[BTF_SOCK_TYPE_SOCK],
381+
.arg2_type = ARG_PTR_TO_BTF_ID_SOCK_COMMON,
399382
};
400383

401384
struct bpf_sk_storage_diag {

0 commit comments

Comments
 (0)