From: John Garry john.garry@huawei.com
mainline inclusion from mainline-v5.14-rc4 commit c07d5c922698 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I63VF5 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------------------------------------------------
Commit c47a5599eda324ba ("perf tools: Fix pattern matching for same substring in different PMU type"), may have fixed some alias matching, but has broken some others.
Firstly it cannot handle the simple scenario of PMU name in form pmu_name{digits} - it can only handle pmu_name_{digits}.
Secondly it cannot handle more complex matching in the case where we have multiple tokens. In this scenario, the code failed to realise that we may examine multiple substrings in the PMU name.
Fix in two ways:
- Change perf_pmu__valid_suffix() to accept a PMU name without '_' in the suffix
- Only pay attention to perf_pmu__valid_suffix() for the final token
Also add const qualifiers as necessary to avoid casting.
Fixes: c47a5599eda324ba ("perf tools: Fix pattern matching for same substring in different PMU type") Signed-off-by: John Garry john.garry@huawei.com Tested-by: Jin Yao yao.jin@linux.intel.com Cc: Alexander Shishkin alexander.shishkin@linux.intel.com Cc: Ian Rogers irogers@google.com Cc: Jiri Olsa jolsa@redhat.com Cc: Kajol Jain kjain@linux.ibm.com Cc: Mark Rutland mark.rutland@arm.com Cc: Namhyung Kim namhyung@kernel.org Cc: Peter Zijlstra peterz@infradead.org Link: http://lore.kernel.org/lkml/1626793819-79090-1-git-send-email-john.garry@hua... Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Junhao He hejunhao3@huawei.com --- tools/perf/util/pmu.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-)
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 59ff23aeca7e..7d86dcc941d9 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -719,9 +719,13 @@ struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu) return map; }
-static bool perf_pmu__valid_suffix(char *pmu_name, char *tok) +/* + * Suffix must be in form tok_{digits}, or tok{digits}, or same as pmu_name + * to be valid. + */ +static bool perf_pmu__valid_suffix(const char *pmu_name, char *tok) { - char *p; + const char *p;
if (strncmp(pmu_name, tok, strlen(tok))) return false; @@ -730,12 +734,16 @@ static bool perf_pmu__valid_suffix(char *pmu_name, char *tok) if (*p == 0) return true;
- if (*p != '_') - return false; + if (*p == '_') + ++p;
- ++p; - if (*p == 0 || !isdigit(*p)) - return false; + /* Ensure we end in a number */ + while (1) { + if (!isdigit(*p)) + return false; + if (*(++p) == 0) + break; + }
return true; } @@ -771,12 +779,19 @@ bool pmu_uncore_alias_match(const char *pmu_name, const char *name) * match "socket" in "socketX_pmunameY" and then "pmuname" in * "pmunameY". */ - for (; tok; name += strlen(tok), tok = strtok_r(NULL, ",", &tmp)) { + while (1) { + char *next_tok = strtok_r(NULL, ",", &tmp); + name = strstr(name, tok); - if (!name || !perf_pmu__valid_suffix((char *)name, tok)) { + if (!name || + (!next_tok && !perf_pmu__valid_suffix(name, tok))) { res = false; goto out; } + if (!next_tok) + break; + tok = next_tok; + name += strlen(tok); }
res = true;