aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@kernel.org>2017-12-18 23:15:20 -0500
committerDaniel Borkmann <daniel@iogearbox.net>2017-12-20 20:26:29 -0500
commit82abbf8d2fc46d79611ab58daa7c608df14bb3ee (patch)
tree288d426963ab3a782ef0876a8ad41ce1d5856401 /tools
parent3db9128fcf02dcaafa3860a69a8a55d5529b6e30 (diff)
bpf: do not allow root to mangle valid pointers
Do not allow root to convert valid pointers into unknown scalars. In particular disallow: ptr &= reg ptr <<= reg ptr += ptr and explicitly allow: ptr -= ptr since pkt_end - pkt == length 1. This minimizes amount of address leaks root can do. In the future may need to further tighten the leaks with kptr_restrict. 2. If program has such pointer math it's likely a user mistake and when verifier complains about it right away instead of many instructions later on invalid memory access it's easier for users to fix their progs. 3. when register holding a pointer cannot change to scalar it allows JITs to optimize better. Like 32-bit archs could use single register for pointers instead of a pair required to hold 64-bit scalars. 4. reduces architecture dependent behavior. Since code: r1 = r10; r1 &= 0xff; if (r1 ...) will behave differently arm64 vs x64 and offloaded vs native. A significant chunk of ptr mangling was allowed by commit f1174f77b50c ("bpf/verifier: rework value tracking") yet some of it was allowed even earlier. Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c56
1 files changed, 29 insertions, 27 deletions
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 961c1426fbf2..b51017404c62 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -422,9 +422,7 @@ static struct bpf_test tests[] = {
422 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0), 422 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
423 BPF_EXIT_INSN(), 423 BPF_EXIT_INSN(),
424 }, 424 },
425 .errstr_unpriv = "R1 subtraction from stack pointer", 425 .errstr = "R1 subtraction from stack pointer",
426 .result_unpriv = REJECT,
427 .errstr = "R1 invalid mem access",
428 .result = REJECT, 426 .result = REJECT,
429 }, 427 },
430 { 428 {
@@ -1859,9 +1857,8 @@ static struct bpf_test tests[] = {
1859 BPF_MOV64_IMM(BPF_REG_0, 0), 1857 BPF_MOV64_IMM(BPF_REG_0, 0),
1860 BPF_EXIT_INSN(), 1858 BPF_EXIT_INSN(),
1861 }, 1859 },
1862 .result = ACCEPT, 1860 .result = REJECT,
1863 .result_unpriv = REJECT, 1861 .errstr = "R1 pointer += pointer",
1864 .errstr_unpriv = "R1 pointer += pointer",
1865 }, 1862 },
1866 { 1863 {
1867 "unpriv: neg pointer", 1864 "unpriv: neg pointer",
@@ -2589,7 +2586,8 @@ static struct bpf_test tests[] = {
2589 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, 2586 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
2590 offsetof(struct __sk_buff, data)), 2587 offsetof(struct __sk_buff, data)),
2591 BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_4), 2588 BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_4),
2592 BPF_MOV64_REG(BPF_REG_2, BPF_REG_1), 2589 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
2590 offsetof(struct __sk_buff, len)),
2593 BPF_ALU64_IMM(BPF_LSH, BPF_REG_2, 49), 2591 BPF_ALU64_IMM(BPF_LSH, BPF_REG_2, 49),
2594 BPF_ALU64_IMM(BPF_RSH, BPF_REG_2, 49), 2592 BPF_ALU64_IMM(BPF_RSH, BPF_REG_2, 49),
2595 BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_2), 2593 BPF_ALU64_REG(BPF_ADD, BPF_REG_3, BPF_REG_2),
@@ -2896,7 +2894,7 @@ static struct bpf_test tests[] = {
2896 BPF_MOV64_IMM(BPF_REG_0, 0), 2894 BPF_MOV64_IMM(BPF_REG_0, 0),
2897 BPF_EXIT_INSN(), 2895 BPF_EXIT_INSN(),
2898 }, 2896 },
2899 .errstr = "invalid access to packet", 2897 .errstr = "R3 pointer arithmetic on PTR_TO_PACKET_END",
2900 .result = REJECT, 2898 .result = REJECT,
2901 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 2899 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
2902 }, 2900 },
@@ -3882,9 +3880,7 @@ static struct bpf_test tests[] = {
3882 BPF_EXIT_INSN(), 3880 BPF_EXIT_INSN(),
3883 }, 3881 },
3884 .fixup_map2 = { 3, 11 }, 3882 .fixup_map2 = { 3, 11 },
3885 .errstr_unpriv = "R0 pointer += pointer", 3883 .errstr = "R0 pointer += pointer",
3886 .errstr = "R0 invalid mem access 'inv'",
3887 .result_unpriv = REJECT,
3888 .result = REJECT, 3884 .result = REJECT,
3889 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, 3885 .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
3890 }, 3886 },
@@ -3925,7 +3921,7 @@ static struct bpf_test tests[] = {
3925 BPF_EXIT_INSN(), 3921 BPF_EXIT_INSN(),
3926 }, 3922 },
3927 .fixup_map1 = { 4 }, 3923 .fixup_map1 = { 4 },
3928 .errstr = "R4 invalid mem access", 3924 .errstr = "R4 pointer arithmetic on PTR_TO_MAP_VALUE_OR_NULL",
3929 .result = REJECT, 3925 .result = REJECT,
3930 .prog_type = BPF_PROG_TYPE_SCHED_CLS 3926 .prog_type = BPF_PROG_TYPE_SCHED_CLS
3931 }, 3927 },
@@ -3946,7 +3942,7 @@ static struct bpf_test tests[] = {
3946 BPF_EXIT_INSN(), 3942 BPF_EXIT_INSN(),
3947 }, 3943 },
3948 .fixup_map1 = { 4 }, 3944 .fixup_map1 = { 4 },
3949 .errstr = "R4 invalid mem access", 3945 .errstr = "R4 pointer arithmetic on PTR_TO_MAP_VALUE_OR_NULL",
3950 .result = REJECT, 3946 .result = REJECT,
3951 .prog_type = BPF_PROG_TYPE_SCHED_CLS 3947 .prog_type = BPF_PROG_TYPE_SCHED_CLS
3952 }, 3948 },
@@ -3967,7 +3963,7 @@ static struct bpf_test tests[] = {
3967 BPF_EXIT_INSN(), 3963 BPF_EXIT_INSN(),
3968 }, 3964 },
3969 .fixup_map1 = { 4 }, 3965 .fixup_map1 = { 4 },
3970 .errstr = "R4 invalid mem access", 3966 .errstr = "R4 pointer arithmetic on PTR_TO_MAP_VALUE_OR_NULL",
3971 .result = REJECT, 3967 .result = REJECT,
3972 .prog_type = BPF_PROG_TYPE_SCHED_CLS 3968 .prog_type = BPF_PROG_TYPE_SCHED_CLS
3973 }, 3969 },
@@ -5192,10 +5188,8 @@ static struct bpf_test tests[] = {
5192 BPF_EXIT_INSN(), 5188 BPF_EXIT_INSN(),
5193 }, 5189 },
5194 .fixup_map2 = { 3 }, 5190 .fixup_map2 = { 3 },
5195 .errstr_unpriv = "R0 bitwise operator &= on pointer", 5191 .errstr = "R0 bitwise operator &= on pointer",
5196 .errstr = "invalid mem access 'inv'",
5197 .result = REJECT, 5192 .result = REJECT,
5198 .result_unpriv = REJECT,
5199 }, 5193 },
5200 { 5194 {
5201 "map element value illegal alu op, 2", 5195 "map element value illegal alu op, 2",
@@ -5211,10 +5205,8 @@ static struct bpf_test tests[] = {
5211 BPF_EXIT_INSN(), 5205 BPF_EXIT_INSN(),
5212 }, 5206 },
5213 .fixup_map2 = { 3 }, 5207 .fixup_map2 = { 3 },
5214 .errstr_unpriv = "R0 32-bit pointer arithmetic prohibited", 5208 .errstr = "R0 32-bit pointer arithmetic prohibited",
5215 .errstr = "invalid mem access 'inv'",
5216 .result = REJECT, 5209 .result = REJECT,
5217 .result_unpriv = REJECT,
5218 }, 5210 },
5219 { 5211 {
5220 "map element value illegal alu op, 3", 5212 "map element value illegal alu op, 3",
@@ -5230,10 +5222,8 @@ static struct bpf_test tests[] = {
5230 BPF_EXIT_INSN(), 5222 BPF_EXIT_INSN(),
5231 }, 5223 },
5232 .fixup_map2 = { 3 }, 5224 .fixup_map2 = { 3 },
5233 .errstr_unpriv = "R0 pointer arithmetic with /= operator", 5225 .errstr = "R0 pointer arithmetic with /= operator",
5234 .errstr = "invalid mem access 'inv'",
5235 .result = REJECT, 5226 .result = REJECT,
5236 .result_unpriv = REJECT,
5237 }, 5227 },
5238 { 5228 {
5239 "map element value illegal alu op, 4", 5229 "map element value illegal alu op, 4",
@@ -6016,8 +6006,7 @@ static struct bpf_test tests[] = {
6016 BPF_EXIT_INSN(), 6006 BPF_EXIT_INSN(),
6017 }, 6007 },
6018 .fixup_map_in_map = { 3 }, 6008 .fixup_map_in_map = { 3 },
6019 .errstr = "R1 type=inv expected=map_ptr", 6009 .errstr = "R1 pointer arithmetic on CONST_PTR_TO_MAP prohibited",
6020 .errstr_unpriv = "R1 pointer arithmetic on CONST_PTR_TO_MAP prohibited",
6021 .result = REJECT, 6010 .result = REJECT,
6022 }, 6011 },
6023 { 6012 {
@@ -7645,6 +7634,19 @@ static struct bpf_test tests[] = {
7645 .prog_type = BPF_PROG_TYPE_SCHED_CLS, 7634 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
7646 }, 7635 },
7647 { 7636 {
7637 "pkt_end - pkt_start is allowed",
7638 .insns = {
7639 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
7640 offsetof(struct __sk_buff, data_end)),
7641 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
7642 offsetof(struct __sk_buff, data)),
7643 BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_2),
7644 BPF_EXIT_INSN(),
7645 },
7646 .result = ACCEPT,
7647 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
7648 },
7649 {
7648 "XDP pkt read, pkt_end mangling, bad access 1", 7650 "XDP pkt read, pkt_end mangling, bad access 1",
7649 .insns = { 7651 .insns = {
7650 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 7652 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
@@ -7659,7 +7661,7 @@ static struct bpf_test tests[] = {
7659 BPF_MOV64_IMM(BPF_REG_0, 0), 7661 BPF_MOV64_IMM(BPF_REG_0, 0),
7660 BPF_EXIT_INSN(), 7662 BPF_EXIT_INSN(),
7661 }, 7663 },
7662 .errstr = "R1 offset is outside of the packet", 7664 .errstr = "R3 pointer arithmetic on PTR_TO_PACKET_END",
7663 .result = REJECT, 7665 .result = REJECT,
7664 .prog_type = BPF_PROG_TYPE_XDP, 7666 .prog_type = BPF_PROG_TYPE_XDP,
7665 }, 7667 },
@@ -7678,7 +7680,7 @@ static struct bpf_test tests[] = {
7678 BPF_MOV64_IMM(BPF_REG_0, 0), 7680 BPF_MOV64_IMM(BPF_REG_0, 0),
7679 BPF_EXIT_INSN(), 7681 BPF_EXIT_INSN(),
7680 }, 7682 },
7681 .errstr = "R1 offset is outside of the packet", 7683 .errstr = "R3 pointer arithmetic on PTR_TO_PACKET_END",
7682 .result = REJECT, 7684 .result = REJECT,
7683 .prog_type = BPF_PROG_TYPE_XDP, 7685 .prog_type = BPF_PROG_TYPE_XDP,
7684 }, 7686 },