net-tcp: fastopen: fix high order allocations
This patch fixes two bugs in fastopen : 1) The tcp_sendmsg(..., @size) argument was ignored. Code was relying on user not fooling the kernel with iovec mismatches 2) When MTU is about 64KB, tcp_send_syn_data() attempts order-5 allocations, which are likely to fail when memory gets fragmented. Fixes: 783237e8daf13 ("net-tcp: Fast Open client - sending SYN-data") Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Yuchung Cheng <ycheng@google.com> Acked-by: Yuchung Cheng <ycheng@google.com> Tested-by: Yuchung Cheng <ycheng@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
68ad785c00
commit
f5ddcbbb40
@ -1303,7 +1303,8 @@ struct tcp_fastopen_request {
|
|||||||
/* Fast Open cookie. Size 0 means a cookie request */
|
/* Fast Open cookie. Size 0 means a cookie request */
|
||||||
struct tcp_fastopen_cookie cookie;
|
struct tcp_fastopen_cookie cookie;
|
||||||
struct msghdr *data; /* data in MSG_FASTOPEN */
|
struct msghdr *data; /* data in MSG_FASTOPEN */
|
||||||
u16 copied; /* queued in tcp_connect() */
|
size_t size;
|
||||||
|
int copied; /* queued in tcp_connect() */
|
||||||
};
|
};
|
||||||
void tcp_free_fastopen_req(struct tcp_sock *tp);
|
void tcp_free_fastopen_req(struct tcp_sock *tp);
|
||||||
|
|
||||||
|
@ -1044,7 +1044,8 @@ void tcp_free_fastopen_req(struct tcp_sock *tp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, int *size)
|
static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
|
||||||
|
int *copied, size_t size)
|
||||||
{
|
{
|
||||||
struct tcp_sock *tp = tcp_sk(sk);
|
struct tcp_sock *tp = tcp_sk(sk);
|
||||||
int err, flags;
|
int err, flags;
|
||||||
@ -1059,11 +1060,12 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, int *size)
|
|||||||
if (unlikely(tp->fastopen_req == NULL))
|
if (unlikely(tp->fastopen_req == NULL))
|
||||||
return -ENOBUFS;
|
return -ENOBUFS;
|
||||||
tp->fastopen_req->data = msg;
|
tp->fastopen_req->data = msg;
|
||||||
|
tp->fastopen_req->size = size;
|
||||||
|
|
||||||
flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0;
|
flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0;
|
||||||
err = __inet_stream_connect(sk->sk_socket, msg->msg_name,
|
err = __inet_stream_connect(sk->sk_socket, msg->msg_name,
|
||||||
msg->msg_namelen, flags);
|
msg->msg_namelen, flags);
|
||||||
*size = tp->fastopen_req->copied;
|
*copied = tp->fastopen_req->copied;
|
||||||
tcp_free_fastopen_req(tp);
|
tcp_free_fastopen_req(tp);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -1083,7 +1085,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
|||||||
|
|
||||||
flags = msg->msg_flags;
|
flags = msg->msg_flags;
|
||||||
if (flags & MSG_FASTOPEN) {
|
if (flags & MSG_FASTOPEN) {
|
||||||
err = tcp_sendmsg_fastopen(sk, msg, &copied_syn);
|
err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size);
|
||||||
if (err == -EINPROGRESS && copied_syn > 0)
|
if (err == -EINPROGRESS && copied_syn > 0)
|
||||||
goto out;
|
goto out;
|
||||||
else if (err)
|
else if (err)
|
||||||
|
@ -2908,7 +2908,12 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
|
|||||||
space = __tcp_mtu_to_mss(sk, inet_csk(sk)->icsk_pmtu_cookie) -
|
space = __tcp_mtu_to_mss(sk, inet_csk(sk)->icsk_pmtu_cookie) -
|
||||||
MAX_TCP_OPTION_SPACE;
|
MAX_TCP_OPTION_SPACE;
|
||||||
|
|
||||||
syn_data = skb_copy_expand(syn, skb_headroom(syn), space,
|
space = min_t(size_t, space, fo->size);
|
||||||
|
|
||||||
|
/* limit to order-0 allocations */
|
||||||
|
space = min_t(size_t, space, SKB_MAX_HEAD(MAX_TCP_HEADER));
|
||||||
|
|
||||||
|
syn_data = skb_copy_expand(syn, MAX_TCP_HEADER, space,
|
||||||
sk->sk_allocation);
|
sk->sk_allocation);
|
||||||
if (syn_data == NULL)
|
if (syn_data == NULL)
|
||||||
goto fallback;
|
goto fallback;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user