From: Sasha Levin Date: Sat, 31 Dec 2022 20:03:57 +0000 (-0500) Subject: Fixes for 5.15 X-Git-Tag: v6.0.17~38 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d08eb2f61148b381d8cccbf937a70501f2afee87;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.15 Signed-off-by: Sasha Levin --- 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 index 00000000000..1b314005839 --- /dev/null +++ b/queue-5.15/cifs-fix-oops-during-encryption.patch @@ -0,0 +1,410 @@ +From b3fca551795d4937c78dc9a7f9e21d0c926a01c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 11 Dec 2022 18:18:55 -0300 +Subject: cifs: fix oops during encryption + +From: Paulo Alcantara + +[ 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) +Cc: stable@vger.kernel.org +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include ++#include + #include + #include + #include "cifs_fs_sb.h" +@@ -21,6 +23,7 @@ + #include + #include + #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 index 00000000000..b3fe5228bf1 --- /dev/null +++ b/queue-5.15/revert-selftests-bpf-add-test-for-unstable-ct-lookup.patch @@ -0,0 +1,200 @@ +From e9d7eb9c702b120c8a86c617a41088a39221975a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 +--- + 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 +-#include +-#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 +-#include +- +-#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 index 00000000000..c4473d3cd74 --- /dev/null +++ b/queue-5.15/series @@ -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 index 00000000000..3c181069fa5 --- /dev/null +++ b/queue-5.15/usb-dwc3-qcom-fix-memory-leak-in-dwc3_qcom_interconn.patch @@ -0,0 +1,67 @@ +From eb7d885d16cd28ef83f4bba760438c9d4b3eb190 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Dec 2022 12:17:31 +0400 +Subject: usb: dwc3: qcom: Fix memory leak in dwc3_qcom_interconnect_init + +From: Miaoqian Lin + +[ 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 +Acked-by: Thinh Nguyen +Signed-off-by: Miaoqian Lin +Link: https://lore.kernel.org/r/20221206081731.818107-1-linmq006@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 +