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

perf record: Ensure space for lost samples

Previous allocation didn't account for sample ID written after the
lost samples event. Switch from malloc/free to a stack allocation.

Reported-by: Milian Wolff <milian.wolff@kdab.com>
Closes: https://lore.kernel.org/linux-perf-users/23879991.0LEYPuXRzz@milian-workstation/
Signed-off-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/r/20240611050626.1223155-1-irogers@google.com

authored by

Ian Rogers and committed by
Namhyung Kim
6c1785cd 6828d692

+15 -25
+6
tools/lib/perf/include/perf/event.h
··· 77 77 __u64 lost; 78 78 }; 79 79 80 + #define MAX_ID_HDR_ENTRIES 6 81 + struct perf_record_lost_samples_and_ids { 82 + struct perf_record_lost_samples lost; 83 + __u64 sample_ids[MAX_ID_HDR_ENTRIES]; 84 + }; 85 + 80 86 /* 81 87 * PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID | PERF_FORMAT_LOST 82 88 */
+9 -25
tools/perf/builtin-record.c
··· 1926 1926 static void record__read_lost_samples(struct record *rec) 1927 1927 { 1928 1928 struct perf_session *session = rec->session; 1929 - struct perf_record_lost_samples *lost = NULL; 1929 + struct perf_record_lost_samples_and_ids lost; 1930 1930 struct evsel *evsel; 1931 1931 1932 1932 /* there was an error during record__open */ ··· 1951 1951 1952 1952 if (perf_evsel__read(&evsel->core, x, y, &count) < 0) { 1953 1953 pr_debug("read LOST count failed\n"); 1954 - goto out; 1954 + return; 1955 1955 } 1956 1956 1957 1957 if (count.lost) { 1958 - if (!lost) { 1959 - lost = zalloc(sizeof(*lost) + 1960 - session->machines.host.id_hdr_size); 1961 - if (!lost) { 1962 - pr_debug("Memory allocation failed\n"); 1963 - return; 1964 - } 1965 - lost->header.type = PERF_RECORD_LOST_SAMPLES; 1966 - } 1967 - __record__save_lost_samples(rec, evsel, lost, 1958 + memset(&lost.lost, 0, sizeof(lost)); 1959 + lost.lost.header.type = PERF_RECORD_LOST_SAMPLES; 1960 + __record__save_lost_samples(rec, evsel, &lost.lost, 1968 1961 x, y, count.lost, 0); 1969 1962 } 1970 1963 } ··· 1965 1972 1966 1973 lost_count = perf_bpf_filter__lost_count(evsel); 1967 1974 if (lost_count) { 1968 - if (!lost) { 1969 - lost = zalloc(sizeof(*lost) + 1970 - session->machines.host.id_hdr_size); 1971 - if (!lost) { 1972 - pr_debug("Memory allocation failed\n"); 1973 - return; 1974 - } 1975 - lost->header.type = PERF_RECORD_LOST_SAMPLES; 1976 - } 1977 - __record__save_lost_samples(rec, evsel, lost, 0, 0, lost_count, 1975 + memset(&lost.lost, 0, sizeof(lost)); 1976 + lost.lost.header.type = PERF_RECORD_LOST_SAMPLES; 1977 + __record__save_lost_samples(rec, evsel, &lost.lost, 0, 0, lost_count, 1978 1978 PERF_RECORD_MISC_LOST_SAMPLES_BPF); 1979 1979 } 1980 1980 } 1981 - out: 1982 - free(lost); 1983 1981 } 1984 1982 1985 1983 static volatile sig_atomic_t workload_exec_errno; ··· 3182 3198 unsigned long val; 3183 3199 3184 3200 /* 3185 - * If we're using --switch-output-events, then we imply its 3201 + * If we're using --switch-output-events, then we imply its 3186 3202 * --switch-output=signal, as we'll send a SIGUSR2 from the side band 3187 3203 * thread to its parent. 3188 3204 */