From cec864b7938f1138d1432ab0720f4e1d51ea6ae4 Mon Sep 17 00:00:00 2001 From: Etienne AUJAMES Date: Tue, 19 Oct 2021 16:10:43 +0200 Subject: [PATCH] LU-15130 nrs: null pointer dereference in nrs_tbf_id_parse cfs_gettok() set next->ls_str to NULL if no delimiter is found but it does not update next->ls_len to 0. We have to check if next->ls_str is null inside nrs_tbf_id_parse() to verify if the tbf expression is valid. * Reproducer * lctl set_param mds.MDS.mdt.nrs_tbf_rule="start tbf_name gid{500} rate=100" This patch fix cfs_gettok() to update "next->ls_len = 0;" if no delimiter is found. Signed-off-by: Etienne AUJAMES Change-Id: Iaa4eb5085262cee547ea3a944ddb94c6df1f8aa3 Reviewed-on: https://review.whamcloud.com/45291 Tested-by: jenkins Reviewed-by: Andreas Dilger Tested-by: Maloo Reviewed-by: Li Xi Reviewed-by: Oleg Drokin --- libcfs/libcfs/libcfs_string.c | 1 + libcfs/libcfs/util/string.c | 1 + lustre/ptlrpc/nrs_tbf.c | 8 ++++---- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libcfs/libcfs/libcfs_string.c b/libcfs/libcfs/libcfs_string.c index 5549417..7ba00df 100644 --- a/libcfs/libcfs/libcfs_string.c +++ b/libcfs/libcfs/libcfs_string.c @@ -151,6 +151,7 @@ cfs_gettok(struct cfs_lstr *next, char delim, struct cfs_lstr *res) /* there is no the delimeter in the string */ end = next->ls_str + next->ls_len; next->ls_str = NULL; + next->ls_len = 0; } else { next->ls_str = end + 1; next->ls_len -= (end - res->ls_str + 1); diff --git a/libcfs/libcfs/util/string.c b/libcfs/libcfs/util/string.c index 9e92339..700f002 100644 --- a/libcfs/libcfs/util/string.c +++ b/libcfs/libcfs/util/string.c @@ -84,6 +84,7 @@ cfs_gettok(struct cfs_lstr *next, char delim, struct cfs_lstr *res) /* there is no the delimeter in the string */ end = next->ls_str + next->ls_len; next->ls_str = NULL; + next->ls_len = 0; } else { next->ls_str = end + 1; next->ls_len -= (end - res->ls_str + 1); diff --git a/lustre/ptlrpc/nrs_tbf.c b/lustre/ptlrpc/nrs_tbf.c index 37edf58..2b819e7 100644 --- a/lustre/ptlrpc/nrs_tbf.c +++ b/lustre/ptlrpc/nrs_tbf.c @@ -929,8 +929,8 @@ static int nrs_tbf_check_id_value(struct cfs_lstr *src, char *key) rc = cfs_gettok(src, '=', &res); if (rc == 0 || res.ls_len != keylen || strncmp(res.ls_str, key, keylen) != 0 || - src->ls_len <= 2 || src->ls_str[0] != '{' || - src->ls_str[src->ls_len - 1] != '}') + !src->ls_str || src->ls_len <= 2 || + src->ls_str[0] != '{' || src->ls_str[src->ls_len - 1] != '}') return -EINVAL; /* Skip '{' and '}' */ @@ -1840,8 +1840,8 @@ nrs_tbf_expression_parse(struct cfs_lstr *src, struct list_head *cond_list) return -ENOMEM; rc = cfs_gettok(src, NRS_TBF_EXPRESSION_DELIM, &field); - if (rc == 0 || src->ls_len <= 2 || src->ls_str[0] != '{' || - src->ls_str[src->ls_len - 1] != '}') + if (rc == 0 || !src->ls_str || src->ls_len <= 2 || + src->ls_str[0] != '{' || src->ls_str[src->ls_len - 1] != '}') GOTO(out, rc = -EINVAL); /* Skip '{' and '}' */ -- 1.8.3.1