net: hns3: fix race condition in debugfs
authorYufeng Mo <moyufeng@huawei.com>
Fri, 10 Dec 2021 13:09:34 +0000 (21:09 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Dec 2021 08:32:40 +0000 (09:32 +0100)
[ Upstream commit 6dde452bceca3f2ed2b33bc46a16ff5682a03a2e ]

When multiple threads concurrently access the debugfs content, data
and pointer exceptions may occur. Therefore, mutex lock protection is
added for debugfs.

Fixes: 5e69ea7ee2a6 ("net: hns3: refactor the debugfs process")
Signed-off-by: Yufeng Mo <moyufeng@huawei.com>
Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/hisilicon/hns3/hnae3.h
drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c

index d701451596c825e78b55bb3164b76790df3a578a..47bba4c62f0404e69735aad09cc99b179a6c36b9 100644 (file)
@@ -830,6 +830,8 @@ struct hnae3_handle {
 
        u8 netdev_flags;
        struct dentry *hnae3_dbgfs;
+       /* protects concurrent contention between debugfs commands */
+       struct mutex dbgfs_lock;
 
        /* Network interface message level enabled bits */
        u32 msg_enable;
index e54f96251fea97eafd5f2eb912feff6f07cd51df..3205849bdb95bde8180044d01a6b0fca4e785e59 100644 (file)
@@ -1021,6 +1021,7 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer,
        if (ret)
                return ret;
 
+       mutex_lock(&handle->dbgfs_lock);
        save_buf = &hns3_dbg_cmd[index].buf;
 
        if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) ||
@@ -1033,15 +1034,15 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer,
                read_buf = *save_buf;
        } else {
                read_buf = kvzalloc(hns3_dbg_cmd[index].buf_len, GFP_KERNEL);
-               if (!read_buf)
-                       return -ENOMEM;
+               if (!read_buf) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
 
                /* save the buffer addr until the last read operation */
                *save_buf = read_buf;
-       }
 
-       /* get data ready for the first time to read */
-       if (!*ppos) {
+               /* get data ready for the first time to read */
                ret = hns3_dbg_read_cmd(dbg_data, hns3_dbg_cmd[index].cmd,
                                        read_buf, hns3_dbg_cmd[index].buf_len);
                if (ret)
@@ -1050,8 +1051,10 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer,
 
        size = simple_read_from_buffer(buffer, count, ppos, read_buf,
                                       strlen(read_buf));
-       if (size > 0)
+       if (size > 0) {
+               mutex_unlock(&handle->dbgfs_lock);
                return size;
+       }
 
 out:
        /* free the buffer for the last read operation */
@@ -1060,6 +1063,7 @@ out:
                *save_buf = NULL;
        }
 
+       mutex_unlock(&handle->dbgfs_lock);
        return ret;
 }
 
@@ -1132,6 +1136,8 @@ int hns3_dbg_init(struct hnae3_handle *handle)
                        debugfs_create_dir(hns3_dbg_dentry[i].name,
                                           handle->hnae3_dbgfs);
 
+       mutex_init(&handle->dbgfs_lock);
+
        for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd); i++) {
                if ((hns3_dbg_cmd[i].cmd == HNAE3_DBG_CMD_TM_NODES &&
                     ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2) ||
@@ -1158,6 +1164,7 @@ int hns3_dbg_init(struct hnae3_handle *handle)
        return 0;
 
 out:
+       mutex_destroy(&handle->dbgfs_lock);
        debugfs_remove_recursive(handle->hnae3_dbgfs);
        handle->hnae3_dbgfs = NULL;
        return ret;
@@ -1173,6 +1180,7 @@ void hns3_dbg_uninit(struct hnae3_handle *handle)
                        hns3_dbg_cmd[i].buf = NULL;
                }
 
+       mutex_destroy(&handle->dbgfs_lock);
        debugfs_remove_recursive(handle->hnae3_dbgfs);
        handle->hnae3_dbgfs = NULL;
 }