Whamcloud - gitweb
LU-18415 pcc: fix panic when add/remove PCC backends 24/56824/3
authorQian Yingjin <qian@ddn.com>
Wed, 30 Oct 2024 08:56:35 +0000 (16:56 +0800)
committerOleg Drokin <green@whamcloud.com>
Mon, 2 Dec 2024 05:55:07 +0000 (05:55 +0000)
PCC panic on CSI drvier when add/remove PCC backends on a client
as follows:
RIP: 0010:strlen+0x0/0x20
Call Trace:
pcc_dataset_rule_init [lustre]
pcc_cmd_handle [lustre]
ll_pcc_seq_write [lustre]
vfs_write
ksys_write

There are some bugs in the error handling for PCC setup and
cleanup. This may result in double memory free or list struct
corrupting. Fix it accordingly.

Signed-off-by: Qian Yingjin <qian@ddn.com>
Change-Id: I04d616395c095748aa195df5f2979a85de79dded
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/56824
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Li Xi <lixi@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/llite/pcc.c

index b1fc32b..30fbdf5 100644 (file)
@@ -225,8 +225,11 @@ static void pcc_cmd_fini(struct pcc_cmd *cmd)
        if (cmd->pccc_cmd == PCC_ADD_DATASET) {
                if (!list_empty(&cmd->u.pccc_add.pccc_conds))
                        pcc_rule_conds_free(&cmd->u.pccc_add.pccc_conds);
-               OBD_FREE(cmd->u.pccc_add.pccc_conds_str,
-                        strlen(cmd->u.pccc_add.pccc_conds_str) + 1);
+               if (cmd->u.pccc_add.pccc_conds_str) {
+                       OBD_FREE(cmd->u.pccc_add.pccc_conds_str,
+                                strlen(cmd->u.pccc_add.pccc_conds_str) + 1);
+                       cmd->u.pccc_add.pccc_conds_str = NULL;
+               }
        }
 }
 
@@ -751,6 +754,7 @@ pcc_dataset_rule_init(struct pcc_match_rule *rule, struct pcc_cmd *cmd)
        int rc = 0;
 
        LASSERT(cmd->u.pccc_add.pccc_conds_str);
+       INIT_LIST_HEAD(&rule->pmr_conds);
        OBD_ALLOC(rule->pmr_conds_str,
                  strlen(cmd->u.pccc_add.pccc_conds_str) + 1);
        if (rule->pmr_conds_str == NULL)
@@ -760,7 +764,6 @@ pcc_dataset_rule_init(struct pcc_match_rule *rule, struct pcc_cmd *cmd)
               cmd->u.pccc_add.pccc_conds_str,
               strlen(cmd->u.pccc_add.pccc_conds_str));
 
-       INIT_LIST_HEAD(&rule->pmr_conds);
        if (!list_empty(&cmd->u.pccc_add.pccc_conds))
                rc = pcc_conds_parse(rule->pmr_conds_str,
                                     &rule->pmr_conds);
@@ -1199,7 +1202,7 @@ static bool pathname_is_valid(const char *pathname)
 static struct pcc_cmd *
 pcc_cmd_parse(char *buffer, unsigned long count)
 {
-       static struct pcc_cmd *cmd;
+       struct pcc_cmd *cmd;
        char *token;
        char *val;
        int rc = 0;
@@ -1220,12 +1223,14 @@ pcc_cmd_parse(char *buffer, unsigned long count)
                GOTO(out_free_cmd, rc = -EINVAL);
 
        /* Type of the command */
-       if (strcmp(token, "add") == 0)
+       if (strcmp(token, "add") == 0) {
                cmd->pccc_cmd = PCC_ADD_DATASET;
-       else if (strcmp(token, "del") == 0)
+               INIT_LIST_HEAD(&cmd->u.pccc_add.pccc_conds);
+       } else if (strcmp(token, "del") == 0) {
                cmd->pccc_cmd = PCC_DEL_DATASET;
-       else
+       } else {
                GOTO(out_free_cmd, rc = -EINVAL);
+       }
 
        /* Pathname of the dataset */
        token = strsep(&val, " ");