diff options
Diffstat (limited to 'kernel/bpf/verifier.c')
-rw-r--r-- | kernel/bpf/verifier.c | 42 |
1 files changed, 26 insertions, 16 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 5fb69a85d967..c6eff108aa99 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c | |||
@@ -1356,6 +1356,13 @@ static bool is_ctx_reg(struct bpf_verifier_env *env, int regno) | |||
1356 | return reg->type == PTR_TO_CTX; | 1356 | return reg->type == PTR_TO_CTX; |
1357 | } | 1357 | } |
1358 | 1358 | ||
1359 | static bool is_pkt_reg(struct bpf_verifier_env *env, int regno) | ||
1360 | { | ||
1361 | const struct bpf_reg_state *reg = cur_regs(env) + regno; | ||
1362 | |||
1363 | return type_is_pkt_pointer(reg->type); | ||
1364 | } | ||
1365 | |||
1359 | static int check_pkt_ptr_alignment(struct bpf_verifier_env *env, | 1366 | static int check_pkt_ptr_alignment(struct bpf_verifier_env *env, |
1360 | const struct bpf_reg_state *reg, | 1367 | const struct bpf_reg_state *reg, |
1361 | int off, int size, bool strict) | 1368 | int off, int size, bool strict) |
@@ -1416,10 +1423,10 @@ static int check_generic_ptr_alignment(struct bpf_verifier_env *env, | |||
1416 | } | 1423 | } |
1417 | 1424 | ||
1418 | static int check_ptr_alignment(struct bpf_verifier_env *env, | 1425 | static int check_ptr_alignment(struct bpf_verifier_env *env, |
1419 | const struct bpf_reg_state *reg, | 1426 | const struct bpf_reg_state *reg, int off, |
1420 | int off, int size) | 1427 | int size, bool strict_alignment_once) |
1421 | { | 1428 | { |
1422 | bool strict = env->strict_alignment; | 1429 | bool strict = env->strict_alignment || strict_alignment_once; |
1423 | const char *pointer_desc = ""; | 1430 | const char *pointer_desc = ""; |
1424 | 1431 | ||
1425 | switch (reg->type) { | 1432 | switch (reg->type) { |
@@ -1576,9 +1583,9 @@ static void coerce_reg_to_size(struct bpf_reg_state *reg, int size) | |||
1576 | * if t==write && value_regno==-1, some unknown value is stored into memory | 1583 | * if t==write && value_regno==-1, some unknown value is stored into memory |
1577 | * if t==read && value_regno==-1, don't care what we read from memory | 1584 | * if t==read && value_regno==-1, don't care what we read from memory |
1578 | */ | 1585 | */ |
1579 | static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regno, int off, | 1586 | static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regno, |
1580 | int bpf_size, enum bpf_access_type t, | 1587 | int off, int bpf_size, enum bpf_access_type t, |
1581 | int value_regno) | 1588 | int value_regno, bool strict_alignment_once) |
1582 | { | 1589 | { |
1583 | struct bpf_reg_state *regs = cur_regs(env); | 1590 | struct bpf_reg_state *regs = cur_regs(env); |
1584 | struct bpf_reg_state *reg = regs + regno; | 1591 | struct bpf_reg_state *reg = regs + regno; |
@@ -1590,7 +1597,7 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn | |||
1590 | return size; | 1597 | return size; |
1591 | 1598 | ||
1592 | /* alignment checks will add in reg->off themselves */ | 1599 | /* alignment checks will add in reg->off themselves */ |
1593 | err = check_ptr_alignment(env, reg, off, size); | 1600 | err = check_ptr_alignment(env, reg, off, size, strict_alignment_once); |
1594 | if (err) | 1601 | if (err) |
1595 | return err; | 1602 | return err; |
1596 | 1603 | ||
@@ -1735,21 +1742,23 @@ static int check_xadd(struct bpf_verifier_env *env, int insn_idx, struct bpf_ins | |||
1735 | return -EACCES; | 1742 | return -EACCES; |
1736 | } | 1743 | } |
1737 | 1744 | ||
1738 | if (is_ctx_reg(env, insn->dst_reg)) { | 1745 | if (is_ctx_reg(env, insn->dst_reg) || |
1739 | verbose(env, "BPF_XADD stores into R%d context is not allowed\n", | 1746 | is_pkt_reg(env, insn->dst_reg)) { |
1740 | insn->dst_reg); | 1747 | verbose(env, "BPF_XADD stores into R%d %s is not allowed\n", |
1748 | insn->dst_reg, is_ctx_reg(env, insn->dst_reg) ? | ||
1749 | "context" : "packet"); | ||
1741 | return -EACCES; | 1750 | return -EACCES; |
1742 | } | 1751 | } |
1743 | 1752 | ||
1744 | /* check whether atomic_add can read the memory */ | 1753 | /* check whether atomic_add can read the memory */ |
1745 | err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off, | 1754 | err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off, |
1746 | BPF_SIZE(insn->code), BPF_READ, -1); | 1755 | BPF_SIZE(insn->code), BPF_READ, -1, true); |
1747 | if (err) | 1756 | if (err) |
1748 | return err; | 1757 | return err; |
1749 | 1758 | ||
1750 | /* check whether atomic_add can write into the same memory */ | 1759 | /* check whether atomic_add can write into the same memory */ |
1751 | return check_mem_access(env, insn_idx, insn->dst_reg, insn->off, | 1760 | return check_mem_access(env, insn_idx, insn->dst_reg, insn->off, |
1752 | BPF_SIZE(insn->code), BPF_WRITE, -1); | 1761 | BPF_SIZE(insn->code), BPF_WRITE, -1, true); |
1753 | } | 1762 | } |
1754 | 1763 | ||
1755 | /* when register 'regno' is passed into function that will read 'access_size' | 1764 | /* when register 'regno' is passed into function that will read 'access_size' |
@@ -2388,7 +2397,8 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn | |||
2388 | * is inferred from register state. | 2397 | * is inferred from register state. |
2389 | */ | 2398 | */ |
2390 | for (i = 0; i < meta.access_size; i++) { | 2399 | for (i = 0; i < meta.access_size; i++) { |
2391 | err = check_mem_access(env, insn_idx, meta.regno, i, BPF_B, BPF_WRITE, -1); | 2400 | err = check_mem_access(env, insn_idx, meta.regno, i, BPF_B, |
2401 | BPF_WRITE, -1, false); | ||
2392 | if (err) | 2402 | if (err) |
2393 | return err; | 2403 | return err; |
2394 | } | 2404 | } |
@@ -4632,7 +4642,7 @@ static int do_check(struct bpf_verifier_env *env) | |||
4632 | */ | 4642 | */ |
4633 | err = check_mem_access(env, insn_idx, insn->src_reg, insn->off, | 4643 | err = check_mem_access(env, insn_idx, insn->src_reg, insn->off, |
4634 | BPF_SIZE(insn->code), BPF_READ, | 4644 | BPF_SIZE(insn->code), BPF_READ, |
4635 | insn->dst_reg); | 4645 | insn->dst_reg, false); |
4636 | if (err) | 4646 | if (err) |
4637 | return err; | 4647 | return err; |
4638 | 4648 | ||
@@ -4684,7 +4694,7 @@ static int do_check(struct bpf_verifier_env *env) | |||
4684 | /* check that memory (dst_reg + off) is writeable */ | 4694 | /* check that memory (dst_reg + off) is writeable */ |
4685 | err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off, | 4695 | err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off, |
4686 | BPF_SIZE(insn->code), BPF_WRITE, | 4696 | BPF_SIZE(insn->code), BPF_WRITE, |
4687 | insn->src_reg); | 4697 | insn->src_reg, false); |
4688 | if (err) | 4698 | if (err) |
4689 | return err; | 4699 | return err; |
4690 | 4700 | ||
@@ -4719,7 +4729,7 @@ static int do_check(struct bpf_verifier_env *env) | |||
4719 | /* check that memory (dst_reg + off) is writeable */ | 4729 | /* check that memory (dst_reg + off) is writeable */ |
4720 | err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off, | 4730 | err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off, |
4721 | BPF_SIZE(insn->code), BPF_WRITE, | 4731 | BPF_SIZE(insn->code), BPF_WRITE, |
4722 | -1); | 4732 | -1, false); |
4723 | if (err) | 4733 | if (err) |
4724 | return err; | 4734 | return err; |
4725 | 4735 | ||