aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2018-08-29 10:50:36 -0400
committerAlexei Starovoitov <ast@kernel.org>2018-08-29 13:47:17 -0400
commita8cf76a9023bc6709b1361d06bb2fae5227b9d68 (patch)
treedaa8c87faa188cf123e905140f1ab3e995439fc4
parent2e43f95dd8ee62bc8bf57f2afac37fbd70c8d565 (diff)
bpf: fix sg shift repair start offset in bpf_msg_pull_data
When we perform the sg shift repair for the scatterlist ring, we currently start out at i = first_sg + 1. However, this is not correct since the first_sg could point to the sge sitting at slot MAX_SKB_FRAGS - 1, and a subsequent i = MAX_SKB_FRAGS will access the scatterlist ring (sg) out of bounds. Add the sk_msg_iter_var() helper for iterating through the ring, and apply the same rule for advancing to the next ring element as we do elsewhere. Later work will use this helper also in other places. Fixes: 015632bb30da ("bpf: sk_msg program helper bpf_sk_msg_pull_data") Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: John Fastabend <john.fastabend@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
-rw-r--r--net/core/filter.c26
1 files changed, 13 insertions, 13 deletions
diff --git a/net/core/filter.c b/net/core/filter.c
index 43ba5f8c38ca..2c7801f6737a 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -2282,6 +2282,13 @@ static const struct bpf_func_proto bpf_msg_cork_bytes_proto = {
2282 .arg2_type = ARG_ANYTHING, 2282 .arg2_type = ARG_ANYTHING,
2283}; 2283};
2284 2284
2285#define sk_msg_iter_var(var) \
2286 do { \
2287 var++; \
2288 if (var == MAX_SKB_FRAGS) \
2289 var = 0; \
2290 } while (0)
2291
2285BPF_CALL_4(bpf_msg_pull_data, 2292BPF_CALL_4(bpf_msg_pull_data,
2286 struct sk_msg_buff *, msg, u32, start, u32, end, u64, flags) 2293 struct sk_msg_buff *, msg, u32, start, u32, end, u64, flags)
2287{ 2294{
@@ -2302,9 +2309,7 @@ BPF_CALL_4(bpf_msg_pull_data,
2302 if (start < offset + len) 2309 if (start < offset + len)
2303 break; 2310 break;
2304 offset += len; 2311 offset += len;
2305 i++; 2312 sk_msg_iter_var(i);
2306 if (i == MAX_SKB_FRAGS)
2307 i = 0;
2308 } while (i != msg->sg_end); 2313 } while (i != msg->sg_end);
2309 2314
2310 if (unlikely(start >= offset + len)) 2315 if (unlikely(start >= offset + len))
@@ -2330,9 +2335,7 @@ BPF_CALL_4(bpf_msg_pull_data,
2330 */ 2335 */
2331 do { 2336 do {
2332 copy += sg[i].length; 2337 copy += sg[i].length;
2333 i++; 2338 sk_msg_iter_var(i);
2334 if (i == MAX_SKB_FRAGS)
2335 i = 0;
2336 if (bytes_sg_total <= copy) 2339 if (bytes_sg_total <= copy)
2337 break; 2340 break;
2338 } while (i != msg->sg_end); 2341 } while (i != msg->sg_end);
@@ -2358,9 +2361,7 @@ BPF_CALL_4(bpf_msg_pull_data,
2358 sg[i].length = 0; 2361 sg[i].length = 0;
2359 put_page(sg_page(&sg[i])); 2362 put_page(sg_page(&sg[i]));
2360 2363
2361 i++; 2364 sk_msg_iter_var(i);
2362 if (i == MAX_SKB_FRAGS)
2363 i = 0;
2364 } while (i != last_sg); 2365 } while (i != last_sg);
2365 2366
2366 sg[first_sg].length = copy; 2367 sg[first_sg].length = copy;
@@ -2377,7 +2378,8 @@ BPF_CALL_4(bpf_msg_pull_data,
2377 if (!shift) 2378 if (!shift)
2378 goto out; 2379 goto out;
2379 2380
2380 i = first_sg + 1; 2381 i = first_sg;
2382 sk_msg_iter_var(i);
2381 do { 2383 do {
2382 int move_from; 2384 int move_from;
2383 2385
@@ -2394,9 +2396,7 @@ BPF_CALL_4(bpf_msg_pull_data,
2394 sg[move_from].page_link = 0; 2396 sg[move_from].page_link = 0;
2395 sg[move_from].offset = 0; 2397 sg[move_from].offset = 0;
2396 2398
2397 i++; 2399 sk_msg_iter_var(i);
2398 if (i == MAX_SKB_FRAGS)
2399 i = 0;
2400 } while (1); 2400 } while (1);
2401 msg->sg_end -= shift; 2401 msg->sg_end -= shift;
2402 if (msg->sg_end < 0) 2402 if (msg->sg_end < 0)