]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.15
authorSasha Levin <sashal@kernel.org>
Sat, 31 Dec 2022 20:03:57 +0000 (15:03 -0500)
committerSasha Levin <sashal@kernel.org>
Sat, 31 Dec 2022 20:03:57 +0000 (15:03 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.15/cifs-fix-oops-during-encryption.patch [new file with mode: 0644]
queue-5.15/revert-selftests-bpf-add-test-for-unstable-ct-lookup.patch [new file with mode: 0644]
queue-5.15/series [new file with mode: 0644]
queue-5.15/usb-dwc3-qcom-fix-memory-leak-in-dwc3_qcom_interconn.patch [new file with mode: 0644]

diff --git a/queue-5.15/cifs-fix-oops-during-encryption.patch b/queue-5.15/cifs-fix-oops-during-encryption.patch
new file mode 100644 (file)
index 0000000..1b31400
--- /dev/null
@@ -0,0 +1,410 @@
+From b3fca551795d4937c78dc9a7f9e21d0c926a01c1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 11 Dec 2022 18:18:55 -0300
+Subject: cifs: fix oops during encryption
+
+From: Paulo Alcantara <pc@cjr.nz>
+
+[ Upstream commit f7f291e14dde32a07b1f0aa06921d28f875a7b54 ]
+
+When running xfstests against Azure the following oops occurred on an
+arm64 system
+
+  Unable to handle kernel write to read-only memory at virtual address
+  ffff0001221cf000
+  Mem abort info:
+    ESR = 0x9600004f
+    EC = 0x25: DABT (current EL), IL = 32 bits
+    SET = 0, FnV = 0
+    EA = 0, S1PTW = 0
+    FSC = 0x0f: level 3 permission fault
+  Data abort info:
+    ISV = 0, ISS = 0x0000004f
+    CM = 0, WnR = 1
+  swapper pgtable: 4k pages, 48-bit VAs, pgdp=00000000294f3000
+  [ffff0001221cf000] pgd=18000001ffff8003, p4d=18000001ffff8003,
+  pud=18000001ff82e003, pmd=18000001ff71d003, pte=00600001221cf787
+  Internal error: Oops: 9600004f [#1] PREEMPT SMP
+  ...
+  pstate: 80000005 (Nzcv daif -PAN -UAO -TCO BTYPE=--)
+  pc : __memcpy+0x40/0x230
+  lr : scatterwalk_copychunks+0xe0/0x200
+  sp : ffff800014e92de0
+  x29: ffff800014e92de0 x28: ffff000114f9de80 x27: 0000000000000008
+  x26: 0000000000000008 x25: ffff800014e92e78 x24: 0000000000000008
+  x23: 0000000000000001 x22: 0000040000000000 x21: ffff000000000000
+  x20: 0000000000000001 x19: ffff0001037c4488 x18: 0000000000000014
+  x17: 235e1c0d6efa9661 x16: a435f9576b6edd6c x15: 0000000000000058
+  x14: 0000000000000001 x13: 0000000000000008 x12: ffff000114f2e590
+  x11: ffffffffffffffff x10: 0000040000000000 x9 : ffff8000105c3580
+  x8 : 2e9413b10000001a x7 : 534b4410fb86b005 x6 : 534b4410fb86b005
+  x5 : ffff0001221cf008 x4 : ffff0001037c4490 x3 : 0000000000000001
+  x2 : 0000000000000008 x1 : ffff0001037c4488 x0 : ffff0001221cf000
+  Call trace:
+   __memcpy+0x40/0x230
+   scatterwalk_map_and_copy+0x98/0x100
+   crypto_ccm_encrypt+0x150/0x180
+   crypto_aead_encrypt+0x2c/0x40
+   crypt_message+0x750/0x880
+   smb3_init_transform_rq+0x298/0x340
+   smb_send_rqst.part.11+0xd8/0x180
+   smb_send_rqst+0x3c/0x100
+   compound_send_recv+0x534/0xbc0
+   smb2_query_info_compound+0x32c/0x440
+   smb2_set_ea+0x438/0x4c0
+   cifs_xattr_set+0x5d4/0x7c0
+
+This is because in scatterwalk_copychunks(), we attempted to write to
+a buffer (@sign) that was allocated in the stack (vmalloc area) by
+crypt_message() and thus accessing its remaining 8 (x2) bytes ended up
+crossing a page boundary.
+
+To simply fix it, we could just pass @sign kmalloc'd from
+crypt_message() and then we're done.  Luckily, we don't seem to pass
+any other vmalloc'd buffers in smb_rqst::rq_iov...
+
+Instead, let's map the correct pages and offsets from vmalloc buffers
+as well in cifs_sg_set_buf() and then avoiding such oopses.
+
+Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
+Cc: stable@vger.kernel.org
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/cifs/cifsglob.h  |  69 +++++++++++++++++++++
+ fs/cifs/cifsproto.h |   4 +-
+ fs/cifs/misc.c      |   4 +-
+ fs/cifs/smb2ops.c   | 143 +++++++++++++++++++++-----------------------
+ 4 files changed, 141 insertions(+), 79 deletions(-)
+
+diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
+index 1ab72c3d0bff..0f1b9c48838c 100644
+--- a/fs/cifs/cifsglob.h
++++ b/fs/cifs/cifsglob.h
+@@ -13,6 +13,8 @@
+ #include <linux/in6.h>
+ #include <linux/inet.h>
+ #include <linux/slab.h>
++#include <linux/scatterlist.h>
++#include <linux/mm.h>
+ #include <linux/mempool.h>
+ #include <linux/workqueue.h>
+ #include "cifs_fs_sb.h"
+@@ -21,6 +23,7 @@
+ #include <linux/scatterlist.h>
+ #include <uapi/linux/cifs/cifs_mount.h>
+ #include "smb2pdu.h"
++#include "smb2glob.h"
+ #define CIFS_MAGIC_NUMBER 0xFF534D42      /* the first four bytes of SMB PDUs */
+@@ -1972,4 +1975,70 @@ static inline bool cifs_is_referral_server(struct cifs_tcon *tcon,
+       return is_tcon_dfs(tcon) || (ref && (ref->flags & DFSREF_REFERRAL_SERVER));
+ }
++static inline unsigned int cifs_get_num_sgs(const struct smb_rqst *rqst,
++                                          int num_rqst,
++                                          const u8 *sig)
++{
++      unsigned int len, skip;
++      unsigned int nents = 0;
++      unsigned long addr;
++      int i, j;
++
++      /* Assumes the first rqst has a transform header as the first iov.
++       * I.e.
++       * rqst[0].rq_iov[0]  is transform header
++       * rqst[0].rq_iov[1+] data to be encrypted/decrypted
++       * rqst[1+].rq_iov[0+] data to be encrypted/decrypted
++       */
++      for (i = 0; i < num_rqst; i++) {
++              /*
++               * The first rqst has a transform header where the
++               * first 20 bytes are not part of the encrypted blob.
++               */
++              for (j = 0; j < rqst[i].rq_nvec; j++) {
++                      struct kvec *iov = &rqst[i].rq_iov[j];
++
++                      skip = (i == 0) && (j == 0) ? 20 : 0;
++                      addr = (unsigned long)iov->iov_base + skip;
++                      if (unlikely(is_vmalloc_addr((void *)addr))) {
++                              len = iov->iov_len - skip;
++                              nents += DIV_ROUND_UP(offset_in_page(addr) + len,
++                                                    PAGE_SIZE);
++                      } else {
++                              nents++;
++                      }
++              }
++              nents += rqst[i].rq_npages;
++      }
++      nents += DIV_ROUND_UP(offset_in_page(sig) + SMB2_SIGNATURE_SIZE, PAGE_SIZE);
++      return nents;
++}
++
++/* We can not use the normal sg_set_buf() as we will sometimes pass a
++ * stack object as buf.
++ */
++static inline struct scatterlist *cifs_sg_set_buf(struct scatterlist *sg,
++                                                const void *buf,
++                                                unsigned int buflen)
++{
++      unsigned long addr = (unsigned long)buf;
++      unsigned int off = offset_in_page(addr);
++
++      addr &= PAGE_MASK;
++      if (unlikely(is_vmalloc_addr((void *)addr))) {
++              do {
++                      unsigned int len = min_t(unsigned int, buflen, PAGE_SIZE - off);
++
++                      sg_set_page(sg++, vmalloc_to_page((void *)addr), len, off);
++
++                      off = 0;
++                      addr += PAGE_SIZE;
++                      buflen -= len;
++              } while (buflen);
++      } else {
++              sg_set_page(sg++, virt_to_page(addr), buflen, off);
++      }
++      return sg;
++}
++
+ #endif        /* _CIFS_GLOB_H */
+diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
+index b2697356b5e7..50844d51da5d 100644
+--- a/fs/cifs/cifsproto.h
++++ b/fs/cifs/cifsproto.h
+@@ -590,8 +590,8 @@ int cifs_alloc_hash(const char *name, struct crypto_shash **shash,
+                   struct sdesc **sdesc);
+ void cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc);
+-extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
+-                              unsigned int *len, unsigned int *offset);
++void rqst_page_get_length(const struct smb_rqst *rqst, unsigned int page,
++                        unsigned int *len, unsigned int *offset);
+ struct cifs_chan *
+ cifs_ses_find_chan(struct cifs_ses *ses, struct TCP_Server_Info *server);
+ int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses);
+diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
+index 94143d7f58c7..3a90ee314ed7 100644
+--- a/fs/cifs/misc.c
++++ b/fs/cifs/misc.c
+@@ -1134,8 +1134,8 @@ cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc)
+  * @len: Where to store the length for this page:
+  * @offset: Where to store the offset for this page
+  */
+-void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
+-                              unsigned int *len, unsigned int *offset)
++void rqst_page_get_length(const struct smb_rqst *rqst, unsigned int page,
++                        unsigned int *len, unsigned int *offset)
+ {
+       *len = rqst->rq_pagesz;
+       *offset = (page == 0) ? rqst->rq_offset : 0;
+diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
+index 5e6526c201fe..817d78129bd2 100644
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -4416,69 +4416,82 @@ fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
+       memcpy(&tr_hdr->SessionId, &shdr->SessionId, 8);
+ }
+-/* We can not use the normal sg_set_buf() as we will sometimes pass a
+- * stack object as buf.
+- */
+-static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
+-                                 unsigned int buflen)
++static void *smb2_aead_req_alloc(struct crypto_aead *tfm, const struct smb_rqst *rqst,
++                               int num_rqst, const u8 *sig, u8 **iv,
++                               struct aead_request **req, struct scatterlist **sgl,
++                               unsigned int *num_sgs)
+ {
+-      void *addr;
+-      /*
+-       * VMAP_STACK (at least) puts stack into the vmalloc address space
+-       */
+-      if (is_vmalloc_addr(buf))
+-              addr = vmalloc_to_page(buf);
+-      else
+-              addr = virt_to_page(buf);
+-      sg_set_page(sg, addr, buflen, offset_in_page(buf));
++      unsigned int req_size = sizeof(**req) + crypto_aead_reqsize(tfm);
++      unsigned int iv_size = crypto_aead_ivsize(tfm);
++      unsigned int len;
++      u8 *p;
++
++      *num_sgs = cifs_get_num_sgs(rqst, num_rqst, sig);
++
++      len = iv_size;
++      len += crypto_aead_alignmask(tfm) & ~(crypto_tfm_ctx_alignment() - 1);
++      len = ALIGN(len, crypto_tfm_ctx_alignment());
++      len += req_size;
++      len = ALIGN(len, __alignof__(struct scatterlist));
++      len += *num_sgs * sizeof(**sgl);
++
++      p = kmalloc(len, GFP_ATOMIC);
++      if (!p)
++              return NULL;
++
++      *iv = (u8 *)PTR_ALIGN(p, crypto_aead_alignmask(tfm) + 1);
++      *req = (struct aead_request *)PTR_ALIGN(*iv + iv_size,
++                                              crypto_tfm_ctx_alignment());
++      *sgl = (struct scatterlist *)PTR_ALIGN((u8 *)*req + req_size,
++                                             __alignof__(struct scatterlist));
++      return p;
+ }
+-/* Assumes the first rqst has a transform header as the first iov.
+- * I.e.
+- * rqst[0].rq_iov[0]  is transform header
+- * rqst[0].rq_iov[1+] data to be encrypted/decrypted
+- * rqst[1+].rq_iov[0+] data to be encrypted/decrypted
+- */
+-static struct scatterlist *
+-init_sg(int num_rqst, struct smb_rqst *rqst, u8 *sign)
++static void *smb2_get_aead_req(struct crypto_aead *tfm, const struct smb_rqst *rqst,
++                             int num_rqst, const u8 *sig, u8 **iv,
++                             struct aead_request **req, struct scatterlist **sgl)
+ {
+-      unsigned int sg_len;
++      unsigned int off, len, skip;
+       struct scatterlist *sg;
+-      unsigned int i;
+-      unsigned int j;
+-      unsigned int idx = 0;
+-      int skip;
+-
+-      sg_len = 1;
+-      for (i = 0; i < num_rqst; i++)
+-              sg_len += rqst[i].rq_nvec + rqst[i].rq_npages;
++      unsigned int num_sgs;
++      unsigned long addr;
++      int i, j;
++      void *p;
+-      sg = kmalloc_array(sg_len, sizeof(struct scatterlist), GFP_KERNEL);
+-      if (!sg)
++      p = smb2_aead_req_alloc(tfm, rqst, num_rqst, sig, iv, req, sgl, &num_sgs);
++      if (!p)
+               return NULL;
+-      sg_init_table(sg, sg_len);
++      sg_init_table(*sgl, num_sgs);
++      sg = *sgl;
++
++      /* Assumes the first rqst has a transform header as the first iov.
++       * I.e.
++       * rqst[0].rq_iov[0]  is transform header
++       * rqst[0].rq_iov[1+] data to be encrypted/decrypted
++       * rqst[1+].rq_iov[0+] data to be encrypted/decrypted
++       */
+       for (i = 0; i < num_rqst; i++) {
++              /*
++               * The first rqst has a transform header where the
++               * first 20 bytes are not part of the encrypted blob.
++               */
+               for (j = 0; j < rqst[i].rq_nvec; j++) {
+-                      /*
+-                       * The first rqst has a transform header where the
+-                       * first 20 bytes are not part of the encrypted blob
+-                       */
+-                      skip = (i == 0) && (j == 0) ? 20 : 0;
+-                      smb2_sg_set_buf(&sg[idx++],
+-                                      rqst[i].rq_iov[j].iov_base + skip,
+-                                      rqst[i].rq_iov[j].iov_len - skip);
+-                      }
++                      struct kvec *iov = &rqst[i].rq_iov[j];
++                      skip = (i == 0) && (j == 0) ? 20 : 0;
++                      addr = (unsigned long)iov->iov_base + skip;
++                      len = iov->iov_len - skip;
++                      sg = cifs_sg_set_buf(sg, (void *)addr, len);
++              }
+               for (j = 0; j < rqst[i].rq_npages; j++) {
+-                      unsigned int len, offset;
+-
+-                      rqst_page_get_length(&rqst[i], j, &len, &offset);
+-                      sg_set_page(&sg[idx++], rqst[i].rq_pages[j], len, offset);
++                      rqst_page_get_length(&rqst[i], j, &len, &off);
++                      sg_set_page(sg++, rqst[i].rq_pages[j], len, off);
+               }
+       }
+-      smb2_sg_set_buf(&sg[idx], sign, SMB2_SIGNATURE_SIZE);
+-      return sg;
++      cifs_sg_set_buf(sg, sig, SMB2_SIGNATURE_SIZE);
++
++      return p;
+ }
+ static int
+@@ -4522,11 +4535,11 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
+       u8 sign[SMB2_SIGNATURE_SIZE] = {};
+       u8 key[SMB3_ENC_DEC_KEY_SIZE];
+       struct aead_request *req;
+-      char *iv;
+-      unsigned int iv_len;
++      u8 *iv;
+       DECLARE_CRYPTO_WAIT(wait);
+       struct crypto_aead *tfm;
+       unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
++      void *creq;
+       rc = smb2_get_enc_key(server, tr_hdr->SessionId, enc, key);
+       if (rc) {
+@@ -4561,32 +4574,15 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
+               return rc;
+       }
+-      req = aead_request_alloc(tfm, GFP_KERNEL);
+-      if (!req) {
+-              cifs_server_dbg(VFS, "%s: Failed to alloc aead request\n", __func__);
++      creq = smb2_get_aead_req(tfm, rqst, num_rqst, sign, &iv, &req, &sg);
++      if (unlikely(!creq))
+               return -ENOMEM;
+-      }
+       if (!enc) {
+               memcpy(sign, &tr_hdr->Signature, SMB2_SIGNATURE_SIZE);
+               crypt_len += SMB2_SIGNATURE_SIZE;
+       }
+-      sg = init_sg(num_rqst, rqst, sign);
+-      if (!sg) {
+-              cifs_server_dbg(VFS, "%s: Failed to init sg\n", __func__);
+-              rc = -ENOMEM;
+-              goto free_req;
+-      }
+-
+-      iv_len = crypto_aead_ivsize(tfm);
+-      iv = kzalloc(iv_len, GFP_KERNEL);
+-      if (!iv) {
+-              cifs_server_dbg(VFS, "%s: Failed to alloc iv\n", __func__);
+-              rc = -ENOMEM;
+-              goto free_sg;
+-      }
+-
+       if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||
+           (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
+               memcpy(iv, (char *)tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
+@@ -4595,6 +4591,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
+               memcpy(iv + 1, (char *)tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
+       }
++      aead_request_set_tfm(req, tfm);
+       aead_request_set_crypt(req, sg, sg, crypt_len, iv);
+       aead_request_set_ad(req, assoc_data_len);
+@@ -4607,11 +4604,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
+       if (!rc && enc)
+               memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE);
+-      kfree(iv);
+-free_sg:
+-      kfree(sg);
+-free_req:
+-      kfree(req);
++      kfree_sensitive(creq);
+       return rc;
+ }
+-- 
+2.35.1
+
diff --git a/queue-5.15/revert-selftests-bpf-add-test-for-unstable-ct-lookup.patch b/queue-5.15/revert-selftests-bpf-add-test-for-unstable-ct-lookup.patch
new file mode 100644 (file)
index 0000000..b3fe522
--- /dev/null
@@ -0,0 +1,200 @@
+From e9d7eb9c702b120c8a86c617a41088a39221975a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 31 Dec 2022 10:14:21 -0500
+Subject: Revert "selftests/bpf: Add test for unstable CT lookup API"
+
+This reverts commit f463a1295c4fa73eac0b16fbfbdfc5726b06445d.
+
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/bpf/config            |   4 -
+ .../testing/selftests/bpf/prog_tests/bpf_nf.c |  48 --------
+ .../testing/selftests/bpf/progs/test_bpf_nf.c | 109 ------------------
+ 3 files changed, 161 deletions(-)
+ delete mode 100644 tools/testing/selftests/bpf/prog_tests/bpf_nf.c
+ delete mode 100644 tools/testing/selftests/bpf/progs/test_bpf_nf.c
+
+diff --git a/tools/testing/selftests/bpf/config b/tools/testing/selftests/bpf/config
+index 4a2a47fcd6ef..5192305159ec 100644
+--- a/tools/testing/selftests/bpf/config
++++ b/tools/testing/selftests/bpf/config
+@@ -46,7 +46,3 @@ CONFIG_IMA_READ_POLICY=y
+ CONFIG_BLK_DEV_LOOP=y
+ CONFIG_FUNCTION_TRACER=y
+ CONFIG_DYNAMIC_FTRACE=y
+-CONFIG_NETFILTER=y
+-CONFIG_NF_DEFRAG_IPV4=y
+-CONFIG_NF_DEFRAG_IPV6=y
+-CONFIG_NF_CONNTRACK=y
+diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_nf.c b/tools/testing/selftests/bpf/prog_tests/bpf_nf.c
+deleted file mode 100644
+index e3166a81e989..000000000000
+--- a/tools/testing/selftests/bpf/prog_tests/bpf_nf.c
++++ /dev/null
+@@ -1,48 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-#include <test_progs.h>
+-#include <network_helpers.h>
+-#include "test_bpf_nf.skel.h"
+-
+-enum {
+-      TEST_XDP,
+-      TEST_TC_BPF,
+-};
+-
+-void test_bpf_nf_ct(int mode)
+-{
+-      struct test_bpf_nf *skel;
+-      int prog_fd, err, retval;
+-
+-      skel = test_bpf_nf__open_and_load();
+-      if (!ASSERT_OK_PTR(skel, "test_bpf_nf__open_and_load"))
+-              return;
+-
+-      if (mode == TEST_XDP)
+-              prog_fd = bpf_program__fd(skel->progs.nf_xdp_ct_test);
+-      else
+-              prog_fd = bpf_program__fd(skel->progs.nf_skb_ct_test);
+-
+-      err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4), NULL, NULL,
+-                              (__u32 *)&retval, NULL);
+-      if (!ASSERT_OK(err, "bpf_prog_test_run"))
+-              goto end;
+-
+-      ASSERT_EQ(skel->bss->test_einval_bpf_tuple, -EINVAL, "Test EINVAL for NULL bpf_tuple");
+-      ASSERT_EQ(skel->bss->test_einval_reserved, -EINVAL, "Test EINVAL for reserved not set to 0");
+-      ASSERT_EQ(skel->bss->test_einval_netns_id, -EINVAL, "Test EINVAL for netns_id < -1");
+-      ASSERT_EQ(skel->bss->test_einval_len_opts, -EINVAL, "Test EINVAL for len__opts != NF_BPF_CT_OPTS_SZ");
+-      ASSERT_EQ(skel->bss->test_eproto_l4proto, -EPROTO, "Test EPROTO for l4proto != TCP or UDP");
+-      ASSERT_EQ(skel->bss->test_enonet_netns_id, -ENONET, "Test ENONET for bad but valid netns_id");
+-      ASSERT_EQ(skel->bss->test_enoent_lookup, -ENOENT, "Test ENOENT for failed lookup");
+-      ASSERT_EQ(skel->bss->test_eafnosupport, -EAFNOSUPPORT, "Test EAFNOSUPPORT for invalid len__tuple");
+-end:
+-      test_bpf_nf__destroy(skel);
+-}
+-
+-void test_bpf_nf(void)
+-{
+-      if (test__start_subtest("xdp-ct"))
+-              test_bpf_nf_ct(TEST_XDP);
+-      if (test__start_subtest("tc-bpf-ct"))
+-              test_bpf_nf_ct(TEST_TC_BPF);
+-}
+diff --git a/tools/testing/selftests/bpf/progs/test_bpf_nf.c b/tools/testing/selftests/bpf/progs/test_bpf_nf.c
+deleted file mode 100644
+index 6f131c993c0b..000000000000
+--- a/tools/testing/selftests/bpf/progs/test_bpf_nf.c
++++ /dev/null
+@@ -1,109 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-#include <vmlinux.h>
+-#include <bpf/bpf_helpers.h>
+-
+-#define EAFNOSUPPORT 97
+-#define EPROTO 71
+-#define ENONET 64
+-#define EINVAL 22
+-#define ENOENT 2
+-
+-int test_einval_bpf_tuple = 0;
+-int test_einval_reserved = 0;
+-int test_einval_netns_id = 0;
+-int test_einval_len_opts = 0;
+-int test_eproto_l4proto = 0;
+-int test_enonet_netns_id = 0;
+-int test_enoent_lookup = 0;
+-int test_eafnosupport = 0;
+-
+-struct nf_conn *bpf_xdp_ct_lookup(struct xdp_md *, struct bpf_sock_tuple *, u32,
+-                                struct bpf_ct_opts *, u32) __ksym;
+-struct nf_conn *bpf_skb_ct_lookup(struct __sk_buff *, struct bpf_sock_tuple *, u32,
+-                                struct bpf_ct_opts *, u32) __ksym;
+-void bpf_ct_release(struct nf_conn *) __ksym;
+-
+-static __always_inline void
+-nf_ct_test(struct nf_conn *(*func)(void *, struct bpf_sock_tuple *, u32,
+-                                 struct bpf_ct_opts *, u32),
+-         void *ctx)
+-{
+-      struct bpf_ct_opts opts_def = { .l4proto = IPPROTO_TCP, .netns_id = -1 };
+-      struct bpf_sock_tuple bpf_tuple;
+-      struct nf_conn *ct;
+-
+-      __builtin_memset(&bpf_tuple, 0, sizeof(bpf_tuple.ipv4));
+-
+-      ct = func(ctx, NULL, 0, &opts_def, sizeof(opts_def));
+-      if (ct)
+-              bpf_ct_release(ct);
+-      else
+-              test_einval_bpf_tuple = opts_def.error;
+-
+-      opts_def.reserved[0] = 1;
+-      ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def, sizeof(opts_def));
+-      opts_def.reserved[0] = 0;
+-      opts_def.l4proto = IPPROTO_TCP;
+-      if (ct)
+-              bpf_ct_release(ct);
+-      else
+-              test_einval_reserved = opts_def.error;
+-
+-      opts_def.netns_id = -2;
+-      ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def, sizeof(opts_def));
+-      opts_def.netns_id = -1;
+-      if (ct)
+-              bpf_ct_release(ct);
+-      else
+-              test_einval_netns_id = opts_def.error;
+-
+-      ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def, sizeof(opts_def) - 1);
+-      if (ct)
+-              bpf_ct_release(ct);
+-      else
+-              test_einval_len_opts = opts_def.error;
+-
+-      opts_def.l4proto = IPPROTO_ICMP;
+-      ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def, sizeof(opts_def));
+-      opts_def.l4proto = IPPROTO_TCP;
+-      if (ct)
+-              bpf_ct_release(ct);
+-      else
+-              test_eproto_l4proto = opts_def.error;
+-
+-      opts_def.netns_id = 0xf00f;
+-      ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def, sizeof(opts_def));
+-      opts_def.netns_id = -1;
+-      if (ct)
+-              bpf_ct_release(ct);
+-      else
+-              test_enonet_netns_id = opts_def.error;
+-
+-      ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def, sizeof(opts_def));
+-      if (ct)
+-              bpf_ct_release(ct);
+-      else
+-              test_enoent_lookup = opts_def.error;
+-
+-      ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4) - 1, &opts_def, sizeof(opts_def));
+-      if (ct)
+-              bpf_ct_release(ct);
+-      else
+-              test_eafnosupport = opts_def.error;
+-}
+-
+-SEC("xdp")
+-int nf_xdp_ct_test(struct xdp_md *ctx)
+-{
+-      nf_ct_test((void *)bpf_xdp_ct_lookup, ctx);
+-      return 0;
+-}
+-
+-SEC("tc")
+-int nf_skb_ct_test(struct __sk_buff *ctx)
+-{
+-      nf_ct_test((void *)bpf_skb_ct_lookup, ctx);
+-      return 0;
+-}
+-
+-char _license[] SEC("license") = "GPL";
+-- 
+2.35.1
+
diff --git a/queue-5.15/series b/queue-5.15/series
new file mode 100644 (file)
index 0000000..c4473d3
--- /dev/null
@@ -0,0 +1,3 @@
+usb-dwc3-qcom-fix-memory-leak-in-dwc3_qcom_interconn.patch
+cifs-fix-oops-during-encryption.patch
+revert-selftests-bpf-add-test-for-unstable-ct-lookup.patch
diff --git a/queue-5.15/usb-dwc3-qcom-fix-memory-leak-in-dwc3_qcom_interconn.patch b/queue-5.15/usb-dwc3-qcom-fix-memory-leak-in-dwc3_qcom_interconn.patch
new file mode 100644 (file)
index 0000000..3c18106
--- /dev/null
@@ -0,0 +1,67 @@
+From eb7d885d16cd28ef83f4bba760438c9d4b3eb190 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Dec 2022 12:17:31 +0400
+Subject: usb: dwc3: qcom: Fix memory leak in dwc3_qcom_interconnect_init
+
+From: Miaoqian Lin <linmq006@gmail.com>
+
+[ Upstream commit 97a48da1619ba6bd42a0e5da0a03aa490a9496b1 ]
+
+of_icc_get() alloc resources for path handle, we should release it when not
+need anymore. Like the release in dwc3_qcom_interconnect_exit() function.
+Add icc_put() in error handling to fix this.
+
+Fixes: bea46b981515 ("usb: dwc3: qcom: Add interconnect support in dwc3 driver")
+Cc: stable <stable@kernel.org>
+Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Signed-off-by: Miaoqian Lin <linmq006@gmail.com>
+Link: https://lore.kernel.org/r/20221206081731.818107-1-linmq006@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/dwc3/dwc3-qcom.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
+index d0352daab012..ec1de6f6c290 100644
+--- a/drivers/usb/dwc3/dwc3-qcom.c
++++ b/drivers/usb/dwc3/dwc3-qcom.c
+@@ -258,7 +258,8 @@ static int dwc3_qcom_interconnect_init(struct dwc3_qcom *qcom)
+       if (IS_ERR(qcom->icc_path_apps)) {
+               dev_err(dev, "failed to get apps-usb path: %ld\n",
+                               PTR_ERR(qcom->icc_path_apps));
+-              return PTR_ERR(qcom->icc_path_apps);
++              ret = PTR_ERR(qcom->icc_path_apps);
++              goto put_path_ddr;
+       }
+       if (usb_get_maximum_speed(&qcom->dwc3->dev) >= USB_SPEED_SUPER ||
+@@ -271,17 +272,23 @@ static int dwc3_qcom_interconnect_init(struct dwc3_qcom *qcom)
+       if (ret) {
+               dev_err(dev, "failed to set bandwidth for usb-ddr path: %d\n", ret);
+-              return ret;
++              goto put_path_apps;
+       }
+       ret = icc_set_bw(qcom->icc_path_apps,
+               APPS_USB_AVG_BW, APPS_USB_PEAK_BW);
+       if (ret) {
+               dev_err(dev, "failed to set bandwidth for apps-usb path: %d\n", ret);
+-              return ret;
++              goto put_path_apps;
+       }
+       return 0;
++
++put_path_apps:
++      icc_put(qcom->icc_path_apps);
++put_path_ddr:
++      icc_put(qcom->icc_path_ddr);
++      return ret;
+ }
+ /**
+-- 
+2.35.1
+