History

bpf: Add PTR_TO_BTF_ID_OR_NULL support

Add bpf_reg_type PTR_TO_BTF_ID_OR_NULL support. For tracing/iter program, the bpf program context definition, e.g., for previous bpf_map target, looks like struct bpf_iter__bpf_map { struct bpf_iter_meta *meta; struct bpf_map *map; }; The kernel guarantees that meta is not NULL, but map pointer maybe NULL. The NULL map indicates that all objects have been traversed, so bpf program can take proper action, e.g., do final aggregation and/or send final report to user space. Add btf_id_or_null_non0_off to prog->aux structure, to indicate that if the context access offset is not 0, set to PTR_TO_BTF_ID_OR_NULL instead of PTR_TO_BTF_ID. This bit is set for tracing/iter program.

Yonghong Song committed 6 years ago

Commit b121b341 parent eaaacd23 files · +18 −5Browse files

Unified · Split

3 files
  1. include/linux/bpf.h +2 −0
  2. kernel/bpf/btf.c +4 −1
  3. kernel/bpf/verifier.c +12 −4
include/linux/bpf.h+2−0
@@ -320,6 +320,7 @@ enum bpf_reg_type { · 319 unmodified lines
320320 PTR_TO_TP_BUFFER, /* reg points to a writable raw tp's buffer */
321321 PTR_TO_XDP_SOCK, /* reg points to struct xdp_sock */
322322 PTR_TO_BTF_ID, /* reg points to kernel struct */
323+ PTR_TO_BTF_ID_OR_NULL, /* reg points to kernel struct or NULL */
323324 };
324325
325326 /* The information passed from prog-specific *_is_valid_access
@@ -658,6 +659,7 @@ struct bpf_prog_aux { · 332 unmodified lines
658659 bool offload_requested;
659660 bool attach_btf_trace; /* true if attaching to BTF-enabled raw tp */
660661 bool func_proto_unreliable;
662+ bool btf_id_or_null_non0_off;
661663 enum bpf_tramp_prog_type trampoline_prog_type;
662664 struct bpf_trampoline *trampoline;
663665 struct hlist_node tramp_hlist;
kernel/bpf/btf.c+4−1
@@ -3790,7 +3790,10 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type, · 3789 unmodified lines
37903790 return true;
37913791
37923792 /* this is a pointer to another type */
3793− info->reg_type = PTR_TO_BTF_ID;
3793+ if (off != 0 && prog->aux->btf_id_or_null_non0_off)
3794+ info->reg_type = PTR_TO_BTF_ID_OR_NULL;
3795+ else
3796+ info->reg_type = PTR_TO_BTF_ID;
37943797
37953798 if (tgt_prog) {
37963799 ret = btf_translate_to_vmlinux(log, btf, t, tgt_prog->type, arg);
kernel/bpf/verifier.c+12−4
@@ -398,7 +398,8 @@ static bool reg_type_may_be_null(enum bpf_reg_type type) · 397 unmodified lines
398398 return type == PTR_TO_MAP_VALUE_OR_NULL ||
399399 type == PTR_TO_SOCKET_OR_NULL ||
400400 type == PTR_TO_SOCK_COMMON_OR_NULL ||
401− type == PTR_TO_TCP_SOCK_OR_NULL;
401+ type == PTR_TO_TCP_SOCK_OR_NULL ||
402+ type == PTR_TO_BTF_ID_OR_NULL;
402403 }
403404
404405 static bool reg_may_point_to_spin_lock(const struct bpf_reg_state *reg)
@@ -483,6 +484,7 @@ static const char * const reg_type_str[] = { · 78 unmodified lines
483484 [PTR_TO_TP_BUFFER] = "tp_buffer",
484485 [PTR_TO_XDP_SOCK] = "xdp_sock",
485486 [PTR_TO_BTF_ID] = "ptr_",
487+ [PTR_TO_BTF_ID_OR_NULL] = "ptr_or_null_",
486488 };
487489
488490 static char slot_type_char[] = {
@@ -543,7 +545,7 @@ static void print_verifier_state(struct bpf_verifier_env *env, · 54 unmodified lines
543545 /* reg->off should be 0 for SCALAR_VALUE */
544546 verbose(env, "%lld", reg->var_off.value + reg->off);
545547 } else {
546− if (t == PTR_TO_BTF_ID)
548+ if (t == PTR_TO_BTF_ID || t == PTR_TO_BTF_ID_OR_NULL)
547549 verbose(env, "%s", kernel_type_name(reg->btf_id));
548550 verbose(env, "(id=%d", reg->id);
549551 if (reg_type_may_be_refcounted_or_null(t))
@@ -2139,6 +2141,7 @@ static bool is_spillable_regtype(enum bpf_reg_type type) · 1589 unmodified lines
21392141 case PTR_TO_TCP_SOCK_OR_NULL:
21402142 case PTR_TO_XDP_SOCK:
21412143 case PTR_TO_BTF_ID:
2144+ case PTR_TO_BTF_ID_OR_NULL:
21422145 return true;
21432146 default:
21442147 return false;
@@ -2659,7 +2662,7 @@ static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off, · 514 unmodified lines
26592662 */
26602663 *reg_type = info.reg_type;
26612664
2662− if (*reg_type == PTR_TO_BTF_ID)
2665+ if (*reg_type == PTR_TO_BTF_ID || *reg_type == PTR_TO_BTF_ID_OR_NULL)
26632666 *btf_id = info.btf_id;
26642667 else
26652668 env->insn_aux_data[insn_idx].ctx_field_size = info.ctx_field_size;
@@ -3243,7 +3246,8 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn · 577 unmodified lines
32433246 * a sub-register.
32443247 */
32453248 regs[value_regno].subreg_def = DEF_NOT_SUBREG;
3246− if (reg_type == PTR_TO_BTF_ID)
3249+ if (reg_type == PTR_TO_BTF_ID ||
3250+ reg_type == PTR_TO_BTF_ID_OR_NULL)
32473251 regs[value_regno].btf_id = btf_id;
32483252 }
32493253 regs[value_regno].type = reg_type;
@@ -6572,6 +6576,8 @@ static void mark_ptr_or_null_reg(struct bpf_func_state *state, · 3322 unmodified lines
65726576 reg->type = PTR_TO_SOCK_COMMON;
65736577 } else if (reg->type == PTR_TO_TCP_SOCK_OR_NULL) {
65746578 reg->type = PTR_TO_TCP_SOCK;
6579+ } else if (reg->type == PTR_TO_BTF_ID_OR_NULL) {
6580+ reg->type = PTR_TO_BTF_ID;
65756581 }
65766582 if (is_null) {
65776583 /* We don't need id and ref_obj_id from this point
@@ -8429,6 +8435,7 @@ static bool reg_type_mismatch_ok(enum bpf_reg_type type) · 1851 unmodified lines
84298435 case PTR_TO_TCP_SOCK_OR_NULL:
84308436 case PTR_TO_XDP_SOCK:
84318437 case PTR_TO_BTF_ID:
8438+ case PTR_TO_BTF_ID_OR_NULL:
84328439 return false;
84338440 default:
84348441 return true;
@@ -10640,6 +10647,7 @@ static int check_attach_btf_id(struct bpf_verifier_env *env) · 2205 unmodified lines
1064010647 prog->aux->attach_func_proto = t;
1064110648 if (!bpf_iter_prog_supported(prog))
1064210649 return -EINVAL;
10650+ prog->aux->btf_id_or_null_non0_off = true;
1064310651 ret = btf_distill_func_proto(&env->log, btf, t,
1064410652 tname, &fmodel);
1064510653 return ret;