perf evsel: Do not access outside hw cache name arrays
authorArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 18 Aug 2016 19:30:28 +0000 (16:30 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 18 Aug 2016 19:39:46 +0000 (16:39 -0300)
We have to check if the values are >= *_MAX, not just >, fix it.

From the bugzilla report:

''In file /tools/perf/util/evsel.c  function __perf_evsel__hw_cache_name
it appears that there is a bug that reads beyond the end of the buffer.
The statement "if (type > PERF_COUNT_HW_CACHE_MAX)" allows type to be
equal to the maximum value. Later, when statement "if
(!perf_evsel__is_cache_op_valid(type, op))" is executed, the function
can access array perf_evsel__hw_cache_stat[type] beyond the end of the
buffer.

It appears to me that the statement "if (type > PERF_COUNT_HW_CACHE_MAX)"
should be "if (type >= PERF_COUNT_HW_CACHE_MAX)"

Bug found with Coverity and manual code review. No attempts were made to
execute the code with a maximum type value.''

Committer note:

Testing it:

  $ perf record -e $(echo $(perf list cache | cut -d \[ -f1) | sed 's/ /,/g') usleep 1
  [ perf record: Woken up 16 times to write data ]
  [ perf record: Captured and wrote 0.023 MB perf.data (34 samples) ]
  $ perf evlist
  L1-dcache-load-misses
  L1-dcache-loads
  L1-dcache-stores
  L1-icache-load-misses
  LLC-load-misses
  LLC-loads
  LLC-store-misses
  LLC-stores
  branch-load-misses
  branch-loads
  dTLB-load-misses
  dTLB-loads
  dTLB-store-misses
  dTLB-stores
  iTLB-load-misses
  iTLB-loads
  node-load-misses
  node-loads
  node-store-misses
  node-stores
  $ perf list cache

  List of pre-defined events (to be used in -e):

    L1-dcache-load-misses        [Hardware cache event]
    L1-dcache-loads              [Hardware cache event]
    L1-dcache-stores             [Hardware cache event]
    L1-icache-load-misses        [Hardware cache event]
    LLC-load-misses              [Hardware cache event]
    LLC-loads                    [Hardware cache event]
    LLC-store-misses             [Hardware cache event]
    LLC-stores                   [Hardware cache event]
    branch-load-misses           [Hardware cache event]
    branch-loads                 [Hardware cache event]
    dTLB-load-misses             [Hardware cache event]
    dTLB-loads                   [Hardware cache event]
    dTLB-store-misses            [Hardware cache event]
    dTLB-stores                  [Hardware cache event]
    iTLB-load-misses             [Hardware cache event]
    iTLB-loads                   [Hardware cache event]
    node-load-misses             [Hardware cache event]
    node-loads                   [Hardware cache event]
    node-store-misses            [Hardware cache event]
    node-stores                  [Hardware cache event]
  $

Reported-by: Brian Sweeney <bsweeney@lgsinnovations.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=153351
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/evsel.c

index d9b80ef881cde43a1e134b89c6a752f2ae06d108..21fd573106edd90ee4c33b3a0a9b46e43ecd052b 100644 (file)
@@ -507,17 +507,17 @@ static int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size)
        u8 op, result, type = (config >>  0) & 0xff;
        const char *err = "unknown-ext-hardware-cache-type";
 
-       if (type > PERF_COUNT_HW_CACHE_MAX)
+       if (type >= PERF_COUNT_HW_CACHE_MAX)
                goto out_err;
 
        op = (config >>  8) & 0xff;
        err = "unknown-ext-hardware-cache-op";
-       if (op > PERF_COUNT_HW_CACHE_OP_MAX)
+       if (op >= PERF_COUNT_HW_CACHE_OP_MAX)
                goto out_err;
 
        result = (config >> 16) & 0xff;
        err = "unknown-ext-hardware-cache-result";
-       if (result > PERF_COUNT_HW_CACHE_RESULT_MAX)
+       if (result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
                goto out_err;
 
        err = "invalid-cache";