diff options
author | David S. Miller <davem@davemloft.net> | 2017-05-02 11:46:29 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-05-02 11:46:29 -0400 |
commit | a481649e1c2a4900450e967165524282bbdf91e0 (patch) | |
tree | 6f6d73b367e877b7c4cc14d991ea659df5959480 | |
parent | 4e9c3a667135799d50f2778a8a8dae2ca13aafd0 (diff) | |
parent | 586f8525979ad9574bf61637fd58c98d5077f29d (diff) |
Merge branch 'bpf-test-prog-fixes'
I say:
====================
Fix some bpf program testing framework bugs
This series fixes two issue:
1) Accidental user pointer dereference in bpf_test_finish()
2) The packet data given to the test programs is not aligned correctly
The first issue is fixed simply because we have a kernel side copy
of the datastructure in question already. And the second bug is
a simple matter of applying NET_IP_ALIGN where needed.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/bpf/test_run.c | 19 |
1 files changed, 10 insertions, 9 deletions
diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c index 8a6d0a37c30c..6be41a44d688 100644 --- a/net/bpf/test_run.c +++ b/net/bpf/test_run.c | |||
@@ -49,10 +49,11 @@ static u32 bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat, u32 *time) | |||
49 | return ret; | 49 | return ret; |
50 | } | 50 | } |
51 | 51 | ||
52 | static int bpf_test_finish(union bpf_attr __user *uattr, const void *data, | 52 | static int bpf_test_finish(const union bpf_attr *kattr, |
53 | union bpf_attr __user *uattr, const void *data, | ||
53 | u32 size, u32 retval, u32 duration) | 54 | u32 size, u32 retval, u32 duration) |
54 | { | 55 | { |
55 | void __user *data_out = u64_to_user_ptr(uattr->test.data_out); | 56 | void __user *data_out = u64_to_user_ptr(kattr->test.data_out); |
56 | int err = -EFAULT; | 57 | int err = -EFAULT; |
57 | 58 | ||
58 | if (data_out && copy_to_user(data_out, data, size)) | 59 | if (data_out && copy_to_user(data_out, data, size)) |
@@ -99,7 +100,7 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr, | |||
99 | void *data; | 100 | void *data; |
100 | int ret; | 101 | int ret; |
101 | 102 | ||
102 | data = bpf_test_init(kattr, size, NET_SKB_PAD, | 103 | data = bpf_test_init(kattr, size, NET_SKB_PAD + NET_IP_ALIGN, |
103 | SKB_DATA_ALIGN(sizeof(struct skb_shared_info))); | 104 | SKB_DATA_ALIGN(sizeof(struct skb_shared_info))); |
104 | if (IS_ERR(data)) | 105 | if (IS_ERR(data)) |
105 | return PTR_ERR(data); | 106 | return PTR_ERR(data); |
@@ -124,7 +125,7 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr, | |||
124 | return -ENOMEM; | 125 | return -ENOMEM; |
125 | } | 126 | } |
126 | 127 | ||
127 | skb_reserve(skb, NET_SKB_PAD); | 128 | skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN); |
128 | __skb_put(skb, size); | 129 | __skb_put(skb, size); |
129 | skb->protocol = eth_type_trans(skb, current->nsproxy->net_ns->loopback_dev); | 130 | skb->protocol = eth_type_trans(skb, current->nsproxy->net_ns->loopback_dev); |
130 | skb_reset_network_header(skb); | 131 | skb_reset_network_header(skb); |
@@ -140,7 +141,7 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr, | |||
140 | /* bpf program can never convert linear skb to non-linear */ | 141 | /* bpf program can never convert linear skb to non-linear */ |
141 | if (WARN_ON_ONCE(skb_is_nonlinear(skb))) | 142 | if (WARN_ON_ONCE(skb_is_nonlinear(skb))) |
142 | size = skb_headlen(skb); | 143 | size = skb_headlen(skb); |
143 | ret = bpf_test_finish(uattr, skb->data, size, retval, duration); | 144 | ret = bpf_test_finish(kattr, uattr, skb->data, size, retval, duration); |
144 | kfree_skb(skb); | 145 | kfree_skb(skb); |
145 | return ret; | 146 | return ret; |
146 | } | 147 | } |
@@ -155,18 +156,18 @@ int bpf_prog_test_run_xdp(struct bpf_prog *prog, const union bpf_attr *kattr, | |||
155 | void *data; | 156 | void *data; |
156 | int ret; | 157 | int ret; |
157 | 158 | ||
158 | data = bpf_test_init(kattr, size, XDP_PACKET_HEADROOM, 0); | 159 | data = bpf_test_init(kattr, size, XDP_PACKET_HEADROOM + NET_IP_ALIGN, 0); |
159 | if (IS_ERR(data)) | 160 | if (IS_ERR(data)) |
160 | return PTR_ERR(data); | 161 | return PTR_ERR(data); |
161 | 162 | ||
162 | xdp.data_hard_start = data; | 163 | xdp.data_hard_start = data; |
163 | xdp.data = data + XDP_PACKET_HEADROOM; | 164 | xdp.data = data + XDP_PACKET_HEADROOM + NET_IP_ALIGN; |
164 | xdp.data_end = xdp.data + size; | 165 | xdp.data_end = xdp.data + size; |
165 | 166 | ||
166 | retval = bpf_test_run(prog, &xdp, repeat, &duration); | 167 | retval = bpf_test_run(prog, &xdp, repeat, &duration); |
167 | if (xdp.data != data + XDP_PACKET_HEADROOM) | 168 | if (xdp.data != data + XDP_PACKET_HEADROOM + NET_IP_ALIGN) |
168 | size = xdp.data_end - xdp.data; | 169 | size = xdp.data_end - xdp.data; |
169 | ret = bpf_test_finish(uattr, xdp.data, size, retval, duration); | 170 | ret = bpf_test_finish(kattr, uattr, xdp.data, size, retval, duration); |
170 | kfree(data); | 171 | kfree(data); |
171 | return ret; | 172 | return ret; |
172 | } | 173 | } |