Commit a8cf76a9 authored by Daniel Borkmann's avatar Daniel Borkmann Committed by Alexei Starovoitov

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: 015632bb ("bpf: sk_msg program helper bpf_sk_msg_pull_data")
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Acked-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 2e43f95d
...@@ -2282,6 +2282,13 @@ static const struct bpf_func_proto bpf_msg_cork_bytes_proto = { ...@@ -2282,6 +2282,13 @@ static const struct bpf_func_proto bpf_msg_cork_bytes_proto = {
.arg2_type = ARG_ANYTHING, .arg2_type = ARG_ANYTHING,
}; };
#define sk_msg_iter_var(var) \
do { \
var++; \
if (var == MAX_SKB_FRAGS) \
var = 0; \
} while (0)
BPF_CALL_4(bpf_msg_pull_data, BPF_CALL_4(bpf_msg_pull_data,
struct sk_msg_buff *, msg, u32, start, u32, end, u64, flags) struct sk_msg_buff *, msg, u32, start, u32, end, u64, flags)
{ {
...@@ -2302,9 +2309,7 @@ BPF_CALL_4(bpf_msg_pull_data, ...@@ -2302,9 +2309,7 @@ BPF_CALL_4(bpf_msg_pull_data,
if (start < offset + len) if (start < offset + len)
break; break;
offset += len; offset += len;
i++; sk_msg_iter_var(i);
if (i == MAX_SKB_FRAGS)
i = 0;
} while (i != msg->sg_end); } while (i != msg->sg_end);
if (unlikely(start >= offset + len)) if (unlikely(start >= offset + len))
...@@ -2330,9 +2335,7 @@ BPF_CALL_4(bpf_msg_pull_data, ...@@ -2330,9 +2335,7 @@ BPF_CALL_4(bpf_msg_pull_data,
*/ */
do { do {
copy += sg[i].length; copy += sg[i].length;
i++; sk_msg_iter_var(i);
if (i == MAX_SKB_FRAGS)
i = 0;
if (bytes_sg_total <= copy) if (bytes_sg_total <= copy)
break; break;
} while (i != msg->sg_end); } while (i != msg->sg_end);
...@@ -2358,9 +2361,7 @@ BPF_CALL_4(bpf_msg_pull_data, ...@@ -2358,9 +2361,7 @@ BPF_CALL_4(bpf_msg_pull_data,
sg[i].length = 0; sg[i].length = 0;
put_page(sg_page(&sg[i])); put_page(sg_page(&sg[i]));
i++; sk_msg_iter_var(i);
if (i == MAX_SKB_FRAGS)
i = 0;
} while (i != last_sg); } while (i != last_sg);
sg[first_sg].length = copy; sg[first_sg].length = copy;
...@@ -2377,7 +2378,8 @@ BPF_CALL_4(bpf_msg_pull_data, ...@@ -2377,7 +2378,8 @@ BPF_CALL_4(bpf_msg_pull_data,
if (!shift) if (!shift)
goto out; goto out;
i = first_sg + 1; i = first_sg;
sk_msg_iter_var(i);
do { do {
int move_from; int move_from;
...@@ -2394,9 +2396,7 @@ BPF_CALL_4(bpf_msg_pull_data, ...@@ -2394,9 +2396,7 @@ BPF_CALL_4(bpf_msg_pull_data,
sg[move_from].page_link = 0; sg[move_from].page_link = 0;
sg[move_from].offset = 0; sg[move_from].offset = 0;
i++; sk_msg_iter_var(i);
if (i == MAX_SKB_FRAGS)
i = 0;
} while (1); } while (1);
msg->sg_end -= shift; msg->sg_end -= shift;
if (msg->sg_end < 0) if (msg->sg_end < 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment