Commit bbdff6d5 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'perf-tools-fixes-for-v5.16-2021-12-11' of...

Merge tag 'perf-tools-fixes-for-v5.16-2021-12-11' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

Pull perf tools fixes from Arnaldo Carvalho de Melo:

 - Prevent out-of-bounds access to per sample registers.

 - Fix NULL vs IS_ERR_OR_NULL() checking on the python binding.

 - Intel PT fixes, half of those are one-liners:
      - Fix some PGE (packet generation enable/control flow packets) usage.
      - Fix sync state when a PSB (synchronization) packet is found.
      - Fix intel_pt_fup_event() assumptions about setting state type.
      - Fix state setting when receiving overflow (OVF) packet.
      - Fix next 'err' value, walking trace.
      - Fix missing 'instruction' events with 'q' option.
      - Fix error timestamp setting on the decoder error path.

* tag 'perf-tools-fixes-for-v5.16-2021-12-11' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux:
  perf python: Fix NULL vs IS_ERR_OR_NULL() checking
  perf intel-pt: Fix error timestamp setting on the decoder error path
  perf intel-pt: Fix missing 'instruction' events with 'q' option
  perf intel-pt: Fix next 'err' value, walking trace
  perf intel-pt: Fix state setting when receiving overflow (OVF) packet
  perf intel-pt: Fix intel_pt_fup_event() assumptions about setting state type
  perf intel-pt: Fix sync state when a PSB (synchronization) packet is found
  perf intel-pt: Fix some PGE (packet generation enable/control flow packets) usage
  perf tools: Prevent out-of-bounds access to registers
parents eccea80b 9937e8da
...@@ -44,13 +44,16 @@ struct perf_event_attr; ...@@ -44,13 +44,16 @@ struct perf_event_attr;
/* perf sample has 16 bits size limit */ /* perf sample has 16 bits size limit */
#define PERF_SAMPLE_MAX_SIZE (1 << 16) #define PERF_SAMPLE_MAX_SIZE (1 << 16)
/* number of register is bound by the number of bits in regs_dump::mask (64) */
#define PERF_SAMPLE_REGS_CACHE_SIZE (8 * sizeof(u64))
struct regs_dump { struct regs_dump {
u64 abi; u64 abi;
u64 mask; u64 mask;
u64 *regs; u64 *regs;
/* Cached values/mask filled by first register access. */ /* Cached values/mask filled by first register access. */
u64 cache_regs[PERF_REGS_MAX]; u64 cache_regs[PERF_SAMPLE_REGS_CACHE_SIZE];
u64 cache_mask; u64 cache_mask;
}; };
......
...@@ -1205,61 +1205,69 @@ static int intel_pt_walk_insn(struct intel_pt_decoder *decoder, ...@@ -1205,61 +1205,69 @@ static int intel_pt_walk_insn(struct intel_pt_decoder *decoder,
static bool intel_pt_fup_event(struct intel_pt_decoder *decoder) static bool intel_pt_fup_event(struct intel_pt_decoder *decoder)
{ {
enum intel_pt_sample_type type = decoder->state.type;
bool ret = false; bool ret = false;
decoder->state.type &= ~INTEL_PT_BRANCH;
if (decoder->set_fup_tx_flags) { if (decoder->set_fup_tx_flags) {
decoder->set_fup_tx_flags = false; decoder->set_fup_tx_flags = false;
decoder->tx_flags = decoder->fup_tx_flags; decoder->tx_flags = decoder->fup_tx_flags;
decoder->state.type = INTEL_PT_TRANSACTION; decoder->state.type |= INTEL_PT_TRANSACTION;
if (decoder->fup_tx_flags & INTEL_PT_ABORT_TX) if (decoder->fup_tx_flags & INTEL_PT_ABORT_TX)
decoder->state.type |= INTEL_PT_BRANCH; decoder->state.type |= INTEL_PT_BRANCH;
decoder->state.from_ip = decoder->ip;
decoder->state.to_ip = 0;
decoder->state.flags = decoder->fup_tx_flags; decoder->state.flags = decoder->fup_tx_flags;
return true; ret = true;
} }
if (decoder->set_fup_ptw) { if (decoder->set_fup_ptw) {
decoder->set_fup_ptw = false; decoder->set_fup_ptw = false;
decoder->state.type = INTEL_PT_PTW; decoder->state.type |= INTEL_PT_PTW;
decoder->state.flags |= INTEL_PT_FUP_IP; decoder->state.flags |= INTEL_PT_FUP_IP;
decoder->state.from_ip = decoder->ip;
decoder->state.to_ip = 0;
decoder->state.ptw_payload = decoder->fup_ptw_payload; decoder->state.ptw_payload = decoder->fup_ptw_payload;
return true; ret = true;
} }
if (decoder->set_fup_mwait) { if (decoder->set_fup_mwait) {
decoder->set_fup_mwait = false; decoder->set_fup_mwait = false;
decoder->state.type = INTEL_PT_MWAIT_OP; decoder->state.type |= INTEL_PT_MWAIT_OP;
decoder->state.from_ip = decoder->ip;
decoder->state.to_ip = 0;
decoder->state.mwait_payload = decoder->fup_mwait_payload; decoder->state.mwait_payload = decoder->fup_mwait_payload;
ret = true; ret = true;
} }
if (decoder->set_fup_pwre) { if (decoder->set_fup_pwre) {
decoder->set_fup_pwre = false; decoder->set_fup_pwre = false;
decoder->state.type |= INTEL_PT_PWR_ENTRY; decoder->state.type |= INTEL_PT_PWR_ENTRY;
decoder->state.type &= ~INTEL_PT_BRANCH;
decoder->state.from_ip = decoder->ip;
decoder->state.to_ip = 0;
decoder->state.pwre_payload = decoder->fup_pwre_payload; decoder->state.pwre_payload = decoder->fup_pwre_payload;
ret = true; ret = true;
} }
if (decoder->set_fup_exstop) { if (decoder->set_fup_exstop) {
decoder->set_fup_exstop = false; decoder->set_fup_exstop = false;
decoder->state.type |= INTEL_PT_EX_STOP; decoder->state.type |= INTEL_PT_EX_STOP;
decoder->state.type &= ~INTEL_PT_BRANCH;
decoder->state.flags |= INTEL_PT_FUP_IP; decoder->state.flags |= INTEL_PT_FUP_IP;
decoder->state.from_ip = decoder->ip;
decoder->state.to_ip = 0;
ret = true; ret = true;
} }
if (decoder->set_fup_bep) { if (decoder->set_fup_bep) {
decoder->set_fup_bep = false; decoder->set_fup_bep = false;
decoder->state.type |= INTEL_PT_BLK_ITEMS; decoder->state.type |= INTEL_PT_BLK_ITEMS;
decoder->state.type &= ~INTEL_PT_BRANCH; ret = true;
}
if (decoder->overflow) {
decoder->overflow = false;
if (!ret && !decoder->pge) {
if (decoder->hop) {
decoder->state.type = 0;
decoder->pkt_state = INTEL_PT_STATE_RESAMPLE;
}
decoder->pge = true;
decoder->state.type |= INTEL_PT_BRANCH | INTEL_PT_TRACE_BEGIN;
decoder->state.from_ip = 0;
decoder->state.to_ip = decoder->ip;
return true;
}
}
if (ret) {
decoder->state.from_ip = decoder->ip; decoder->state.from_ip = decoder->ip;
decoder->state.to_ip = 0; decoder->state.to_ip = 0;
ret = true; } else {
decoder->state.type = type;
} }
return ret; return ret;
} }
...@@ -1608,7 +1616,16 @@ static int intel_pt_overflow(struct intel_pt_decoder *decoder) ...@@ -1608,7 +1616,16 @@ static int intel_pt_overflow(struct intel_pt_decoder *decoder)
intel_pt_clear_tx_flags(decoder); intel_pt_clear_tx_flags(decoder);
intel_pt_set_nr(decoder); intel_pt_set_nr(decoder);
decoder->timestamp_insn_cnt = 0; decoder->timestamp_insn_cnt = 0;
decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
decoder->state.from_ip = decoder->ip;
decoder->ip = 0;
decoder->pge = false;
decoder->set_fup_tx_flags = false;
decoder->set_fup_ptw = false;
decoder->set_fup_mwait = false;
decoder->set_fup_pwre = false;
decoder->set_fup_exstop = false;
decoder->set_fup_bep = false;
decoder->overflow = true; decoder->overflow = true;
return -EOVERFLOW; return -EOVERFLOW;
} }
...@@ -2666,6 +2683,8 @@ static int intel_pt_scan_for_psb(struct intel_pt_decoder *decoder); ...@@ -2666,6 +2683,8 @@ static int intel_pt_scan_for_psb(struct intel_pt_decoder *decoder);
/* Hop mode: Ignore TNT, do not walk code, but get ip from FUPs and TIPs */ /* Hop mode: Ignore TNT, do not walk code, but get ip from FUPs and TIPs */
static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, int *err) static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, int *err)
{ {
*err = 0;
/* Leap from PSB to PSB, getting ip from FUP within PSB+ */ /* Leap from PSB to PSB, getting ip from FUP within PSB+ */
if (decoder->leap && !decoder->in_psb && decoder->packet.type != INTEL_PT_PSB) { if (decoder->leap && !decoder->in_psb && decoder->packet.type != INTEL_PT_PSB) {
*err = intel_pt_scan_for_psb(decoder); *err = intel_pt_scan_for_psb(decoder);
...@@ -2678,6 +2697,7 @@ static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, in ...@@ -2678,6 +2697,7 @@ static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, in
return HOP_IGNORE; return HOP_IGNORE;
case INTEL_PT_TIP_PGD: case INTEL_PT_TIP_PGD:
decoder->pge = false;
if (!decoder->packet.count) { if (!decoder->packet.count) {
intel_pt_set_nr(decoder); intel_pt_set_nr(decoder);
return HOP_IGNORE; return HOP_IGNORE;
...@@ -2705,18 +2725,21 @@ static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, in ...@@ -2705,18 +2725,21 @@ static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, in
if (!decoder->packet.count) if (!decoder->packet.count)
return HOP_IGNORE; return HOP_IGNORE;
intel_pt_set_ip(decoder); intel_pt_set_ip(decoder);
if (intel_pt_fup_event(decoder)) if (decoder->set_fup_mwait || decoder->set_fup_pwre)
return HOP_RETURN; *no_tip = true;
if (!decoder->branch_enable) if (!decoder->branch_enable || !decoder->pge)
*no_tip = true; *no_tip = true;
if (*no_tip) { if (*no_tip) {
decoder->state.type = INTEL_PT_INSTRUCTION; decoder->state.type = INTEL_PT_INSTRUCTION;
decoder->state.from_ip = decoder->ip; decoder->state.from_ip = decoder->ip;
decoder->state.to_ip = 0; decoder->state.to_ip = 0;
intel_pt_fup_event(decoder);
return HOP_RETURN; return HOP_RETURN;
} }
intel_pt_fup_event(decoder);
decoder->state.type |= INTEL_PT_INSTRUCTION | INTEL_PT_BRANCH;
*err = intel_pt_walk_fup_tip(decoder); *err = intel_pt_walk_fup_tip(decoder);
if (!*err) if (!*err && decoder->state.to_ip)
decoder->pkt_state = INTEL_PT_STATE_RESAMPLE; decoder->pkt_state = INTEL_PT_STATE_RESAMPLE;
return HOP_RETURN; return HOP_RETURN;
...@@ -2897,7 +2920,7 @@ static bool intel_pt_psb_with_fup(struct intel_pt_decoder *decoder, int *err) ...@@ -2897,7 +2920,7 @@ static bool intel_pt_psb_with_fup(struct intel_pt_decoder *decoder, int *err)
{ {
struct intel_pt_psb_info data = { .fup = false }; struct intel_pt_psb_info data = { .fup = false };
if (!decoder->branch_enable || !decoder->pge) if (!decoder->branch_enable)
return false; return false;
intel_pt_pkt_lookahead(decoder, intel_pt_psb_lookahead_cb, &data); intel_pt_pkt_lookahead(decoder, intel_pt_psb_lookahead_cb, &data);
...@@ -2924,6 +2947,7 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder) ...@@ -2924,6 +2947,7 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder)
if (err) if (err)
return err; return err;
next: next:
err = 0;
if (decoder->cyc_threshold) { if (decoder->cyc_threshold) {
if (decoder->sample_cyc && last_packet_type != INTEL_PT_CYC) if (decoder->sample_cyc && last_packet_type != INTEL_PT_CYC)
decoder->sample_cyc = false; decoder->sample_cyc = false;
...@@ -2962,6 +2986,7 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder) ...@@ -2962,6 +2986,7 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder)
case INTEL_PT_TIP_PGE: { case INTEL_PT_TIP_PGE: {
decoder->pge = true; decoder->pge = true;
decoder->overflow = false;
intel_pt_mtc_cyc_cnt_pge(decoder); intel_pt_mtc_cyc_cnt_pge(decoder);
intel_pt_set_nr(decoder); intel_pt_set_nr(decoder);
if (decoder->packet.count == 0) { if (decoder->packet.count == 0) {
...@@ -2999,7 +3024,7 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder) ...@@ -2999,7 +3024,7 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder)
break; break;
} }
intel_pt_set_last_ip(decoder); intel_pt_set_last_ip(decoder);
if (!decoder->branch_enable) { if (!decoder->branch_enable || !decoder->pge) {
decoder->ip = decoder->last_ip; decoder->ip = decoder->last_ip;
if (intel_pt_fup_event(decoder)) if (intel_pt_fup_event(decoder))
return 0; return 0;
...@@ -3467,10 +3492,10 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder) ...@@ -3467,10 +3492,10 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder)
decoder->set_fup_pwre = false; decoder->set_fup_pwre = false;
decoder->set_fup_exstop = false; decoder->set_fup_exstop = false;
decoder->set_fup_bep = false; decoder->set_fup_bep = false;
decoder->overflow = false;
if (!decoder->branch_enable) { if (!decoder->branch_enable) {
decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
decoder->overflow = false;
decoder->state.type = 0; /* Do not have a sample */ decoder->state.type = 0; /* Do not have a sample */
return 0; return 0;
} }
...@@ -3485,7 +3510,6 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder) ...@@ -3485,7 +3510,6 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder)
decoder->pkt_state = INTEL_PT_STATE_RESAMPLE; decoder->pkt_state = INTEL_PT_STATE_RESAMPLE;
else else
decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
decoder->overflow = false;
decoder->state.from_ip = 0; decoder->state.from_ip = 0;
decoder->state.to_ip = decoder->ip; decoder->state.to_ip = decoder->ip;
...@@ -3607,7 +3631,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder) ...@@ -3607,7 +3631,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder)
} }
decoder->have_last_ip = true; decoder->have_last_ip = true;
decoder->pkt_state = INTEL_PT_STATE_NO_IP; decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
err = intel_pt_walk_psb(decoder); err = intel_pt_walk_psb(decoder);
if (err) if (err)
...@@ -3704,7 +3728,8 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) ...@@ -3704,7 +3728,8 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
if (err) { if (err) {
decoder->state.err = intel_pt_ext_err(err); decoder->state.err = intel_pt_ext_err(err);
decoder->state.from_ip = decoder->ip; if (err != -EOVERFLOW)
decoder->state.from_ip = decoder->ip;
intel_pt_update_sample_time(decoder); intel_pt_update_sample_time(decoder);
decoder->sample_tot_cyc_cnt = decoder->tot_cyc_cnt; decoder->sample_tot_cyc_cnt = decoder->tot_cyc_cnt;
intel_pt_set_nr(decoder); intel_pt_set_nr(decoder);
......
...@@ -2565,6 +2565,7 @@ static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp) ...@@ -2565,6 +2565,7 @@ static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp)
ptq->sync_switch = false; ptq->sync_switch = false;
intel_pt_next_tid(pt, ptq); intel_pt_next_tid(pt, ptq);
} }
ptq->timestamp = state->est_timestamp;
if (pt->synth_opts.errors) { if (pt->synth_opts.errors) {
err = intel_ptq_synth_error(ptq, state); err = intel_ptq_synth_error(ptq, state);
if (err) if (err)
......
...@@ -25,6 +25,9 @@ int perf_reg_value(u64 *valp, struct regs_dump *regs, int id) ...@@ -25,6 +25,9 @@ int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
int i, idx = 0; int i, idx = 0;
u64 mask = regs->mask; u64 mask = regs->mask;
if ((u64)id >= PERF_SAMPLE_REGS_CACHE_SIZE)
return -EINVAL;
if (regs->cache_mask & (1ULL << id)) if (regs->cache_mask & (1ULL << id))
goto out; goto out;
......
...@@ -461,7 +461,7 @@ get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name) ...@@ -461,7 +461,7 @@ get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name)
struct tep_event *tp_format; struct tep_event *tp_format;
tp_format = trace_event__tp_format_id(evsel->core.attr.config); tp_format = trace_event__tp_format_id(evsel->core.attr.config);
if (!tp_format) if (IS_ERR_OR_NULL(tp_format))
return NULL; return NULL;
evsel->tp_format = tp_format; evsel->tp_format = tp_format;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment