]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 27 Mar 2024 14:51:23 +0000 (15:51 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 27 Mar 2024 14:51:23 +0000 (15:51 +0100)
added patches:
cgroup-cpuset-fix-retval-in-update_cpumask.patch
crypto-rk3288-fix-use-after-free-in-unprepare.patch
crypto-sun8i-ce-fix-use-after-free-in-unprepare.patch
drivers-hv-vmbus-calculate-ring-buffer-size-for-more-efficient-use-of-memory.patch
drm-nouveau-fix-stale-locked-mutex-in-nouveau_gem_ioctl_pushbuf.patch
mm-mmap-fix-vma_merge-case-7-with-vma_ops-close.patch
net-fix-ipstats_mib_outpkgs-increment-in-outforwdatagrams.patch
netfilter-nf_tables-disallow-anonymous-set-with-timeout-flag.patch
netfilter-nf_tables-mark-set-as-dead-when-unbinding-anonymous-set-with-timeout.patch
netfilter-nf_tables-reject-constant-set-with-timeout.patch
nouveau-lock-the-client-object-tree.patch
selftests-mptcp-diag-return-ksft_fail-not-test_cnt.patch
usb-typec-tpcm-fix-port_reset-behavior-for-self-powered-devices.patch
xfrm-avoid-clang-fortify-warning-in-copy_to_user_tmpl.patch

15 files changed:
queue-6.6/cgroup-cpuset-fix-retval-in-update_cpumask.patch [new file with mode: 0644]
queue-6.6/crypto-rk3288-fix-use-after-free-in-unprepare.patch [new file with mode: 0644]
queue-6.6/crypto-sun8i-ce-fix-use-after-free-in-unprepare.patch [new file with mode: 0644]
queue-6.6/drivers-hv-vmbus-calculate-ring-buffer-size-for-more-efficient-use-of-memory.patch [new file with mode: 0644]
queue-6.6/drm-nouveau-fix-stale-locked-mutex-in-nouveau_gem_ioctl_pushbuf.patch [new file with mode: 0644]
queue-6.6/mm-mmap-fix-vma_merge-case-7-with-vma_ops-close.patch [new file with mode: 0644]
queue-6.6/net-fix-ipstats_mib_outpkgs-increment-in-outforwdatagrams.patch [new file with mode: 0644]
queue-6.6/netfilter-nf_tables-disallow-anonymous-set-with-timeout-flag.patch [new file with mode: 0644]
queue-6.6/netfilter-nf_tables-mark-set-as-dead-when-unbinding-anonymous-set-with-timeout.patch [new file with mode: 0644]
queue-6.6/netfilter-nf_tables-reject-constant-set-with-timeout.patch [new file with mode: 0644]
queue-6.6/nouveau-lock-the-client-object-tree.patch [new file with mode: 0644]
queue-6.6/selftests-mptcp-diag-return-ksft_fail-not-test_cnt.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/usb-typec-tpcm-fix-port_reset-behavior-for-self-powered-devices.patch [new file with mode: 0644]
queue-6.6/xfrm-avoid-clang-fortify-warning-in-copy_to_user_tmpl.patch [new file with mode: 0644]

diff --git a/queue-6.6/cgroup-cpuset-fix-retval-in-update_cpumask.patch b/queue-6.6/cgroup-cpuset-fix-retval-in-update_cpumask.patch
new file mode 100644 (file)
index 0000000..d63b678
--- /dev/null
@@ -0,0 +1,37 @@
+From 25125a4762835d62ba1e540c1351d447fc1f6c7c Mon Sep 17 00:00:00 2001
+From: Kamalesh Babulal <kamalesh.babulal@oracle.com>
+Date: Thu, 29 Feb 2024 15:41:14 +0530
+Subject: cgroup/cpuset: Fix retval in update_cpumask()
+
+From: Kamalesh Babulal <kamalesh.babulal@oracle.com>
+
+commit 25125a4762835d62ba1e540c1351d447fc1f6c7c upstream.
+
+The update_cpumask(), checks for newly requested cpumask by calling
+validate_change(), which returns an error on passing an invalid set
+of cpu(s). Independent of the error returned, update_cpumask() always
+returns zero, suppressing the error and returning success to the user
+on writing an invalid cpu range for a cpuset. Fix it by returning
+retval instead, which is returned by validate_change().
+
+Fixes: 99fe36ba6fc1 ("cgroup/cpuset: Improve temporary cpumasks handling")
+Signed-off-by: Kamalesh Babulal <kamalesh.babulal@oracle.com>
+Reviewed-by: Waiman Long <longman@redhat.com>
+Cc: stable@vger.kernel.org # v6.6+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/cgroup/cpuset.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/cgroup/cpuset.c
++++ b/kernel/cgroup/cpuset.c
+@@ -1948,7 +1948,7 @@ static int update_cpumask(struct cpuset
+       }
+ out_free:
+       free_cpumasks(NULL, &tmp);
+-      return 0;
++      return retval;
+ }
+ /*
diff --git a/queue-6.6/crypto-rk3288-fix-use-after-free-in-unprepare.patch b/queue-6.6/crypto-rk3288-fix-use-after-free-in-unprepare.patch
new file mode 100644 (file)
index 0000000..1bd8478
--- /dev/null
@@ -0,0 +1,45 @@
+From c0afb6b88fbbc177fa322a835f874be217bffe45 Mon Sep 17 00:00:00 2001
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Wed, 28 Feb 2024 17:13:16 +0800
+Subject: crypto: rk3288 - Fix use after free in unprepare
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+commit c0afb6b88fbbc177fa322a835f874be217bffe45 upstream.
+
+The unprepare call must be carried out before the finalize call
+as the latter can free the request.
+
+Fixes: c66c17a0f69b ("crypto: rk3288 - Remove prepare/unprepare request")
+Reported-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Reviewed-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/rockchip/rk3288_crypto_ahash.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/crypto/rockchip/rk3288_crypto_ahash.c b/drivers/crypto/rockchip/rk3288_crypto_ahash.c
+index 1b13b4aa16ec..a235e6c300f1 100644
+--- a/drivers/crypto/rockchip/rk3288_crypto_ahash.c
++++ b/drivers/crypto/rockchip/rk3288_crypto_ahash.c
+@@ -332,12 +332,12 @@ static int rk_hash_run(struct crypto_engine *engine, void *breq)
+ theend:
+       pm_runtime_put_autosuspend(rkc->dev);
++      rk_hash_unprepare(engine, breq);
++
+       local_bh_disable();
+       crypto_finalize_hash_request(engine, breq, err);
+       local_bh_enable();
+-      rk_hash_unprepare(engine, breq);
+-
+       return 0;
+ }
+-- 
+2.44.0
+
diff --git a/queue-6.6/crypto-sun8i-ce-fix-use-after-free-in-unprepare.patch b/queue-6.6/crypto-sun8i-ce-fix-use-after-free-in-unprepare.patch
new file mode 100644 (file)
index 0000000..feb1b43
--- /dev/null
@@ -0,0 +1,155 @@
+From 183420038444547c149a0fc5f58e792c2752860c Mon Sep 17 00:00:00 2001
+From: Andrey Skvortsov <andrej.skvortzov@gmail.com>
+Date: Tue, 27 Feb 2024 00:53:57 +0300
+Subject: crypto: sun8i-ce - Fix use after free in unprepare
+
+From: Andrey Skvortsov <andrej.skvortzov@gmail.com>
+
+commit 183420038444547c149a0fc5f58e792c2752860c upstream.
+
+sun8i_ce_cipher_unprepare should be called before
+crypto_finalize_skcipher_request, because client callbacks may
+immediately free memory, that isn't needed anymore. But it will be
+used by unprepare after free. Before removing prepare/unprepare
+callbacks it was handled by crypto engine in crypto_finalize_request.
+
+Usually that results in a pointer dereference problem during a in
+crypto selftest.
+ Unable to handle kernel NULL pointer dereference at
+                                      virtual address 0000000000000030
+ Mem abort info:
+   ESR = 0x0000000096000004
+   EC = 0x25: DABT (current EL), IL = 32 bits
+   SET = 0, FnV = 0
+   EA = 0, S1PTW = 0
+   FSC = 0x04: level 0 translation fault
+ Data abort info:
+   ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
+   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
+   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
+ user pgtable: 4k pages, 48-bit VAs, pgdp=000000004716d000
+ [0000000000000030] pgd=0000000000000000, p4d=0000000000000000
+ Internal error: Oops: 0000000096000004 [#1] SMP
+
+This problem is detected by KASAN as well.
+ ==================================================================
+ BUG: KASAN: slab-use-after-free in sun8i_ce_cipher_do_one+0x6e8/0xf80 [sun8i_ce]
+ Read of size 8 at addr ffff00000dcdc040 by task 1c15000.crypto-/373
+
+ Hardware name: Pine64 PinePhone (1.2) (DT)
+ Call trace:
+  dump_backtrace+0x9c/0x128
+  show_stack+0x20/0x38
+  dump_stack_lvl+0x48/0x60
+  print_report+0xf8/0x5d8
+  kasan_report+0x90/0xd0
+  __asan_load8+0x9c/0xc0
+  sun8i_ce_cipher_do_one+0x6e8/0xf80 [sun8i_ce]
+  crypto_pump_work+0x354/0x620 [crypto_engine]
+  kthread_worker_fn+0x244/0x498
+  kthread+0x168/0x178
+  ret_from_fork+0x10/0x20
+
+ Allocated by task 379:
+  kasan_save_stack+0x3c/0x68
+  kasan_set_track+0x2c/0x40
+  kasan_save_alloc_info+0x24/0x38
+  __kasan_kmalloc+0xd4/0xd8
+  __kmalloc+0x74/0x1d0
+  alg_test_skcipher+0x90/0x1f0
+  alg_test+0x24c/0x830
+  cryptomgr_test+0x38/0x60
+  kthread+0x168/0x178
+  ret_from_fork+0x10/0x20
+
+ Freed by task 379:
+  kasan_save_stack+0x3c/0x68
+  kasan_set_track+0x2c/0x40
+  kasan_save_free_info+0x38/0x60
+  __kasan_slab_free+0x100/0x170
+  slab_free_freelist_hook+0xd4/0x1e8
+  __kmem_cache_free+0x15c/0x290
+  kfree+0x74/0x100
+  kfree_sensitive+0x80/0xb0
+  alg_test_skcipher+0x12c/0x1f0
+  alg_test+0x24c/0x830
+  cryptomgr_test+0x38/0x60
+  kthread+0x168/0x178
+  ret_from_fork+0x10/0x20
+
+ The buggy address belongs to the object at ffff00000dcdc000
+  which belongs to the cache kmalloc-256 of size 256
+ The buggy address is located 64 bytes inside of
+  freed 256-byte region [ffff00000dcdc000, ffff00000dcdc100)
+
+Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
+Fixes: 4136212ab18e ("crypto: sun8i-ce - Remove prepare/unprepare request")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../allwinner/sun8i-ce/sun8i-ce-cipher.c      | 34 +++++++++----------
+ 1 file changed, 17 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c
+index 1262a7773ef3..de50c00ba218 100644
+--- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c
++++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c
+@@ -299,22 +299,6 @@ static int sun8i_ce_cipher_prepare(struct crypto_engine *engine, void *async_req
+       return err;
+ }
+-static void sun8i_ce_cipher_run(struct crypto_engine *engine, void *areq)
+-{
+-      struct skcipher_request *breq = container_of(areq, struct skcipher_request, base);
+-      struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(breq);
+-      struct sun8i_cipher_tfm_ctx *op = crypto_skcipher_ctx(tfm);
+-      struct sun8i_ce_dev *ce = op->ce;
+-      struct sun8i_cipher_req_ctx *rctx = skcipher_request_ctx(breq);
+-      int flow, err;
+-
+-      flow = rctx->flow;
+-      err = sun8i_ce_run_task(ce, flow, crypto_tfm_alg_name(breq->base.tfm));
+-      local_bh_disable();
+-      crypto_finalize_skcipher_request(engine, breq, err);
+-      local_bh_enable();
+-}
+-
+ static void sun8i_ce_cipher_unprepare(struct crypto_engine *engine,
+                                     void *async_req)
+ {
+@@ -360,6 +344,23 @@ static void sun8i_ce_cipher_unprepare(struct crypto_engine *engine,
+       dma_unmap_single(ce->dev, rctx->addr_key, op->keylen, DMA_TO_DEVICE);
+ }
++static void sun8i_ce_cipher_run(struct crypto_engine *engine, void *areq)
++{
++      struct skcipher_request *breq = container_of(areq, struct skcipher_request, base);
++      struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(breq);
++      struct sun8i_cipher_tfm_ctx *op = crypto_skcipher_ctx(tfm);
++      struct sun8i_ce_dev *ce = op->ce;
++      struct sun8i_cipher_req_ctx *rctx = skcipher_request_ctx(breq);
++      int flow, err;
++
++      flow = rctx->flow;
++      err = sun8i_ce_run_task(ce, flow, crypto_tfm_alg_name(breq->base.tfm));
++      sun8i_ce_cipher_unprepare(engine, areq);
++      local_bh_disable();
++      crypto_finalize_skcipher_request(engine, breq, err);
++      local_bh_enable();
++}
++
+ int sun8i_ce_cipher_do_one(struct crypto_engine *engine, void *areq)
+ {
+       int err = sun8i_ce_cipher_prepare(engine, areq);
+@@ -368,7 +369,6 @@ int sun8i_ce_cipher_do_one(struct crypto_engine *engine, void *areq)
+               return err;
+       sun8i_ce_cipher_run(engine, areq);
+-      sun8i_ce_cipher_unprepare(engine, areq);
+       return 0;
+ }
+-- 
+2.44.0
+
diff --git a/queue-6.6/drivers-hv-vmbus-calculate-ring-buffer-size-for-more-efficient-use-of-memory.patch b/queue-6.6/drivers-hv-vmbus-calculate-ring-buffer-size-for-more-efficient-use-of-memory.patch
new file mode 100644 (file)
index 0000000..9de3d30
--- /dev/null
@@ -0,0 +1,89 @@
+From b8209544296edbd1af186e2ea9c648642c37b18c Mon Sep 17 00:00:00 2001
+From: Michael Kelley <mhklinux@outlook.com>
+Date: Wed, 28 Feb 2024 16:45:33 -0800
+Subject: Drivers: hv: vmbus: Calculate ring buffer size for more efficient use of memory
+
+From: Michael Kelley <mhklinux@outlook.com>
+
+commit b8209544296edbd1af186e2ea9c648642c37b18c upstream.
+
+The VMBUS_RING_SIZE macro adds space for a ring buffer header to the
+requested ring buffer size.  The header size is always 1 page, and so
+its size varies based on the PAGE_SIZE for which the kernel is built.
+If the requested ring buffer size is a large power-of-2 size and the header
+size is small, the resulting size is inefficient in its use of memory.
+For example, a 512 Kbyte ring buffer with a 4 Kbyte page size results in
+a 516 Kbyte allocation, which is rounded to up 1 Mbyte by the memory
+allocator, and wastes 508 Kbytes of memory.
+
+In such situations, the exact size of the ring buffer isn't that important,
+and it's OK to allocate the 4 Kbyte header at the beginning of the 512
+Kbytes, leaving the ring buffer itself with just 508 Kbytes. The memory
+allocation can be 512 Kbytes instead of 1 Mbyte and nothing is wasted.
+
+Update VMBUS_RING_SIZE to implement this approach for "large" ring buffer
+sizes.  "Large" is somewhat arbitrarily defined as 8 times the size of
+the ring buffer header (which is of size PAGE_SIZE).  For example, for
+4 Kbyte PAGE_SIZE, ring buffers of 32 Kbytes and larger use the first
+4 Kbytes as the ring buffer header.  For 64 Kbyte PAGE_SIZE, ring buffers
+of 512 Kbytes and larger use the first 64 Kbytes as the ring buffer
+header.  In both cases, smaller sizes add space for the header so
+the ring size isn't reduced too much by using part of the space for
+the header.  For example, with a 64 Kbyte page size, we don't want
+a 128 Kbyte ring buffer to be reduced to 64 Kbytes by allocating half
+of the space for the header.  In such a case, the memory allocation
+is less efficient, but it's the best that can be done.
+
+While the new algorithm slightly changes the amount of space allocated
+for ring buffers by drivers that use VMBUS_RING_SIZE, the devices aren't
+known to be sensitive to small changes in ring buffer size, so there
+shouldn't be any effect.
+
+Fixes: c1135c7fd0e9 ("Drivers: hv: vmbus: Introduce types of GPADL")
+Fixes: 6941f67ad37d ("hv_netvsc: Calculate correct ring size when PAGE_SIZE is not 4 Kbytes")
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218502
+Cc: stable@vger.kernel.org
+Signed-off-by: Michael Kelley <mhklinux@outlook.com>
+Reviewed-by: Saurabh Sengar <ssengar@linux.microsoft.com>
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Tested-by: Souradeep Chakrabarti <schakrabarti@linux.microsoft.com>
+Link: https://lore.kernel.org/r/20240229004533.313662-1-mhklinux@outlook.com
+Signed-off-by: Wei Liu <wei.liu@kernel.org>
+Message-ID: <20240229004533.313662-1-mhklinux@outlook.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/hyperv.h |   22 +++++++++++++++++++++-
+ 1 file changed, 21 insertions(+), 1 deletion(-)
+
+--- a/include/linux/hyperv.h
++++ b/include/linux/hyperv.h
+@@ -164,8 +164,28 @@ struct hv_ring_buffer {
+       u8 buffer[];
+ } __packed;
++
++/*
++ * If the requested ring buffer size is at least 8 times the size of the
++ * header, steal space from the ring buffer for the header. Otherwise, add
++ * space for the header so that is doesn't take too much of the ring buffer
++ * space.
++ *
++ * The factor of 8 is somewhat arbitrary. The goal is to prevent adding a
++ * relatively small header (4 Kbytes on x86) to a large-ish power-of-2 ring
++ * buffer size (such as 128 Kbytes) and so end up making a nearly twice as
++ * large allocation that will be almost half wasted. As a contrasting example,
++ * on ARM64 with 64 Kbyte page size, we don't want to take 64 Kbytes for the
++ * header from a 128 Kbyte allocation, leaving only 64 Kbytes for the ring.
++ * In this latter case, we must add 64 Kbytes for the header and not worry
++ * about what's wasted.
++ */
++#define VMBUS_HEADER_ADJ(payload_sz) \
++      ((payload_sz) >=  8 * sizeof(struct hv_ring_buffer) ? \
++      0 : sizeof(struct hv_ring_buffer))
++
+ /* Calculate the proper size of a ringbuffer, it must be page-aligned */
+-#define VMBUS_RING_SIZE(payload_sz) PAGE_ALIGN(sizeof(struct hv_ring_buffer) + \
++#define VMBUS_RING_SIZE(payload_sz) PAGE_ALIGN(VMBUS_HEADER_ADJ(payload_sz) + \
+                                              (payload_sz))
+ struct hv_ring_buffer_info {
diff --git a/queue-6.6/drm-nouveau-fix-stale-locked-mutex-in-nouveau_gem_ioctl_pushbuf.patch b/queue-6.6/drm-nouveau-fix-stale-locked-mutex-in-nouveau_gem_ioctl_pushbuf.patch
new file mode 100644 (file)
index 0000000..641565b
--- /dev/null
@@ -0,0 +1,37 @@
+From daf8739c3322a762ce84f240f50e0c39181a41ab Mon Sep 17 00:00:00 2001
+From: Karol Herbst <kherbst@redhat.com>
+Date: Tue, 5 Mar 2024 14:38:52 +0100
+Subject: drm/nouveau: fix stale locked mutex in nouveau_gem_ioctl_pushbuf
+
+From: Karol Herbst <kherbst@redhat.com>
+
+commit daf8739c3322a762ce84f240f50e0c39181a41ab upstream.
+
+If VM_BIND is enabled on the client the legacy submission ioctl can't be
+used, however if a client tries to do so regardless it will return an
+error. In this case the clients mutex remained unlocked leading to a
+deadlock inside nouveau_drm_postclose or any other nouveau ioctl call.
+
+Fixes: b88baab82871 ("drm/nouveau: implement new VM_BIND uAPI")
+Cc: Danilo Krummrich <dakr@redhat.com>
+Cc: <stable@vger.kernel.org> # v6.6+
+Signed-off-by: Karol Herbst <kherbst@redhat.com>
+Reviewed-by: Lyude Paul <lyude@redhat.com>
+Reviewed-by: Danilo Krummrich <dakr@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240305133853.2214268-1-kherbst@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/nouveau/nouveau_gem.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
++++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
+@@ -758,7 +758,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_dev
+               return -ENOMEM;
+       if (unlikely(nouveau_cli_uvmm(cli)))
+-              return -ENOSYS;
++              return nouveau_abi16_put(abi16, -ENOSYS);
+       list_for_each_entry(temp, &abi16->channels, head) {
+               if (temp->chan->chid == req->channel) {
diff --git a/queue-6.6/mm-mmap-fix-vma_merge-case-7-with-vma_ops-close.patch b/queue-6.6/mm-mmap-fix-vma_merge-case-7-with-vma_ops-close.patch
new file mode 100644 (file)
index 0000000..aec0633
--- /dev/null
@@ -0,0 +1,104 @@
+From fc0c8f9089c20d198d8fe51ddc28bfa1af588dce Mon Sep 17 00:00:00 2001
+From: Vlastimil Babka <vbabka@suse.cz>
+Date: Thu, 22 Feb 2024 22:59:31 +0100
+Subject: mm, mmap: fix vma_merge() case 7 with vma_ops->close
+
+From: Vlastimil Babka <vbabka@suse.cz>
+
+commit fc0c8f9089c20d198d8fe51ddc28bfa1af588dce upstream.
+
+When debugging issues with a workload using SysV shmem, Michal Hocko has
+come up with a reproducer that shows how a series of mprotect() operations
+can result in an elevated shm_nattch and thus leak of the resource.
+
+The problem is caused by wrong assumptions in vma_merge() commit
+714965ca8252 ("mm/mmap: start distinguishing if vma can be removed in
+mergeability test").  The shmem vmas have a vma_ops->close callback that
+decrements shm_nattch, and we remove the vma without calling it.
+
+vma_merge() has thus historically avoided merging vma's with
+vma_ops->close and commit 714965ca8252 was supposed to keep it that way.
+It relaxed the checks for vma_ops->close in can_vma_merge_after() assuming
+that it is never called on a vma that would be a candidate for removal.
+However, the vma_merge() code does also use the result of this check in
+the decision to remove a different vma in the merge case 7.
+
+A robust solution would be to refactor vma_merge() code in a way that the
+vma_ops->close check is only done for vma's that are actually going to be
+removed, and not as part of the preliminary checks.  That would both solve
+the existing bug, and also allow additional merges that the checks
+currently prevent unnecessarily in some cases.
+
+However to fix the existing bug first with a minimized risk, and for
+easier stable backports, this patch only adds a vma_ops->close check to
+the buggy case 7 specifically.  All other cases of vma removal are covered
+by the can_vma_merge_before() check that includes the test for
+vma_ops->close.
+
+The reproducer code, adapted from Michal Hocko's code:
+
+int main(int argc, char *argv[]) {
+  int segment_id;
+  size_t segment_size = 20 * PAGE_SIZE;
+  char * sh_mem;
+  struct shmid_ds shmid_ds;
+
+  key_t key = 0x1234;
+  segment_id = shmget(key, segment_size,
+                      IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
+  sh_mem = (char *)shmat(segment_id, NULL, 0);
+
+  mprotect(sh_mem + 2*PAGE_SIZE, PAGE_SIZE, PROT_NONE);
+
+  mprotect(sh_mem + PAGE_SIZE, PAGE_SIZE, PROT_WRITE);
+
+  mprotect(sh_mem + 2*PAGE_SIZE, PAGE_SIZE, PROT_WRITE);
+
+  shmdt(sh_mem);
+
+  shmctl(segment_id, IPC_STAT, &shmid_ds);
+  printf("nattch after shmdt(): %lu (expected: 0)\n", shmid_ds.shm_nattch);
+
+  if (shmctl(segment_id, IPC_RMID, 0))
+          printf("IPCRM failed %d\n", errno);
+  return (shmid_ds.shm_nattch) ? 1 : 0;
+}
+
+Link: https://lkml.kernel.org/r/20240222215930.14637-2-vbabka@suse.cz
+Fixes: 714965ca8252 ("mm/mmap: start distinguishing if vma can be removed in mergeability test")
+Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
+Reported-by: Michal Hocko <mhocko@suse.com>
+Reviewed-by: Lorenzo Stoakes <lstoakes@gmail.com>
+Reviewed-by: Liam R. Howlett <Liam.Howlett@oracle.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/mmap.c |   10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/mm/mmap.c
++++ b/mm/mmap.c
+@@ -949,13 +949,21 @@ struct vm_area_struct *vma_merge(struct
+       } else if (merge_prev) {                        /* case 2 */
+               if (curr) {
+                       vma_start_write(curr);
+-                      err = dup_anon_vma(prev, curr, &anon_dup);
+                       if (end == curr->vm_end) {      /* case 7 */
++                              /*
++                               * can_vma_merge_after() assumed we would not be
++                               * removing prev vma, so it skipped the check
++                               * for vm_ops->close, but we are removing curr
++                               */
++                              if (curr->vm_ops && curr->vm_ops->close)
++                                      err = -EINVAL;
+                               remove = curr;
+                       } else {                        /* case 5 */
+                               adjust = curr;
+                               adj_start = (end - curr->vm_start);
+                       }
++                      if (!err)
++                              err = dup_anon_vma(prev, curr, &anon_dup);
+               }
+       } else { /* merge_next */
+               vma_start_write(next);
diff --git a/queue-6.6/net-fix-ipstats_mib_outpkgs-increment-in-outforwdatagrams.patch b/queue-6.6/net-fix-ipstats_mib_outpkgs-increment-in-outforwdatagrams.patch
new file mode 100644 (file)
index 0000000..4d2649b
--- /dev/null
@@ -0,0 +1,264 @@
+From b4a11b2033b7d3dfdd46592f7036a775b18cecd1 Mon Sep 17 00:00:00 2001
+From: Heng Guo <heng.guo@windriver.com>
+Date: Thu, 19 Oct 2023 09:20:53 +0800
+Subject: net: fix IPSTATS_MIB_OUTPKGS increment in OutForwDatagrams.
+
+From: Heng Guo <heng.guo@windriver.com>
+
+commit b4a11b2033b7d3dfdd46592f7036a775b18cecd1 upstream.
+
+Reproduce environment:
+network with 3 VM linuxs is connected as below:
+VM1<---->VM2(latest kernel 6.5.0-rc7)<---->VM3
+VM1: eth0 ip: 192.168.122.207 MTU 1500
+VM2: eth0 ip: 192.168.122.208, eth1 ip: 192.168.123.224 MTU 1500
+VM3: eth0 ip: 192.168.123.240 MTU 1500
+
+Reproduce:
+VM1 send 1400 bytes UDP data to VM3 using tools scapy with flags=0.
+scapy command:
+send(IP(dst="192.168.123.240",flags=0)/UDP()/str('0'*1400),count=1,
+inter=1.000000)
+
+Result:
+Before IP data is sent.
+----------------------------------------------------------------------
+root@qemux86-64:~# cat /proc/net/snmp
+Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors
+  ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests
+  OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails
+  FragOKs FragFails FragCreates
+Ip: 1 64 11 0 3 4 0 0 4 7 0 0 0 0 0 0 0 0 0
+......
+----------------------------------------------------------------------
+After IP data is sent.
+----------------------------------------------------------------------
+root@qemux86-64:~# cat /proc/net/snmp
+Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors
+  ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests
+  OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails
+  FragOKs FragFails FragCreates
+Ip: 1 64 12 0 3 5 0 0 4 8 0 0 0 0 0 0 0 0 0
+......
+----------------------------------------------------------------------
+"ForwDatagrams" increase from 4 to 5 and "OutRequests" also increase
+from 7 to 8.
+
+Issue description and patch:
+IPSTATS_MIB_OUTPKTS("OutRequests") is counted with IPSTATS_MIB_OUTOCTETS
+("OutOctets") in ip_finish_output2().
+According to RFC 4293, it is "OutOctets" counted with "OutTransmits" but
+not "OutRequests". "OutRequests" does not include any datagrams counted
+in "ForwDatagrams".
+ipSystemStatsOutOctets OBJECT-TYPE
+    DESCRIPTION
+           "The total number of octets in IP datagrams delivered to the
+            lower layers for transmission.  Octets from datagrams
+            counted in ipIfStatsOutTransmits MUST be counted here.
+ipSystemStatsOutRequests OBJECT-TYPE
+    DESCRIPTION
+           "The total number of IP datagrams that local IP user-
+            protocols (including ICMP) supplied to IP in requests for
+            transmission.  Note that this counter does not include any
+            datagrams counted in ipSystemStatsOutForwDatagrams.
+So do patch to define IPSTATS_MIB_OUTPKTS to "OutTransmits" and add
+IPSTATS_MIB_OUTREQUESTS for "OutRequests".
+Add IPSTATS_MIB_OUTREQUESTS counter in __ip_local_out() for ipv4 and add
+IPSTATS_MIB_OUT counter in ip6_finish_output2() for ipv6.
+
+Test result with patch:
+Before IP data is sent.
+----------------------------------------------------------------------
+root@qemux86-64:~# cat /proc/net/snmp
+Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors
+  ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests
+  OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails
+  FragOKs FragFails FragCreates OutTransmits
+Ip: 1 64 9 0 5 1 0 0 3 3 0 0 0 0 0 0 0 0 0 4
+......
+root@qemux86-64:~# cat /proc/net/netstat
+......
+IpExt: InNoRoutes InTruncatedPkts InMcastPkts OutMcastPkts InBcastPkts
+  OutBcastPkts InOctets OutOctets InMcastOctets OutMcastOctets
+  InBcastOctets OutBcastOctets InCsumErrors InNoECTPkts InECT1Pkts
+  InECT0Pkts InCEPkts ReasmOverlaps
+IpExt: 0 0 0 0 0 0 2976 1896 0 0 0 0 0 9 0 0 0 0
+----------------------------------------------------------------------
+After IP data is sent.
+----------------------------------------------------------------------
+root@qemux86-64:~# cat /proc/net/snmp
+Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors
+  ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests
+  OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails
+  FragOKs FragFails FragCreates OutTransmits
+Ip: 1 64 10 0 5 2 0 0 3 3 0 0 0 0 0 0 0 0 0 5
+......
+root@qemux86-64:~# cat /proc/net/netstat
+......
+IpExt: InNoRoutes InTruncatedPkts InMcastPkts OutMcastPkts InBcastPkts
+  OutBcastPkts InOctets OutOctets InMcastOctets OutMcastOctets
+  InBcastOctets OutBcastOctets InCsumErrors InNoECTPkts InECT1Pkts
+  InECT0Pkts InCEPkts ReasmOverlaps
+IpExt: 0 0 0 0 0 0 4404 3324 0 0 0 0 0 10 0 0 0 0
+----------------------------------------------------------------------
+"ForwDatagrams" increase from 1 to 2 and "OutRequests" is keeping 3.
+"OutTransmits" increase from 4 to 5 and "OutOctets" increase 1428.
+
+Signed-off-by: Heng Guo <heng.guo@windriver.com>
+Reviewed-by: Kun Song <Kun.Song@windriver.com>
+Reviewed-by: Filip Pudak <filip.pudak@windriver.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Reported-by: Vitezslav Samel <vitezslav@samel.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/uapi/linux/snmp.h |    3 ++-
+ net/ipv4/ip_output.c      |    2 ++
+ net/ipv4/proc.c           |    3 ++-
+ net/ipv6/ip6_output.c     |    6 ++++--
+ net/ipv6/mcast.c          |    5 ++---
+ net/ipv6/ndisc.c          |    2 +-
+ net/ipv6/proc.c           |    3 ++-
+ net/ipv6/raw.c            |    2 +-
+ 8 files changed, 16 insertions(+), 10 deletions(-)
+
+--- a/include/uapi/linux/snmp.h
++++ b/include/uapi/linux/snmp.h
+@@ -24,7 +24,7 @@ enum
+       IPSTATS_MIB_INOCTETS,                   /* InOctets */
+       IPSTATS_MIB_INDELIVERS,                 /* InDelivers */
+       IPSTATS_MIB_OUTFORWDATAGRAMS,           /* OutForwDatagrams */
+-      IPSTATS_MIB_OUTPKTS,                    /* OutRequests */
++      IPSTATS_MIB_OUTREQUESTS,                /* OutRequests */
+       IPSTATS_MIB_OUTOCTETS,                  /* OutOctets */
+ /* other fields */
+       IPSTATS_MIB_INHDRERRORS,                /* InHdrErrors */
+@@ -57,6 +57,7 @@ enum
+       IPSTATS_MIB_ECT0PKTS,                   /* InECT0Pkts */
+       IPSTATS_MIB_CEPKTS,                     /* InCEPkts */
+       IPSTATS_MIB_REASM_OVERLAPS,             /* ReasmOverlaps */
++      IPSTATS_MIB_OUTPKTS,                    /* OutTransmits */
+       __IPSTATS_MIB_MAX
+ };
+--- a/net/ipv4/ip_output.c
++++ b/net/ipv4/ip_output.c
+@@ -101,6 +101,8 @@ int __ip_local_out(struct net *net, stru
+ {
+       struct iphdr *iph = ip_hdr(skb);
++      IP_INC_STATS(net, IPSTATS_MIB_OUTREQUESTS);
++
+       iph_set_totlen(iph, skb->len);
+       ip_send_check(iph);
+--- a/net/ipv4/proc.c
++++ b/net/ipv4/proc.c
+@@ -83,7 +83,7 @@ static const struct snmp_mib snmp4_ipsta
+       SNMP_MIB_ITEM("InUnknownProtos", IPSTATS_MIB_INUNKNOWNPROTOS),
+       SNMP_MIB_ITEM("InDiscards", IPSTATS_MIB_INDISCARDS),
+       SNMP_MIB_ITEM("InDelivers", IPSTATS_MIB_INDELIVERS),
+-      SNMP_MIB_ITEM("OutRequests", IPSTATS_MIB_OUTPKTS),
++      SNMP_MIB_ITEM("OutRequests", IPSTATS_MIB_OUTREQUESTS),
+       SNMP_MIB_ITEM("OutDiscards", IPSTATS_MIB_OUTDISCARDS),
+       SNMP_MIB_ITEM("OutNoRoutes", IPSTATS_MIB_OUTNOROUTES),
+       SNMP_MIB_ITEM("ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT),
+@@ -93,6 +93,7 @@ static const struct snmp_mib snmp4_ipsta
+       SNMP_MIB_ITEM("FragOKs", IPSTATS_MIB_FRAGOKS),
+       SNMP_MIB_ITEM("FragFails", IPSTATS_MIB_FRAGFAILS),
+       SNMP_MIB_ITEM("FragCreates", IPSTATS_MIB_FRAGCREATES),
++      SNMP_MIB_ITEM("OutTransmits", IPSTATS_MIB_OUTPKTS),
+       SNMP_MIB_SENTINEL
+ };
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -117,6 +117,8 @@ static int ip6_finish_output2(struct net
+                       return res;
+       }
++      IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
++
+       rcu_read_lock();
+       nexthop = rt6_nexthop((struct rt6_info *)dst, daddr);
+       neigh = __ipv6_neigh_lookup_noref(dev, nexthop);
+@@ -335,7 +337,7 @@ int ip6_xmit(const struct sock *sk, stru
+       mtu = dst_mtu(dst);
+       if ((skb->len <= mtu) || skb->ignore_df || skb_is_gso(skb)) {
+-              IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
++              IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+               /* if egress device is enslaved to an L3 master device pass the
+                * skb to its handler for processing
+@@ -1995,7 +1997,7 @@ struct sk_buff *__ip6_make_skb(struct so
+       skb->tstamp = cork->base.transmit_time;
+       ip6_cork_steal_dst(skb, cork);
+-      IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
++      IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
+       if (proto == IPPROTO_ICMPV6) {
+               struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
+               u8 icmp6_type;
+--- a/net/ipv6/mcast.c
++++ b/net/ipv6/mcast.c
+@@ -1789,7 +1789,7 @@ static void mld_sendpack(struct sk_buff
+       rcu_read_lock();
+       idev = __in6_dev_get(skb->dev);
+-      IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
++      IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+       payload_len = (skb_tail_pointer(skb) - skb_network_header(skb)) -
+               sizeof(*pip6);
+@@ -2147,8 +2147,7 @@ static void igmp6_send(struct in6_addr *
+       full_len = sizeof(struct ipv6hdr) + payload_len;
+       rcu_read_lock();
+-      IP6_UPD_PO_STATS(net, __in6_dev_get(dev),
+-                    IPSTATS_MIB_OUT, full_len);
++      IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_OUTREQUESTS);
+       rcu_read_unlock();
+       skb = sock_alloc_send_skb(sk, hlen + tlen + full_len, 1, &err);
+--- a/net/ipv6/ndisc.c
++++ b/net/ipv6/ndisc.c
+@@ -504,7 +504,7 @@ void ndisc_send_skb(struct sk_buff *skb,
+       rcu_read_lock();
+       idev = __in6_dev_get(dst->dev);
+-      IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
++      IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTREQUESTS);
+       err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
+                     net, sk, skb, NULL, dst->dev,
+--- a/net/ipv6/proc.c
++++ b/net/ipv6/proc.c
+@@ -61,7 +61,7 @@ static const struct snmp_mib snmp6_ipsta
+       SNMP_MIB_ITEM("Ip6InDiscards", IPSTATS_MIB_INDISCARDS),
+       SNMP_MIB_ITEM("Ip6InDelivers", IPSTATS_MIB_INDELIVERS),
+       SNMP_MIB_ITEM("Ip6OutForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS),
+-      SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTPKTS),
++      SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTREQUESTS),
+       SNMP_MIB_ITEM("Ip6OutDiscards", IPSTATS_MIB_OUTDISCARDS),
+       SNMP_MIB_ITEM("Ip6OutNoRoutes", IPSTATS_MIB_OUTNOROUTES),
+       SNMP_MIB_ITEM("Ip6ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT),
+@@ -84,6 +84,7 @@ static const struct snmp_mib snmp6_ipsta
+       SNMP_MIB_ITEM("Ip6InECT1Pkts", IPSTATS_MIB_ECT1PKTS),
+       SNMP_MIB_ITEM("Ip6InECT0Pkts", IPSTATS_MIB_ECT0PKTS),
+       SNMP_MIB_ITEM("Ip6InCEPkts", IPSTATS_MIB_CEPKTS),
++      SNMP_MIB_ITEM("Ip6OutTransmits", IPSTATS_MIB_OUTPKTS),
+       SNMP_MIB_SENTINEL
+ };
+--- a/net/ipv6/raw.c
++++ b/net/ipv6/raw.c
+@@ -651,7 +651,7 @@ static int rawv6_send_hdrinc(struct sock
+        * have been queued for deletion.
+        */
+       rcu_read_lock();
+-      IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
++      IP6_INC_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
+       err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb,
+                     NULL, rt->dst.dev, dst_output);
+       if (err > 0)
diff --git a/queue-6.6/netfilter-nf_tables-disallow-anonymous-set-with-timeout-flag.patch b/queue-6.6/netfilter-nf_tables-disallow-anonymous-set-with-timeout-flag.patch
new file mode 100644 (file)
index 0000000..770df41
--- /dev/null
@@ -0,0 +1,33 @@
+From 16603605b667b70da974bea8216c93e7db043bf1 Mon Sep 17 00:00:00 2001
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+Date: Fri, 1 Mar 2024 00:11:10 +0100
+Subject: netfilter: nf_tables: disallow anonymous set with timeout flag
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+commit 16603605b667b70da974bea8216c93e7db043bf1 upstream.
+
+Anonymous sets are never used with timeout from userspace, reject this.
+Exception to this rule is NFT_SET_EVAL to ensure legacy meters still work.
+
+Cc: stable@vger.kernel.org
+Fixes: 761da2935d6e ("netfilter: nf_tables: add set timeout API support")
+Reported-by: lonial con <kongln9170@gmail.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/netfilter/nf_tables_api.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -4942,6 +4942,9 @@ static int nf_tables_newset(struct sk_bu
+               if ((flags & (NFT_SET_EVAL | NFT_SET_OBJECT)) ==
+                            (NFT_SET_EVAL | NFT_SET_OBJECT))
+                       return -EOPNOTSUPP;
++              if ((flags & (NFT_SET_ANONYMOUS | NFT_SET_TIMEOUT | NFT_SET_EVAL)) ==
++                           (NFT_SET_ANONYMOUS | NFT_SET_TIMEOUT))
++                      return -EOPNOTSUPP;
+       }
+       desc.dtype = 0;
diff --git a/queue-6.6/netfilter-nf_tables-mark-set-as-dead-when-unbinding-anonymous-set-with-timeout.patch b/queue-6.6/netfilter-nf_tables-mark-set-as-dead-when-unbinding-anonymous-set-with-timeout.patch
new file mode 100644 (file)
index 0000000..bbdd763
--- /dev/null
@@ -0,0 +1,45 @@
+From 552705a3650bbf46a22b1adedc1b04181490fc36 Mon Sep 17 00:00:00 2001
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+Date: Mon, 4 Mar 2024 14:22:12 +0100
+Subject: netfilter: nf_tables: mark set as dead when unbinding anonymous set with timeout
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+commit 552705a3650bbf46a22b1adedc1b04181490fc36 upstream.
+
+While the rhashtable set gc runs asynchronously, a race allows it to
+collect elements from anonymous sets with timeouts while it is being
+released from the commit path.
+
+Mingi Cho originally reported this issue in a different path in 6.1.x
+with a pipapo set with low timeouts which is not possible upstream since
+7395dfacfff6 ("netfilter: nf_tables: use timestamp to check for set
+element timeout").
+
+Fix this by setting on the dead flag for anonymous sets to skip async gc
+in this case.
+
+According to 08e4c8c5919f ("netfilter: nf_tables: mark newset as dead on
+transaction abort"), Florian plans to accelerate abort path by releasing
+objects via workqueue, therefore, this sets on the dead flag for abort
+path too.
+
+Cc: stable@vger.kernel.org
+Fixes: 5f68718b34a5 ("netfilter: nf_tables: GC transaction API to avoid race with control plane")
+Reported-by: Mingi Cho <mgcho.minic@gmail.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/netfilter/nf_tables_api.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -5367,6 +5367,7 @@ static void nf_tables_unbind_set(const s
+       if (list_empty(&set->bindings) && nft_set_is_anonymous(set)) {
+               list_del_rcu(&set->list);
++              set->dead = 1;
+               if (event)
+                       nf_tables_set_notify(ctx, set, NFT_MSG_DELSET,
+                                            GFP_KERNEL);
diff --git a/queue-6.6/netfilter-nf_tables-reject-constant-set-with-timeout.patch b/queue-6.6/netfilter-nf_tables-reject-constant-set-with-timeout.patch
new file mode 100644 (file)
index 0000000..8c8d511
--- /dev/null
@@ -0,0 +1,34 @@
+From 5f4fc4bd5cddb4770ab120ce44f02695c4505562 Mon Sep 17 00:00:00 2001
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+Date: Fri, 1 Mar 2024 01:04:11 +0100
+Subject: netfilter: nf_tables: reject constant set with timeout
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+commit 5f4fc4bd5cddb4770ab120ce44f02695c4505562 upstream.
+
+This set combination is weird: it allows for elements to be
+added/deleted, but once bound to the rule it cannot be updated anymore.
+Eventually, all elements expire, leading to an empty set which cannot
+be updated anymore. Reject this flags combination.
+
+Cc: stable@vger.kernel.org
+Fixes: 761da2935d6e ("netfilter: nf_tables: add set timeout API support")
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/netfilter/nf_tables_api.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -4945,6 +4945,9 @@ static int nf_tables_newset(struct sk_bu
+               if ((flags & (NFT_SET_ANONYMOUS | NFT_SET_TIMEOUT | NFT_SET_EVAL)) ==
+                            (NFT_SET_ANONYMOUS | NFT_SET_TIMEOUT))
+                       return -EOPNOTSUPP;
++              if ((flags & (NFT_SET_CONSTANT | NFT_SET_TIMEOUT)) ==
++                           (NFT_SET_CONSTANT | NFT_SET_TIMEOUT))
++                      return -EOPNOTSUPP;
+       }
+       desc.dtype = 0;
diff --git a/queue-6.6/nouveau-lock-the-client-object-tree.patch b/queue-6.6/nouveau-lock-the-client-object-tree.patch
new file mode 100644 (file)
index 0000000..0340049
--- /dev/null
@@ -0,0 +1,163 @@
+From b7cc4ff787a572edf2c55caeffaa88cd801eb135 Mon Sep 17 00:00:00 2001
+From: Dave Airlie <airlied@redhat.com>
+Date: Wed, 28 Feb 2024 16:19:47 +1000
+Subject: nouveau: lock the client object tree.
+
+From: Dave Airlie <airlied@redhat.com>
+
+commit b7cc4ff787a572edf2c55caeffaa88cd801eb135 upstream.
+
+It appears the client object tree has no locking unless I've missed
+something else. Fix races around adding/removing client objects,
+mostly vram bar mappings.
+
+ 4562.099306] general protection fault, probably for non-canonical address 0x6677ed422bceb80c: 0000 [#1] PREEMPT SMP PTI
+[ 4562.099314] CPU: 2 PID: 23171 Comm: deqp-vk Not tainted 6.8.0-rc6+ #27
+[ 4562.099324] Hardware name: Gigabyte Technology Co., Ltd. Z390 I AORUS PRO WIFI/Z390 I AORUS PRO WIFI-CF, BIOS F8 11/05/2021
+[ 4562.099330] RIP: 0010:nvkm_object_search+0x1d/0x70 [nouveau]
+[ 4562.099503] Code: 90 90 90 90 90 90 90 90 90 90 90 90 90 66 0f 1f 00 0f 1f 44 00 00 48 89 f8 48 85 f6 74 39 48 8b 87 a0 00 00 00 48 85 c0 74 12 <48> 8b 48 f8 48 39 ce 73 15 48 8b 40 10 48 85 c0 75 ee 48 c7 c0 fe
+[ 4562.099506] RSP: 0000:ffffa94cc420bbf8 EFLAGS: 00010206
+[ 4562.099512] RAX: 6677ed422bceb814 RBX: ffff98108791f400 RCX: ffff9810f26b8f58
+[ 4562.099517] RDX: 0000000000000000 RSI: ffff9810f26b9158 RDI: ffff98108791f400
+[ 4562.099519] RBP: ffff9810f26b9158 R08: 0000000000000000 R09: 0000000000000000
+[ 4562.099521] R10: ffffa94cc420bc48 R11: 0000000000000001 R12: ffff9810f02a7cc0
+[ 4562.099526] R13: 0000000000000000 R14: 00000000000000ff R15: 0000000000000007
+[ 4562.099528] FS:  00007f629c5017c0(0000) GS:ffff98142c700000(0000) knlGS:0000000000000000
+[ 4562.099534] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 4562.099536] CR2: 00007f629a882000 CR3: 000000017019e004 CR4: 00000000003706f0
+[ 4562.099541] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[ 4562.099542] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+[ 4562.099544] Call Trace:
+[ 4562.099555]  <TASK>
+[ 4562.099573]  ? die_addr+0x36/0x90
+[ 4562.099583]  ? exc_general_protection+0x246/0x4a0
+[ 4562.099593]  ? asm_exc_general_protection+0x26/0x30
+[ 4562.099600]  ? nvkm_object_search+0x1d/0x70 [nouveau]
+[ 4562.099730]  nvkm_ioctl+0xa1/0x250 [nouveau]
+[ 4562.099861]  nvif_object_map_handle+0xc8/0x180 [nouveau]
+[ 4562.099986]  nouveau_ttm_io_mem_reserve+0x122/0x270 [nouveau]
+[ 4562.100156]  ? dma_resv_test_signaled+0x26/0xb0
+[ 4562.100163]  ttm_bo_vm_fault_reserved+0x97/0x3c0 [ttm]
+[ 4562.100182]  ? __mutex_unlock_slowpath+0x2a/0x270
+[ 4562.100189]  nouveau_ttm_fault+0x69/0xb0 [nouveau]
+[ 4562.100356]  __do_fault+0x32/0x150
+[ 4562.100362]  do_fault+0x7c/0x560
+[ 4562.100369]  __handle_mm_fault+0x800/0xc10
+[ 4562.100382]  handle_mm_fault+0x17c/0x3e0
+[ 4562.100388]  do_user_addr_fault+0x208/0x860
+[ 4562.100395]  exc_page_fault+0x7f/0x200
+[ 4562.100402]  asm_exc_page_fault+0x26/0x30
+[ 4562.100412] RIP: 0033:0x9b9870
+[ 4562.100419] Code: 85 a8 f7 ff ff 8b 8d 80 f7 ff ff 89 08 e9 18 f2 ff ff 0f 1f 84 00 00 00 00 00 44 89 32 e9 90 fa ff ff 0f 1f 84 00 00 00 00 00 <44> 89 32 e9 f8 f1 ff ff 0f 1f 84 00 00 00 00 00 66 44 89 32 e9 e7
+[ 4562.100422] RSP: 002b:00007fff9ba2dc70 EFLAGS: 00010246
+[ 4562.100426] RAX: 0000000000000004 RBX: 000000000dd65e10 RCX: 000000fff0000000
+[ 4562.100428] RDX: 00007f629a882000 RSI: 00007f629a882000 RDI: 0000000000000066
+[ 4562.100432] RBP: 00007fff9ba2e570 R08: 0000000000000000 R09: 0000000123ddf000
+[ 4562.100434] R10: 0000000000000001 R11: 0000000000000246 R12: 000000007fffffff
+[ 4562.100436] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
+[ 4562.100446]  </TASK>
+[ 4562.100448] Modules linked in: nf_conntrack_netbios_ns nf_conntrack_broadcast nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 ip_set nf_tables libcrc32c nfnetlink cmac bnep sunrpc iwlmvm intel_rapl_msr intel_rapl_common snd_sof_pci_intel_cnl x86_pkg_temp_thermal intel_powerclamp snd_sof_intel_hda_common mac80211 coretemp snd_soc_acpi_intel_match kvm_intel snd_soc_acpi snd_soc_hdac_hda snd_sof_pci snd_sof_xtensa_dsp snd_sof_intel_hda_mlink snd_sof_intel_hda snd_sof kvm snd_sof_utils snd_soc_core snd_hda_codec_realtek libarc4 snd_hda_codec_generic snd_compress snd_hda_ext_core vfat fat snd_hda_intel snd_intel_dspcfg irqbypass iwlwifi snd_hda_codec snd_hwdep snd_hda_core btusb btrtl mei_hdcp iTCO_wdt rapl mei_pxp btintel snd_seq iTCO_vendor_support btbcm snd_seq_device intel_cstate bluetooth snd_pcm cfg80211 intel_wmi_thunderbolt wmi_bmof intel_uncore snd_timer mei_me snd ecdh_generic i2c_i801
+[ 4562.100541]  ecc mei i2c_smbus soundcore rfkill intel_pch_thermal acpi_pad zram nouveau drm_ttm_helper ttm gpu_sched i2c_algo_bit drm_gpuvm drm_exec mxm_wmi drm_display_helper drm_kms_helper drm crct10dif_pclmul crc32_pclmul nvme e1000e crc32c_intel nvme_core ghash_clmulni_intel video wmi pinctrl_cannonlake ip6_tables ip_tables fuse
+[ 4562.100616] ---[ end trace 0000000000000000 ]---
+
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/nouveau/include/nvkm/core/client.h |    1 
+ drivers/gpu/drm/nouveau/nvkm/core/client.c         |    1 
+ drivers/gpu/drm/nouveau/nvkm/core/object.c         |   26 ++++++++++++++++-----
+ 3 files changed, 22 insertions(+), 6 deletions(-)
+
+--- a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h
+@@ -11,6 +11,7 @@ struct nvkm_client {
+       u32 debug;
+       struct rb_root objroot;
++      spinlock_t obj_lock;
+       void *data;
+       int (*event)(u64 token, void *argv, u32 argc);
+--- a/drivers/gpu/drm/nouveau/nvkm/core/client.c
++++ b/drivers/gpu/drm/nouveau/nvkm/core/client.c
+@@ -180,6 +180,7 @@ nvkm_client_new(const char *name, u64 de
+       client->device = device;
+       client->debug = nvkm_dbgopt(dbg, "CLIENT");
+       client->objroot = RB_ROOT;
++      spin_lock_init(&client->obj_lock);
+       client->event = event;
+       INIT_LIST_HEAD(&client->umem);
+       spin_lock_init(&client->lock);
+--- a/drivers/gpu/drm/nouveau/nvkm/core/object.c
++++ b/drivers/gpu/drm/nouveau/nvkm/core/object.c
+@@ -30,8 +30,10 @@ nvkm_object_search(struct nvkm_client *c
+                  const struct nvkm_object_func *func)
+ {
+       struct nvkm_object *object;
++      unsigned long flags;
+       if (handle) {
++              spin_lock_irqsave(&client->obj_lock, flags);
+               struct rb_node *node = client->objroot.rb_node;
+               while (node) {
+                       object = rb_entry(node, typeof(*object), node);
+@@ -40,9 +42,12 @@ nvkm_object_search(struct nvkm_client *c
+                       else
+                       if (handle > object->object)
+                               node = node->rb_right;
+-                      else
++                      else {
++                              spin_unlock_irqrestore(&client->obj_lock, flags);
+                               goto done;
++                      }
+               }
++              spin_unlock_irqrestore(&client->obj_lock, flags);
+               return ERR_PTR(-ENOENT);
+       } else {
+               object = &client->object;
+@@ -57,30 +62,39 @@ done:
+ void
+ nvkm_object_remove(struct nvkm_object *object)
+ {
++      unsigned long flags;
++
++      spin_lock_irqsave(&object->client->obj_lock, flags);
+       if (!RB_EMPTY_NODE(&object->node))
+               rb_erase(&object->node, &object->client->objroot);
++      spin_unlock_irqrestore(&object->client->obj_lock, flags);
+ }
+ bool
+ nvkm_object_insert(struct nvkm_object *object)
+ {
+-      struct rb_node **ptr = &object->client->objroot.rb_node;
++      struct rb_node **ptr;
+       struct rb_node *parent = NULL;
++      unsigned long flags;
++      spin_lock_irqsave(&object->client->obj_lock, flags);
++      ptr = &object->client->objroot.rb_node;
+       while (*ptr) {
+               struct nvkm_object *this = rb_entry(*ptr, typeof(*this), node);
+               parent = *ptr;
+-              if (object->object < this->object)
++              if (object->object < this->object) {
+                       ptr = &parent->rb_left;
+-              else
+-              if (object->object > this->object)
++              } else if (object->object > this->object) {
+                       ptr = &parent->rb_right;
+-              else
++              } else {
++                      spin_unlock_irqrestore(&object->client->obj_lock, flags);
+                       return false;
++              }
+       }
+       rb_link_node(&object->node, parent, ptr);
+       rb_insert_color(&object->node, &object->client->objroot);
++      spin_unlock_irqrestore(&object->client->obj_lock, flags);
+       return true;
+ }
diff --git a/queue-6.6/selftests-mptcp-diag-return-ksft_fail-not-test_cnt.patch b/queue-6.6/selftests-mptcp-diag-return-ksft_fail-not-test_cnt.patch
new file mode 100644 (file)
index 0000000..bb945ab
--- /dev/null
@@ -0,0 +1,52 @@
+From 45bcc0346561daa3f59e19a753cc7f3e08e8dff1 Mon Sep 17 00:00:00 2001
+From: Geliang Tang <tanggeliang@kylinos.cn>
+Date: Fri, 1 Mar 2024 18:11:22 +0100
+Subject: selftests: mptcp: diag: return KSFT_FAIL not test_cnt
+
+From: Geliang Tang <tanggeliang@kylinos.cn>
+
+commit 45bcc0346561daa3f59e19a753cc7f3e08e8dff1 upstream.
+
+The test counter 'test_cnt' should not be returned in diag.sh, e.g. what
+if only the 4th test fail? Will do 'exit 4' which is 'exit ${KSFT_SKIP}',
+the whole test will be marked as skipped instead of 'failed'!
+
+So we should do ret=${KSFT_FAIL} instead.
+
+Fixes: df62f2ec3df6 ("selftests/mptcp: add diag interface tests")
+Cc: stable@vger.kernel.org
+Fixes: 42fb6cddec3b ("selftests: mptcp: more stable diag tests")
+Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
+Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/net/mptcp/diag.sh |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/tools/testing/selftests/net/mptcp/diag.sh
++++ b/tools/testing/selftests/net/mptcp/diag.sh
+@@ -69,7 +69,7 @@ __chk_nr()
+               else
+                       echo "[ fail ] expected $expected found $nr"
+                       mptcp_lib_result_fail "${msg}"
+-                      ret=$test_cnt
++                      ret=${KSFT_FAIL}
+               fi
+       else
+               echo "[  ok  ]"
+@@ -115,11 +115,11 @@ wait_msk_nr()
+       if [ $i -ge $timeout ]; then
+               echo "[ fail ] timeout while expecting $expected max $max last $nr"
+               mptcp_lib_result_fail "${msg} # timeout"
+-              ret=$test_cnt
++              ret=${KSFT_FAIL}
+       elif [ $nr != $expected ]; then
+               echo "[ fail ] expected $expected found $nr"
+               mptcp_lib_result_fail "${msg} # unexpected result"
+-              ret=$test_cnt
++              ret=${KSFT_FAIL}
+       else
+               echo "[  ok  ]"
+               mptcp_lib_result_pass "${msg}"
index dfe2bc6265e3fc04b80312a1e51ec52af07ee9d6..02cc7c9f51d4911ed24e1edbe8ebc264299b1ddb 100644 (file)
@@ -193,3 +193,17 @@ drm-bridge-lt8912b-clear-the-edid-property-on-failur.patch
 drm-bridge-lt8912b-do-not-return-negative-values-fro.patch
 workqueue-shorten-events_freezable_power_efficient-name.patch
 drm-amd-display-use-freesync-when-drm_edid_feature_continuous_freq-found.patch
+net-fix-ipstats_mib_outpkgs-increment-in-outforwdatagrams.patch
+netfilter-nf_tables-mark-set-as-dead-when-unbinding-anonymous-set-with-timeout.patch
+netfilter-nf_tables-disallow-anonymous-set-with-timeout-flag.patch
+netfilter-nf_tables-reject-constant-set-with-timeout.patch
+drivers-hv-vmbus-calculate-ring-buffer-size-for-more-efficient-use-of-memory.patch
+nouveau-lock-the-client-object-tree.patch
+drm-nouveau-fix-stale-locked-mutex-in-nouveau_gem_ioctl_pushbuf.patch
+crypto-rk3288-fix-use-after-free-in-unprepare.patch
+crypto-sun8i-ce-fix-use-after-free-in-unprepare.patch
+xfrm-avoid-clang-fortify-warning-in-copy_to_user_tmpl.patch
+mm-mmap-fix-vma_merge-case-7-with-vma_ops-close.patch
+selftests-mptcp-diag-return-ksft_fail-not-test_cnt.patch
+usb-typec-tpcm-fix-port_reset-behavior-for-self-powered-devices.patch
+cgroup-cpuset-fix-retval-in-update_cpumask.patch
diff --git a/queue-6.6/usb-typec-tpcm-fix-port_reset-behavior-for-self-powered-devices.patch b/queue-6.6/usb-typec-tpcm-fix-port_reset-behavior-for-self-powered-devices.patch
new file mode 100644 (file)
index 0000000..8028f65
--- /dev/null
@@ -0,0 +1,59 @@
+From 197331b27ac890d0209232d5f669830cd00e8918 Mon Sep 17 00:00:00 2001
+From: Badhri Jagan Sridharan <badhri@google.com>
+Date: Wed, 28 Feb 2024 00:05:12 +0000
+Subject: usb: typec: tpcm: Fix PORT_RESET behavior for self powered devices
+
+From: Badhri Jagan Sridharan <badhri@google.com>
+
+commit 197331b27ac890d0209232d5f669830cd00e8918 upstream.
+
+While commit 69f89168b310 ("usb: typec: tpcm: Fix issues with power being
+removed during reset") fixes the boot issues for bus powered devices such
+as LibreTech Renegade Elite/Firefly, it trades off the CC pins NOT being
+Hi-Zed during errory recovery (i.e PORT_RESET) for devices which are NOT
+bus powered(a.k.a self powered). This change Hi-Zs the CC pins only for
+self powered devices, thus preventing brown out for bus powered devices
+
+Adhering to spec is gaining more importance due to the Common charger
+initiative enforced by the European Union.
+
+Quoting from the spec:
+    4.5.2.2.2.1 ErrorRecovery State Requirements
+    The port shall not drive VBUS or VCONN, and shall present a
+    high-impedance to ground (above zOPEN) on its CC1 and CC2 pins.
+
+Hi-Zing the CC pins is the inteded behavior for PORT_RESET.
+CC pins are set to default state after tErrorRecovery in
+PORT_RESET_WAIT_OFF.
+
+    4.5.2.2.2.2 Exiting From ErrorRecovery State
+    A Sink shall transition to Unattached.SNK after tErrorRecovery.
+    A Source shall transition to Unattached.SRC after tErrorRecovery.
+
+Fixes: 69f89168b310 ("usb: typec: tpcm: Fix issues with power being removed during reset")
+Cc: stable@vger.kernel.org
+Cc: Mark Brown <broonie@kernel.org>
+Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
+Tested-by: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/r/20240228000512.746252-1-badhri@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/tcpm/tcpm.c |    7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/typec/tcpm/tcpm.c
++++ b/drivers/usb/typec/tcpm/tcpm.c
+@@ -4859,8 +4859,11 @@ static void run_state_machine(struct tcp
+               break;
+       case PORT_RESET:
+               tcpm_reset_port(port);
+-              tcpm_set_cc(port, tcpm_default_state(port) == SNK_UNATTACHED ?
+-                          TYPEC_CC_RD : tcpm_rp_cc(port));
++              if (port->self_powered)
++                      tcpm_set_cc(port, TYPEC_CC_OPEN);
++              else
++                      tcpm_set_cc(port, tcpm_default_state(port) == SNK_UNATTACHED ?
++                                  TYPEC_CC_RD : tcpm_rp_cc(port));
+               tcpm_set_state(port, PORT_RESET_WAIT_OFF,
+                              PD_T_ERROR_RECOVERY);
+               break;
diff --git a/queue-6.6/xfrm-avoid-clang-fortify-warning-in-copy_to_user_tmpl.patch b/queue-6.6/xfrm-avoid-clang-fortify-warning-in-copy_to_user_tmpl.patch
new file mode 100644 (file)
index 0000000..9806d57
--- /dev/null
@@ -0,0 +1,56 @@
+From 1a807e46aa93ebad1dfbed4f82dc3bf779423a6e Mon Sep 17 00:00:00 2001
+From: Nathan Chancellor <nathan@kernel.org>
+Date: Wed, 21 Feb 2024 14:46:21 -0700
+Subject: xfrm: Avoid clang fortify warning in copy_to_user_tmpl()
+
+From: Nathan Chancellor <nathan@kernel.org>
+
+commit 1a807e46aa93ebad1dfbed4f82dc3bf779423a6e upstream.
+
+After a couple recent changes in LLVM, there is a warning (or error with
+CONFIG_WERROR=y or W=e) from the compile time fortify source routines,
+specifically the memset() in copy_to_user_tmpl().
+
+  In file included from net/xfrm/xfrm_user.c:14:
+  ...
+  include/linux/fortify-string.h:438:4: error: call to '__write_overflow_field' declared with 'warning' attribute: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Werror,-Wattribute-warning]
+    438 |                         __write_overflow_field(p_size_field, size);
+        |                         ^
+  1 error generated.
+
+While ->xfrm_nr has been validated against XFRM_MAX_DEPTH when its value
+is first assigned in copy_templates() by calling validate_tmpl() first
+(so there should not be any issue in practice), LLVM/clang cannot really
+deduce that across the boundaries of these functions. Without that
+knowledge, it cannot assume that the loop stops before i is greater than
+XFRM_MAX_DEPTH, which would indeed result a stack buffer overflow in the
+memset().
+
+To make the bounds of ->xfrm_nr clear to the compiler and add additional
+defense in case copy_to_user_tmpl() is ever used in a path where
+->xfrm_nr has not been properly validated against XFRM_MAX_DEPTH first,
+add an explicit bound check and early return, which clears up the
+warning.
+
+Cc: stable@vger.kernel.org
+Link: https://github.com/ClangBuiltLinux/linux/issues/1985
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/xfrm/xfrm_user.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -2017,6 +2017,9 @@ static int copy_to_user_tmpl(struct xfrm
+       if (xp->xfrm_nr == 0)
+               return 0;
++      if (xp->xfrm_nr > XFRM_MAX_DEPTH)
++              return -ENOBUFS;
++
+       for (i = 0; i < xp->xfrm_nr; i++) {
+               struct xfrm_user_tmpl *up = &vec[i];
+               struct xfrm_tmpl *kp = &xp->xfrm_vec[i];