From: Greg Kroah-Hartman Date: Sat, 23 Apr 2022 11:03:53 +0000 (+0200) Subject: 4.19-stable patches X-Git-Tag: v4.9.312~60 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=86b24a39072c1e7687361b40e256a770befb4a7b;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: alsa-usb-audio-clear-midi-port-active-flag-after-draining.patch tcp-fix-potential-use-after-free-due-to-double-kfree.patch --- diff --git a/queue-4.19/alsa-usb-audio-clear-midi-port-active-flag-after-draining.patch b/queue-4.19/alsa-usb-audio-clear-midi-port-active-flag-after-draining.patch new file mode 100644 index 00000000000..2619bf8d84a --- /dev/null +++ b/queue-4.19/alsa-usb-audio-clear-midi-port-active-flag-after-draining.patch @@ -0,0 +1,41 @@ +From 0665886ad1392e6b5bae85d7a6ccbed48dca1522 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 20 Apr 2022 15:02:47 +0200 +Subject: ALSA: usb-audio: Clear MIDI port active flag after draining + +From: Takashi Iwai + +commit 0665886ad1392e6b5bae85d7a6ccbed48dca1522 upstream. + +When a rawmidi output stream is closed, it calls the drain at first, +then does trigger-off only when the drain returns -ERESTARTSYS as a +fallback. It implies that each driver should turn off the stream +properly after the drain. Meanwhile, USB-audio MIDI interface didn't +change the port->active flag after the drain. This may leave the +output work picking up the port that is closed right now, which +eventually leads to a use-after-free for the already released rawmidi +object. + +This patch fixes the bug by properly clearing the port->active flag +after the output drain. + +Reported-by: syzbot+70e777a39907d6d5fd0a@syzkaller.appspotmail.com +Cc: +Link: https://lore.kernel.org/r/00000000000011555605dceaff03@google.com +Link: https://lore.kernel.org/r/20220420130247.22062-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/usb/midi.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/usb/midi.c ++++ b/sound/usb/midi.c +@@ -1211,6 +1211,7 @@ static void snd_usbmidi_output_drain(str + } while (drain_urbs && timeout); + finish_wait(&ep->drain_wait, &wait); + } ++ port->active = 0; + spin_unlock_irq(&ep->buffer_lock); + } + diff --git a/queue-4.19/series b/queue-4.19/series index 6c3addf5ee1..1bf682aee6d 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -4,4 +4,6 @@ tracing-dump-stacktrace-trigger-to-the-corresponding-instance.patch can-usb_8dev-usb_8dev_start_xmit-fix-double-dev_kfree_skb-in-error-path.patch dm-integrity-fix-memory-corruption-when-tag_size-is-less-than-digest-size.patch gfs2-assign-rgrp-glock-before-compute_bitstructs.patch +alsa-usb-audio-clear-midi-port-active-flag-after-draining.patch tcp-fix-race-condition-when-creating-child-sockets-f.patch +tcp-fix-potential-use-after-free-due-to-double-kfree.patch diff --git a/queue-4.19/tcp-fix-potential-use-after-free-due-to-double-kfree.patch b/queue-4.19/tcp-fix-potential-use-after-free-due-to-double-kfree.patch new file mode 100644 index 00000000000..5e166698934 --- /dev/null +++ b/queue-4.19/tcp-fix-potential-use-after-free-due-to-double-kfree.patch @@ -0,0 +1,76 @@ +From c89dffc70b340780e5b933832d8c3e045ef3791e Mon Sep 17 00:00:00 2001 +From: Kuniyuki Iwashima +Date: Mon, 18 Jan 2021 14:59:20 +0900 +Subject: tcp: Fix potential use-after-free due to double kfree() + +From: Kuniyuki Iwashima + +commit c89dffc70b340780e5b933832d8c3e045ef3791e upstream. + +Receiving ACK with a valid SYN cookie, cookie_v4_check() allocates struct +request_sock and then can allocate inet_rsk(req)->ireq_opt. After that, +tcp_v4_syn_recv_sock() allocates struct sock and copies ireq_opt to +inet_sk(sk)->inet_opt. Normally, tcp_v4_syn_recv_sock() inserts the full +socket into ehash and sets NULL to ireq_opt. Otherwise, +tcp_v4_syn_recv_sock() has to reset inet_opt by NULL and free the full +socket. + +The commit 01770a1661657 ("tcp: fix race condition when creating child +sockets from syncookies") added a new path, in which more than one cores +create full sockets for the same SYN cookie. Currently, the core which +loses the race frees the full socket without resetting inet_opt, resulting +in that both sock_put() and reqsk_put() call kfree() for the same memory: + + sock_put + sk_free + __sk_free + sk_destruct + __sk_destruct + sk->sk_destruct/inet_sock_destruct + kfree(rcu_dereference_protected(inet->inet_opt, 1)); + + reqsk_put + reqsk_free + __reqsk_free + req->rsk_ops->destructor/tcp_v4_reqsk_destructor + kfree(rcu_dereference_protected(inet_rsk(req)->ireq_opt, 1)); + +Calling kmalloc() between the double kfree() can lead to use-after-free, so +this patch fixes it by setting NULL to inet_opt before sock_put(). + +As a side note, this kind of issue does not happen for IPv6. This is +because tcp_v6_syn_recv_sock() clones both ipv6_opt and pktopts which +correspond to ireq_opt in IPv4. + +Fixes: 01770a166165 ("tcp: fix race condition when creating child sockets from syncookies") +CC: Ricardo Dias +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Benjamin Herrenschmidt +Reviewed-by: Eric Dumazet +Link: https://lore.kernel.org/r/20210118055920.82516-1-kuniyu@amazon.co.jp +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/tcp_ipv4.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -1492,6 +1492,8 @@ struct sock *tcp_v4_syn_recv_sock(const + tcp_move_syn(newtp, req); + ireq->ireq_opt = NULL; + } else { ++ newinet->inet_opt = NULL; ++ + if (!req_unhash && found_dup_sk) { + /* This code path should only be executed in the + * syncookie case only +@@ -1499,8 +1501,6 @@ struct sock *tcp_v4_syn_recv_sock(const + bh_unlock_sock(newsk); + sock_put(newsk); + newsk = NULL; +- } else { +- newinet->inet_opt = NULL; + } + } + return newsk; diff --git a/queue-4.19/tcp-fix-race-condition-when-creating-child-sockets-f.patch b/queue-4.19/tcp-fix-race-condition-when-creating-child-sockets-f.patch index 24722c314bb..bba28f3cc9d 100644 --- a/queue-4.19/tcp-fix-race-condition-when-creating-child-sockets-f.patch +++ b/queue-4.19/tcp-fix-race-condition-when-creating-child-sockets-f.patch @@ -46,20 +46,18 @@ Link: https://lore.kernel.org/r/20201120111133.GA67501@rdias-suse-pc.lan Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- - include/net/inet_hashtables.h | 5 ++- - net/dccp/ipv4.c | 2 +- - net/dccp/ipv6.c | 2 +- - net/ipv4/inet_connection_sock.c | 2 +- - net/ipv4/inet_hashtables.c | 68 +++++++++++++++++++++++++++++---- - net/ipv4/tcp_ipv4.c | 15 +++++++- - net/ipv6/tcp_ipv6.c | 13 ++++++- + include/net/inet_hashtables.h | 5 +- + net/dccp/ipv4.c | 2 - + net/dccp/ipv6.c | 2 - + net/ipv4/inet_connection_sock.c | 2 - + net/ipv4/inet_hashtables.c | 68 +++++++++++++++++++++++++++++++++++----- + net/ipv4/tcp_ipv4.c | 15 +++++++- + net/ipv6/tcp_ipv6.c | 13 +++++++ 7 files changed, 91 insertions(+), 16 deletions(-) -diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h -index b875dcef173c..fa5fe23ca6aa 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h -@@ -232,8 +232,9 @@ void inet_hashinfo2_init(struct inet_hashinfo *h, const char *name, +@@ -232,8 +232,9 @@ void inet_hashinfo2_init(struct inet_has unsigned long low_limit, unsigned long high_limit); @@ -71,11 +69,9 @@ index b875dcef173c..fa5fe23ca6aa 100644 int __inet_hash(struct sock *sk, struct sock *osk); int inet_hash(struct sock *sk); void inet_unhash(struct sock *sk); -diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c -index 176bddacc16e..7e93087d1366 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c -@@ -428,7 +428,7 @@ struct sock *dccp_v4_request_recv_sock(const struct sock *sk, +@@ -428,7 +428,7 @@ struct sock *dccp_v4_request_recv_sock(c if (__inet_inherit_port(sk, newsk) < 0) goto put_and_exit; @@ -84,11 +80,9 @@ index 176bddacc16e..7e93087d1366 100644 if (*own_req) ireq->ireq_opt = NULL; else -diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c -index 2cd3508a3786..ae4851fdbe9e 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c -@@ -538,7 +538,7 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk, +@@ -538,7 +538,7 @@ static struct sock *dccp_v6_request_recv dccp_done(newsk); goto out; } @@ -97,11 +91,9 @@ index 2cd3508a3786..ae4851fdbe9e 100644 /* Clone pktoptions received with SYN, if we own the req */ if (*own_req && ireq->pktopts) { newnp->pktoptions = skb_clone(ireq->pktopts, GFP_ATOMIC); -diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c -index 439a55d1aa99..0a69f92da71b 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c -@@ -793,7 +793,7 @@ static void reqsk_queue_hash_req(struct request_sock *req, +@@ -793,7 +793,7 @@ static void reqsk_queue_hash_req(struct timer_setup(&req->rsk_timer, reqsk_timer_handler, TIMER_PINNED); mod_timer(&req->rsk_timer, jiffies + timeout); @@ -110,8 +102,6 @@ index 439a55d1aa99..0a69f92da71b 100644 /* before letting lookups find us, make sure all req fields * are committed to memory and refcnt initialized. */ -diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c -index 3a5f12f011cb..c96a5871b49d 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -24,6 +24,9 @@ @@ -124,7 +114,7 @@ index 3a5f12f011cb..c96a5871b49d 100644 #include #include #include -@@ -513,10 +516,52 @@ static u32 inet_sk_port_offset(const struct sock *sk) +@@ -513,10 +516,52 @@ static u32 inet_sk_port_offset(const str inet->inet_dport); } @@ -180,7 +170,7 @@ index 3a5f12f011cb..c96a5871b49d 100644 { struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; struct hlist_nulls_head *list; -@@ -535,16 +580,23 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk) +@@ -535,16 +580,23 @@ bool inet_ehash_insert(struct sock *sk, if (osk) { WARN_ON_ONCE(sk->sk_hash != osk->sk_hash); ret = sk_nulls_del_node_init_rcu(osk); @@ -206,7 +196,7 @@ index 3a5f12f011cb..c96a5871b49d 100644 if (ok) { sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); -@@ -588,7 +640,7 @@ int __inet_hash(struct sock *sk, struct sock *osk) +@@ -588,7 +640,7 @@ int __inet_hash(struct sock *sk, struct int err = 0; if (sk->sk_state != TCP_LISTEN) { @@ -215,7 +205,7 @@ index 3a5f12f011cb..c96a5871b49d 100644 return 0; } WARN_ON(!sk_unhashed(sk)); -@@ -683,7 +735,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row, +@@ -683,7 +735,7 @@ int __inet_hash_connect(struct inet_time tb = inet_csk(sk)->icsk_bind_hash; spin_lock_bh(&head->lock); if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) { @@ -224,7 +214,7 @@ index 3a5f12f011cb..c96a5871b49d 100644 spin_unlock_bh(&head->lock); return 0; } -@@ -759,7 +811,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row, +@@ -759,7 +811,7 @@ ok: inet_bind_hash(sk, tb, port); if (sk_unhashed(sk)) { inet_sk(sk)->inet_sport = htons(port); @@ -233,11 +223,9 @@ index 3a5f12f011cb..c96a5871b49d 100644 } if (tw) inet_twsk_bind_unhash(tw, hinfo); -diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c -index de4edfbc9e46..7ebdfab5b24a 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c -@@ -1415,6 +1415,7 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, +@@ -1415,6 +1415,7 @@ struct sock *tcp_v4_syn_recv_sock(const bool *own_req) { struct inet_request_sock *ireq; @@ -245,7 +233,7 @@ index de4edfbc9e46..7ebdfab5b24a 100644 struct inet_sock *newinet; struct tcp_sock *newtp; struct sock *newsk; -@@ -1485,12 +1486,22 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb, +@@ -1485,12 +1486,22 @@ struct sock *tcp_v4_syn_recv_sock(const if (__inet_inherit_port(sk, newsk) < 0) goto put_and_exit; @@ -270,11 +258,9 @@ index de4edfbc9e46..7ebdfab5b24a 100644 } return newsk; -diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c -index e8d206725cb7..c332f75f4e9a 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c -@@ -1090,6 +1090,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * +@@ -1090,6 +1090,7 @@ static struct sock *tcp_v6_syn_recv_sock struct ipv6_txoptions *opt; struct tcp6_sock *newtcp6sk; struct inet_sock *newinet; @@ -282,7 +268,7 @@ index e8d206725cb7..c332f75f4e9a 100644 struct tcp_sock *newtp; struct sock *newsk; #ifdef CONFIG_TCP_MD5SIG -@@ -1258,7 +1259,8 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * +@@ -1258,7 +1259,8 @@ static struct sock *tcp_v6_syn_recv_sock tcp_done(newsk); goto out; } @@ -292,7 +278,7 @@ index e8d206725cb7..c332f75f4e9a 100644 if (*own_req) { tcp_move_syn(newtp, req); -@@ -1273,6 +1275,15 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * +@@ -1273,6 +1275,15 @@ static struct sock *tcp_v6_syn_recv_sock skb_set_owner_r(newnp->pktoptions, newsk); } } @@ -308,6 +294,3 @@ index e8d206725cb7..c332f75f4e9a 100644 } return newsk; --- -2.35.1 -