summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pagano <mpagano@gentoo.org>2020-07-31 14:07:39 -0400
committerMike Pagano <mpagano@gentoo.org>2020-07-31 14:07:39 -0400
commit3019bd9ccad7fa58df721cc1831b0444e4fb1d3b (patch)
tree79ec9d6c1bed2b61c4f425bc8c876a4679b8940d
parentLinux patch 5.7.11 (diff)
downloadlinux-patches-3019bd9c.tar.gz
linux-patches-3019bd9c.tar.bz2
linux-patches-3019bd9c.zip
Linux patch 5.7.125.7-13
Signed-off-by: Mike Pagano <mpagano@gentoo.org>
-rw-r--r--0000_README4
-rw-r--r--1011_linux-5.7.12.patch784
2 files changed, 788 insertions, 0 deletions
diff --git a/0000_README b/0000_README
index 6409a512..21eff3a5 100644
--- a/0000_README
+++ b/0000_README
@@ -87,6 +87,10 @@ Patch: 1010_linux-5.7.11.patch
From: http://www.kernel.org
Desc: Linux 5.7.11
+Patch: 1011_linux-5.7.12.patch
+From: http://www.kernel.org
+Desc: Linux 5.7.12
+
Patch: 1500_XATTR_USER_PREFIX.patch
From: https://bugs.gentoo.org/show_bug.cgi?id=470644
Desc: Support for namespace user.pax.* on tmpfs.
diff --git a/1011_linux-5.7.12.patch b/1011_linux-5.7.12.patch
new file mode 100644
index 00000000..bd95a59d
--- /dev/null
+++ b/1011_linux-5.7.12.patch
@@ -0,0 +1,784 @@
+diff --git a/Makefile b/Makefile
+index 12777a95833f..401d58b35e61 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 5
+ PATCHLEVEL = 7
+-SUBLEVEL = 11
++SUBLEVEL = 12
+ EXTRAVERSION =
+ NAME = Kleptomaniac Octopus
+
+diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
+index e16afa27700d..f58baff2be0a 100644
+--- a/drivers/base/regmap/regmap-debugfs.c
++++ b/drivers/base/regmap/regmap-debugfs.c
+@@ -227,6 +227,9 @@ static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from,
+ if (*ppos < 0 || !count)
+ return -EINVAL;
+
++ if (count > (PAGE_SIZE << (MAX_ORDER - 1)))
++ count = PAGE_SIZE << (MAX_ORDER - 1);
++
+ buf = kmalloc(count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+@@ -371,6 +374,9 @@ static ssize_t regmap_reg_ranges_read_file(struct file *file,
+ if (*ppos < 0 || !count)
+ return -EINVAL;
+
++ if (count > (PAGE_SIZE << (MAX_ORDER - 1)))
++ count = PAGE_SIZE << (MAX_ORDER - 1);
++
+ buf = kmalloc(count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
+index 69773d228ec1..84640a0c13f3 100644
+--- a/drivers/net/wan/x25_asy.c
++++ b/drivers/net/wan/x25_asy.c
+@@ -183,7 +183,7 @@ static inline void x25_asy_unlock(struct x25_asy *sl)
+ netif_wake_queue(sl->dev);
+ }
+
+-/* Send one completely decapsulated IP datagram to the IP layer. */
++/* Send an LAPB frame to the LAPB module to process. */
+
+ static void x25_asy_bump(struct x25_asy *sl)
+ {
+@@ -195,13 +195,12 @@ static void x25_asy_bump(struct x25_asy *sl)
+ count = sl->rcount;
+ dev->stats.rx_bytes += count;
+
+- skb = dev_alloc_skb(count+1);
++ skb = dev_alloc_skb(count);
+ if (skb == NULL) {
+ netdev_warn(sl->dev, "memory squeeze, dropping packet\n");
+ dev->stats.rx_dropped++;
+ return;
+ }
+- skb_push(skb, 1); /* LAPB internal control */
+ skb_put_data(skb, sl->rbuff, count);
+ skb->protocol = x25_type_trans(skb, sl->dev);
+ err = lapb_data_received(skb->dev, skb);
+@@ -209,7 +208,6 @@ static void x25_asy_bump(struct x25_asy *sl)
+ kfree_skb(skb);
+ printk(KERN_DEBUG "x25_asy: data received err - %d\n", err);
+ } else {
+- netif_rx(skb);
+ dev->stats.rx_packets++;
+ }
+ }
+@@ -356,12 +354,21 @@ static netdev_tx_t x25_asy_xmit(struct sk_buff *skb,
+ */
+
+ /*
+- * Called when I frame data arrives. We did the work above - throw it
+- * at the net layer.
++ * Called when I frame data arrive. We add a pseudo header for upper
++ * layers and pass it to upper layers.
+ */
+
+ static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb)
+ {
++ if (skb_cow(skb, 1)) {
++ kfree_skb(skb);
++ return NET_RX_DROP;
++ }
++ skb_push(skb, 1);
++ skb->data[0] = X25_IFACE_DATA;
++
++ skb->protocol = x25_type_trans(skb, dev);
++
+ return netif_rx(skb);
+ }
+
+@@ -657,7 +664,7 @@ static void x25_asy_unesc(struct x25_asy *sl, unsigned char s)
+ switch (s) {
+ case X25_END:
+ if (!test_and_clear_bit(SLF_ERROR, &sl->flags) &&
+- sl->rcount > 2)
++ sl->rcount >= 2)
+ x25_asy_bump(sl);
+ clear_bit(SLF_ESCAPE, &sl->flags);
+ sl->rcount = 0;
+diff --git a/fs/io_uring.c b/fs/io_uring.c
+index 51be3a20ade1..d0d3efaaa4d4 100644
+--- a/fs/io_uring.c
++++ b/fs/io_uring.c
+@@ -581,6 +581,7 @@ enum {
+
+ struct async_poll {
+ struct io_poll_iocb poll;
++ struct io_poll_iocb *double_poll;
+ struct io_wq_work work;
+ };
+
+@@ -4220,9 +4221,9 @@ static bool io_poll_rewait(struct io_kiocb *req, struct io_poll_iocb *poll)
+ return false;
+ }
+
+-static void io_poll_remove_double(struct io_kiocb *req)
++static void io_poll_remove_double(struct io_kiocb *req, void *data)
+ {
+- struct io_poll_iocb *poll = (struct io_poll_iocb *) req->io;
++ struct io_poll_iocb *poll = data;
+
+ lockdep_assert_held(&req->ctx->completion_lock);
+
+@@ -4242,7 +4243,7 @@ static void io_poll_complete(struct io_kiocb *req, __poll_t mask, int error)
+ {
+ struct io_ring_ctx *ctx = req->ctx;
+
+- io_poll_remove_double(req);
++ io_poll_remove_double(req, req->io);
+ req->poll.done = true;
+ io_cqring_fill_event(req, error ? error : mangle_poll(mask));
+ io_commit_cqring(ctx);
+@@ -4285,21 +4286,21 @@ static int io_poll_double_wake(struct wait_queue_entry *wait, unsigned mode,
+ int sync, void *key)
+ {
+ struct io_kiocb *req = wait->private;
+- struct io_poll_iocb *poll = (struct io_poll_iocb *) req->io;
++ struct io_poll_iocb *poll = req->apoll->double_poll;
+ __poll_t mask = key_to_poll(key);
+
+ /* for instances that support it check for an event match first: */
+ if (mask && !(mask & poll->events))
+ return 0;
+
+- if (req->poll.head) {
++ if (poll && poll->head) {
+ bool done;
+
+- spin_lock(&req->poll.head->lock);
+- done = list_empty(&req->poll.wait.entry);
++ spin_lock(&poll->head->lock);
++ done = list_empty(&poll->wait.entry);
+ if (!done)
+- list_del_init(&req->poll.wait.entry);
+- spin_unlock(&req->poll.head->lock);
++ list_del_init(&poll->wait.entry);
++ spin_unlock(&poll->head->lock);
+ if (!done)
+ __io_async_wake(req, poll, mask, io_poll_task_func);
+ }
+@@ -4319,7 +4320,8 @@ static void io_init_poll_iocb(struct io_poll_iocb *poll, __poll_t events,
+ }
+
+ static void __io_queue_proc(struct io_poll_iocb *poll, struct io_poll_table *pt,
+- struct wait_queue_head *head)
++ struct wait_queue_head *head,
++ struct io_poll_iocb **poll_ptr)
+ {
+ struct io_kiocb *req = pt->req;
+
+@@ -4330,7 +4332,7 @@ static void __io_queue_proc(struct io_poll_iocb *poll, struct io_poll_table *pt,
+ */
+ if (unlikely(poll->head)) {
+ /* already have a 2nd entry, fail a third attempt */
+- if (req->io) {
++ if (*poll_ptr) {
+ pt->error = -EINVAL;
+ return;
+ }
+@@ -4342,7 +4344,7 @@ static void __io_queue_proc(struct io_poll_iocb *poll, struct io_poll_table *pt,
+ io_init_poll_iocb(poll, req->poll.events, io_poll_double_wake);
+ refcount_inc(&req->refs);
+ poll->wait.private = req;
+- req->io = (void *) poll;
++ *poll_ptr = poll;
+ }
+
+ pt->error = 0;
+@@ -4354,8 +4356,9 @@ static void io_async_queue_proc(struct file *file, struct wait_queue_head *head,
+ struct poll_table_struct *p)
+ {
+ struct io_poll_table *pt = container_of(p, struct io_poll_table, pt);
++ struct async_poll *apoll = pt->req->apoll;
+
+- __io_queue_proc(&pt->req->apoll->poll, pt, head);
++ __io_queue_proc(&apoll->poll, pt, head, &apoll->double_poll);
+ }
+
+ static void io_sq_thread_drop_mm(struct io_ring_ctx *ctx)
+@@ -4409,6 +4412,7 @@ static void io_async_task_func(struct callback_head *cb)
+ memcpy(&req->work, &apoll->work, sizeof(req->work));
+
+ if (canceled) {
++ kfree(apoll->double_poll);
+ kfree(apoll);
+ io_cqring_ev_posted(ctx);
+ end_req:
+@@ -4426,6 +4430,7 @@ end_req:
+ __io_queue_sqe(req, NULL);
+ mutex_unlock(&ctx->uring_lock);
+
++ kfree(apoll->double_poll);
+ kfree(apoll);
+ }
+
+@@ -4497,7 +4502,6 @@ static bool io_arm_poll_handler(struct io_kiocb *req)
+ struct async_poll *apoll;
+ struct io_poll_table ipt;
+ __poll_t mask, ret;
+- bool had_io;
+
+ if (!req->file || !file_can_poll(req->file))
+ return false;
+@@ -4509,10 +4513,10 @@ static bool io_arm_poll_handler(struct io_kiocb *req)
+ apoll = kmalloc(sizeof(*apoll), GFP_ATOMIC);
+ if (unlikely(!apoll))
+ return false;
++ apoll->double_poll = NULL;
+
+ req->flags |= REQ_F_POLLED;
+ memcpy(&apoll->work, &req->work, sizeof(req->work));
+- had_io = req->io != NULL;
+
+ get_task_struct(current);
+ req->task = current;
+@@ -4531,12 +4535,10 @@ static bool io_arm_poll_handler(struct io_kiocb *req)
+ ret = __io_arm_poll_handler(req, &apoll->poll, &ipt, mask,
+ io_async_wake);
+ if (ret) {
+- ipt.error = 0;
+- /* only remove double add if we did it here */
+- if (!had_io)
+- io_poll_remove_double(req);
++ io_poll_remove_double(req, apoll->double_poll);
+ spin_unlock_irq(&ctx->completion_lock);
+ memcpy(&req->work, &apoll->work, sizeof(req->work));
++ kfree(apoll->double_poll);
+ kfree(apoll);
+ return false;
+ }
+@@ -4567,11 +4569,13 @@ static bool io_poll_remove_one(struct io_kiocb *req)
+ bool do_complete;
+
+ if (req->opcode == IORING_OP_POLL_ADD) {
+- io_poll_remove_double(req);
++ io_poll_remove_double(req, req->io);
+ do_complete = __io_poll_remove_one(req, &req->poll);
+ } else {
+ struct async_poll *apoll = req->apoll;
+
++ io_poll_remove_double(req, apoll->double_poll);
++
+ /* non-poll requests have submit ref still */
+ do_complete = __io_poll_remove_one(req, &apoll->poll);
+ if (do_complete) {
+@@ -4582,6 +4586,7 @@ static bool io_poll_remove_one(struct io_kiocb *req)
+ * final reference.
+ */
+ memcpy(&req->work, &apoll->work, sizeof(req->work));
++ kfree(apoll->double_poll);
+ kfree(apoll);
+ }
+ }
+@@ -4682,7 +4687,7 @@ static void io_poll_queue_proc(struct file *file, struct wait_queue_head *head,
+ {
+ struct io_poll_table *pt = container_of(p, struct io_poll_table, pt);
+
+- __io_queue_proc(&pt->req->poll, pt, head);
++ __io_queue_proc(&pt->req->poll, pt, head, (struct io_poll_iocb **) &pt->req->io);
+ }
+
+ static int io_poll_add_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+diff --git a/include/linux/tcp.h b/include/linux/tcp.h
+index 4f8159e90ce1..0bba582e83ca 100644
+--- a/include/linux/tcp.h
++++ b/include/linux/tcp.h
+@@ -217,6 +217,8 @@ struct tcp_sock {
+ } rack;
+ u16 advmss; /* Advertised MSS */
+ u8 compressed_ack;
++ u8 tlp_retrans:1, /* TLP is a retransmission */
++ unused:7;
+ u32 chrono_start; /* Start time in jiffies of a TCP chrono */
+ u32 chrono_stat[3]; /* Time in jiffies for chrono_stat stats */
+ u8 chrono_type:2, /* current chronograph type */
+@@ -239,7 +241,7 @@ struct tcp_sock {
+ save_syn:1, /* Save headers of SYN packet */
+ is_cwnd_limited:1,/* forward progress limited by snd_cwnd? */
+ syn_smc:1; /* SYN includes SMC */
+- u32 tlp_high_seq; /* snd_nxt at the time of TLP retransmit. */
++ u32 tlp_high_seq; /* snd_nxt at the time of TLP */
+
+ u32 tcp_tx_delay; /* delay (in usec) added to TX packets */
+ u64 tcp_wstamp_ns; /* departure time for next sent data packet */
+diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
+index fd91cd34f25e..dec3f35467c9 100644
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -1187,7 +1187,10 @@ static int __must_check ax25_connect(struct socket *sock,
+ if (addr_len > sizeof(struct sockaddr_ax25) &&
+ fsa->fsa_ax25.sax25_ndigis != 0) {
+ /* Valid number of digipeaters ? */
+- if (fsa->fsa_ax25.sax25_ndigis < 1 || fsa->fsa_ax25.sax25_ndigis > AX25_MAX_DIGIS) {
++ if (fsa->fsa_ax25.sax25_ndigis < 1 ||
++ fsa->fsa_ax25.sax25_ndigis > AX25_MAX_DIGIS ||
++ addr_len < sizeof(struct sockaddr_ax25) +
++ sizeof(ax25_address) * fsa->fsa_ax25.sax25_ndigis) {
+ err = -EINVAL;
+ goto out_release;
+ }
+@@ -1507,7 +1510,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
+ struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)usax;
+
+ /* Valid number of digipeaters ? */
+- if (usax->sax25_ndigis < 1 || usax->sax25_ndigis > AX25_MAX_DIGIS) {
++ if (usax->sax25_ndigis < 1 ||
++ usax->sax25_ndigis > AX25_MAX_DIGIS ||
++ addr_len < sizeof(struct sockaddr_ax25) +
++ sizeof(ax25_address) * usax->sax25_ndigis) {
+ err = -EINVAL;
+ goto out;
+ }
+diff --git a/net/core/dev.c b/net/core/dev.c
+index c9ee5d80d5ea..c1c2688a955c 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -5504,7 +5504,7 @@ static void flush_backlog(struct work_struct *work)
+ skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) {
+ if (skb->dev->reg_state == NETREG_UNREGISTERING) {
+ __skb_unlink(skb, &sd->input_pkt_queue);
+- kfree_skb(skb);
++ dev_kfree_skb_irq(skb);
+ input_queue_head_incr(sd);
+ }
+ }
+diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
+index 4773ad6ec111..f67f5ca39d63 100644
+--- a/net/core/net-sysfs.c
++++ b/net/core/net-sysfs.c
+@@ -1077,7 +1077,7 @@ static ssize_t tx_timeout_show(struct netdev_queue *queue, char *buf)
+ trans_timeout = queue->trans_timeout;
+ spin_unlock_irq(&queue->_xmit_lock);
+
+- return sprintf(buf, "%lu", trans_timeout);
++ return sprintf(buf, fmt_ulong, trans_timeout);
+ }
+
+ static unsigned int get_netdev_queue_index(struct netdev_queue *queue)
+diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
+index 709ebbf8ab5b..78345e39e54a 100644
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -3337,7 +3337,8 @@ replay:
+ */
+ if (err < 0) {
+ /* If device is not registered at all, free it now */
+- if (dev->reg_state == NETREG_UNINITIALIZED)
++ if (dev->reg_state == NETREG_UNINITIALIZED ||
++ dev->reg_state == NETREG_UNREGISTERED)
+ free_netdev(dev);
+ goto out;
+ }
+diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c
+index adcb3aea576d..bbdd3c7b6cb5 100644
+--- a/net/core/sock_reuseport.c
++++ b/net/core/sock_reuseport.c
+@@ -101,6 +101,7 @@ static struct sock_reuseport *reuseport_grow(struct sock_reuseport *reuse)
+ more_reuse->prog = reuse->prog;
+ more_reuse->reuseport_id = reuse->reuseport_id;
+ more_reuse->bind_inany = reuse->bind_inany;
++ more_reuse->has_conns = reuse->has_conns;
+
+ memcpy(more_reuse->socks, reuse->socks,
+ reuse->num_socks * sizeof(struct sock *));
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index 31c58e00d25b..32ac66a8c657 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -3506,10 +3506,8 @@ static void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq)
+ }
+ }
+
+-/* This routine deals with acks during a TLP episode.
+- * We mark the end of a TLP episode on receiving TLP dupack or when
+- * ack is after tlp_high_seq.
+- * Ref: loss detection algorithm in draft-dukkipati-tcpm-tcp-loss-probe.
++/* This routine deals with acks during a TLP episode and ends an episode by
++ * resetting tlp_high_seq. Ref: TLP algorithm in draft-ietf-tcpm-rack
+ */
+ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag)
+ {
+@@ -3518,7 +3516,10 @@ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag)
+ if (before(ack, tp->tlp_high_seq))
+ return;
+
+- if (flag & FLAG_DSACKING_ACK) {
++ if (!tp->tlp_retrans) {
++ /* TLP of new data has been acknowledged */
++ tp->tlp_high_seq = 0;
++ } else if (flag & FLAG_DSACKING_ACK) {
+ /* This DSACK means original and TLP probe arrived; no loss */
+ tp->tlp_high_seq = 0;
+ } else if (after(ack, tp->tlp_high_seq)) {
+diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
+index bee2f9b8b8a1..b1c2484b4314 100644
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -2625,6 +2625,11 @@ void tcp_send_loss_probe(struct sock *sk)
+ int pcount;
+ int mss = tcp_current_mss(sk);
+
++ /* At most one outstanding TLP */
++ if (tp->tlp_high_seq)
++ goto rearm_timer;
++
++ tp->tlp_retrans = 0;
+ skb = tcp_send_head(sk);
+ if (skb && tcp_snd_wnd_test(tp, skb, mss)) {
+ pcount = tp->packets_out;
+@@ -2642,10 +2647,6 @@ void tcp_send_loss_probe(struct sock *sk)
+ return;
+ }
+
+- /* At most one outstanding TLP retransmission. */
+- if (tp->tlp_high_seq)
+- goto rearm_timer;
+-
+ if (skb_still_in_host_queue(sk, skb))
+ goto rearm_timer;
+
+@@ -2667,10 +2668,12 @@ void tcp_send_loss_probe(struct sock *sk)
+ if (__tcp_retransmit_skb(sk, skb, 1))
+ goto rearm_timer;
+
++ tp->tlp_retrans = 1;
++
++probe_sent:
+ /* Record snd_nxt for loss detection. */
+ tp->tlp_high_seq = tp->snd_nxt;
+
+-probe_sent:
+ NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPLOSSPROBES);
+ /* Reset s.t. tcp_rearm_rto will restart timer from now */
+ inet_csk(sk)->icsk_pending = 0;
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index 32564b350823..6ffef9861fa9 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -413,7 +413,7 @@ static struct sock *udp4_lib_lookup2(struct net *net,
+ struct udp_hslot *hslot2,
+ struct sk_buff *skb)
+ {
+- struct sock *sk, *result;
++ struct sock *sk, *result, *reuseport_result;
+ int score, badness;
+ u32 hash = 0;
+
+@@ -423,17 +423,20 @@ static struct sock *udp4_lib_lookup2(struct net *net,
+ score = compute_score(sk, net, saddr, sport,
+ daddr, hnum, dif, sdif);
+ if (score > badness) {
++ reuseport_result = NULL;
++
+ if (sk->sk_reuseport &&
+ sk->sk_state != TCP_ESTABLISHED) {
+ hash = udp_ehashfn(net, daddr, hnum,
+ saddr, sport);
+- result = reuseport_select_sock(sk, hash, skb,
+- sizeof(struct udphdr));
+- if (result && !reuseport_has_conns(sk, false))
+- return result;
++ reuseport_result = reuseport_select_sock(sk, hash, skb,
++ sizeof(struct udphdr));
++ if (reuseport_result && !reuseport_has_conns(sk, false))
++ return reuseport_result;
+ }
++
++ result = reuseport_result ? : sk;
+ badness = score;
+- result = sk;
+ }
+ }
+ return result;
+@@ -2048,7 +2051,7 @@ static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
+ /*
+ * UDP-Lite specific tests, ignored on UDP sockets
+ */
+- if ((is_udplite & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) {
++ if ((up->pcflag & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) {
+
+ /*
+ * MIB statistics other than incrementing the error count are
+diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
+index 6532bde82b40..3a57fb9ce049 100644
+--- a/net/ipv6/ip6_gre.c
++++ b/net/ipv6/ip6_gre.c
+@@ -1562,17 +1562,18 @@ static void ip6gre_destroy_tunnels(struct net *net, struct list_head *head)
+ static int __net_init ip6gre_init_net(struct net *net)
+ {
+ struct ip6gre_net *ign = net_generic(net, ip6gre_net_id);
++ struct net_device *ndev;
+ int err;
+
+ if (!net_has_fallback_tunnels(net))
+ return 0;
+- ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0",
+- NET_NAME_UNKNOWN,
+- ip6gre_tunnel_setup);
+- if (!ign->fb_tunnel_dev) {
++ ndev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0",
++ NET_NAME_UNKNOWN, ip6gre_tunnel_setup);
++ if (!ndev) {
+ err = -ENOMEM;
+ goto err_alloc_dev;
+ }
++ ign->fb_tunnel_dev = ndev;
+ dev_net_set(ign->fb_tunnel_dev, net);
+ /* FB netdevice is special: we have one, and only one per netns.
+ * Allowing to move it to another netns is clearly unsafe.
+@@ -1592,7 +1593,7 @@ static int __net_init ip6gre_init_net(struct net *net)
+ return 0;
+
+ err_reg_dev:
+- free_netdev(ign->fb_tunnel_dev);
++ free_netdev(ndev);
+ err_alloc_dev:
+ return err;
+ }
+diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
+index 7d4151747340..a8d74f44056a 100644
+--- a/net/ipv6/udp.c
++++ b/net/ipv6/udp.c
+@@ -148,7 +148,7 @@ static struct sock *udp6_lib_lookup2(struct net *net,
+ int dif, int sdif, struct udp_hslot *hslot2,
+ struct sk_buff *skb)
+ {
+- struct sock *sk, *result;
++ struct sock *sk, *result, *reuseport_result;
+ int score, badness;
+ u32 hash = 0;
+
+@@ -158,17 +158,20 @@ static struct sock *udp6_lib_lookup2(struct net *net,
+ score = compute_score(sk, net, saddr, sport,
+ daddr, hnum, dif, sdif);
+ if (score > badness) {
++ reuseport_result = NULL;
++
+ if (sk->sk_reuseport &&
+ sk->sk_state != TCP_ESTABLISHED) {
+ hash = udp6_ehashfn(net, daddr, hnum,
+ saddr, sport);
+
+- result = reuseport_select_sock(sk, hash, skb,
+- sizeof(struct udphdr));
+- if (result && !reuseport_has_conns(sk, false))
+- return result;
++ reuseport_result = reuseport_select_sock(sk, hash, skb,
++ sizeof(struct udphdr));
++ if (reuseport_result && !reuseport_has_conns(sk, false))
++ return reuseport_result;
+ }
+- result = sk;
++
++ result = reuseport_result ? : sk;
+ badness = score;
+ }
+ }
+@@ -643,7 +646,7 @@ static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
+ /*
+ * UDP-Lite specific tests, ignored on UDP sockets (see net/ipv4/udp.c).
+ */
+- if ((is_udplite & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) {
++ if ((up->pcflag & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) {
+
+ if (up->pcrlen == 0) { /* full coverage was set */
+ net_dbg_ratelimited("UDPLITE6: partial coverage %d while full coverage %d requested\n",
+diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c
+index 24a8c3c6da0d..300a104b9a0f 100644
+--- a/net/qrtr/qrtr.c
++++ b/net/qrtr/qrtr.c
+@@ -1180,6 +1180,7 @@ static int qrtr_release(struct socket *sock)
+ sk->sk_state_change(sk);
+
+ sock_set_flag(sk, SOCK_DEAD);
++ sock_orphan(sk);
+ sock->sk = NULL;
+
+ if (!sock_flag(sk, SOCK_ZAPPED))
+diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
+index 8578c39ec839..6896a33ef842 100644
+--- a/net/rxrpc/recvmsg.c
++++ b/net/rxrpc/recvmsg.c
+@@ -464,7 +464,7 @@ try_again:
+ list_empty(&rx->recvmsg_q) &&
+ rx->sk.sk_state != RXRPC_SERVER_LISTENING) {
+ release_sock(&rx->sk);
+- return -ENODATA;
++ return -EAGAIN;
+ }
+
+ if (list_empty(&rx->recvmsg_q)) {
+diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c
+index 5e9c43d4a314..49d03c8c64da 100644
+--- a/net/rxrpc/sendmsg.c
++++ b/net/rxrpc/sendmsg.c
+@@ -306,7 +306,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
+ /* this should be in poll */
+ sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
+
+- if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
++ if (sk->sk_shutdown & SEND_SHUTDOWN)
+ return -EPIPE;
+
+ more = msg->msg_flags & MSG_MORE;
+diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
+index 6a114f80e54b..e191f2728389 100644
+--- a/net/sched/act_ct.c
++++ b/net/sched/act_ct.c
+@@ -671,9 +671,10 @@ static int tcf_ct_ipv6_is_fragment(struct sk_buff *skb, bool *frag)
+ }
+
+ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
+- u8 family, u16 zone)
++ u8 family, u16 zone, bool *defrag)
+ {
+ enum ip_conntrack_info ctinfo;
++ struct qdisc_skb_cb cb;
+ struct nf_conn *ct;
+ int err = 0;
+ bool frag;
+@@ -691,6 +692,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
+ return err;
+
+ skb_get(skb);
++ cb = *qdisc_skb_cb(skb);
+
+ if (family == NFPROTO_IPV4) {
+ enum ip_defrag_users user = IP_DEFRAG_CONNTRACK_IN + zone;
+@@ -701,6 +703,9 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
+ local_bh_enable();
+ if (err && err != -EINPROGRESS)
+ goto out_free;
++
++ if (!err)
++ *defrag = true;
+ } else { /* NFPROTO_IPV6 */
+ #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
+ enum ip6_defrag_users user = IP6_DEFRAG_CONNTRACK_IN + zone;
+@@ -709,12 +714,16 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb,
+ err = nf_ct_frag6_gather(net, skb, user);
+ if (err && err != -EINPROGRESS)
+ goto out_free;
++
++ if (!err)
++ *defrag = true;
+ #else
+ err = -EOPNOTSUPP;
+ goto out_free;
+ #endif
+ }
+
++ *qdisc_skb_cb(skb) = cb;
+ skb_clear_hash(skb);
+ skb->ignore_df = 1;
+ return err;
+@@ -912,6 +921,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
+ int nh_ofs, err, retval;
+ struct tcf_ct_params *p;
+ bool skip_add = false;
++ bool defrag = false;
+ struct nf_conn *ct;
+ u8 family;
+
+@@ -942,7 +952,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a,
+ */
+ nh_ofs = skb_network_offset(skb);
+ skb_pull_rcsum(skb, nh_ofs);
+- err = tcf_ct_handle_fragments(net, skb, family, p->zone);
++ err = tcf_ct_handle_fragments(net, skb, family, p->zone, &defrag);
+ if (err == -EINPROGRESS) {
+ retval = TC_ACT_STOLEN;
+ goto out;
+@@ -1010,6 +1020,8 @@ out_push:
+
+ out:
+ tcf_action_update_bstats(&c->common, skb);
++ if (defrag)
++ qdisc_skb_cb(skb)->pkt_len = skb->len;
+ return retval;
+
+ drop:
+diff --git a/net/sctp/stream.c b/net/sctp/stream.c
+index 67f7e71f9129..bda2536dd740 100644
+--- a/net/sctp/stream.c
++++ b/net/sctp/stream.c
+@@ -22,17 +22,11 @@
+ #include <net/sctp/sm.h>
+ #include <net/sctp/stream_sched.h>
+
+-/* Migrates chunks from stream queues to new stream queues if needed,
+- * but not across associations. Also, removes those chunks to streams
+- * higher than the new max.
+- */
+-static void sctp_stream_outq_migrate(struct sctp_stream *stream,
+- struct sctp_stream *new, __u16 outcnt)
++static void sctp_stream_shrink_out(struct sctp_stream *stream, __u16 outcnt)
+ {
+ struct sctp_association *asoc;
+ struct sctp_chunk *ch, *temp;
+ struct sctp_outq *outq;
+- int i;
+
+ asoc = container_of(stream, struct sctp_association, stream);
+ outq = &asoc->outqueue;
+@@ -56,6 +50,19 @@ static void sctp_stream_outq_migrate(struct sctp_stream *stream,
+
+ sctp_chunk_free(ch);
+ }
++}
++
++/* Migrates chunks from stream queues to new stream queues if needed,
++ * but not across associations. Also, removes those chunks to streams
++ * higher than the new max.
++ */
++static void sctp_stream_outq_migrate(struct sctp_stream *stream,
++ struct sctp_stream *new, __u16 outcnt)
++{
++ int i;
++
++ if (stream->outcnt > outcnt)
++ sctp_stream_shrink_out(stream, outcnt);
+
+ if (new) {
+ /* Here we actually move the old ext stuff into the new
+@@ -1037,11 +1044,13 @@ struct sctp_chunk *sctp_process_strreset_resp(
+ nums = ntohs(addstrm->number_of_streams);
+ number = stream->outcnt - nums;
+
+- if (result == SCTP_STRRESET_PERFORMED)
++ if (result == SCTP_STRRESET_PERFORMED) {
+ for (i = number; i < stream->outcnt; i++)
+ SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
+- else
++ } else {
++ sctp_stream_shrink_out(stream, number);
+ stream->outcnt = number;
++ }
+
+ *evp = sctp_ulpevent_make_stream_change_event(asoc, flags,
+ 0, nums, GFP_ATOMIC);
+diff --git a/net/tipc/link.c b/net/tipc/link.c
+index d4675e922a8f..e18369201a15 100644
+--- a/net/tipc/link.c
++++ b/net/tipc/link.c
+@@ -813,11 +813,11 @@ int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq)
+ state |= l->bc_rcvlink->rcv_unacked;
+ state |= l->rcv_unacked;
+ state |= !skb_queue_empty(&l->transmq);
+- state |= !skb_queue_empty(&l->deferdq);
+ probe = mstate->probing;
+ probe |= l->silent_intv_cnt;
+ if (probe || mstate->monitoring)
+ l->silent_intv_cnt++;
++ probe |= !skb_queue_empty(&l->deferdq);
+ if (l->snd_nxt == l->checkpoint) {
+ tipc_link_update_cwin(l, 0, 0);
+ probe = true;