aboutsummaryrefslogtreecommitdiffstats
path: root/samples/bpf/test_verifier.c
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@plumgrid.com>2015-06-04 13:11:54 -0400
committerDavid S. Miller <davem@davemloft.net>2015-06-07 05:01:33 -0400
commitd691f9e8d4405c334aa10d556e73c8bf44cb0e01 (patch)
tree295b1d647364407c42990d916358a72381f4d534 /samples/bpf/test_verifier.c
parent3431205e03977aaf32bce6d4b16fb8244b510056 (diff)
bpf: allow programs to write to certain skb fields
allow programs read/write skb->mark, tc_index fields and ((struct qdisc_skb_cb *)cb)->data. mark and tc_index are generically useful in TC. cb[0]-cb[4] are primarily used to pass arguments from one program to another called via bpf_tail_call() which can be seen in sockex3_kern.c example. All fields of 'struct __sk_buff' are readable to socket and tc_cls_act progs. mark, tc_index are writeable from tc_cls_act only. cb[0]-cb[4] are writeable by both sockets and tc_cls_act. Add verifier tests and improve sample code. Signed-off-by: Alexei Starovoitov <ast@plumgrid.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'samples/bpf/test_verifier.c')
-rw-r--r--samples/bpf/test_verifier.c84
1 files changed, 82 insertions, 2 deletions
diff --git a/samples/bpf/test_verifier.c b/samples/bpf/test_verifier.c
index 12f3780af73f..693605997abc 100644
--- a/samples/bpf/test_verifier.c
+++ b/samples/bpf/test_verifier.c
@@ -29,6 +29,7 @@ struct bpf_test {
29 ACCEPT, 29 ACCEPT,
30 REJECT 30 REJECT
31 } result; 31 } result;
32 enum bpf_prog_type prog_type;
32}; 33};
33 34
34static struct bpf_test tests[] = { 35static struct bpf_test tests[] = {
@@ -743,6 +744,84 @@ static struct bpf_test tests[] = {
743 .errstr = "different pointers", 744 .errstr = "different pointers",
744 .result = REJECT, 745 .result = REJECT,
745 }, 746 },
747 {
748 "check skb->mark is not writeable by sockets",
749 .insns = {
750 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
751 offsetof(struct __sk_buff, mark)),
752 BPF_EXIT_INSN(),
753 },
754 .errstr = "invalid bpf_context access",
755 .result = REJECT,
756 },
757 {
758 "check skb->tc_index is not writeable by sockets",
759 .insns = {
760 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
761 offsetof(struct __sk_buff, tc_index)),
762 BPF_EXIT_INSN(),
763 },
764 .errstr = "invalid bpf_context access",
765 .result = REJECT,
766 },
767 {
768 "check non-u32 access to cb",
769 .insns = {
770 BPF_STX_MEM(BPF_H, BPF_REG_1, BPF_REG_1,
771 offsetof(struct __sk_buff, cb[0])),
772 BPF_EXIT_INSN(),
773 },
774 .errstr = "invalid bpf_context access",
775 .result = REJECT,
776 },
777 {
778 "check out of range skb->cb access",
779 .insns = {
780 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
781 offsetof(struct __sk_buff, cb[60])),
782 BPF_EXIT_INSN(),
783 },
784 .errstr = "invalid bpf_context access",
785 .result = REJECT,
786 .prog_type = BPF_PROG_TYPE_SCHED_ACT,
787 },
788 {
789 "write skb fields from socket prog",
790 .insns = {
791 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
792 offsetof(struct __sk_buff, cb[4])),
793 BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
794 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
795 offsetof(struct __sk_buff, mark)),
796 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
797 offsetof(struct __sk_buff, tc_index)),
798 BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
799 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
800 offsetof(struct __sk_buff, cb[0])),
801 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_1,
802 offsetof(struct __sk_buff, cb[2])),
803 BPF_EXIT_INSN(),
804 },
805 .result = ACCEPT,
806 },
807 {
808 "write skb fields from tc_cls_act prog",
809 .insns = {
810 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
811 offsetof(struct __sk_buff, cb[0])),
812 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
813 offsetof(struct __sk_buff, mark)),
814 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
815 offsetof(struct __sk_buff, tc_index)),
816 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
817 offsetof(struct __sk_buff, tc_index)),
818 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
819 offsetof(struct __sk_buff, cb[3])),
820 BPF_EXIT_INSN(),
821 },
822 .result = ACCEPT,
823 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
824 },
746}; 825};
747 826
748static int probe_filter_length(struct bpf_insn *fp) 827static int probe_filter_length(struct bpf_insn *fp)
@@ -775,6 +854,7 @@ static int test(void)
775 854
776 for (i = 0; i < ARRAY_SIZE(tests); i++) { 855 for (i = 0; i < ARRAY_SIZE(tests); i++) {
777 struct bpf_insn *prog = tests[i].insns; 856 struct bpf_insn *prog = tests[i].insns;
857 int prog_type = tests[i].prog_type;
778 int prog_len = probe_filter_length(prog); 858 int prog_len = probe_filter_length(prog);
779 int *fixup = tests[i].fixup; 859 int *fixup = tests[i].fixup;
780 int map_fd = -1; 860 int map_fd = -1;
@@ -789,8 +869,8 @@ static int test(void)
789 } 869 }
790 printf("#%d %s ", i, tests[i].descr); 870 printf("#%d %s ", i, tests[i].descr);
791 871
792 prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, prog, 872 prog_fd = bpf_prog_load(prog_type ?: BPF_PROG_TYPE_SOCKET_FILTER,
793 prog_len * sizeof(struct bpf_insn), 873 prog, prog_len * sizeof(struct bpf_insn),
794 "GPL", 0); 874 "GPL", 0);
795 875
796 if (tests[i].result == ACCEPT) { 876 if (tests[i].result == ACCEPT) {