Skip to content

Commit

Permalink
bpf: sockmap: initialize sg table entries properly
Browse files Browse the repository at this point in the history
When CONFIG_DEBUG_SG is set, sg->sg_magic is initialized in
sg_init_table() and it is verified in sg api while navigating. We hit
BUG_ON when magic check is failed.

In functions sg_tcp_sendpage and sg_tcp_sendmsg, the struct containing
the scatterlist is already zeroed out. So to avoid extra memset, we
use sg_init_marker() to initialize sg_magic.

Fixed following things:
- In bpf_tcp_sendpage: initialize sg using sg_init_marker
- In bpf_tcp_sendmsg: Replace sg_init_table with sg_init_marker
- In bpf_tcp_push: Replace memset with sg_init_table where consumed
  sg entry needs to be re-initialized.

Signed-off-by: Prashant Bhole <[email protected]>
Acked-by: John Fastabend <[email protected]>
Signed-off-by: Daniel Borkmann <[email protected]>
  • Loading branch information
pbhole authored and borkmann committed Mar 30, 2018
1 parent f385178 commit 6ef6d84
Showing 1 changed file with 8 additions and 5 deletions.
13 changes: 8 additions & 5 deletions kernel/bpf/sockmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ static int bpf_tcp_push(struct sock *sk, int apply_bytes,
md->sg_start++;
if (md->sg_start == MAX_SKB_FRAGS)
md->sg_start = 0;
memset(sg, 0, sizeof(*sg));
sg_init_table(sg, 1);

if (md->sg_start == md->sg_end)
break;
Expand Down Expand Up @@ -843,7 +843,7 @@ static int bpf_tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
}

sg = md.sg_data;
sg_init_table(sg, MAX_SKB_FRAGS);
sg_init_marker(sg, MAX_SKB_FRAGS);
rcu_read_unlock();

lock_sock(sk);
Expand Down Expand Up @@ -950,18 +950,21 @@ static int bpf_tcp_sendpage(struct sock *sk, struct page *page,

lock_sock(sk);

if (psock->cork_bytes)
if (psock->cork_bytes) {
m = psock->cork;
else
sg = &m->sg_data[m->sg_end];
} else {
m = &md;
sg = m->sg_data;
sg_init_marker(sg, MAX_SKB_FRAGS);
}

/* Catch case where ring is full and sendpage is stalled. */
if (unlikely(m->sg_end == m->sg_start &&
m->sg_data[m->sg_end].length))
goto out_err;

psock->sg_size += size;
sg = &m->sg_data[m->sg_end];
sg_set_page(sg, page, size, offset);
get_page(page);
m->sg_copy[m->sg_end] = true;
Expand Down

0 comments on commit 6ef6d84

Please sign in to comment.