Skip to content

Commit 69b4507

Browse files
author
Alexei Starovoitov
committed
Merge branch 'misc-BPF-improvements'
Daniel Borkmann says: ==================== This set adds various patches I still had in my queue, first two are test cases to provide coverage for the recent two fixes that went to bpf tree, then a small improvement on the error message for gpl helpers. Next, we expose prog and map id into fdinfo in order to allow for inspection of these objections currently used in applications. Patch after that removes a retpoline call for map lookup/update/delete helpers. A new helper is added in the subsequent patch to lookup the skb's socket's cgroup v2 id which can be used in an efficient way for e.g. lookups on egress side. Next one is a fix to fully clear state info in tunnel/xfrm helpers. Given this is full cap_sys_admin from init ns and has same priv requirements like tracing, bpf-next should be okay. A small bug fix for bpf_asm follows, and next a fix for context access in tracing which was recently reported. Lastly, a small update in the maintainer's file to add patchwork url and missing files. Thanks! v2 -> v3: - Noticed a merge artefact inside uapi header comment, sigh, fixed now. v1 -> v2: - minor fix in getting context access work on 32 bit for tracing - add paragraph to uapi helper doc to better describe kernel build deps for cggroup helper ==================== Signed-off-by: Alexei Starovoitov <[email protected]>
2 parents 25c1013 + 10a7656 commit 69b4507

File tree

13 files changed

+421
-70
lines changed

13 files changed

+421
-70
lines changed

MAINTAINERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2722,6 +2722,7 @@ L: [email protected]
27222722
27232723
T: git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git
27242724
T: git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git
2725+
Q: https://patchwork.ozlabs.org/project/netdev/list/?delegate=77147
27252726
S: Supported
27262727
F: arch/x86/net/bpf_jit*
27272728
F: Documentation/networking/filter.txt
@@ -2740,6 +2741,7 @@ F: net/sched/act_bpf.c
27402741
F: net/sched/cls_bpf.c
27412742
F: samples/bpf/
27422743
F: tools/bpf/
2744+
F: tools/lib/bpf/
27432745
F: tools/testing/selftests/bpf/
27442746

27452747
BROADCOM B44 10/100 ETHERNET DRIVER

include/linux/filter.h

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,21 @@ struct xdp_buff;
289289
.off = OFF, \
290290
.imm = 0 })
291291

292+
/* Relative call */
293+
294+
#define BPF_CALL_REL(TGT) \
295+
((struct bpf_insn) { \
296+
.code = BPF_JMP | BPF_CALL, \
297+
.dst_reg = 0, \
298+
.src_reg = BPF_PSEUDO_CALL, \
299+
.off = 0, \
300+
.imm = TGT })
301+
292302
/* Function call */
293303

304+
#define BPF_CAST_CALL(x) \
305+
((u64 (*)(u64, u64, u64, u64, u64))(x))
306+
294307
#define BPF_EMIT_CALL(FUNC) \
295308
((struct bpf_insn) { \
296309
.code = BPF_JMP | BPF_CALL, \
@@ -626,16 +639,34 @@ static inline bool bpf_prog_was_classic(const struct bpf_prog *prog)
626639
return prog->type == BPF_PROG_TYPE_UNSPEC;
627640
}
628641

629-
static inline bool
630-
bpf_ctx_narrow_access_ok(u32 off, u32 size, const u32 size_default)
642+
static inline u32 bpf_ctx_off_adjust_machine(u32 size)
643+
{
644+
const u32 size_machine = sizeof(unsigned long);
645+
646+
if (size > size_machine && size % size_machine == 0)
647+
size = size_machine;
648+
649+
return size;
650+
}
651+
652+
static inline bool bpf_ctx_narrow_align_ok(u32 off, u32 size_access,
653+
u32 size_default)
631654
{
632-
bool off_ok;
655+
size_default = bpf_ctx_off_adjust_machine(size_default);
656+
size_access = bpf_ctx_off_adjust_machine(size_access);
657+
633658
#ifdef __LITTLE_ENDIAN
634-
off_ok = (off & (size_default - 1)) == 0;
659+
return (off & (size_default - 1)) == 0;
635660
#else
636-
off_ok = (off & (size_default - 1)) + size == size_default;
661+
return (off & (size_default - 1)) + size_access == size_default;
637662
#endif
638-
return off_ok && size <= size_default && (size & (size - 1)) == 0;
663+
}
664+
665+
static inline bool
666+
bpf_ctx_narrow_access_ok(u32 off, u32 size, u32 size_default)
667+
{
668+
return bpf_ctx_narrow_align_ok(off, size, size_default) &&
669+
size <= size_default && (size & (size - 1)) == 0;
639670
}
640671

641672
#define bpf_classic_proglen(fprog) (fprog->len * sizeof(fprog->filter[0]))

include/uapi/linux/bpf.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2054,6 +2054,22 @@ union bpf_attr {
20542054
*
20552055
* Return
20562056
* 0
2057+
*
2058+
* uint64_t bpf_skb_cgroup_id(struct sk_buff *skb)
2059+
* Description
2060+
* Return the cgroup v2 id of the socket associated with the *skb*.
2061+
* This is roughly similar to the **bpf_get_cgroup_classid**\ ()
2062+
* helper for cgroup v1 by providing a tag resp. identifier that
2063+
* can be matched on or used for map lookups e.g. to implement
2064+
* policy. The cgroup v2 id of a given path in the hierarchy is
2065+
* exposed in user space through the f_handle API in order to get
2066+
* to the same 64-bit id.
2067+
*
2068+
* This helper can be used on TC egress path, but not on ingress,
2069+
* and is available only if the kernel was compiled with the
2070+
* **CONFIG_SOCK_CGROUP_DATA** configuration option.
2071+
* Return
2072+
* The id is returned or 0 in case the id could not be retrieved.
20572073
*/
20582074
#define __BPF_FUNC_MAPPER(FN) \
20592075
FN(unspec), \
@@ -2134,7 +2150,8 @@ union bpf_attr {
21342150
FN(lwt_seg6_adjust_srh), \
21352151
FN(lwt_seg6_action), \
21362152
FN(rc_repeat), \
2137-
FN(rc_keydown),
2153+
FN(rc_keydown), \
2154+
FN(skb_cgroup_id),
21382155

21392156
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
21402157
* function eBPF program intends to call
@@ -2251,7 +2268,7 @@ struct bpf_tunnel_key {
22512268
};
22522269
__u8 tunnel_tos;
22532270
__u8 tunnel_ttl;
2254-
__u16 tunnel_ext;
2271+
__u16 tunnel_ext; /* Padding, future use. */
22552272
__u32 tunnel_label;
22562273
};
22572274

@@ -2262,6 +2279,7 @@ struct bpf_xfrm_state {
22622279
__u32 reqid;
22632280
__u32 spi; /* Stored in network byte order */
22642281
__u16 family;
2282+
__u16 ext; /* Padding, future use. */
22652283
union {
22662284
__u32 remote_ipv4; /* Stored in network byte order */
22672285
__u32 remote_ipv6[4]; /* Stored in network byte order */

kernel/bpf/hashtab.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,9 @@ static u32 htab_map_gen_lookup(struct bpf_map *map, struct bpf_insn *insn_buf)
503503
struct bpf_insn *insn = insn_buf;
504504
const int ret = BPF_REG_0;
505505

506-
*insn++ = BPF_EMIT_CALL((u64 (*)(u64, u64, u64, u64, u64))__htab_map_lookup_elem);
506+
BUILD_BUG_ON(!__same_type(&__htab_map_lookup_elem,
507+
(void *(*)(struct bpf_map *map, void *key))NULL));
508+
*insn++ = BPF_EMIT_CALL(BPF_CAST_CALL(__htab_map_lookup_elem));
507509
*insn++ = BPF_JMP_IMM(BPF_JEQ, ret, 0, 1);
508510
*insn++ = BPF_ALU64_IMM(BPF_ADD, ret,
509511
offsetof(struct htab_elem, key) +
@@ -530,7 +532,9 @@ static u32 htab_lru_map_gen_lookup(struct bpf_map *map,
530532
const int ret = BPF_REG_0;
531533
const int ref_reg = BPF_REG_1;
532534

533-
*insn++ = BPF_EMIT_CALL((u64 (*)(u64, u64, u64, u64, u64))__htab_map_lookup_elem);
535+
BUILD_BUG_ON(!__same_type(&__htab_map_lookup_elem,
536+
(void *(*)(struct bpf_map *map, void *key))NULL));
537+
*insn++ = BPF_EMIT_CALL(BPF_CAST_CALL(__htab_map_lookup_elem));
534538
*insn++ = BPF_JMP_IMM(BPF_JEQ, ret, 0, 4);
535539
*insn++ = BPF_LDX_MEM(BPF_B, ref_reg, ret,
536540
offsetof(struct htab_elem, lru_node) +
@@ -1369,7 +1373,9 @@ static u32 htab_of_map_gen_lookup(struct bpf_map *map,
13691373
struct bpf_insn *insn = insn_buf;
13701374
const int ret = BPF_REG_0;
13711375

1372-
*insn++ = BPF_EMIT_CALL((u64 (*)(u64, u64, u64, u64, u64))__htab_map_lookup_elem);
1376+
BUILD_BUG_ON(!__same_type(&__htab_map_lookup_elem,
1377+
(void *(*)(struct bpf_map *map, void *key))NULL));
1378+
*insn++ = BPF_EMIT_CALL(BPF_CAST_CALL(__htab_map_lookup_elem));
13731379
*insn++ = BPF_JMP_IMM(BPF_JEQ, ret, 0, 2);
13741380
*insn++ = BPF_ALU64_IMM(BPF_ADD, ret,
13751381
offsetof(struct htab_elem, key) +

kernel/bpf/syscall.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -327,13 +327,15 @@ static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp)
327327
"value_size:\t%u\n"
328328
"max_entries:\t%u\n"
329329
"map_flags:\t%#x\n"
330-
"memlock:\t%llu\n",
330+
"memlock:\t%llu\n"
331+
"map_id:\t%u\n",
331332
map->map_type,
332333
map->key_size,
333334
map->value_size,
334335
map->max_entries,
335336
map->map_flags,
336-
map->pages * 1ULL << PAGE_SHIFT);
337+
map->pages * 1ULL << PAGE_SHIFT,
338+
map->id);
337339

338340
if (owner_prog_type) {
339341
seq_printf(m, "owner_prog_type:\t%u\n",
@@ -1070,11 +1072,13 @@ static void bpf_prog_show_fdinfo(struct seq_file *m, struct file *filp)
10701072
"prog_type:\t%u\n"
10711073
"prog_jited:\t%u\n"
10721074
"prog_tag:\t%s\n"
1073-
"memlock:\t%llu\n",
1075+
"memlock:\t%llu\n"
1076+
"prog_id:\t%u\n",
10741077
prog->type,
10751078
prog->jited,
10761079
prog_tag,
1077-
prog->pages * 1ULL << PAGE_SHIFT);
1080+
prog->pages * 1ULL << PAGE_SHIFT,
1081+
prog->aux->id);
10781082
}
10791083
#endif
10801084

kernel/bpf/verifier.c

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2421,8 +2421,11 @@ record_func_map(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta,
24212421
struct bpf_insn_aux_data *aux = &env->insn_aux_data[insn_idx];
24222422

24232423
if (func_id != BPF_FUNC_tail_call &&
2424-
func_id != BPF_FUNC_map_lookup_elem)
2424+
func_id != BPF_FUNC_map_lookup_elem &&
2425+
func_id != BPF_FUNC_map_update_elem &&
2426+
func_id != BPF_FUNC_map_delete_elem)
24252427
return 0;
2428+
24262429
if (meta->map_ptr == NULL) {
24272430
verbose(env, "kernel subsystem misconfigured verifier\n");
24282431
return -EINVAL;
@@ -2462,7 +2465,7 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn
24622465

24632466
/* eBPF programs must be GPL compatible to use GPL-ed functions */
24642467
if (!env->prog->gpl_compatible && fn->gpl_only) {
2465-
verbose(env, "cannot call GPL only function from proprietary program\n");
2468+
verbose(env, "cannot call GPL-restricted function from non-GPL compatible program\n");
24662469
return -EINVAL;
24672470
}
24682471

@@ -5346,6 +5349,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
53465349
*/
53475350
is_narrower_load = size < ctx_field_size;
53485351
if (is_narrower_load) {
5352+
u32 size_default = bpf_ctx_off_adjust_machine(ctx_field_size);
53495353
u32 off = insn->off;
53505354
u8 size_code;
53515355

@@ -5360,7 +5364,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
53605364
else if (ctx_field_size == 8)
53615365
size_code = BPF_DW;
53625366

5363-
insn->off = off & ~(ctx_field_size - 1);
5367+
insn->off = off & ~(size_default - 1);
53645368
insn->code = BPF_LDX | BPF_MEM | size_code;
53655369
}
53665370

@@ -5586,6 +5590,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
55865590
struct bpf_insn *insn = prog->insnsi;
55875591
const struct bpf_func_proto *fn;
55885592
const int insn_cnt = prog->len;
5593+
const struct bpf_map_ops *ops;
55895594
struct bpf_insn_aux_data *aux;
55905595
struct bpf_insn insn_buf[16];
55915596
struct bpf_prog *new_prog;
@@ -5715,35 +5720,61 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
57155720
}
57165721

57175722
/* BPF_EMIT_CALL() assumptions in some of the map_gen_lookup
5718-
* handlers are currently limited to 64 bit only.
5723+
* and other inlining handlers are currently limited to 64 bit
5724+
* only.
57195725
*/
57205726
if (prog->jit_requested && BITS_PER_LONG == 64 &&
5721-
insn->imm == BPF_FUNC_map_lookup_elem) {
5727+
(insn->imm == BPF_FUNC_map_lookup_elem ||
5728+
insn->imm == BPF_FUNC_map_update_elem ||
5729+
insn->imm == BPF_FUNC_map_delete_elem)) {
57225730
aux = &env->insn_aux_data[i + delta];
57235731
if (bpf_map_ptr_poisoned(aux))
57245732
goto patch_call_imm;
57255733

57265734
map_ptr = BPF_MAP_PTR(aux->map_state);
5727-
if (!map_ptr->ops->map_gen_lookup)
5728-
goto patch_call_imm;
5735+
ops = map_ptr->ops;
5736+
if (insn->imm == BPF_FUNC_map_lookup_elem &&
5737+
ops->map_gen_lookup) {
5738+
cnt = ops->map_gen_lookup(map_ptr, insn_buf);
5739+
if (cnt == 0 || cnt >= ARRAY_SIZE(insn_buf)) {
5740+
verbose(env, "bpf verifier is misconfigured\n");
5741+
return -EINVAL;
5742+
}
57295743

5730-
cnt = map_ptr->ops->map_gen_lookup(map_ptr, insn_buf);
5731-
if (cnt == 0 || cnt >= ARRAY_SIZE(insn_buf)) {
5732-
verbose(env, "bpf verifier is misconfigured\n");
5733-
return -EINVAL;
5734-
}
5744+
new_prog = bpf_patch_insn_data(env, i + delta,
5745+
insn_buf, cnt);
5746+
if (!new_prog)
5747+
return -ENOMEM;
57355748

5736-
new_prog = bpf_patch_insn_data(env, i + delta, insn_buf,
5737-
cnt);
5738-
if (!new_prog)
5739-
return -ENOMEM;
5749+
delta += cnt - 1;
5750+
env->prog = prog = new_prog;
5751+
insn = new_prog->insnsi + i + delta;
5752+
continue;
5753+
}
57405754

5741-
delta += cnt - 1;
5755+
BUILD_BUG_ON(!__same_type(ops->map_lookup_elem,
5756+
(void *(*)(struct bpf_map *map, void *key))NULL));
5757+
BUILD_BUG_ON(!__same_type(ops->map_delete_elem,
5758+
(int (*)(struct bpf_map *map, void *key))NULL));
5759+
BUILD_BUG_ON(!__same_type(ops->map_update_elem,
5760+
(int (*)(struct bpf_map *map, void *key, void *value,
5761+
u64 flags))NULL));
5762+
switch (insn->imm) {
5763+
case BPF_FUNC_map_lookup_elem:
5764+
insn->imm = BPF_CAST_CALL(ops->map_lookup_elem) -
5765+
__bpf_call_base;
5766+
continue;
5767+
case BPF_FUNC_map_update_elem:
5768+
insn->imm = BPF_CAST_CALL(ops->map_update_elem) -
5769+
__bpf_call_base;
5770+
continue;
5771+
case BPF_FUNC_map_delete_elem:
5772+
insn->imm = BPF_CAST_CALL(ops->map_delete_elem) -
5773+
__bpf_call_base;
5774+
continue;
5775+
}
57425776

5743-
/* keep walking new program and skip insns we just inserted */
5744-
env->prog = prog = new_prog;
5745-
insn = new_prog->insnsi + i + delta;
5746-
continue;
5777+
goto patch_call_imm;
57475778
}
57485779

57495780
if (insn->imm == BPF_FUNC_redirect_map) {

kernel/trace/bpf_trace.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -880,8 +880,14 @@ static bool pe_prog_is_valid_access(int off, int size, enum bpf_access_type type
880880
return false;
881881
if (type != BPF_READ)
882882
return false;
883-
if (off % size != 0)
884-
return false;
883+
if (off % size != 0) {
884+
if (sizeof(unsigned long) != 4)
885+
return false;
886+
if (size != 8)
887+
return false;
888+
if (off % size != 4)
889+
return false;
890+
}
885891

886892
switch (off) {
887893
case bpf_ctx_range(struct bpf_perf_event_data, sample_period):

0 commit comments

Comments
 (0)