Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf header: Sanity check HEADER_NRCPUS and HEADER_CPU_DOMAIN_INFO

While working on some cleanups sashiko questioned about pre-existing
issues, namely lacking sanity checks for perf.data headers, add some
with the help of Claude.

Cc: Ian Rogers <irogers@google.com>
Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
Assisted-by: Claude Code:claude-opus-4-6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>

authored by

Arnaldo Carvalho de Melo and committed by
Namhyung Kim
376ce5a9 06452a41

+44 -1
+44 -1
tools/perf/util/header.c
··· 63 63 #include <event-parse.h> 64 64 #endif 65 65 66 + #define MAX_SCHED_DOMAINS 64 67 + 66 68 /* 67 69 * magic2 = "PERFILE2" 68 70 * must be a numerical value to let the endianness ··· 2724 2722 ret = do_read_u32(ff, &nr_cpus_online); 2725 2723 if (ret) 2726 2724 return ret; 2725 + 2726 + if (nr_cpus_online > nr_cpus_avail) { 2727 + pr_err("Invalid HEADER_NRCPUS: nr_cpus_online (%u) > nr_cpus_avail (%u)\n", 2728 + nr_cpus_online, nr_cpus_avail); 2729 + return -1; 2730 + } 2731 + 2727 2732 env->nr_cpus_avail = (int)nr_cpus_avail; 2728 2733 env->nr_cpus_online = (int)nr_cpus_online; 2729 2734 return 0; ··· 3707 3698 nra = env->nr_cpus_avail; 3708 3699 nr = env->nr_cpus_online; 3709 3700 3701 + if (nra == 0 || nr == 0) { 3702 + pr_err("Invalid HEADER_CPU_DOMAIN_INFO: missing HEADER_NRCPUS\n"); 3703 + return -1; 3704 + } 3705 + 3706 + if (ff->size < 2 * sizeof(u32) + nr * 2 * sizeof(u32)) { 3707 + pr_err("Invalid HEADER_CPU_DOMAIN_INFO: section too small (%zu) for %u CPUs\n", 3708 + (size_t)ff->size, nr); 3709 + return -1; 3710 + } 3711 + 3710 3712 cd_map = calloc(nra, sizeof(*cd_map)); 3711 3713 if (!cd_map) 3712 3714 return -1; ··· 3734 3714 if (ret) 3735 3715 return ret; 3736 3716 3717 + /* 3718 + * Sanity check: real systems have at most ~10 sched domain levels 3719 + * (SMT, CLS, MC, PKG + NUMA hops). Reject obviously bogus values 3720 + * from malformed perf.data files before they cause excessive 3721 + * allocation in the per-CPU loop. 3722 + */ 3723 + if (max_sched_domains > MAX_SCHED_DOMAINS) { 3724 + pr_err("Invalid HEADER_CPU_DOMAIN_INFO: max_sched_domains %u > %u\n", 3725 + max_sched_domains, MAX_SCHED_DOMAINS); 3726 + return -1; 3727 + } 3728 + 3737 3729 env->max_sched_domains = max_sched_domains; 3738 3730 3739 3731 for (i = 0; i < nr; i++) { ··· 3754 3722 3755 3723 if (cpu >= nra) { 3756 3724 pr_err("Invalid HEADER_CPU_DOMAIN_INFO: cpu %d >= nr_cpus_avail (%d)\n", cpu, nra); 3725 + return -1; 3726 + } 3727 + 3728 + if (cd_map[cpu]) { 3729 + pr_err("Invalid HEADER_CPU_DOMAIN_INFO: duplicate cpu %u\n", cpu); 3757 3730 return -1; 3758 3731 } 3759 3732 ··· 3797 3760 if (!d_info) 3798 3761 return -1; 3799 3762 3800 - assert(cd_map[cpu]->domains[domain] == NULL); 3763 + if (cd_map[cpu]->domains[domain]) { 3764 + pr_err("Invalid HEADER_CPU_DOMAIN_INFO: duplicate domain %u for cpu %u\n", 3765 + domain, cpu); 3766 + free(d_info); 3767 + return -1; 3768 + } 3769 + 3801 3770 cd_map[cpu]->domains[domain] = d_info; 3802 3771 d_info->domain = domain; 3803 3772