forked from luck/tmp_suning_uos_patched
bpf: verifier: Use target program's type for access verifications
This patch adds changes in verifier to make decisions such as granting of read / write access or enforcement of return code status based on the program type of the target program while using dynamic program extension (of type BPF_PROG_TYPE_EXT). The BPF_PROG_TYPE_EXT type can be used to extend types such as XDP, SKB and others. Since the BPF_PROG_TYPE_EXT program type on itself is just a placeholder for those, we need this extended check for those extended programs to actually work with proper access, while using this option. Specifically, it introduces following changes: - may_access_direct_pkt_data: allow access to packet data based on the target prog - check_return_code: enforce return code based on the target prog (currently, this check is skipped for EXT program) - check_ld_abs: check for 'may_access_skb' based on the target prog - check_map_prog_compatibility: enforce the map compatibility check based on the target prog - may_update_sockmap: allow sockmap update based on the target prog Some other occurrences of prog->type is left as it without replacing with the 'resolved' type: - do_check_common() and check_attach_btf_id(): already have specific logic to handle the EXT prog type - jit_subprogs() and bpf_check(): Not changed for jit compilation or while inferring env->ops Next few patches in this series include selftests for some of these cases. Signed-off-by: Udip Pant <udippant@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/20200825232003.2877030-2-udippant@fb.com
This commit is contained in:
parent
7100ff7c62
commit
7e40781cc8
|
@ -2625,11 +2625,19 @@ static int check_map_access(struct bpf_verifier_env *env, u32 regno,
|
|||
|
||||
#define MAX_PACKET_OFF 0xffff
|
||||
|
||||
static enum bpf_prog_type resolve_prog_type(struct bpf_prog *prog)
|
||||
{
|
||||
return prog->aux->linked_prog ? prog->aux->linked_prog->type
|
||||
: prog->type;
|
||||
}
|
||||
|
||||
static bool may_access_direct_pkt_data(struct bpf_verifier_env *env,
|
||||
const struct bpf_call_arg_meta *meta,
|
||||
enum bpf_access_type t)
|
||||
{
|
||||
switch (env->prog->type) {
|
||||
enum bpf_prog_type prog_type = resolve_prog_type(env->prog);
|
||||
|
||||
switch (prog_type) {
|
||||
/* Program types only with direct read access go here! */
|
||||
case BPF_PROG_TYPE_LWT_IN:
|
||||
case BPF_PROG_TYPE_LWT_OUT:
|
||||
|
@ -4186,7 +4194,7 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
|
|||
static bool may_update_sockmap(struct bpf_verifier_env *env, int func_id)
|
||||
{
|
||||
enum bpf_attach_type eatype = env->prog->expected_attach_type;
|
||||
enum bpf_prog_type type = env->prog->type;
|
||||
enum bpf_prog_type type = resolve_prog_type(env->prog);
|
||||
|
||||
if (func_id != BPF_FUNC_map_update_elem)
|
||||
return false;
|
||||
|
@ -7376,7 +7384,7 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
|
|||
u8 mode = BPF_MODE(insn->code);
|
||||
int i, err;
|
||||
|
||||
if (!may_access_skb(env->prog->type)) {
|
||||
if (!may_access_skb(resolve_prog_type(env->prog))) {
|
||||
verbose(env, "BPF_LD_[ABS|IND] instructions not allowed for this program type\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -7464,11 +7472,12 @@ static int check_return_code(struct bpf_verifier_env *env)
|
|||
const struct bpf_prog *prog = env->prog;
|
||||
struct bpf_reg_state *reg;
|
||||
struct tnum range = tnum_range(0, 1);
|
||||
enum bpf_prog_type prog_type = resolve_prog_type(env->prog);
|
||||
int err;
|
||||
|
||||
/* LSM and struct_ops func-ptr's return type could be "void" */
|
||||
if ((env->prog->type == BPF_PROG_TYPE_STRUCT_OPS ||
|
||||
env->prog->type == BPF_PROG_TYPE_LSM) &&
|
||||
if ((prog_type == BPF_PROG_TYPE_STRUCT_OPS ||
|
||||
prog_type == BPF_PROG_TYPE_LSM) &&
|
||||
!prog->aux->attach_func_proto->type)
|
||||
return 0;
|
||||
|
||||
|
@ -7487,7 +7496,7 @@ static int check_return_code(struct bpf_verifier_env *env)
|
|||
return -EACCES;
|
||||
}
|
||||
|
||||
switch (env->prog->type) {
|
||||
switch (prog_type) {
|
||||
case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
|
||||
if (env->prog->expected_attach_type == BPF_CGROUP_UDP4_RECVMSG ||
|
||||
env->prog->expected_attach_type == BPF_CGROUP_UDP6_RECVMSG ||
|
||||
|
@ -9243,6 +9252,7 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
|
|||
struct bpf_prog *prog)
|
||||
|
||||
{
|
||||
enum bpf_prog_type prog_type = resolve_prog_type(prog);
|
||||
/*
|
||||
* Validate that trace type programs use preallocated hash maps.
|
||||
*
|
||||
|
@ -9260,8 +9270,8 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
|
|||
* now, but warnings are emitted so developers are made aware of
|
||||
* the unsafety and can fix their programs before this is enforced.
|
||||
*/
|
||||
if (is_tracing_prog_type(prog->type) && !is_preallocated_map(map)) {
|
||||
if (prog->type == BPF_PROG_TYPE_PERF_EVENT) {
|
||||
if (is_tracing_prog_type(prog_type) && !is_preallocated_map(map)) {
|
||||
if (prog_type == BPF_PROG_TYPE_PERF_EVENT) {
|
||||
verbose(env, "perf_event programs can only use preallocated hash map\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -9273,8 +9283,8 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env,
|
|||
verbose(env, "trace type programs with run-time allocated hash maps are unsafe. Switch to preallocated hash maps.\n");
|
||||
}
|
||||
|
||||
if ((is_tracing_prog_type(prog->type) ||
|
||||
prog->type == BPF_PROG_TYPE_SOCKET_FILTER) &&
|
||||
if ((is_tracing_prog_type(prog_type) ||
|
||||
prog_type == BPF_PROG_TYPE_SOCKET_FILTER) &&
|
||||
map_value_has_spin_lock(map)) {
|
||||
verbose(env, "tracing progs cannot use bpf_spin_lock yet\n");
|
||||
return -EINVAL;
|
||||
|
@ -9986,7 +9996,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
|
|||
insn->code = BPF_LDX | BPF_PROBE_MEM |
|
||||
BPF_SIZE((insn)->code);
|
||||
env->prog->aux->num_exentries++;
|
||||
} else if (env->prog->type != BPF_PROG_TYPE_STRUCT_OPS) {
|
||||
} else if (resolve_prog_type(env->prog) != BPF_PROG_TYPE_STRUCT_OPS) {
|
||||
verbose(env, "Writes through BTF pointers are not allowed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user