Skip to content

Commit 872a38d

Browse files
author
Alexei Starovoitov
committed
Merge branch 'bpf-next/master' into for-next
Signed-off-by: Alexei Starovoitov <[email protected]>
2 parents d056a06 + 3413bc0 commit 872a38d

File tree

15 files changed

+483
-51
lines changed

15 files changed

+483
-51
lines changed

include/linux/btf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ u32 btf_nr_types(const struct btf *btf);
223223
struct btf *btf_base_btf(const struct btf *btf);
224224
bool btf_type_is_i32(const struct btf_type *t);
225225
bool btf_type_is_i64(const struct btf_type *t);
226+
bool btf_type_is_primitive(const struct btf_type *t);
226227
bool btf_member_is_reg_int(const struct btf *btf, const struct btf_type *s,
227228
const struct btf_member *m,
228229
u32 expected_offset, u32 expected_size);

kernel/bpf/btf.c

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,12 @@ bool btf_type_is_i64(const struct btf_type *t)
891891
return btf_type_is_int(t) && __btf_type_int_is_regular(t, 8);
892892
}
893893

894+
bool btf_type_is_primitive(const struct btf_type *t)
895+
{
896+
return (btf_type_is_int(t) && btf_type_int_is_regular(t)) ||
897+
btf_is_any_enum(t);
898+
}
899+
894900
/*
895901
* Check that given struct member is a regular int with expected
896902
* offset and size.
@@ -6915,6 +6921,7 @@ enum bpf_struct_walk_result {
69156921
/* < 0 error */
69166922
WALK_SCALAR = 0,
69176923
WALK_PTR,
6924+
WALK_PTR_UNTRUSTED,
69186925
WALK_STRUCT,
69196926
};
69206927

@@ -7156,6 +7163,8 @@ static int btf_struct_walk(struct bpf_verifier_log *log, const struct btf *btf,
71567163
*field_name = mname;
71577164
return WALK_PTR;
71587165
}
7166+
7167+
return WALK_PTR_UNTRUSTED;
71597168
}
71607169

71617170
/* Allow more flexible access within an int as long as
@@ -7228,6 +7237,9 @@ int btf_struct_access(struct bpf_verifier_log *log,
72287237
*next_btf_id = id;
72297238
*flag = tmp_flag;
72307239
return PTR_TO_BTF_ID;
7240+
case WALK_PTR_UNTRUSTED:
7241+
*flag = MEM_RDONLY | PTR_UNTRUSTED;
7242+
return PTR_TO_MEM;
72317243
case WALK_SCALAR:
72327244
return SCALAR_VALUE;
72337245
case WALK_STRUCT:
@@ -7640,11 +7652,12 @@ static int btf_get_ptr_to_btf_id(struct bpf_verifier_log *log, int arg_idx,
76407652
}
76417653

76427654
enum btf_arg_tag {
7643-
ARG_TAG_CTX = BIT_ULL(0),
7644-
ARG_TAG_NONNULL = BIT_ULL(1),
7645-
ARG_TAG_TRUSTED = BIT_ULL(2),
7646-
ARG_TAG_NULLABLE = BIT_ULL(3),
7647-
ARG_TAG_ARENA = BIT_ULL(4),
7655+
ARG_TAG_CTX = BIT_ULL(0),
7656+
ARG_TAG_NONNULL = BIT_ULL(1),
7657+
ARG_TAG_TRUSTED = BIT_ULL(2),
7658+
ARG_TAG_UNTRUSTED = BIT_ULL(3),
7659+
ARG_TAG_NULLABLE = BIT_ULL(4),
7660+
ARG_TAG_ARENA = BIT_ULL(5),
76487661
};
76497662

76507663
/* Process BTF of a function to produce high-level expectation of function
@@ -7752,6 +7765,8 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
77527765
tags |= ARG_TAG_CTX;
77537766
} else if (strcmp(tag, "trusted") == 0) {
77547767
tags |= ARG_TAG_TRUSTED;
7768+
} else if (strcmp(tag, "untrusted") == 0) {
7769+
tags |= ARG_TAG_UNTRUSTED;
77557770
} else if (strcmp(tag, "nonnull") == 0) {
77567771
tags |= ARG_TAG_NONNULL;
77577772
} else if (strcmp(tag, "nullable") == 0) {
@@ -7812,6 +7827,38 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
78127827
sub->args[i].btf_id = kern_type_id;
78137828
continue;
78147829
}
7830+
if (tags & ARG_TAG_UNTRUSTED) {
7831+
struct btf *vmlinux_btf;
7832+
int kern_type_id;
7833+
7834+
if (tags & ~ARG_TAG_UNTRUSTED) {
7835+
bpf_log(log, "arg#%d untrusted cannot be combined with any other tags\n", i);
7836+
return -EINVAL;
7837+
}
7838+
7839+
ref_t = btf_type_skip_modifiers(btf, t->type, NULL);
7840+
if (btf_type_is_void(ref_t) || btf_type_is_primitive(ref_t)) {
7841+
sub->args[i].arg_type = ARG_PTR_TO_MEM | MEM_RDONLY | PTR_UNTRUSTED;
7842+
sub->args[i].mem_size = 0;
7843+
continue;
7844+
}
7845+
7846+
kern_type_id = btf_get_ptr_to_btf_id(log, i, btf, t);
7847+
if (kern_type_id < 0)
7848+
return kern_type_id;
7849+
7850+
vmlinux_btf = bpf_get_btf_vmlinux();
7851+
ref_t = btf_type_by_id(vmlinux_btf, kern_type_id);
7852+
if (!btf_type_is_struct(ref_t)) {
7853+
tname = __btf_name_by_offset(vmlinux_btf, t->name_off);
7854+
bpf_log(log, "arg#%d has type %s '%s', but only struct or primitive types are allowed\n",
7855+
i, btf_type_str(ref_t), tname);
7856+
return -EINVAL;
7857+
}
7858+
sub->args[i].arg_type = ARG_PTR_TO_BTF_ID | PTR_UNTRUSTED;
7859+
sub->args[i].btf_id = kern_type_id;
7860+
continue;
7861+
}
78157862
if (tags & ARG_TAG_ARENA) {
78167863
if (tags & ~ARG_TAG_ARENA) {
78177864
bpf_log(log, "arg#%d arena cannot be combined with any other tags\n", i);

kernel/bpf/core.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3244,6 +3244,7 @@ int bpf_prog_get_file_line(struct bpf_prog *prog, unsigned long ip, const char *
32443244
struct bpf_line_info *linfo;
32453245
void **jited_linfo;
32463246
struct btf *btf;
3247+
int nr_linfo;
32473248

32483249
btf = prog->aux->btf;
32493250
linfo = prog->aux->linfo;
@@ -3258,8 +3259,9 @@ int bpf_prog_get_file_line(struct bpf_prog *prog, unsigned long ip, const char *
32583259

32593260
insn_start = linfo[0].insn_off;
32603261
insn_end = insn_start + len;
3262+
nr_linfo = prog->aux->nr_linfo - prog->aux->linfo_idx;
32613263

3262-
for (int i = 0; i < prog->aux->nr_linfo &&
3264+
for (int i = 0; i < nr_linfo &&
32633265
linfo[i].insn_off >= insn_start && linfo[i].insn_off < insn_end; i++) {
32643266
if (jited_linfo[i] >= (void *)ip)
32653267
break;

kernel/bpf/stream.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,11 +498,11 @@ static bool dump_stack_cb(void *cookie, u64 ip, u64 sp, u64 bp)
498498
if (ret < 0)
499499
goto end;
500500
ctxp->err = bpf_stream_stage_printk(ctxp->ss, "%pS\n %s @ %s:%d\n",
501-
(void *)ip, line, file, num);
501+
(void *)(long)ip, line, file, num);
502502
return !ctxp->err;
503503
}
504504
end:
505-
ctxp->err = bpf_stream_stage_printk(ctxp->ss, "%pS\n", (void *)ip);
505+
ctxp->err = bpf_stream_stage_printk(ctxp->ss, "%pS\n", (void *)(long)ip);
506506
return !ctxp->err;
507507
}
508508

kernel/bpf/syscall.c

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5344,21 +5344,10 @@ static int bpf_task_fd_query_copy(const union bpf_attr *attr,
53445344

53455345
if (put_user(zero, ubuf))
53465346
return -EFAULT;
5347-
} else if (input_len >= len + 1) {
5348-
/* ubuf can hold the string with NULL terminator */
5349-
if (copy_to_user(ubuf, buf, len + 1))
5350-
return -EFAULT;
53515347
} else {
5352-
/* ubuf cannot hold the string with NULL terminator,
5353-
* do a partial copy with NULL terminator.
5354-
*/
5355-
char zero = '\0';
5356-
5357-
err = -ENOSPC;
5358-
if (copy_to_user(ubuf, buf, input_len - 1))
5359-
return -EFAULT;
5360-
if (put_user(zero, ubuf + input_len - 1))
5361-
return -EFAULT;
5348+
err = bpf_copy_to_user(ubuf, buf, input_len, len);
5349+
if (err == -EFAULT)
5350+
return err;
53625351
}
53635352
}
53645353

kernel/bpf/verifier.c

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2796,22 +2796,33 @@ static void mark_reg_not_init(struct bpf_verifier_env *env,
27962796
__mark_reg_not_init(env, regs + regno);
27972797
}
27982798

2799-
static void mark_btf_ld_reg(struct bpf_verifier_env *env,
2800-
struct bpf_reg_state *regs, u32 regno,
2801-
enum bpf_reg_type reg_type,
2802-
struct btf *btf, u32 btf_id,
2803-
enum bpf_type_flag flag)
2799+
static int mark_btf_ld_reg(struct bpf_verifier_env *env,
2800+
struct bpf_reg_state *regs, u32 regno,
2801+
enum bpf_reg_type reg_type,
2802+
struct btf *btf, u32 btf_id,
2803+
enum bpf_type_flag flag)
28042804
{
2805-
if (reg_type == SCALAR_VALUE) {
2805+
switch (reg_type) {
2806+
case SCALAR_VALUE:
28062807
mark_reg_unknown(env, regs, regno);
2807-
return;
2808+
return 0;
2809+
case PTR_TO_BTF_ID:
2810+
mark_reg_known_zero(env, regs, regno);
2811+
regs[regno].type = PTR_TO_BTF_ID | flag;
2812+
regs[regno].btf = btf;
2813+
regs[regno].btf_id = btf_id;
2814+
if (type_may_be_null(flag))
2815+
regs[regno].id = ++env->id_gen;
2816+
return 0;
2817+
case PTR_TO_MEM:
2818+
mark_reg_known_zero(env, regs, regno);
2819+
regs[regno].type = PTR_TO_MEM | flag;
2820+
regs[regno].mem_size = 0;
2821+
return 0;
2822+
default:
2823+
verifier_bug(env, "unexpected reg_type %d in %s\n", reg_type, __func__);
2824+
return -EFAULT;
28082825
}
2809-
mark_reg_known_zero(env, regs, regno);
2810-
regs[regno].type = PTR_TO_BTF_ID | flag;
2811-
regs[regno].btf = btf;
2812-
regs[regno].btf_id = btf_id;
2813-
if (type_may_be_null(flag))
2814-
regs[regno].id = ++env->id_gen;
28152826
}
28162827

28172828
#define DEF_NOT_SUBREG (0)
@@ -5965,6 +5976,7 @@ static int check_map_kptr_access(struct bpf_verifier_env *env, u32 regno,
59655976
struct bpf_insn *insn = &env->prog->insnsi[insn_idx];
59665977
int class = BPF_CLASS(insn->code);
59675978
struct bpf_reg_state *val_reg;
5979+
int ret;
59685980

59695981
/* Things we already checked for in check_map_access and caller:
59705982
* - Reject cases where variable offset may touch kptr
@@ -5998,8 +6010,11 @@ static int check_map_kptr_access(struct bpf_verifier_env *env, u32 regno,
59986010
/* We can simply mark the value_regno receiving the pointer
59996011
* value from map as PTR_TO_BTF_ID, with the correct type.
60006012
*/
6001-
mark_btf_ld_reg(env, cur_regs(env), value_regno, PTR_TO_BTF_ID, kptr_field->kptr.btf,
6002-
kptr_field->kptr.btf_id, btf_ld_kptr_type(env, kptr_field));
6013+
ret = mark_btf_ld_reg(env, cur_regs(env), value_regno, PTR_TO_BTF_ID,
6014+
kptr_field->kptr.btf, kptr_field->kptr.btf_id,
6015+
btf_ld_kptr_type(env, kptr_field));
6016+
if (ret < 0)
6017+
return ret;
60036018
} else if (class == BPF_STX) {
60046019
val_reg = reg_state(env, value_regno);
60056020
if (!register_is_null(val_reg) &&
@@ -7298,8 +7313,11 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env,
72987313
clear_trusted_flags(&flag);
72997314
}
73007315

7301-
if (atype == BPF_READ && value_regno >= 0)
7302-
mark_btf_ld_reg(env, regs, value_regno, ret, reg->btf, btf_id, flag);
7316+
if (atype == BPF_READ && value_regno >= 0) {
7317+
ret = mark_btf_ld_reg(env, regs, value_regno, ret, reg->btf, btf_id, flag);
7318+
if (ret < 0)
7319+
return ret;
7320+
}
73037321

73047322
return 0;
73057323
}
@@ -7353,13 +7371,19 @@ static int check_ptr_to_map_access(struct bpf_verifier_env *env,
73537371

73547372
/* Simulate access to a PTR_TO_BTF_ID */
73557373
memset(&map_reg, 0, sizeof(map_reg));
7356-
mark_btf_ld_reg(env, &map_reg, 0, PTR_TO_BTF_ID, btf_vmlinux, *map->ops->map_btf_id, 0);
7374+
ret = mark_btf_ld_reg(env, &map_reg, 0, PTR_TO_BTF_ID,
7375+
btf_vmlinux, *map->ops->map_btf_id, 0);
7376+
if (ret < 0)
7377+
return ret;
73577378
ret = btf_struct_access(&env->log, &map_reg, off, size, atype, &btf_id, &flag, NULL);
73587379
if (ret < 0)
73597380
return ret;
73607381

7361-
if (value_regno >= 0)
7362-
mark_btf_ld_reg(env, regs, value_regno, ret, btf_vmlinux, btf_id, flag);
7382+
if (value_regno >= 0) {
7383+
ret = mark_btf_ld_reg(env, regs, value_regno, ret, btf_vmlinux, btf_id, flag);
7384+
if (ret < 0)
7385+
return ret;
7386+
}
73637387

73647388
return 0;
73657389
}
@@ -10413,6 +10437,12 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
1041310437
bpf_log(log, "R%d is not a scalar\n", regno);
1041410438
return -EINVAL;
1041510439
}
10440+
} else if (arg->arg_type & PTR_UNTRUSTED) {
10441+
/*
10442+
* Anything is allowed for untrusted arguments, as these are
10443+
* read-only and probe read instructions would protect against
10444+
* invalid memory access.
10445+
*/
1041610446
} else if (arg->arg_type == ARG_PTR_TO_CTX) {
1041710447
ret = check_func_arg_reg_off(env, reg, regno, ARG_DONTCARE);
1041810448
if (ret < 0)
@@ -19923,6 +19953,7 @@ static int do_check(struct bpf_verifier_env *env)
1992319953

1992419954
for (;;) {
1992519955
struct bpf_insn *insn;
19956+
struct bpf_insn_aux_data *insn_aux;
1992619957
int err;
1992719958

1992819959
/* reset current history entry on each new instruction */
@@ -19936,6 +19967,7 @@ static int do_check(struct bpf_verifier_env *env)
1993619967
}
1993719968

1993819969
insn = &insns[env->insn_idx];
19970+
insn_aux = &env->insn_aux_data[env->insn_idx];
1993919971

1994019972
if (++env->insn_processed > BPF_COMPLEXITY_LIMIT_INSNS) {
1994119973
verbose(env,
@@ -20012,19 +20044,19 @@ static int do_check(struct bpf_verifier_env *env)
2001220044
/* Reduce verification complexity by stopping speculative path
2001320045
* verification when a nospec is encountered.
2001420046
*/
20015-
if (state->speculative && cur_aux(env)->nospec)
20047+
if (state->speculative && insn_aux->nospec)
2001620048
goto process_bpf_exit;
2001720049

2001820050
err = do_check_insn(env, &do_print_state);
2001920051
if (error_recoverable_with_nospec(err) && state->speculative) {
2002020052
/* Prevent this speculative path from ever reaching the
2002120053
* insn that would have been unsafe to execute.
2002220054
*/
20023-
cur_aux(env)->nospec = true;
20055+
insn_aux->nospec = true;
2002420056
/* If it was an ADD/SUB insn, potentially remove any
2002520057
* markings for alu sanitization.
2002620058
*/
20027-
cur_aux(env)->alu_state = 0;
20059+
insn_aux->alu_state = 0;
2002820060
goto process_bpf_exit;
2002920061
} else if (err < 0) {
2003020062
return err;
@@ -20033,7 +20065,7 @@ static int do_check(struct bpf_verifier_env *env)
2003320065
}
2003420066
WARN_ON_ONCE(err);
2003520067

20036-
if (state->speculative && cur_aux(env)->nospec_result) {
20068+
if (state->speculative && insn_aux->nospec_result) {
2003720069
/* If we are on a path that performed a jump-op, this
2003820070
* may skip a nospec patched-in after the jump. This can
2003920071
* currently never happen because nospec_result is only
@@ -20042,8 +20074,15 @@ static int do_check(struct bpf_verifier_env *env)
2004220074
* never skip the following insn. Still, add a warning
2004320075
* to document this in case nospec_result is used
2004420076
* elsewhere in the future.
20077+
*
20078+
* All non-branch instructions have a single
20079+
* fall-through edge. For these, nospec_result should
20080+
* already work.
2004520081
*/
20046-
WARN_ON_ONCE(env->insn_idx != prev_insn_idx + 1);
20082+
if (verifier_bug_if(BPF_CLASS(insn->code) == BPF_JMP ||
20083+
BPF_CLASS(insn->code) == BPF_JMP32, env,
20084+
"speculation barrier after jump instruction may not have the desired effect"))
20085+
return -EFAULT;
2004720086
process_bpf_exit:
2004820087
mark_verifier_state_scratched(env);
2004920088
err = update_branch_counts(env, env->cur_state);
@@ -23122,11 +23161,12 @@ static int do_check_common(struct bpf_verifier_env *env, int subprog)
2312223161
__mark_dynptr_reg(reg, BPF_DYNPTR_TYPE_LOCAL, true, ++env->id_gen);
2312323162
} else if (base_type(arg->arg_type) == ARG_PTR_TO_MEM) {
2312423163
reg->type = PTR_TO_MEM;
23125-
if (arg->arg_type & PTR_MAYBE_NULL)
23126-
reg->type |= PTR_MAYBE_NULL;
23164+
reg->type |= arg->arg_type &
23165+
(PTR_MAYBE_NULL | PTR_UNTRUSTED | MEM_RDONLY);
2312723166
mark_reg_known_zero(env, regs, i);
2312823167
reg->mem_size = arg->mem_size;
23129-
reg->id = ++env->id_gen;
23168+
if (arg->arg_type & PTR_MAYBE_NULL)
23169+
reg->id = ++env->id_gen;
2313023170
} else if (base_type(arg->arg_type) == ARG_PTR_TO_BTF_ID) {
2313123171
reg->type = PTR_TO_BTF_ID;
2313223172
if (arg->arg_type & PTR_MAYBE_NULL)

tools/lib/bpf/bpf_helpers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ enum libbpf_tristate {
215215
#define __arg_nonnull __attribute((btf_decl_tag("arg:nonnull")))
216216
#define __arg_nullable __attribute((btf_decl_tag("arg:nullable")))
217217
#define __arg_trusted __attribute((btf_decl_tag("arg:trusted")))
218+
#define __arg_untrusted __attribute((btf_decl_tag("arg:untrusted")))
218219
#define __arg_arena __attribute((btf_decl_tag("arg:arena")))
219220

220221
#ifndef ___bpf_concat

tools/testing/selftests/bpf/config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ CONFIG_IP_NF_IPTABLES=y
105105
CONFIG_IP6_NF_IPTABLES=y
106106
CONFIG_IP6_NF_FILTER=y
107107
CONFIG_NF_NAT=y
108+
CONFIG_PACKET=y
108109
CONFIG_RC_CORE=y
109110
CONFIG_SECURITY=y
110111
CONFIG_SECURITYFS=y

tools/testing/selftests/bpf/prog_tests/linked_list.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ static struct {
7272
{ "new_null_ret", "R0 invalid mem access 'ptr_or_null_'" },
7373
{ "obj_new_acq", "Unreleased reference id=" },
7474
{ "use_after_drop", "invalid mem access 'scalar'" },
75-
{ "ptr_walk_scalar", "type=scalar expected=percpu_ptr_" },
75+
{ "ptr_walk_scalar", "type=rdonly_untrusted_mem expected=percpu_ptr_" },
7676
{ "direct_read_lock", "direct access to bpf_spin_lock is disallowed" },
7777
{ "direct_write_lock", "direct access to bpf_spin_lock is disallowed" },
7878
{ "direct_read_head", "direct access to bpf_list_head is disallowed" },

0 commit comments

Comments
 (0)