Skip to content

Commit 64022d0

Browse files
Eric Dumazetdavem330
authored andcommitted
tcp: fix crashes in do_tcp_sendpages()
Recent network changes allowed high order pages being used for skb fragments. This uncovered a bug in do_tcp_sendpages() which was assuming its caller provided an array of order-0 page pointers. We only have to deal with a single page in this function, and its order is irrelevant. Reported-by: Willy Tarreau <w@1wt.eu> Tested-by: Willy Tarreau <w@1wt.eu> Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 9f8933e commit 64022d0

File tree

1 file changed

+6
-9
lines changed

1 file changed

+6
-9
lines changed

net/ipv4/tcp.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -830,8 +830,8 @@ static int tcp_send_mss(struct sock *sk, int *size_goal, int flags)
830830
return mss_now;
831831
}
832832

833-
static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset,
834-
size_t psize, int flags)
833+
static ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
834+
size_t size, int flags)
835835
{
836836
struct tcp_sock *tp = tcp_sk(sk);
837837
int mss_now, size_goal;
@@ -858,12 +858,9 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffse
858858
if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
859859
goto out_err;
860860

861-
while (psize > 0) {
861+
while (size > 0) {
862862
struct sk_buff *skb = tcp_write_queue_tail(sk);
863-
struct page *page = pages[poffset / PAGE_SIZE];
864863
int copy, i;
865-
int offset = poffset % PAGE_SIZE;
866-
int size = min_t(size_t, psize, PAGE_SIZE - offset);
867864
bool can_coalesce;
868865

869866
if (!tcp_send_head(sk) || (copy = size_goal - skb->len) <= 0) {
@@ -912,8 +909,8 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffse
912909
TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_PSH;
913910

914911
copied += copy;
915-
poffset += copy;
916-
if (!(psize -= copy))
912+
offset += copy;
913+
if (!(size -= copy))
917914
goto out;
918915

919916
if (skb->len < size_goal || (flags & MSG_OOB))
@@ -960,7 +957,7 @@ int tcp_sendpage(struct sock *sk, struct page *page, int offset,
960957
flags);
961958

962959
lock_sock(sk);
963-
res = do_tcp_sendpages(sk, &page, offset, size, flags);
960+
res = do_tcp_sendpages(sk, page, offset, size, flags);
964961
release_sock(sk);
965962
return res;
966963
}

0 commit comments

Comments
 (0)