From: Huajingjing huajingjing1@huawei.com
driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I67J42 CVE: NA
-------------------------------------------------
The BMA software is a system management software offered by Huawei. It supports the status monitoring, performance monitoring and event monitoring of various components, including server CPUs, memory hard disks, NICs, IB cards, PCIe cards, RAID controller cards and optical modules.
In this version, the system resets due to the BMA spin lock when the memory usage is too high, the vulnerability has been rectified.
Signed-off-by: Hua Jingjing huajingjingjing1@huawei.com Reviewed-by: Chen Jiesong chenjiesong@huawei.com Signed-off-by: Yongqiang Liu liuyongqiang13@huawei.com --- .../ethernet/huawei/bma/cdev_drv/bma_cdev.c | 2 +- .../huawei/bma/edma_drv/bma_devintf.c | 110 +++++++++++------- .../ethernet/huawei/bma/edma_drv/bma_pci.h | 2 +- .../huawei/bma/kbox_drv/kbox_include.h | 2 +- .../ethernet/huawei/bma/kbox_drv/kbox_panic.c | 4 +- .../huawei/bma/kbox_drv/kbox_printk.c | 4 +- .../huawei/bma/kbox_drv/kbox_ram_op.c | 2 +- .../ethernet/huawei/bma/veth_drv/veth_hb.c | 7 +- .../ethernet/huawei/bma/veth_drv/veth_hb.h | 2 +- 9 files changed, 81 insertions(+), 54 deletions(-)
diff --git a/drivers/net/ethernet/huawei/bma/cdev_drv/bma_cdev.c b/drivers/net/ethernet/huawei/bma/cdev_drv/bma_cdev.c index 0348a83005d6..9468a5a0c768 100644 --- a/drivers/net/ethernet/huawei/bma/cdev_drv/bma_cdev.c +++ b/drivers/net/ethernet/huawei/bma/cdev_drv/bma_cdev.c @@ -28,7 +28,7 @@ #ifdef DRV_VERSION #define CDEV_VERSION MICRO_TO_STR(DRV_VERSION) #else -#define CDEV_VERSION "0.3.4" +#define CDEV_VERSION "0.3.5" #endif
#define CDEV_DEFAULT_NUM 4 diff --git a/drivers/net/ethernet/huawei/bma/edma_drv/bma_devintf.c b/drivers/net/ethernet/huawei/bma/edma_drv/bma_devintf.c index 7817f58f8635..556130ab8a65 100644 --- a/drivers/net/ethernet/huawei/bma/edma_drv/bma_devintf.c +++ b/drivers/net/ethernet/huawei/bma/edma_drv/bma_devintf.c @@ -419,8 +419,10 @@ EXPORT_SYMBOL(bma_intf_int_to_bmc);
int bma_intf_is_link_ok(void) { - return (g_bma_dev->edma_host.statistics.remote_status == - REGISTERED) ? 1 : 0; + if ((&g_bma_dev->edma_host != NULL) && + (g_bma_dev->edma_host.statistics.remote_status == REGISTERED)) + return 1; + return 0; } EXPORT_SYMBOL(bma_intf_is_link_ok);
@@ -460,14 +462,10 @@ int bma_cdev_recv_msg(void *handle, char __user *data, size_t count) } EXPORT_SYMBOL_GPL(bma_cdev_recv_msg);
-int bma_cdev_add_msg(void *handle, const char __user *msg, size_t msg_len) +static int check_cdev_add_msg_param(struct bma_priv_data_s *handle, +const char __user *msg, size_t msg_len) { struct bma_priv_data_s *priv = NULL; - struct edma_msg_hdr_s *hdr = NULL; - unsigned long flags = 0; - int total_len = 0; - int ret = 0; - struct edma_host_s *phost = &g_bma_dev->edma_host;
if (!handle || !msg || msg_len == 0) { BMA_LOG(DLOG_DEBUG, "input NULL point!\n"); @@ -479,54 +477,80 @@ int bma_cdev_add_msg(void *handle, const char __user *msg, size_t msg_len) return -EINVAL; }
- priv = (struct bma_priv_data_s *)handle; + priv = handle;
if (priv->user.type >= TYPE_MAX) { BMA_LOG(DLOG_DEBUG, "error type = %d\n", priv->user.type); return -EFAULT; } - total_len = SIZE_OF_MSG_HDR + msg_len; + + return 0; +} + +static void edma_msg_hdr_init(struct edma_msg_hdr_s *hdr, + struct bma_priv_data_s *private_data, + char *msg_buf, size_t msg_len) +{ + hdr->type = private_data->user.type; + hdr->sub_type = private_data->user.sub_type; + hdr->user_id = private_data->user.user_id; + hdr->datalen = msg_len; + BMA_LOG(DLOG_DEBUG, "msg_len is %ld\n", msg_len); + + memcpy(hdr->data, msg_buf, msg_len); +} + +int bma_cdev_add_msg(void *handle, const char __user *msg, size_t msg_len) +{ + struct bma_priv_data_s *priv = NULL; + struct edma_msg_hdr_s *hdr = NULL; + unsigned long flags = 0; + unsigned int total_len = 0; + int ret = 0; + struct edma_host_s *phost = &g_bma_dev->edma_host; + char *msg_buf = NULL; + + ret = check_cdev_add_msg_param(handle, msg, msg_len); + if (ret != 0) + return ret; + + priv = (struct bma_priv_data_s *)handle; + + total_len = (unsigned int)(SIZE_OF_MSG_HDR + msg_len); + if (phost->msg_send_write + total_len > HOST_MAX_SEND_MBX_LEN - SIZE_OF_MBX_HDR) { + BMA_LOG(DLOG_DEBUG, "msg lost,msg_send_write: %u,msg_len:%u,max_len: %d\n", + phost->msg_send_write, total_len, HOST_MAX_SEND_MBX_LEN); + return -ENOSPC; + } + + msg_buf = (char *)kmalloc(msg_len, GFP_KERNEL); + if (!msg_buf) { + BMA_LOG(DLOG_ERROR, "malloc msg_buf failed\n"); + return -ENOMEM; + } + + if (copy_from_user(msg_buf, msg, msg_len)) { + BMA_LOG(DLOG_ERROR, "copy_from_user error\n"); + kfree(msg_buf); + return -EFAULT; + }
spin_lock_irqsave(&phost->send_msg_lock, flags);
- if (phost->msg_send_write + total_len <= - HOST_MAX_SEND_MBX_LEN - SIZE_OF_MBX_HDR) { - hdr = (struct edma_msg_hdr_s *)(phost->msg_send_buf + - phost->msg_send_write); - hdr->type = priv->user.type; - hdr->sub_type = priv->user.sub_type; - hdr->user_id = priv->user.user_id; - hdr->datalen = msg_len; - BMA_LOG(DLOG_DEBUG, "msg_len is %ld\n", msg_len); - - if (copy_from_user(hdr->data, msg, msg_len)) { - BMA_LOG(DLOG_ERROR, "copy_from_user error\n"); - ret = -EFAULT; - goto end; - } + hdr = (struct edma_msg_hdr_s *)(phost->msg_send_buf + phost->msg_send_write); + edma_msg_hdr_init(hdr, priv, msg_buf, msg_len);
- phost->msg_send_write += total_len; - phost->statistics.send_bytes += total_len; - phost->statistics.send_pkgs++; + phost->msg_send_write += total_len; + phost->statistics.send_bytes += total_len; + phost->statistics.send_pkgs++; #ifdef EDMA_TIMER - (void)mod_timer(&phost->timer, jiffies_64); + (void)mod_timer(&phost->timer, jiffies_64); #endif - BMA_LOG(DLOG_DEBUG, "msg_send_write = %d\n", - phost->msg_send_write); - - ret = msg_len; - goto end; - } else { - BMA_LOG(DLOG_DEBUG, - "msg lost,msg_send_write: %d,msg_len:%d,max_len: %d\n", - phost->msg_send_write, total_len, - HOST_MAX_SEND_MBX_LEN); - ret = -ENOSPC; - goto end; - } + BMA_LOG(DLOG_DEBUG, "msg_send_write = %d\n", phost->msg_send_write);
-end: + ret = msg_len; spin_unlock_irqrestore(&g_bma_dev->edma_host.send_msg_lock, flags); + kfree(msg_buf); return ret; } EXPORT_SYMBOL_GPL(bma_cdev_add_msg); diff --git a/drivers/net/ethernet/huawei/bma/edma_drv/bma_pci.h b/drivers/net/ethernet/huawei/bma/edma_drv/bma_pci.h index 2851e583666a..b6a0d11704a2 100644 --- a/drivers/net/ethernet/huawei/bma/edma_drv/bma_pci.h +++ b/drivers/net/ethernet/huawei/bma/edma_drv/bma_pci.h @@ -71,7 +71,7 @@ struct bma_pci_dev_s { #ifdef DRV_VERSION #define BMA_VERSION MICRO_TO_STR(DRV_VERSION) #else -#define BMA_VERSION "0.3.4" +#define BMA_VERSION "0.3.5" #endif
#ifdef CONFIG_ARM64 diff --git a/drivers/net/ethernet/huawei/bma/kbox_drv/kbox_include.h b/drivers/net/ethernet/huawei/bma/kbox_drv/kbox_include.h index ffadf3727734..b027306e52c1 100644 --- a/drivers/net/ethernet/huawei/bma/kbox_drv/kbox_include.h +++ b/drivers/net/ethernet/huawei/bma/kbox_drv/kbox_include.h @@ -23,7 +23,7 @@ #ifdef DRV_VERSION #define KBOX_VERSION MICRO_TO_STR(DRV_VERSION) #else -#define KBOX_VERSION "0.3.4" +#define KBOX_VERSION "0.3.5" #endif
#define UNUSED(x) (x = x) diff --git a/drivers/net/ethernet/huawei/bma/kbox_drv/kbox_panic.c b/drivers/net/ethernet/huawei/bma/kbox_drv/kbox_panic.c index 0c17cd2bae49..2b142ae9bff6 100644 --- a/drivers/net/ethernet/huawei/bma/kbox_drv/kbox_panic.c +++ b/drivers/net/ethernet/huawei/bma/kbox_drv/kbox_panic.c @@ -135,7 +135,7 @@ int kbox_panic_init(void) int ret = KBOX_TRUE;
g_panic_info_buf = kmalloc(SLOT_LENGTH, GFP_KERNEL); - if (IS_ERR(g_panic_info_buf) || !g_panic_info_buf) { + if (!g_panic_info_buf) { KBOX_MSG("kmalloc g_panic_info_buf fail!\n"); ret = -ENOMEM; goto fail; @@ -144,7 +144,7 @@ int kbox_panic_init(void) memset(g_panic_info_buf, 0, SLOT_LENGTH);
g_panic_info_buf_tmp = kmalloc(SLOT_LENGTH, GFP_KERNEL); - if (IS_ERR(g_panic_info_buf_tmp) || !g_panic_info_buf_tmp) { + if (!g_panic_info_buf_tmp) { KBOX_MSG("kmalloc g_panic_info_buf_tmp fail!\n"); ret = -ENOMEM; goto fail; diff --git a/drivers/net/ethernet/huawei/bma/kbox_drv/kbox_printk.c b/drivers/net/ethernet/huawei/bma/kbox_drv/kbox_printk.c index 3b04ba206108..630a1e16ea24 100644 --- a/drivers/net/ethernet/huawei/bma/kbox_drv/kbox_printk.c +++ b/drivers/net/ethernet/huawei/bma/kbox_drv/kbox_printk.c @@ -304,7 +304,7 @@ int kbox_printk_init(int kbox_proc_exist)
g_printk_info_buf = kmalloc(SECTION_PRINTK_LEN, GFP_KERNEL); - if (IS_ERR(g_printk_info_buf) || !g_printk_info_buf) { + if (!g_printk_info_buf) { KBOX_MSG("kmalloc g_printk_info_buf fail!\n"); ret = -ENOMEM; goto fail; @@ -314,7 +314,7 @@ int kbox_printk_init(int kbox_proc_exist)
g_printk_info_buf_tmp = kmalloc(SECTION_PRINTK_LEN, GFP_KERNEL); - if (IS_ERR(g_printk_info_buf_tmp) || !g_printk_info_buf_tmp) { + if (!g_printk_info_buf_tmp) { KBOX_MSG("kmalloc g_printk_info_buf_tmp fail!\n"); ret = -ENOMEM; goto fail; diff --git a/drivers/net/ethernet/huawei/bma/kbox_drv/kbox_ram_op.c b/drivers/net/ethernet/huawei/bma/kbox_drv/kbox_ram_op.c index 49690bab1cef..9f6dfe55e3fb 100644 --- a/drivers/net/ethernet/huawei/bma/kbox_drv/kbox_ram_op.c +++ b/drivers/net/ethernet/huawei/bma/kbox_drv/kbox_ram_op.c @@ -432,7 +432,7 @@ int kbox_write_op(long long offset, unsigned int count, return KBOX_FALSE;
temp_buf_char = kmalloc(TEMP_BUF_DATA_SIZE, GFP_KERNEL); - if (!temp_buf_char || IS_ERR(temp_buf_char)) { + if (!temp_buf_char) { KBOX_MSG("kmalloc temp_buf_char fail!\n"); up(&user_sem); return -ENOMEM; diff --git a/drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.c b/drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.c index 9681ce3bfc7b..e226582693b6 100644 --- a/drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.c +++ b/drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.c @@ -638,6 +638,7 @@ s32 veth_refill_rxskb(struct bspveth_rxtx_q *prx_queue, int queue) next_to_fill = (next_to_fill + 1) & BSPVETH_POINT_MASK; }
+ mb();/* memory barriers. */ prx_queue->next_to_fill = next_to_fill;
tail = prx_queue->tail; @@ -672,6 +673,7 @@ s32 bspveth_setup_rx_skb(struct bspveth_device *pvethdev, if (!idx) /* Can't alloc even one packets */ return -EFAULT;
+ mb();/* memory barriers. */ prx_queue->next_to_fill = idx;
VETH_LOG(DLOG_DEBUG, "prx_queue->next_to_fill=%d\n", @@ -886,8 +888,6 @@ s32 bspveth_setup_all_rx_resources(struct bspveth_device *pvethdev) err = bspveth_setup_rx_resources(pvethdev, pvethdev->prx_queue[qid]); if (err) { - kfree(pvethdev->prx_queue[qid]); - pvethdev->prx_queue[qid] = NULL; VETH_LOG(DLOG_ERROR, "Allocation for Rx Queue %u failed\n", qid);
@@ -1328,6 +1328,7 @@ s32 veth_send_one_pkt(struct sk_buff *skb, int queue) pbd_v->off = off; pbd_v->len = skb->len;
+ mb();/* memory barriers. */ head = (head + 1) & BSPVETH_POINT_MASK; ptx_queue->head = head;
@@ -1424,6 +1425,7 @@ s32 veth_free_txskb(struct bspveth_rxtx_q *ptx_queue, int queue) next_to_free = (next_to_free + 1) & BSPVETH_POINT_MASK; }
+ mb(); /* memory barriers. */ ptx_queue->next_to_free = next_to_free; tail = ptx_queue->tail;
@@ -1522,6 +1524,7 @@ s32 veth_recv_pkt(struct bspveth_rxtx_q *prx_queue, int queue) } }
+ mb();/* memory barriers. */ prx_queue->tail = tail; head = prx_queue->head;
diff --git a/drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.h b/drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.h index 9a4d699e6421..503636549320 100644 --- a/drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.h +++ b/drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.h @@ -31,7 +31,7 @@ extern "C" { #ifdef DRV_VERSION #define VETH_VERSION MICRO_TO_STR(DRV_VERSION) #else -#define VETH_VERSION "0.3.4" +#define VETH_VERSION "0.3.5" #endif
#define MODULE_NAME "veth"