From 3bf532a81ed92a12f49278a00dce64ee2a40094a Mon Sep 17 00:00:00 2001 From: linqiheng Date: Sat, 14 Jan 2023 11:29:24 +0800 Subject: [PATCH 01/10] hmdfs: fix nullptr dereference hmdfs_init_writeback Signed-off-by: linqiheng --- fs/hmdfs/client_writeback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/hmdfs/client_writeback.c b/fs/hmdfs/client_writeback.c index d4da7ec482a5..d62c286affc1 100644 --- a/fs/hmdfs/client_writeback.c +++ b/fs/hmdfs/client_writeback.c @@ -512,7 +512,7 @@ int hmdfs_init_writeback(struct hmdfs_sb_info *sbi) free_i_wq: destroy_workqueue(hwb->dirty_inode_writeback_wq); free_bdp: - free_percpu(sbi->h_wb->bdp_ratelimits); + free_percpu(hwb->bdp_ratelimits); free_hwb: kfree(hwb); return ret; -- Gitee From e997e851fffb3bbc6e5f7b9924e84c4e9986177f Mon Sep 17 00:00:00 2001 From: linqiheng Date: Sat, 14 Jan 2023 11:29:24 +0800 Subject: [PATCH 02/10] hmdfs: fix memleak in hmdfs_match_strdup The old *dst would not be freed when parsing duplicated tokens. Signed-off-by: linqiheng --- fs/hmdfs/super.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/hmdfs/super.c b/fs/hmdfs/super.c index 52cc857f5e45..a4b1170153b3 100644 --- a/fs/hmdfs/super.c +++ b/fs/hmdfs/super.c @@ -63,6 +63,8 @@ static int hmdfs_match_strdup(const substring_t *s, char **dst) if (!dup) return -ENOMEM; + if (*dst) + kfree(*dst); *dst = dup; return 0; -- Gitee From fe448e1df5904e999f3dd2cbc6db335c983e79ee Mon Sep 17 00:00:00 2001 From: linqiheng Date: Sat, 14 Jan 2023 11:29:24 +0800 Subject: [PATCH 03/10] hmdfs: remove log of cur_file_ver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit file_version is the unique value initialized at mount time, and its log leakage will make the attack less difficult。 Signed-off-by: linqiheng --- fs/hmdfs/hmdfs_server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/hmdfs/hmdfs_server.c b/fs/hmdfs/hmdfs_server.c index dcb15c8b6446..fc0274233970 100644 --- a/fs/hmdfs/hmdfs_server.c +++ b/fs/hmdfs/hmdfs_server.c @@ -315,8 +315,8 @@ static struct file *get_file_by_fid_and_ver(struct hmdfs_peer *con, __u64 cur_file_ver = hmdfs_server_pack_fid_ver(con, cmd); if (file_ver != cur_file_ver) { - hmdfs_warning("Stale file version %llu for fid %u (ver %llu)", - file_ver, file_id, cur_file_ver); + hmdfs_warning("Stale file version %llu for fid %u", + file_ver, file_id); return ERR_PTR(-EBADF); } -- Gitee From 83644f5bc675b2d5d0eec7f533f3b62dbf735a23 Mon Sep 17 00:00:00 2001 From: linqiheng Date: Sat, 14 Jan 2023 11:29:25 +0800 Subject: [PATCH 04/10] hmdfs: fix nullptr dereference of share_item_timeout_wq Add check of `share_item_timeout_wq` after create_singlethread_workqueue(), to avoid nullptr dereference when destroy workqueue in hmdfs_clear_share_table(). Signed-off-by: linqiheng --- fs/hmdfs/hmdfs_share.c | 6 +++++- fs/hmdfs/hmdfs_share.h | 2 +- fs/hmdfs/main.c | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/fs/hmdfs/hmdfs_share.c b/fs/hmdfs/hmdfs_share.c index c8314a5d7fca..6b9557d02263 100644 --- a/fs/hmdfs/hmdfs_share.c +++ b/fs/hmdfs/hmdfs_share.c @@ -302,7 +302,7 @@ int hmdfs_check_share_access_permission(struct hmdfs_sb_info *sbi, } -void hmdfs_init_share_table(struct hmdfs_sb_info *sbi) +int hmdfs_init_share_table(struct hmdfs_sb_info *sbi) { spin_lock_init(&sbi->share_table.item_list_lock); INIT_LIST_HEAD(&sbi->share_table.item_list_head); @@ -310,6 +310,10 @@ void hmdfs_init_share_table(struct hmdfs_sb_info *sbi) sbi->share_table.max_cnt = HMDFS_SHARE_ITEMS_MAX; sbi->share_table.share_item_timeout_wq = create_singlethread_workqueue("share_item_timeout_wq"); + + if (!sbi->share_table.share_item_timeout_wq) + return -ENOMEM; + return 0; } void hmdfs_clear_share_table(struct hmdfs_sb_info *sbi) diff --git a/fs/hmdfs/hmdfs_share.h b/fs/hmdfs/hmdfs_share.h index eef53bf19bab..3c055805bd6d 100644 --- a/fs/hmdfs/hmdfs_share.h +++ b/fs/hmdfs/hmdfs_share.h @@ -60,7 +60,7 @@ void hmdfs_close_share_item(struct hmdfs_sb_info *sbi, struct file *file, int hmdfs_check_share_access_permission(struct hmdfs_sb_info *sbi, const char *filename, char *cid); -void hmdfs_init_share_table(struct hmdfs_sb_info *sbi); +int hmdfs_init_share_table(struct hmdfs_sb_info *sbi); void hmdfs_clear_share_table(struct hmdfs_sb_info *sbi); int hmdfs_clear_first_item(struct hmdfs_share_table *st); diff --git a/fs/hmdfs/main.c b/fs/hmdfs/main.c index d0a41061bb2f..9443abde8057 100644 --- a/fs/hmdfs/main.c +++ b/fs/hmdfs/main.c @@ -712,7 +712,9 @@ static int hmdfs_init_sbi(struct hmdfs_sb_info *sbi) mutex_init(&sbi->connections.node_lock); INIT_LIST_HEAD(&sbi->connections.node_list); - hmdfs_init_share_table(sbi); + ret = hmdfs_init_share_table(sbi); + if (ret) + goto out; init_waitqueue_head(&sbi->async_readdir_wq); INIT_LIST_HEAD(&sbi->async_readdir_msg_list); INIT_LIST_HEAD(&sbi->async_readdir_work_list); -- Gitee From b1967e9f7b8648c3f3039dc7e49234a48c125045 Mon Sep 17 00:00:00 2001 From: linqiheng Date: Sat, 14 Jan 2023 11:29:25 +0800 Subject: [PATCH 05/10] hmdfs: fix nullptr dereference of kern_path(dev_name) in hmdfs_fill_super Signed-off-by: linqiheng --- fs/hmdfs/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/hmdfs/main.c b/fs/hmdfs/main.c index 9443abde8057..33484bc23be2 100644 --- a/fs/hmdfs/main.c +++ b/fs/hmdfs/main.c @@ -956,6 +956,10 @@ static struct dentry *hmdfs_mount(struct file_system_type *fs_type, int flags, .dev_name = dev_name, .raw_data = raw_data, }; + + /* hmdfs needs a valid dev_name to get the lower_sb's metadata */ + if (!dev_name || !*dev_name) + return ERR_PTR(-EINVAL); return mount_nodev(fs_type, flags, &priv, hmdfs_fill_super); } -- Gitee From 995096ee3b81aa2dbcc2f59e546f4aeecbcf9d4e Mon Sep 17 00:00:00 2001 From: linqiheng Date: Sat, 14 Jan 2023 11:29:25 +0800 Subject: [PATCH 06/10] hmdfs: fix memcpy reads d_name out of bounds Signed-off-by: linqiheng --- fs/hmdfs/inode_root.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/hmdfs/inode_root.c b/fs/hmdfs/inode_root.c index 30d0ca6a2264..b3b2b5c2b2fc 100644 --- a/fs/hmdfs/inode_root.c +++ b/fs/hmdfs/inode_root.c @@ -153,7 +153,7 @@ struct dentry *hmdfs_device_lookup(struct inode *parent_inode, ret_dentry = ERR_PTR(err); goto out; } - memcpy(cid, d_name, HMDFS_CID_SIZE); + strncpy(cid, d_name, HMDFS_CID_SIZE); cid[HMDFS_CID_SIZE] = '\0'; con = hmdfs_lookup_from_cid(sbi, cid); if (!con) { -- Gitee From f898c313c319f3af8ba9c405d2101cf027380627 Mon Sep 17 00:00:00 2001 From: linqiheng Date: Sat, 14 Jan 2023 11:29:25 +0800 Subject: [PATCH 07/10] hmdfs: fix client readdir dentry file leak Signed-off-by: linqiheng --- fs/hmdfs/comm/socket_adapter.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/fs/hmdfs/comm/socket_adapter.c b/fs/hmdfs/comm/socket_adapter.c index eff3d3e1c044..913d667f0f73 100644 --- a/fs/hmdfs/comm/socket_adapter.c +++ b/fs/hmdfs/comm/socket_adapter.c @@ -409,18 +409,23 @@ int hmdfs_sendmessage_request(struct hmdfs_peer *con, struct hmdfs_head_cmd *head = NULL; bool dec = false; - if (!hmdfs_is_node_online(con)) - return -EAGAIN; + if (!hmdfs_is_node_online(con)) { + ret = -EAGAIN; + goto free_filp; + } if (timeout == TIMEOUT_UNINIT) { hmdfs_err_ratelimited("send msg %d with uninitialized timeout", sm->operations.command); - return -EINVAL; + ret = -EINVAL; + goto free_filp; } head = kzalloc(sizeof(struct hmdfs_head_cmd), GFP_KERNEL); - if (!head) - return -ENOMEM; + if (!head) { + ret = -ENOMEM; + goto free_filp; + } sm->out_buf = NULL; head->magic = HMDFS_MSG_MAGIC; @@ -504,6 +509,11 @@ int hmdfs_sendmessage_request(struct hmdfs_peer *con, hmdfs_dec_msg_idr_process(con); kfree(head); return ret; + +free_filp: + if (sm->local_filp) + fput(sm->local_filp); + return ret; } static int hmdfs_send_slice(struct hmdfs_peer *con, struct hmdfs_head_cmd *cmd, -- Gitee From 5eb8e2669d504535738e5d6c0f3e4da0599c602a Mon Sep 17 00:00:00 2001 From: linqiheng Date: Sat, 14 Jan 2023 11:29:25 +0800 Subject: [PATCH 08/10] hmdfs: fix memleak of outdata when recv message error case Signed-off-by: linqiheng --- fs/hmdfs/comm/connection.c | 2 +- fs/hmdfs/comm/socket_adapter.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/hmdfs/comm/connection.c b/fs/hmdfs/comm/connection.c index 5a2e5b0f5b02..7613da514c7c 100644 --- a/fs/hmdfs/comm/connection.c +++ b/fs/hmdfs/comm/connection.c @@ -706,7 +706,7 @@ void connection_handshake_recv_handler(struct connection *conn_impl, void *buf, } fallthrough; default: - return; + break; } out: kfree(data); diff --git a/fs/hmdfs/comm/socket_adapter.c b/fs/hmdfs/comm/socket_adapter.c index 913d667f0f73..7005303e3735 100644 --- a/fs/hmdfs/comm/socket_adapter.c +++ b/fs/hmdfs/comm/socket_adapter.c @@ -1092,7 +1092,7 @@ static void hmdfs_recv_mesg_callback(struct hmdfs_peer *con, void *head, default: hmdfs_err("Fatal! Unexpected msg cmd %d", hmdfs_head->operations.cmd_flag); - break; + goto out_err; } return; -- Gitee From cfe893efbfc3150d92877ca54d2013813f6bfd08 Mon Sep 17 00:00:00 2001 From: linqiheng Date: Sat, 14 Jan 2023 11:29:25 +0800 Subject: [PATCH 09/10] hmdfs: fix double free of sbi->local_dst Signed-off-by: linqiheng --- fs/hmdfs/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/hmdfs/main.c b/fs/hmdfs/main.c index 33484bc23be2..53d698917969 100644 --- a/fs/hmdfs/main.c +++ b/fs/hmdfs/main.c @@ -764,6 +764,7 @@ static int hmdfs_update_dst(struct hmdfs_sb_info *sbi) goto out_err; } kfree(sbi->local_dst); + sbi->local_dst = NULL; len = strlen(sbi->real_dst) + strlen(path_local) + 1; if (len > PATH_MAX) { -- Gitee From 151b7a7df7a540caa9de53a6907d7523cc6f18ea Mon Sep 17 00:00:00 2001 From: linqiheng Date: Sat, 14 Jan 2023 11:29:25 +0800 Subject: [PATCH 10/10] hmdfs: fix the message version check Only the head version of 2.0 is supported, and the corresponding message length must be checked. Signed-off-by: linqiheng Change-Id: I2f55f9ef7822c701f4ca2ccee61e8ff2088c1bb1 --- fs/hmdfs/comm/message_verify.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/fs/hmdfs/comm/message_verify.c b/fs/hmdfs/comm/message_verify.c index c9eb94d8b615..fd76658ef16d 100644 --- a/fs/hmdfs/comm/message_verify.c +++ b/fs/hmdfs/comm/message_verify.c @@ -934,7 +934,9 @@ int hmdfs_message_verify(struct hmdfs_peer *con, struct hmdfs_head_cmd *head, goto handle_bad_msg; } - if (head->version == DFS_2_0) { + if (head->version != DFS_2_0) { + err = -EINVAL; + } else { len = le32_to_cpu(head->data_len) - sizeof(struct hmdfs_head_cmd); min = message_length[flag][cmd][HMDFS_MESSAGE_MIN_INDEX]; @@ -973,13 +975,6 @@ int hmdfs_message_verify(struct hmdfs_peer *con, struct hmdfs_head_cmd *head, } handle_bad_msg: - if (err) { - handle_bad_message(con, head, &err); - return err; - } - - if (head->version == DFS_1_0) - return err; // now, DFS_1_0 version do not verify - - return -EINVAL; + handle_bad_message(con, head, &err); + return err; } -- Gitee