From 639d127de8d72abd84fb07d3edcdcef8b1b0fb66 Mon Sep 17 00:00:00 2001 From: Wen Chen Date: Tue, 23 Dec 2025 20:18:05 +0800 Subject: [PATCH] Repair driver reset work-q uaf urma inclusion category: bugfix bugzilla: https://gitee.com/openeuler/release-management/issues/ID3WJX ---------------------------------------------- 1. This patch primarily fixes issues with workq cleanup and register_seg verification. The implementation provides the following key functionalities: 1. Workq cannot use the flush interface; otherwise, UAF (User-Avoidance-Free) issues will occur. 2. The ubcore_register_seg parameter permission verification is invalid. Fixes: f043d20a1e71 ("Packet throughput decreases with multiple jetty streams") Signed-off-by: Wen Chen --- drivers/ub/urma/ubcore/ubcm/ub_mad.c | 7 ++++-- drivers/ub/urma/ubcore/ubcore_device.c | 4 +-- drivers/ub/urma/ubcore/ubcore_segment.c | 30 +++++++++++++++++++++++ drivers/ub/urma/ubcore/ubcore_workqueue.c | 13 ++++++++++ drivers/ub/urma/ubcore/ubcore_workqueue.h | 1 + 5 files changed, 51 insertions(+), 4 deletions(-) diff --git a/drivers/ub/urma/ubcore/ubcm/ub_mad.c b/drivers/ub/urma/ubcore/ubcm/ub_mad.c index 2ced424cfe50..e6f619db25ba 100644 --- a/drivers/ub/urma/ubcore/ubcm/ub_mad.c +++ b/drivers/ub/urma/ubcore/ubcm/ub_mad.c @@ -149,6 +149,9 @@ static int ubmad_check_eid_in_dev(struct ubcore_device *dev, { int i; + if (IS_ERR_OR_NULL(eid_info) || IS_ERR_OR_NULL(dev->eid_table.eid_entries)) + return -1; + spin_lock(&dev->eid_table.lock); for (i = 0; i < dev->eid_table.eid_cnt; i++) { if (memcmp(&dev->eid_table.eid_entries[i].eid, &eid_info->eid, @@ -968,7 +971,7 @@ static void ubmad_release_device_priv(struct kref *kref) container_of(kref, struct ubmad_device_priv, kref); /* retransmission */ - flush_workqueue(dev_priv->rt_wq); + drain_workqueue(dev_priv->rt_wq); destroy_workqueue(dev_priv->rt_wq); /* rsrc */ @@ -1186,7 +1189,7 @@ static void ubmad_release_agent_priv(struct kref *kref) struct ubmad_agent_priv *agent_priv = container_of(kref, struct ubmad_agent_priv, kref); - flush_workqueue(agent_priv->jfce_wq); + drain_workqueue(agent_priv->jfce_wq); destroy_workqueue(agent_priv->jfce_wq); kfree(agent_priv); diff --git a/drivers/ub/urma/ubcore/ubcore_device.c b/drivers/ub/urma/ubcore/ubcore_device.c index 6170ad347863..6dfad4a5d584 100644 --- a/drivers/ub/urma/ubcore/ubcore_device.c +++ b/drivers/ub/urma/ubcore/ubcore_device.c @@ -1251,8 +1251,8 @@ void ubcore_unregister_device(struct ubcore_device *dev) up_write(&g_device_rwsem); ubcore_clients_remove(dev); - ubcore_flush_workqueue((int)UBCORE_DISPATCH_EVENT_WQ); - ubcore_flush_workqueue((int)UBCORE_SIP_NOTIFY_WQ); + ubcore_drain_workqueue((int)UBCORE_DISPATCH_EVENT_WQ); + ubcore_drain_workqueue((int)UBCORE_SIP_NOTIFY_WQ); ubcore_flush_dev_vtp_work(dev); ubcore_session_flush(dev); diff --git a/drivers/ub/urma/ubcore/ubcore_segment.c b/drivers/ub/urma/ubcore/ubcore_segment.c index f3e38e563648..a5035094ebb9 100644 --- a/drivers/ub/urma/ubcore/ubcore_segment.c +++ b/drivers/ub/urma/ubcore/ubcore_segment.c @@ -67,6 +67,33 @@ int ubcore_free_token_id(struct ubcore_token_id *token_id) } EXPORT_SYMBOL(ubcore_free_token_id); +static bool ubcore_check_register_seg_access(struct ubcore_seg_cfg *cfg) +{ + if ((cfg->flag.bs.access & UBCORE_ACCESS_LOCAL_ONLY) && + (cfg->flag.bs.access & (UBCORE_ACCESS_READ | + UBCORE_ACCESS_WRITE | + UBCORE_ACCESS_ATOMIC))) { + ubcore_log_err( + "Local only access is not allowed to config with other accesses.\n"); + return false; + } + if ((cfg->flag.bs.access & UBCORE_ACCESS_WRITE) && + !(cfg->flag.bs.access & UBCORE_ACCESS_READ)) { + ubcore_log_err( + "Write access should be config with read access.\n"); + return false; + } + if ((cfg->flag.bs.access & UBCORE_ACCESS_ATOMIC) && + !((cfg->flag.bs.access & UBCORE_ACCESS_READ) && + (cfg->flag.bs.access & UBCORE_ACCESS_WRITE))) { + ubcore_log_err( + "Atomic access should be config with read and write access.\n"); + return false; + } + + return true; +} + static int ubcore_check_register_seg_para(struct ubcore_device *dev, struct ubcore_seg_cfg *cfg, struct ubcore_udata *udata) @@ -82,6 +109,9 @@ static int ubcore_check_register_seg_para(struct ubcore_device *dev, if (ubcore_is_bonding_dev(dev)) return 0; + if (!ubcore_check_register_seg_access(cfg)) + return -EINVAL; + if (cfg->flag.bs.pa == 1 && udata != NULL) { ubcore_log_err("invalid parameter of pa.\n"); return -1; diff --git a/drivers/ub/urma/ubcore/ubcore_workqueue.c b/drivers/ub/urma/ubcore/ubcore_workqueue.c index c7585fbe7c74..2155c9d1ed77 100644 --- a/drivers/ub/urma/ubcore/ubcore_workqueue.c +++ b/drivers/ub/urma/ubcore/ubcore_workqueue.c @@ -44,6 +44,19 @@ void ubcore_flush_workqueue(int queue_type) flush_workqueue(g_ubcore_workqueues[queue_type]); } +void ubcore_drain_workqueue(int queue_type) +{ + if (!check_queue_type_valid(queue_type) || + g_ubcore_workqueues[queue_type] == NULL) { + ubcore_log_err( + "queue_type %d out of range or workqueue is NULL\n", + queue_type); + return; + } + + drain_workqueue(g_ubcore_workqueues[queue_type]); +} + int ubcore_queue_work(int queue_type, struct work_struct *work) { if (!check_queue_type_valid(queue_type) || diff --git a/drivers/ub/urma/ubcore/ubcore_workqueue.h b/drivers/ub/urma/ubcore/ubcore_workqueue.h index 54b5682e9b94..55bd985d326f 100644 --- a/drivers/ub/urma/ubcore/ubcore_workqueue.h +++ b/drivers/ub/urma/ubcore/ubcore_workqueue.h @@ -37,6 +37,7 @@ struct ubcore_front_back_work { }; void ubcore_flush_workqueue(int queue_type); +void ubcore_drain_workqueue(int queue_type); int ubcore_queue_work(int queue_type, struct work_struct *work); -- Gitee