From: Zhengchao Shao shaozhengchao@huawei.com
mainline inclusion from mainline-v5.19-rc6 commit 02884a4f12de11f54d4ca67a07dd1f111d96fdbd category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5GEVR CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git/co...
--------------------------------
When kunpeng920 encryption driver is used to deencrypt and decrypt packets during the softirq, it is not allowed to use mutex lock. The kernel will report the following error:
BUG: scheduling while atomic: swapper/57/0/0x00000300 Call trace: dump_backtrace+0x0/0x1e4 show_stack+0x20/0x2c dump_stack+0xd8/0x140 __schedule_bug+0x68/0x80 __schedule+0x728/0x840 schedule+0x50/0xe0 schedule_preempt_disabled+0x18/0x24 __mutex_lock.constprop.0+0x594/0x5dc __mutex_lock_slowpath+0x1c/0x30 mutex_lock+0x50/0x60 sec_request_init+0x8c/0x1a0 [hisi_sec2] sec_process+0x28/0x1ac [hisi_sec2] sec_skcipher_crypto+0xf4/0x1d4 [hisi_sec2] sec_skcipher_encrypt+0x1c/0x30 [hisi_sec2] crypto_skcipher_encrypt+0x2c/0x40 crypto_authenc_encrypt+0xc8/0xfc [authenc] crypto_aead_encrypt+0x2c/0x40 echainiv_encrypt+0x144/0x1a0 [echainiv] crypto_aead_encrypt+0x2c/0x40 esp_output_tail+0x348/0x5c0 [esp4] esp_output+0x120/0x19c [esp4] xfrm_output_one+0x25c/0x4d4 xfrm_output_resume+0x6c/0x1fc xfrm_output+0xac/0x3c0 xfrm4_output+0x64/0x130 ip_build_and_send_pkt+0x158/0x20c tcp_v4_send_synack+0xdc/0x1f0 tcp_conn_request+0x7d0/0x994 tcp_v4_conn_request+0x58/0x6c tcp_v6_conn_request+0xf0/0x100 tcp_rcv_state_process+0x1cc/0xd60 tcp_v4_do_rcv+0x10c/0x250 tcp_v4_rcv+0xfc4/0x10a4 ip_protocol_deliver_rcu+0xf4/0x200 ip_local_deliver_finish+0x58/0x70 ip_local_deliver+0x68/0x120 ip_sublist_rcv_finish+0x70/0x94 ip_list_rcv_finish.constprop.0+0x17c/0x1d0 ip_sublist_rcv+0x40/0xb0 ip_list_rcv+0x140/0x1dc __netif_receive_skb_list_core+0x154/0x28c __netif_receive_skb_list+0x120/0x1a0 netif_receive_skb_list_internal+0xe4/0x1f0 napi_complete_done+0x70/0x1f0 gro_cell_poll+0x9c/0xb0 napi_poll+0xcc/0x264 net_rx_action+0xd4/0x21c __do_softirq+0x130/0x358 irq_exit+0x11c/0x13c __handle_domain_irq+0x88/0xf0 gic_handle_irq+0x78/0x2c0 el1_irq+0xb8/0x140 arch_cpu_idle+0x18/0x40 default_idle_call+0x5c/0x1c0 cpuidle_idle_call+0x174/0x1b0 do_idle+0xc8/0x160 cpu_startup_entry+0x30/0x11c secondary_start_kernel+0x158/0x1e4 softirq: huh, entered softirq 3 NET_RX 0000000093774ee4 with preempt_count 00000100, exited with fffffe00?
Fixes: 416d82204df4 ("crypto: hisilicon - add HiSilicon SEC V2 driver") Signed-off-by: Zhengchao Shao shaozhengchao@huawei.com Signed-off-by: Herbert Xu herbert@gondor.apana.org.au Reviewed-by: Wei Yongjun weiyongjun1@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/crypto/hisilicon/sec2/sec.h | 2 +- drivers/crypto/hisilicon/sec2/sec_crypto.c | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/crypto/hisilicon/sec2/sec.h b/drivers/crypto/hisilicon/sec2/sec.h index d97cf02b1df7..cff00fd29765 100644 --- a/drivers/crypto/hisilicon/sec2/sec.h +++ b/drivers/crypto/hisilicon/sec2/sec.h @@ -119,7 +119,7 @@ struct sec_qp_ctx { struct idr req_idr; struct sec_alg_res res[QM_Q_DEPTH]; struct sec_ctx *ctx; - struct mutex req_lock; + spinlock_t req_lock; struct list_head backlog; struct hisi_acc_sgl_pool *c_in_pool; struct hisi_acc_sgl_pool *c_out_pool; diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c index 9d0a39f60fb2..b2228a935dcd 100644 --- a/drivers/crypto/hisilicon/sec2/sec_crypto.c +++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c @@ -127,11 +127,11 @@ static int sec_alloc_req_id(struct sec_req *req, struct sec_qp_ctx *qp_ctx) { int req_id;
- mutex_lock(&qp_ctx->req_lock); + spin_lock_bh(&qp_ctx->req_lock);
req_id = idr_alloc_cyclic(&qp_ctx->req_idr, NULL, 0, QM_Q_DEPTH, GFP_ATOMIC); - mutex_unlock(&qp_ctx->req_lock); + spin_unlock_bh(&qp_ctx->req_lock); if (unlikely(req_id < 0)) { dev_err(req->ctx->dev, "alloc req id fail!\n"); return req_id; @@ -156,9 +156,9 @@ static void sec_free_req_id(struct sec_req *req) qp_ctx->req_list[req_id] = NULL; req->qp_ctx = NULL;
- mutex_lock(&qp_ctx->req_lock); + spin_lock_bh(&qp_ctx->req_lock); idr_remove(&qp_ctx->req_idr, req_id); - mutex_unlock(&qp_ctx->req_lock); + spin_unlock_bh(&qp_ctx->req_lock); }
static u8 pre_parse_finished_bd(struct bd_status *status, void *resp) @@ -273,7 +273,7 @@ static int sec_bd_send(struct sec_ctx *ctx, struct sec_req *req) !(req->flag & CRYPTO_TFM_REQ_MAY_BACKLOG)) return -EBUSY;
- mutex_lock(&qp_ctx->req_lock); + spin_lock_bh(&qp_ctx->req_lock); ret = hisi_qp_send(qp_ctx->qp, &req->sec_sqe);
if (ctx->fake_req_limit <= @@ -281,10 +281,10 @@ static int sec_bd_send(struct sec_ctx *ctx, struct sec_req *req) list_add_tail(&req->backlog_head, &qp_ctx->backlog); atomic64_inc(&ctx->sec->debug.dfx.send_cnt); atomic64_inc(&ctx->sec->debug.dfx.send_busy_cnt); - mutex_unlock(&qp_ctx->req_lock); + spin_unlock_bh(&qp_ctx->req_lock); return -EBUSY; } - mutex_unlock(&qp_ctx->req_lock); + spin_unlock_bh(&qp_ctx->req_lock);
if (unlikely(ret == -EBUSY)) return -ENOBUFS; @@ -487,7 +487,7 @@ static int sec_create_qp_ctx(struct hisi_qm *qm, struct sec_ctx *ctx,
qp->req_cb = sec_req_cb;
- mutex_init(&qp_ctx->req_lock); + spin_lock_init(&qp_ctx->req_lock); idr_init(&qp_ctx->req_idr); INIT_LIST_HEAD(&qp_ctx->backlog);
@@ -1382,7 +1382,7 @@ static struct sec_req *sec_back_req_clear(struct sec_ctx *ctx, { struct sec_req *backlog_req = NULL;
- mutex_lock(&qp_ctx->req_lock); + spin_lock_bh(&qp_ctx->req_lock); if (ctx->fake_req_limit >= atomic_read(&qp_ctx->qp->qp_status.used) && !list_empty(&qp_ctx->backlog)) { @@ -1390,7 +1390,7 @@ static struct sec_req *sec_back_req_clear(struct sec_ctx *ctx, typeof(*backlog_req), backlog_head); list_del(&backlog_req->backlog_head); } - mutex_unlock(&qp_ctx->req_lock); + spin_unlock_bh(&qp_ctx->req_lock);
return backlog_req; }
From: Yu Kuai yukuai3@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I5HEZ8 CVE: NA
--------------------------------
commit f60df4a0a6ad ("blk-mq: fix kabi broken in struct request") intrudoce 'struct request_wrapper' to fix kabi broken in 'struct request', it requires to allocate more size for 'struct request'. However, flush_rq is missed for such adaptation, which will lead to following slab-out-of-bounds:
================================================================== BUG: KASAN: slab-out-of-bounds in sg_init_table+0x23/0x40 Write of size 4096 at addr ffff88812249a148 by task swapper/0/1
Call Trace: dump_stack+0xbe/0xf9 ? sg_init_table+0x23/0x40 print_address_description.constprop.0+0x1e/0x220 ? _raw_spin_lock_irqsave+0x80/0xe0 ? _raw_write_unlock_irqrestore+0x20/0x20 ? blk_alloc_flush_queue+0xd3/0x1a0 ? sg_init_table+0x23/0x40 ? sg_init_table+0x23/0x40 kasan_report.cold+0x67/0x7f ? sg_init_table+0x23/0x40 check_memory_region+0x17c/0x1e0 memset+0x20/0x40 sg_init_table+0x23/0x40 virtblk_init_request+0x3d/0x50 ? virtblk_map_queues+0x40/0x40 blk_mq_realloc_hw_ctxs+0x44d/0xb50 blk_mq_init_allocated_queue+0x20f/0x980 ? blk_set_default_limits+0x1ac/0x1c0 ? blk_alloc_queue+0x3f0/0x410 blk_mq_init_queue_data+0x58/0xa0 virtblk_probe+0x51b/0xee0 ? cache_type_store+0x1a0/0x1a0 ? __sanitizer_cov_trace_switch+0x50/0x90 ? ioread8+0x89/0xa0 virtio_dev_probe+0x449/0x5d0 ? virtio_features_ok.part.0+0xb0/0xb0 really_probe+0x26d/0x8a0 driver_probe_device+0xef/0x280 device_driver_attach+0xaf/0xc0 __driver_attach+0x158/0x280 ? device_driver_attach+0xc0/0xc0 bus_for_each_dev+0x111/0x180 ? subsys_dev_iter_exit+0x20/0x20 ? bus_add_driver+0xb6/0x3e0 ? klist_node_init+0x7c/0xb0 bus_add_driver+0x336/0x3e0 driver_register+0x105/0x1a0 ? nbd_init+0x273/0x273 init+0x69/0xad do_one_initcall+0xcb/0x370 ? initcall_blacklisted+0x1b0/0x1b0 ? parameq+0x110/0x110 ? __kasan_kmalloc.constprop.0+0xc2/0xd0 ? kasan_unpoison_shadow+0x33/0x40 do_initcalls+0x223/0x265 kernel_init_freeable+0x2bb/0x302 ? rest_init+0xea/0xea kernel_init+0x13/0x1f6 ? rest_init+0xea/0xea ret_from_fork+0x22/0x30
Allocated by task 1: kasan_save_stack+0x1b/0x40 __kasan_kmalloc.constprop.0+0xc2/0xd0 blk_alloc_flush_queue+0xd3/0x1a0 blk_mq_realloc_hw_ctxs+0x9fa/0xb50 blk_mq_init_allocated_queue+0x20f/0x980 blk_mq_init_queue_data+0x58/0xa0 virtblk_probe+0x51b/0xee0 virtio_dev_probe+0x449/0x5d0 really_probe+0x26d/0x8a0 driver_probe_device+0xef/0x280 device_driver_attach+0xaf/0xc0 __driver_attach+0x158/0x280 bus_for_each_dev+0x111/0x180 bus_add_driver+0x336/0x3e0 driver_register+0x105/0x1a0 init+0x69/0xad do_one_initcall+0xcb/0x370 do_initcalls+0x223/0x265 kernel_init_freeable+0x2bb/0x302 kernel_init+0x13/0x1f6 ret_from_fork+0x22/0x30
Fixes: f60df4a0a6ad ("blk-mq: fix kabi broken in struct request") Signed-off-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- block/blk-flush.c | 2 +- drivers/scsi/scsi_error.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/block/blk-flush.c b/block/blk-flush.c index 82919829bc4d..71faf07a626f 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -470,7 +470,7 @@ struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size, gfp_t flags) { struct blk_flush_queue *fq; - int rq_sz = sizeof(struct request); + int rq_sz = sizeof(struct request_wrapper);
fq = kzalloc_node(sizeof(*fq), flags, node); if (!fq) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index f11f51e2465f..bcbeadb2d0f0 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -2359,7 +2359,7 @@ scsi_ioctl_reset(struct scsi_device *dev, int __user *arg) return -EIO;
error = -EIO; - rq = kzalloc(sizeof(struct request) + sizeof(struct scsi_cmnd) + + rq = kzalloc(sizeof(struct request_wrapper) + sizeof(struct scsi_cmnd) + shost->hostt->cmd_size, GFP_KERNEL); if (!rq) goto out_put_autopm_host;
From: GUO Zihua guozihua@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5GRSV CVE: NA
--------------------------------
In function pgp_generate_fingerprint, return value is not set correctly shall kmalloc failed returning 0 while there is in fact a failure, leading to the caller keep going and triggers a read out-of-bound. This patch fixes this issue by setting correct return value on the error path.
Signed-off-by: GUO Zihua guozihua@huawei.com Reviewed-by: Roberto Sassu roberto.sassu@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- crypto/asymmetric_keys/pgp_public_key.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/crypto/asymmetric_keys/pgp_public_key.c b/crypto/asymmetric_keys/pgp_public_key.c index 27b9efeafc4f..33a089797e59 100644 --- a/crypto/asymmetric_keys/pgp_public_key.c +++ b/crypto/asymmetric_keys/pgp_public_key.c @@ -152,8 +152,10 @@ static int pgp_generate_fingerprint(struct pgp_key_data_parse_context *ctx, digest_size = crypto_shash_digestsize(tfm);
raw_fingerprint = kmalloc(digest_size, GFP_KERNEL); - if (!raw_fingerprint) + if (!raw_fingerprint) { + ret = -ENOMEM; goto cleanup_hash; + }
ret = crypto_shash_final(digest, raw_fingerprint); if (ret < 0) @@ -161,8 +163,10 @@ static int pgp_generate_fingerprint(struct pgp_key_data_parse_context *ctx,
ctx->fingerprint_len = digest_size * 2; fingerprint = kmalloc(digest_size * 2 + 1, GFP_KERNEL); - if (!fingerprint) + if (!fingerprint) { + ret = -ENOMEM; goto cleanup_raw_fingerprint; + }
offset = digest_size - 8; pr_debug("offset %u/%u\n", offset, digest_size);
From: GUO Zihua guozihua@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5H4FC CVE: NA
--------------------------------
Under normal condition, when there is a user id packet, there will always be a public key packet in the front, meaning ctx.fingerprint will never be NULL. However, if a malicious or faulty PGP key is provided with only user id packet but not public key packet, a read out-of-bound will be triggered during the generation of key description. To make things worse, a NULL pointer deference could be triggered in pgp_key_generate_id().
This patch adds a safe guard which prevents parsing the key further if no public key packet is provided.
Fixes: a98cb7a4b757 ("KEYS: Provide PGP key description autogeneration") Signed-off-by: GUO Zihua guozihua@huawei.com Reviewed-by: Roberto Sassu roberto.sassu@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- crypto/asymmetric_keys/pgp_public_key.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/crypto/asymmetric_keys/pgp_public_key.c b/crypto/asymmetric_keys/pgp_public_key.c index 33a089797e59..98b1707a0164 100644 --- a/crypto/asymmetric_keys/pgp_public_key.c +++ b/crypto/asymmetric_keys/pgp_public_key.c @@ -315,6 +315,11 @@ static int pgp_key_parse(struct key_preparsed_payload *prep) if (ret < 0) goto error;
+ if (!ctx.fingerprint) { + ret = -EINVAL; + goto error; + } + if (ctx.user_id && ctx.user_id_len > 0) { /* Propose a description for the key * (user ID without the comment)
From: GUO Zihua guozihua@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5H61R CVE: NA
--------------------------------
pgp_key_generate_id() is trying get the size of a flexible length structure, however the sizeof() is called on the pointer itself. Besides, considering it's trying to get the size of a flexible length structure, use struct_size() instead.
Fixes: 4006f47d4e21 ("KEYS: PGP data parser") Signed-off-by: GUO Zihua guozihua@huawei.com Reviewed-by: Roberto Sassu roberto.sassu@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- crypto/asymmetric_keys/pgp_public_key.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/crypto/asymmetric_keys/pgp_public_key.c b/crypto/asymmetric_keys/pgp_public_key.c index 98b1707a0164..928029a13435 100644 --- a/crypto/asymmetric_keys/pgp_public_key.c +++ b/crypto/asymmetric_keys/pgp_public_key.c @@ -283,7 +283,8 @@ static struct asymmetric_key_ids *pgp_key_generate_id( goto error;
kids->id[0] = kid; - kids->id[1] = kmemdup(kid, sizeof(kid) + fingerprint_len, GFP_KERNEL); + kids->id[1] = kmemdup(kid, struct_size(kid, data, fingerprint_len), + GFP_KERNEL); if (!kids->id[1]) goto error;