Skip to content

Commit cdbde08

Browse files
author
Alexei Starovoitov
committed
Merge branch 'bpf-make-trusted-args-nullable'
Vadim Fedorenko says: ==================== bpf: make trusted args nullable Current verifier checks for the arg to be nullable after checking for certain pointer types. It prevents programs to pass NULL to kfunc args even if they are marked as nullable. This patchset adjusts verifier and changes bpf crypto kfuncs to allow null for IV parameter which is optional for some ciphers. Benchmark shows ~4% improvements when there is no need to initialise 0-sized dynptr. v3: - add special selftest for nullable parameters v2: - adjust kdoc accordingly ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
2 parents 373a4e1 + 2d45ab1 commit cdbde08

File tree

8 files changed

+85
-34
lines changed

8 files changed

+85
-34
lines changed

kernel/bpf/crypto.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ static int bpf_crypto_crypt(const struct bpf_crypto_ctx *ctx,
275275
if (__bpf_dynptr_is_rdonly(dst))
276276
return -EINVAL;
277277

278-
siv_len = __bpf_dynptr_size(siv);
278+
siv_len = siv ? __bpf_dynptr_size(siv) : 0;
279279
src_len = __bpf_dynptr_size(src);
280280
dst_len = __bpf_dynptr_size(dst);
281281
if (!src_len || !dst_len)
@@ -303,42 +303,42 @@ static int bpf_crypto_crypt(const struct bpf_crypto_ctx *ctx,
303303

304304
/**
305305
* bpf_crypto_decrypt() - Decrypt buffer using configured context and IV provided.
306-
* @ctx: The crypto context being used. The ctx must be a trusted pointer.
307-
* @src: bpf_dynptr to the encrypted data. Must be a trusted pointer.
308-
* @dst: bpf_dynptr to the buffer where to store the result. Must be a trusted pointer.
309-
* @siv: bpf_dynptr to IV data and state data to be used by decryptor.
306+
* @ctx: The crypto context being used. The ctx must be a trusted pointer.
307+
* @src: bpf_dynptr to the encrypted data. Must be a trusted pointer.
308+
* @dst: bpf_dynptr to the buffer where to store the result. Must be a trusted pointer.
309+
* @siv__nullable: bpf_dynptr to IV data and state data to be used by decryptor. May be NULL.
310310
*
311311
* Decrypts provided buffer using IV data and the crypto context. Crypto context must be configured.
312312
*/
313313
__bpf_kfunc int bpf_crypto_decrypt(struct bpf_crypto_ctx *ctx,
314314
const struct bpf_dynptr *src,
315315
const struct bpf_dynptr *dst,
316-
const struct bpf_dynptr *siv)
316+
const struct bpf_dynptr *siv__nullable)
317317
{
318318
const struct bpf_dynptr_kern *src_kern = (struct bpf_dynptr_kern *)src;
319319
const struct bpf_dynptr_kern *dst_kern = (struct bpf_dynptr_kern *)dst;
320-
const struct bpf_dynptr_kern *siv_kern = (struct bpf_dynptr_kern *)siv;
320+
const struct bpf_dynptr_kern *siv_kern = (struct bpf_dynptr_kern *)siv__nullable;
321321

322322
return bpf_crypto_crypt(ctx, src_kern, dst_kern, siv_kern, true);
323323
}
324324

325325
/**
326326
* bpf_crypto_encrypt() - Encrypt buffer using configured context and IV provided.
327-
* @ctx: The crypto context being used. The ctx must be a trusted pointer.
328-
* @src: bpf_dynptr to the plain data. Must be a trusted pointer.
329-
* @dst: bpf_dynptr to buffer where to store the result. Must be a trusted pointer.
330-
* @siv: bpf_dynptr to IV data and state data to be used by decryptor.
327+
* @ctx: The crypto context being used. The ctx must be a trusted pointer.
328+
* @src: bpf_dynptr to the plain data. Must be a trusted pointer.
329+
* @dst: bpf_dynptr to the buffer where to store the result. Must be a trusted pointer.
330+
* @siv__nullable: bpf_dynptr to IV data and state data to be used by decryptor. May be NULL.
331331
*
332332
* Encrypts provided buffer using IV data and the crypto context. Crypto context must be configured.
333333
*/
334334
__bpf_kfunc int bpf_crypto_encrypt(struct bpf_crypto_ctx *ctx,
335335
const struct bpf_dynptr *src,
336336
const struct bpf_dynptr *dst,
337-
const struct bpf_dynptr *siv)
337+
const struct bpf_dynptr *siv__nullable)
338338
{
339339
const struct bpf_dynptr_kern *src_kern = (struct bpf_dynptr_kern *)src;
340340
const struct bpf_dynptr_kern *dst_kern = (struct bpf_dynptr_kern *)dst;
341-
const struct bpf_dynptr_kern *siv_kern = (struct bpf_dynptr_kern *)siv;
341+
const struct bpf_dynptr_kern *siv_kern = (struct bpf_dynptr_kern *)siv__nullable;
342342

343343
return bpf_crypto_crypt(ctx, src_kern, dst_kern, siv_kern, false);
344344
}

kernel/bpf/verifier.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11187,6 +11187,9 @@ get_kfunc_ptr_arg_type(struct bpf_verifier_env *env,
1118711187
if (btf_is_prog_ctx_type(&env->log, meta->btf, t, resolve_prog_type(env->prog), argno))
1118811188
return KF_ARG_PTR_TO_CTX;
1118911189

11190+
if (is_kfunc_arg_nullable(meta->btf, &args[argno]) && register_is_null(reg))
11191+
return KF_ARG_PTR_TO_NULL;
11192+
1119011193
if (is_kfunc_arg_alloc_obj(meta->btf, &args[argno]))
1119111194
return KF_ARG_PTR_TO_ALLOC_BTF_ID;
1119211195

@@ -11232,9 +11235,6 @@ get_kfunc_ptr_arg_type(struct bpf_verifier_env *env,
1123211235
if (is_kfunc_arg_callback(env, meta->btf, &args[argno]))
1123311236
return KF_ARG_PTR_TO_CALLBACK;
1123411237

11235-
if (is_kfunc_arg_nullable(meta->btf, &args[argno]) && register_is_null(reg))
11236-
return KF_ARG_PTR_TO_NULL;
11237-
1123811238
if (argno + 1 < nargs &&
1123911239
(is_kfunc_arg_mem_size(meta->btf, &args[argno + 1], &regs[regno + 1]) ||
1124011240
is_kfunc_arg_const_mem_size(meta->btf, &args[argno + 1], &regs[regno + 1])))

tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,11 @@ __bpf_kfunc void bpf_kfunc_common_test(void)
154154
{
155155
}
156156

157+
__bpf_kfunc void bpf_kfunc_dynptr_test(struct bpf_dynptr *ptr,
158+
struct bpf_dynptr *ptr__nullable)
159+
{
160+
}
161+
157162
struct bpf_testmod_btf_type_tag_1 {
158163
int a;
159164
};
@@ -363,6 +368,7 @@ BTF_ID_FLAGS(func, bpf_iter_testmod_seq_new, KF_ITER_NEW)
363368
BTF_ID_FLAGS(func, bpf_iter_testmod_seq_next, KF_ITER_NEXT | KF_RET_NULL)
364369
BTF_ID_FLAGS(func, bpf_iter_testmod_seq_destroy, KF_ITER_DESTROY)
365370
BTF_ID_FLAGS(func, bpf_kfunc_common_test)
371+
BTF_ID_FLAGS(func, bpf_kfunc_dynptr_test)
366372
BTF_KFUNCS_END(bpf_testmod_common_kfunc_ids)
367373

368374
static const struct btf_kfunc_id_set bpf_testmod_common_kfunc_set = {

tools/testing/selftests/bpf/bpf_testmod/bpf_testmod_kfunc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,5 @@ int bpf_kfunc_call_sock_sendmsg(struct sendmsg_args *args) __ksym;
134134
int bpf_kfunc_call_kernel_getsockname(struct addr_args *args) __ksym;
135135
int bpf_kfunc_call_kernel_getpeername(struct addr_args *args) __ksym;
136136

137+
void bpf_kfunc_dynptr_test(struct bpf_dynptr *ptr, struct bpf_dynptr *ptr__nullable) __ksym;
137138
#endif /* _BPF_TESTMOD_KFUNC_H */
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
/* Copyright (c) 2024 Meta Platforms, Inc */
4+
5+
#include <test_progs.h>
6+
#include "test_kfunc_param_nullable.skel.h"
7+
8+
void test_kfunc_param_nullable(void)
9+
{
10+
RUN_TESTS(test_kfunc_param_nullable);
11+
}

tools/testing/selftests/bpf/progs/crypto_bench.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ int crypto_encrypt(struct __sk_buff *skb)
5757
{
5858
struct __crypto_ctx_value *v;
5959
struct bpf_crypto_ctx *ctx;
60-
struct bpf_dynptr psrc, pdst, iv;
60+
struct bpf_dynptr psrc, pdst;
6161

6262
v = crypto_ctx_value_lookup();
6363
if (!v) {
@@ -73,9 +73,8 @@ int crypto_encrypt(struct __sk_buff *skb)
7373

7474
bpf_dynptr_from_skb(skb, 0, &psrc);
7575
bpf_dynptr_from_mem(dst, len, 0, &pdst);
76-
bpf_dynptr_from_mem(dst, 0, 0, &iv);
7776

78-
status = bpf_crypto_encrypt(ctx, &psrc, &pdst, &iv);
77+
status = bpf_crypto_encrypt(ctx, &psrc, &pdst, NULL);
7978
__sync_add_and_fetch(&hits, 1);
8079

8180
return 0;
@@ -84,7 +83,7 @@ int crypto_encrypt(struct __sk_buff *skb)
8483
SEC("tc")
8584
int crypto_decrypt(struct __sk_buff *skb)
8685
{
87-
struct bpf_dynptr psrc, pdst, iv;
86+
struct bpf_dynptr psrc, pdst;
8887
struct __crypto_ctx_value *v;
8988
struct bpf_crypto_ctx *ctx;
9089

@@ -98,9 +97,8 @@ int crypto_decrypt(struct __sk_buff *skb)
9897

9998
bpf_dynptr_from_skb(skb, 0, &psrc);
10099
bpf_dynptr_from_mem(dst, len, 0, &pdst);
101-
bpf_dynptr_from_mem(dst, 0, 0, &iv);
102100

103-
status = bpf_crypto_decrypt(ctx, &psrc, &pdst, &iv);
101+
status = bpf_crypto_decrypt(ctx, &psrc, &pdst, NULL);
104102
__sync_add_and_fetch(&hits, 1);
105103

106104
return 0;

tools/testing/selftests/bpf/progs/crypto_sanity.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ int decrypt_sanity(struct __sk_buff *skb)
8989
{
9090
struct __crypto_ctx_value *v;
9191
struct bpf_crypto_ctx *ctx;
92-
struct bpf_dynptr psrc, pdst, iv;
92+
struct bpf_dynptr psrc, pdst;
9393
int err;
9494

9595
err = skb_dynptr_validate(skb, &psrc);
@@ -114,12 +114,8 @@ int decrypt_sanity(struct __sk_buff *skb)
114114
* production code, a percpu map should be used to store the result.
115115
*/
116116
bpf_dynptr_from_mem(dst, sizeof(dst), 0, &pdst);
117-
/* iv dynptr has to be initialized with 0 size, but proper memory region
118-
* has to be provided anyway
119-
*/
120-
bpf_dynptr_from_mem(dst, 0, 0, &iv);
121117

122-
status = bpf_crypto_decrypt(ctx, &psrc, &pdst, &iv);
118+
status = bpf_crypto_decrypt(ctx, &psrc, &pdst, NULL);
123119

124120
return TC_ACT_SHOT;
125121
}
@@ -129,7 +125,7 @@ int encrypt_sanity(struct __sk_buff *skb)
129125
{
130126
struct __crypto_ctx_value *v;
131127
struct bpf_crypto_ctx *ctx;
132-
struct bpf_dynptr psrc, pdst, iv;
128+
struct bpf_dynptr psrc, pdst;
133129
int err;
134130

135131
status = 0;
@@ -156,12 +152,8 @@ int encrypt_sanity(struct __sk_buff *skb)
156152
* production code, a percpu map should be used to store the result.
157153
*/
158154
bpf_dynptr_from_mem(dst, sizeof(dst), 0, &pdst);
159-
/* iv dynptr has to be initialized with 0 size, but proper memory region
160-
* has to be provided anyway
161-
*/
162-
bpf_dynptr_from_mem(dst, 0, 0, &iv);
163155

164-
status = bpf_crypto_encrypt(ctx, &psrc, &pdst, &iv);
156+
status = bpf_crypto_encrypt(ctx, &psrc, &pdst, NULL);
165157

166158
return TC_ACT_SHOT;
167159
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2024 Meta Platforms, Inc */
3+
#include <vmlinux.h>
4+
#include <bpf/bpf_helpers.h>
5+
#include "bpf_misc.h"
6+
#include "bpf_kfuncs.h"
7+
#include "../bpf_testmod/bpf_testmod_kfunc.h"
8+
9+
SEC("tc")
10+
int kfunc_dynptr_nullable_test1(struct __sk_buff *skb)
11+
{
12+
struct bpf_dynptr data;
13+
14+
bpf_dynptr_from_skb(skb, 0, &data);
15+
bpf_kfunc_dynptr_test(&data, NULL);
16+
17+
return 0;
18+
}
19+
20+
SEC("tc")
21+
int kfunc_dynptr_nullable_test2(struct __sk_buff *skb)
22+
{
23+
struct bpf_dynptr data;
24+
25+
bpf_dynptr_from_skb(skb, 0, &data);
26+
bpf_kfunc_dynptr_test(&data, &data);
27+
28+
return 0;
29+
}
30+
31+
SEC("tc")
32+
__failure __msg("expected pointer to stack or dynptr_ptr")
33+
int kfunc_dynptr_nullable_test3(struct __sk_buff *skb)
34+
{
35+
struct bpf_dynptr data;
36+
37+
bpf_dynptr_from_skb(skb, 0, &data);
38+
bpf_kfunc_dynptr_test(NULL, &data);
39+
40+
return 0;
41+
}
42+
43+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)