--- /dev/null
+From b59e286be280fa3c2e94a0716ddcee6ba02bc8ba Mon Sep 17 00:00:00 2001
+From: Hangbin Liu <liuhangbin@gmail.com>
+Date: Tue, 27 Oct 2020 20:33:12 +0800
+Subject: ICMPv6: Add ICMPv6 Parameter Problem, code 3 definition
+
+From: Hangbin Liu <liuhangbin@gmail.com>
+
+commit b59e286be280fa3c2e94a0716ddcee6ba02bc8ba upstream.
+
+Based on RFC7112, Section 6:
+
+ IANA has added the following "Type 4 - Parameter Problem" message to
+ the "Internet Control Message Protocol version 6 (ICMPv6) Parameters"
+ registry:
+
+ CODE NAME/DESCRIPTION
+ 3 IPv6 First Fragment has incomplete IPv6 Header Chain
+
+Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Aviraj CJ <acj@cisco.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/uapi/linux/icmpv6.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/include/uapi/linux/icmpv6.h
++++ b/include/uapi/linux/icmpv6.h
+@@ -137,6 +137,7 @@ struct icmp6hdr {
+ #define ICMPV6_HDR_FIELD 0
+ #define ICMPV6_UNK_NEXTHDR 1
+ #define ICMPV6_UNK_OPTION 2
++#define ICMPV6_HDR_INCOMP 3
+
+ /*
+ * constants for (set|get)sockopt
--- /dev/null
+From 2efdaaaf883a143061296467913c01aa1ff4b3ce Mon Sep 17 00:00:00 2001
+From: Hangbin Liu <liuhangbin@gmail.com>
+Date: Tue, 27 Oct 2020 20:33:13 +0800
+Subject: IPv6: reply ICMP error if the first fragment don't include all headers
+
+From: Hangbin Liu <liuhangbin@gmail.com>
+
+commit 2efdaaaf883a143061296467913c01aa1ff4b3ce upstream.
+
+Based on RFC 8200, Section 4.5 Fragment Header:
+
+ - If the first fragment does not include all headers through an
+ Upper-Layer header, then that fragment should be discarded and
+ an ICMP Parameter Problem, Code 3, message should be sent to
+ the source of the fragment, with the Pointer field set to zero.
+
+Checking each packet header in IPv6 fast path will have performance impact,
+so I put the checking in ipv6_frag_rcv().
+
+As the packet may be any kind of L4 protocol, I only checked some common
+protocols' header length and handle others by (offset + 1) > skb->len.
+Also use !(frag_off & htons(IP6_OFFSET)) to catch atomic fragments
+(fragmented packet with only one fragment).
+
+When send ICMP error message, if the 1st truncated fragment is ICMP message,
+icmp6_send() will break as is_ineligible() return true. So I added a check
+in is_ineligible() to let fragment packet with nexthdr ICMP but no ICMP header
+return false.
+
+Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Aviraj CJ <acj@cisco.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/icmp.c | 8 +++++++-
+ net/ipv6/reassembly.c | 33 ++++++++++++++++++++++++++++++++-
+ 2 files changed, 39 insertions(+), 2 deletions(-)
+
+--- a/net/ipv6/icmp.c
++++ b/net/ipv6/icmp.c
+@@ -158,7 +158,13 @@ static bool is_ineligible(const struct s
+ tp = skb_header_pointer(skb,
+ ptr+offsetof(struct icmp6hdr, icmp6_type),
+ sizeof(_type), &_type);
+- if (!tp || !(*tp & ICMPV6_INFOMSG_MASK))
++
++ /* Based on RFC 8200, Section 4.5 Fragment Header, return
++ * false if this is a fragment packet with no icmp header info.
++ */
++ if (!tp && frag_off != 0)
++ return false;
++ else if (!tp || !(*tp & ICMPV6_INFOMSG_MASK))
+ return true;
+ }
+ return false;
+--- a/net/ipv6/reassembly.c
++++ b/net/ipv6/reassembly.c
+@@ -42,6 +42,8 @@
+ #include <linux/skbuff.h>
+ #include <linux/slab.h>
+ #include <linux/export.h>
++#include <linux/tcp.h>
++#include <linux/udp.h>
+
+ #include <net/sock.h>
+ #include <net/snmp.h>
+@@ -322,7 +324,9 @@ static int ipv6_frag_rcv(struct sk_buff
+ struct frag_queue *fq;
+ const struct ipv6hdr *hdr = ipv6_hdr(skb);
+ struct net *net = dev_net(skb_dst(skb)->dev);
+- int iif;
++ __be16 frag_off;
++ int iif, offset;
++ u8 nexthdr;
+
+ if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED)
+ goto fail_hdr;
+@@ -351,6 +355,33 @@ static int ipv6_frag_rcv(struct sk_buff
+ return 1;
+ }
+
++ /* RFC 8200, Section 4.5 Fragment Header:
++ * If the first fragment does not include all headers through an
++ * Upper-Layer header, then that fragment should be discarded and
++ * an ICMP Parameter Problem, Code 3, message should be sent to
++ * the source of the fragment, with the Pointer field set to zero.
++ */
++ nexthdr = hdr->nexthdr;
++ offset = ipv6_skip_exthdr(skb, skb_transport_offset(skb), &nexthdr, &frag_off);
++ if (offset >= 0) {
++ /* Check some common protocols' header */
++ if (nexthdr == IPPROTO_TCP)
++ offset += sizeof(struct tcphdr);
++ else if (nexthdr == IPPROTO_UDP)
++ offset += sizeof(struct udphdr);
++ else if (nexthdr == IPPROTO_ICMPV6)
++ offset += sizeof(struct icmp6hdr);
++ else
++ offset += 1;
++
++ if (!(frag_off & htons(IP6_OFFSET)) && offset > skb->len) {
++ __IP6_INC_STATS(net, __in6_dev_get_safely(skb->dev),
++ IPSTATS_MIB_INHDRERRORS);
++ icmpv6_param_prob(skb, ICMPV6_HDR_INCOMP, 0);
++ return -1;
++ }
++ }
++
+ iif = skb->dev ? skb->dev->ifindex : 0;
+ fq = fq_find(net, fhdr->identification, hdr, iif);
+ if (fq) {
--- /dev/null
+From b98e762e3d71e893b221f871825dc64694cfb258 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Mon, 25 Jan 2021 12:21:02 -0500
+Subject: nbd: freeze the queue while we're adding connections
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+commit b98e762e3d71e893b221f871825dc64694cfb258 upstream.
+
+When setting up a device, we can krealloc the config->socks array to add
+new sockets to the configuration. However if we happen to get a IO
+request in at this point even though we aren't setup we could hit a UAF,
+as we deref config->socks without any locking, assuming that the
+configuration was setup already and that ->socks is safe to access it as
+we have a reference on the configuration.
+
+But there's nothing really preventing IO from occurring at this point of
+the device setup, we don't want to incur the overhead of a lock to
+access ->socks when it will never change while the device is running.
+To fix this UAF scenario simply freeze the queue if we are adding
+sockets. This will protect us from this particular case without adding
+any additional overhead for the normal running case.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/nbd.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/block/nbd.c
++++ b/drivers/block/nbd.c
+@@ -1014,6 +1014,12 @@ static int nbd_add_socket(struct nbd_dev
+ if (!sock)
+ return err;
+
++ /*
++ * We need to make sure we don't get any errant requests while we're
++ * reallocating the ->socks array.
++ */
++ blk_mq_freeze_queue(nbd->disk->queue);
++
+ if (!netlink && !nbd->task_setup &&
+ !test_bit(NBD_RT_BOUND, &config->runtime_flags))
+ nbd->task_setup = current;
+@@ -1052,10 +1058,12 @@ static int nbd_add_socket(struct nbd_dev
+ nsock->cookie = 0;
+ socks[config->num_connections++] = nsock;
+ atomic_inc(&config->live_connections);
++ blk_mq_unfreeze_queue(nbd->disk->queue);
+
+ return 0;
+
+ put_socket:
++ blk_mq_unfreeze_queue(nbd->disk->queue);
+ sockfd_put(sock);
+ return err;
+ }