From f6f1f8a506f906f3b1aadf2378a195e01ae537c9 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 15 Jun 2023 10:25:24 -0400 Subject: [PATCH] Fixes for 5.4 Signed-off-by: Sasha Levin --- ...dasd-refactor-dasd_ioctl_information.patch | 107 +++++++++++++++++ ...copy-sig-and-digest-in-public_key_ve.patch | 111 ++++++++++++++++++ ...rrect-lock-while-counting-channel-qu.patch | 56 +++++++++ queue-5.4/series | 4 + ...e-fix-a-memory-leak-with-reqs-buffer.patch | 72 ++++++++++++ 5 files changed, 350 insertions(+) create mode 100644 queue-5.4/dasd-refactor-dasd_ioctl_information.patch create mode 100644 queue-5.4/keys-asymmetric-copy-sig-and-digest-in-public_key_ve.patch create mode 100644 queue-5.4/s390-dasd-use-correct-lock-while-counting-channel-qu.patch create mode 100644 queue-5.4/series create mode 100644 queue-5.4/test_firmware-fix-a-memory-leak-with-reqs-buffer.patch diff --git a/queue-5.4/dasd-refactor-dasd_ioctl_information.patch b/queue-5.4/dasd-refactor-dasd_ioctl_information.patch new file mode 100644 index 00000000000..fbd6e15d8be --- /dev/null +++ b/queue-5.4/dasd-refactor-dasd_ioctl_information.patch @@ -0,0 +1,107 @@ +From ed0740831c07938ebf16f5cdc1ee1ae960c6bc71 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 May 2020 16:22:58 +0200 +Subject: dasd: refactor dasd_ioctl_information + +From: Christoph Hellwig + +[ Upstream commit 9353848c6589ffe6373d03f3a58feaeda1009641 ] + +Prepare for in-kernel callers of this functionality. + +Signed-off-by: Christoph Hellwig +[sth@de.ibm.com: remove leftover kfree] +Signed-off-by: Stefan Haberland +Reviewed-by: Peter Oberparleiter +Reviewed-by: Jan Hoeppner +Signed-off-by: Jens Axboe +Stable-dep-of: ccc45cb4e727 ("s390/dasd: Use correct lock while counting channel queue length") +Signed-off-by: Sasha Levin +--- + drivers/s390/block/dasd_ioctl.c | 42 ++++++++++++++++++--------------- + 1 file changed, 23 insertions(+), 19 deletions(-) + +diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c +index 9a5f3add325fc..9b7782395c379 100644 +--- a/drivers/s390/block/dasd_ioctl.c ++++ b/drivers/s390/block/dasd_ioctl.c +@@ -457,10 +457,9 @@ static int dasd_ioctl_read_profile(struct dasd_block *block, void __user *argp) + /* + * Return dasd information. Used for BIODASDINFO and BIODASDINFO2. + */ +-static int dasd_ioctl_information(struct dasd_block *block, +- unsigned int cmd, void __user *argp) ++static int __dasd_ioctl_information(struct dasd_block *block, ++ struct dasd_information2_t *dasd_info) + { +- struct dasd_information2_t *dasd_info; + struct subchannel_id sch_id; + struct ccw_dev_id dev_id; + struct dasd_device *base; +@@ -473,15 +472,9 @@ static int dasd_ioctl_information(struct dasd_block *block, + if (!base->discipline || !base->discipline->fill_info) + return -EINVAL; + +- dasd_info = kzalloc(sizeof(struct dasd_information2_t), GFP_KERNEL); +- if (dasd_info == NULL) +- return -ENOMEM; +- + rc = base->discipline->fill_info(base, dasd_info); +- if (rc) { +- kfree(dasd_info); ++ if (rc) + return rc; +- } + + cdev = base->cdev; + ccw_device_get_id(cdev, &dev_id); +@@ -520,15 +513,24 @@ static int dasd_ioctl_information(struct dasd_block *block, + list_for_each(l, &base->ccw_queue) + dasd_info->chanq_len++; + spin_unlock_irqrestore(&block->queue_lock, flags); ++ return 0; ++} + +- rc = 0; +- if (copy_to_user(argp, dasd_info, +- ((cmd == (unsigned int) BIODASDINFO2) ? +- sizeof(struct dasd_information2_t) : +- sizeof(struct dasd_information_t)))) +- rc = -EFAULT; ++static int dasd_ioctl_information(struct dasd_block *block, void __user *argp, ++ size_t copy_size) ++{ ++ struct dasd_information2_t *dasd_info; ++ int error; ++ ++ dasd_info = kzalloc(sizeof(*dasd_info), GFP_KERNEL); ++ if (!dasd_info) ++ return -ENOMEM; ++ ++ error = __dasd_ioctl_information(block, dasd_info); ++ if (!error && copy_to_user(argp, dasd_info, copy_size)) ++ error = -EFAULT; + kfree(dasd_info); +- return rc; ++ return error; + } + + /* +@@ -622,10 +624,12 @@ int dasd_ioctl(struct block_device *bdev, fmode_t mode, + rc = dasd_ioctl_check_format(bdev, argp); + break; + case BIODASDINFO: +- rc = dasd_ioctl_information(block, cmd, argp); ++ rc = dasd_ioctl_information(block, argp, ++ sizeof(struct dasd_information_t)); + break; + case BIODASDINFO2: +- rc = dasd_ioctl_information(block, cmd, argp); ++ rc = dasd_ioctl_information(block, argp, ++ sizeof(struct dasd_information2_t)); + break; + case BIODASDPRRD: + rc = dasd_ioctl_read_profile(block, argp); +-- +2.39.2 + diff --git a/queue-5.4/keys-asymmetric-copy-sig-and-digest-in-public_key_ve.patch b/queue-5.4/keys-asymmetric-copy-sig-and-digest-in-public_key_ve.patch new file mode 100644 index 00000000000..64368b9db3e --- /dev/null +++ b/queue-5.4/keys-asymmetric-copy-sig-and-digest-in-public_key_ve.patch @@ -0,0 +1,111 @@ +From 5d8d6be6e6dbefd21b8bf9bf5b8aca9fad904491 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 10:56:46 +0100 +Subject: KEYS: asymmetric: Copy sig and digest in + public_key_verify_signature() + +From: Roberto Sassu + +[ Upstream commit c3d03e8e35e005e1a614e51bb59053eeb5857f76 ] + +Commit ac4e97abce9b8 ("scatterlist: sg_set_buf() argument must be in linear +mapping") checks that both the signature and the digest reside in the +linear mapping area. + +However, more recently commit ba14a194a434c ("fork: Add generic vmalloced +stack support") made it possible to move the stack in the vmalloc area, +which is not contiguous, and thus not suitable for sg_set_buf() which needs +adjacent pages. + +Always make a copy of the signature and digest in the same buffer used to +store the key and its parameters, and pass them to sg_init_one(). Prefer it +to conditionally doing the copy if necessary, to keep the code simple. The +buffer allocated with kmalloc() is in the linear mapping area. + +Cc: stable@vger.kernel.org # 4.9.x +Fixes: ba14a194a434 ("fork: Add generic vmalloced stack support") +Link: https://lore.kernel.org/linux-integrity/Y4pIpxbjBdajymBJ@sol.localdomain/ +Suggested-by: Eric Biggers +Signed-off-by: Roberto Sassu +Reviewed-by: Eric Biggers +Tested-by: Stefan Berger +Signed-off-by: Sasha Levin +--- + crypto/asymmetric_keys/public_key.c | 36 ++++++++++++++++------------- + 1 file changed, 20 insertions(+), 16 deletions(-) + +diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c +index e5fae4e838c06..2d57b0b3f9a4a 100644 +--- a/crypto/asymmetric_keys/public_key.c ++++ b/crypto/asymmetric_keys/public_key.c +@@ -255,9 +255,10 @@ int public_key_verify_signature(const struct public_key *pkey, + struct crypto_wait cwait; + struct crypto_akcipher *tfm; + struct akcipher_request *req; +- struct scatterlist src_sg[2]; ++ struct scatterlist src_sg; + char alg_name[CRYPTO_MAX_ALG_NAME]; +- char *key, *ptr; ++ char *buf, *ptr; ++ size_t buf_len; + int ret; + + pr_devel("==>%s()\n", __func__); +@@ -281,28 +282,31 @@ int public_key_verify_signature(const struct public_key *pkey, + if (!req) + goto error_free_tfm; + +- key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen, +- GFP_KERNEL); +- if (!key) ++ buf_len = max_t(size_t, pkey->keylen + sizeof(u32) * 2 + pkey->paramlen, ++ sig->s_size + sig->digest_size); ++ ++ buf = kmalloc(buf_len, GFP_KERNEL); ++ if (!buf) + goto error_free_req; + +- memcpy(key, pkey->key, pkey->keylen); +- ptr = key + pkey->keylen; ++ memcpy(buf, pkey->key, pkey->keylen); ++ ptr = buf + pkey->keylen; + ptr = pkey_pack_u32(ptr, pkey->algo); + ptr = pkey_pack_u32(ptr, pkey->paramlen); + memcpy(ptr, pkey->params, pkey->paramlen); + + if (pkey->key_is_private) +- ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen); ++ ret = crypto_akcipher_set_priv_key(tfm, buf, pkey->keylen); + else +- ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen); ++ ret = crypto_akcipher_set_pub_key(tfm, buf, pkey->keylen); + if (ret) +- goto error_free_key; ++ goto error_free_buf; + +- sg_init_table(src_sg, 2); +- sg_set_buf(&src_sg[0], sig->s, sig->s_size); +- sg_set_buf(&src_sg[1], sig->digest, sig->digest_size); +- akcipher_request_set_crypt(req, src_sg, NULL, sig->s_size, ++ memcpy(buf, sig->s, sig->s_size); ++ memcpy(buf + sig->s_size, sig->digest, sig->digest_size); ++ ++ sg_init_one(&src_sg, buf, sig->s_size + sig->digest_size); ++ akcipher_request_set_crypt(req, &src_sg, NULL, sig->s_size, + sig->digest_size); + crypto_init_wait(&cwait); + akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | +@@ -310,8 +314,8 @@ int public_key_verify_signature(const struct public_key *pkey, + crypto_req_done, &cwait); + ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait); + +-error_free_key: +- kfree(key); ++error_free_buf: ++ kfree(buf); + error_free_req: + akcipher_request_free(req); + error_free_tfm: +-- +2.39.2 + diff --git a/queue-5.4/s390-dasd-use-correct-lock-while-counting-channel-qu.patch b/queue-5.4/s390-dasd-use-correct-lock-while-counting-channel-qu.patch new file mode 100644 index 00000000000..31188877897 --- /dev/null +++ b/queue-5.4/s390-dasd-use-correct-lock-while-counting-channel-qu.patch @@ -0,0 +1,56 @@ +From d00c3efdbbb4f248f21cd40390c471985a5b7f73 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Jun 2023 17:37:50 +0200 +Subject: s390/dasd: Use correct lock while counting channel queue length +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jan Höppner + +[ Upstream commit ccc45cb4e7271c74dbb27776ae8f73d84557f5c6 ] + +The lock around counting the channel queue length in the BIODASDINFO +ioctl was incorrectly changed to the dasd_block->queue_lock with commit +583d6535cb9d ("dasd: remove dead code"). This can lead to endless list +iterations and a subsequent crash. + +The queue_lock is supposed to be used only for queue lists belonging to +dasd_block. For dasd_device related queue lists the ccwdev lock must be +used. + +Fix the mentioned issues by correctly using the ccwdev lock instead of +the queue lock. + +Fixes: 583d6535cb9d ("dasd: remove dead code") +Cc: stable@vger.kernel.org # v5.0+ +Signed-off-by: Jan Höppner +Reviewed-by: Stefan Haberland +Signed-off-by: Stefan Haberland +Link: https://lore.kernel.org/r/20230609153750.1258763-2-sth@linux.ibm.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/s390/block/dasd_ioctl.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c +index 9b7782395c379..d7aed832910c4 100644 +--- a/drivers/s390/block/dasd_ioctl.c ++++ b/drivers/s390/block/dasd_ioctl.c +@@ -509,10 +509,10 @@ static int __dasd_ioctl_information(struct dasd_block *block, + + memcpy(dasd_info->type, base->discipline->name, 4); + +- spin_lock_irqsave(&block->queue_lock, flags); ++ spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags); + list_for_each(l, &base->ccw_queue) + dasd_info->chanq_len++; +- spin_unlock_irqrestore(&block->queue_lock, flags); ++ spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags); + return 0; + } + +-- +2.39.2 + diff --git a/queue-5.4/series b/queue-5.4/series new file mode 100644 index 00000000000..a3aea6057e4 --- /dev/null +++ b/queue-5.4/series @@ -0,0 +1,4 @@ +test_firmware-fix-a-memory-leak-with-reqs-buffer.patch +keys-asymmetric-copy-sig-and-digest-in-public_key_ve.patch +dasd-refactor-dasd_ioctl_information.patch +s390-dasd-use-correct-lock-while-counting-channel-qu.patch diff --git a/queue-5.4/test_firmware-fix-a-memory-leak-with-reqs-buffer.patch b/queue-5.4/test_firmware-fix-a-memory-leak-with-reqs-buffer.patch new file mode 100644 index 00000000000..c9dbe4f1d2d --- /dev/null +++ b/queue-5.4/test_firmware-fix-a-memory-leak-with-reqs-buffer.patch @@ -0,0 +1,72 @@ +From fd4aa324731339a12cc145441e229cf1d44a2984 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 May 2023 10:47:47 +0200 +Subject: test_firmware: fix a memory leak with reqs buffer + +From: Mirsad Goran Todorovac + +[ Upstream commit be37bed754ed90b2655382f93f9724b3c1aae847 ] + +Dan Carpenter spotted that test_fw_config->reqs will be leaked if +trigger_batched_requests_store() is called two or more times. +The same appears with trigger_batched_requests_async_store(). + +This bug wasn't trigger by the tests, but observed by Dan's visual +inspection of the code. + +The recommended workaround was to return -EBUSY if test_fw_config->reqs +is already allocated. + +Fixes: 7feebfa487b92 ("test_firmware: add support for request_firmware_into_buf") +Cc: Luis Chamberlain +Cc: Greg Kroah-Hartman +Cc: Russ Weight +Cc: Tianfei Zhang +Cc: Shuah Khan +Cc: Colin Ian King +Cc: Randy Dunlap +Cc: linux-kselftest@vger.kernel.org +Cc: stable@vger.kernel.org # v5.4 +Suggested-by: Dan Carpenter +Suggested-by: Takashi Iwai +Signed-off-by: Mirsad Goran Todorovac +Reviewed-by: Dan Carpenter +Acked-by: Luis Chamberlain +Link: https://lore.kernel.org/r/20230509084746.48259-2-mirsad.todorovac@alu.unizg.hr +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + lib/test_firmware.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/lib/test_firmware.c b/lib/test_firmware.c +index 3146845f01562..38553944e9675 100644 +--- a/lib/test_firmware.c ++++ b/lib/test_firmware.c +@@ -679,6 +679,11 @@ static ssize_t trigger_batched_requests_store(struct device *dev, + + mutex_lock(&test_fw_mutex); + ++ if (test_fw_config->reqs) { ++ rc = -EBUSY; ++ goto out_bail; ++ } ++ + test_fw_config->reqs = + vzalloc(array3_size(sizeof(struct test_batched_req), + test_fw_config->num_requests, 2)); +@@ -778,6 +783,11 @@ ssize_t trigger_batched_requests_async_store(struct device *dev, + + mutex_lock(&test_fw_mutex); + ++ if (test_fw_config->reqs) { ++ rc = -EBUSY; ++ goto out_bail; ++ } ++ + test_fw_config->reqs = + vzalloc(array3_size(sizeof(struct test_batched_req), + test_fw_config->num_requests, 2)); +-- +2.39.2 + -- 2.47.2