ipv6: add complete rcu protection around np->opt
This patch addresses multiple problems : UDP/RAW sendmsg() need to get a stable struct ipv6_txoptions while socket is not locked : Other threads can change np->opt concurrently. Dmitry posted a syzkaller (http://github.com/google/syzkaller) program desmonstrating use-after-free. Starting with TCP/DCCP lockless listeners, tcp_v6_syn_recv_sock() and dccp_v6_request_recv_sock() also need to use RCU protection to dereference np->opt once (before calling ipv6_dup_options()) This patch adds full RCU protection to np->opt Reported-by: Dmitry Vyukov <dvyukov@google.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
01b3f52157
commit
45f6fad84c
@@ -733,6 +733,7 @@ static int raw6_getfrag(void *from, char *to, int offset, int len, int odd,
|
||||
|
||||
static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
||||
{
|
||||
struct ipv6_txoptions *opt_to_free = NULL;
|
||||
struct ipv6_txoptions opt_space;
|
||||
DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name);
|
||||
struct in6_addr *daddr, *final_p, final;
|
||||
@@ -839,8 +840,10 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
||||
if (!(opt->opt_nflen|opt->opt_flen))
|
||||
opt = NULL;
|
||||
}
|
||||
if (!opt)
|
||||
opt = np->opt;
|
||||
if (!opt) {
|
||||
opt = txopt_get(np);
|
||||
opt_to_free = opt;
|
||||
}
|
||||
if (flowlabel)
|
||||
opt = fl6_merge_options(&opt_space, flowlabel, opt);
|
||||
opt = ipv6_fixup_options(&opt_space, opt);
|
||||
@@ -906,6 +909,7 @@ done:
|
||||
dst_release(dst);
|
||||
out:
|
||||
fl6_sock_release(flowlabel);
|
||||
txopt_put(opt_to_free);
|
||||
return err < 0 ? err : len;
|
||||
do_confirm:
|
||||
dst_confirm(dst);
|
||||
|
Reference in New Issue
Block a user