Skip to content

Commit bbdff6d

Browse files
committed
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
2 parents eccea80 + 9937e8d commit bbdff6d

File tree

5 files changed

+64
-32
lines changed

5 files changed

+64
-32
lines changed

tools/perf/util/event.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,16 @@ struct perf_event_attr;
4444
/* perf sample has 16 bits size limit */
4545
#define PERF_SAMPLE_MAX_SIZE (1 << 16)
4646

47+
/* number of register is bound by the number of bits in regs_dump::mask (64) */
48+
#define PERF_SAMPLE_REGS_CACHE_SIZE (8 * sizeof(u64))
49+
4750
struct regs_dump {
4851
u64 abi;
4952
u64 mask;
5053
u64 *regs;
5154

5255
/* Cached values/mask filled by first register access. */
53-
u64 cache_regs[PERF_REGS_MAX];
56+
u64 cache_regs[PERF_SAMPLE_REGS_CACHE_SIZE];
5457
u64 cache_mask;
5558
};
5659

tools/perf/util/intel-pt-decoder/intel-pt-decoder.c

Lines changed: 55 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,61 +1205,69 @@ static int intel_pt_walk_insn(struct intel_pt_decoder *decoder,
12051205

12061206
static bool intel_pt_fup_event(struct intel_pt_decoder *decoder)
12071207
{
1208+
enum intel_pt_sample_type type = decoder->state.type;
12081209
bool ret = false;
12091210

1211+
decoder->state.type &= ~INTEL_PT_BRANCH;
1212+
12101213
if (decoder->set_fup_tx_flags) {
12111214
decoder->set_fup_tx_flags = false;
12121215
decoder->tx_flags = decoder->fup_tx_flags;
1213-
decoder->state.type = INTEL_PT_TRANSACTION;
1216+
decoder->state.type |= INTEL_PT_TRANSACTION;
12141217
if (decoder->fup_tx_flags & INTEL_PT_ABORT_TX)
12151218
decoder->state.type |= INTEL_PT_BRANCH;
1216-
decoder->state.from_ip = decoder->ip;
1217-
decoder->state.to_ip = 0;
12181219
decoder->state.flags = decoder->fup_tx_flags;
1219-
return true;
1220+
ret = true;
12201221
}
12211222
if (decoder->set_fup_ptw) {
12221223
decoder->set_fup_ptw = false;
1223-
decoder->state.type = INTEL_PT_PTW;
1224+
decoder->state.type |= INTEL_PT_PTW;
12241225
decoder->state.flags |= INTEL_PT_FUP_IP;
1225-
decoder->state.from_ip = decoder->ip;
1226-
decoder->state.to_ip = 0;
12271226
decoder->state.ptw_payload = decoder->fup_ptw_payload;
1228-
return true;
1227+
ret = true;
12291228
}
12301229
if (decoder->set_fup_mwait) {
12311230
decoder->set_fup_mwait = false;
1232-
decoder->state.type = INTEL_PT_MWAIT_OP;
1233-
decoder->state.from_ip = decoder->ip;
1234-
decoder->state.to_ip = 0;
1231+
decoder->state.type |= INTEL_PT_MWAIT_OP;
12351232
decoder->state.mwait_payload = decoder->fup_mwait_payload;
12361233
ret = true;
12371234
}
12381235
if (decoder->set_fup_pwre) {
12391236
decoder->set_fup_pwre = false;
12401237
decoder->state.type |= INTEL_PT_PWR_ENTRY;
1241-
decoder->state.type &= ~INTEL_PT_BRANCH;
1242-
decoder->state.from_ip = decoder->ip;
1243-
decoder->state.to_ip = 0;
12441238
decoder->state.pwre_payload = decoder->fup_pwre_payload;
12451239
ret = true;
12461240
}
12471241
if (decoder->set_fup_exstop) {
12481242
decoder->set_fup_exstop = false;
12491243
decoder->state.type |= INTEL_PT_EX_STOP;
1250-
decoder->state.type &= ~INTEL_PT_BRANCH;
12511244
decoder->state.flags |= INTEL_PT_FUP_IP;
1252-
decoder->state.from_ip = decoder->ip;
1253-
decoder->state.to_ip = 0;
12541245
ret = true;
12551246
}
12561247
if (decoder->set_fup_bep) {
12571248
decoder->set_fup_bep = false;
12581249
decoder->state.type |= INTEL_PT_BLK_ITEMS;
1259-
decoder->state.type &= ~INTEL_PT_BRANCH;
1250+
ret = true;
1251+
}
1252+
if (decoder->overflow) {
1253+
decoder->overflow = false;
1254+
if (!ret && !decoder->pge) {
1255+
if (decoder->hop) {
1256+
decoder->state.type = 0;
1257+
decoder->pkt_state = INTEL_PT_STATE_RESAMPLE;
1258+
}
1259+
decoder->pge = true;
1260+
decoder->state.type |= INTEL_PT_BRANCH | INTEL_PT_TRACE_BEGIN;
1261+
decoder->state.from_ip = 0;
1262+
decoder->state.to_ip = decoder->ip;
1263+
return true;
1264+
}
1265+
}
1266+
if (ret) {
12601267
decoder->state.from_ip = decoder->ip;
12611268
decoder->state.to_ip = 0;
1262-
ret = true;
1269+
} else {
1270+
decoder->state.type = type;
12631271
}
12641272
return ret;
12651273
}
@@ -1608,7 +1616,16 @@ static int intel_pt_overflow(struct intel_pt_decoder *decoder)
16081616
intel_pt_clear_tx_flags(decoder);
16091617
intel_pt_set_nr(decoder);
16101618
decoder->timestamp_insn_cnt = 0;
1611-
decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
1619+
decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1620+
decoder->state.from_ip = decoder->ip;
1621+
decoder->ip = 0;
1622+
decoder->pge = false;
1623+
decoder->set_fup_tx_flags = false;
1624+
decoder->set_fup_ptw = false;
1625+
decoder->set_fup_mwait = false;
1626+
decoder->set_fup_pwre = false;
1627+
decoder->set_fup_exstop = false;
1628+
decoder->set_fup_bep = false;
16121629
decoder->overflow = true;
16131630
return -EOVERFLOW;
16141631
}
@@ -2666,6 +2683,8 @@ static int intel_pt_scan_for_psb(struct intel_pt_decoder *decoder);
26662683
/* Hop mode: Ignore TNT, do not walk code, but get ip from FUPs and TIPs */
26672684
static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, int *err)
26682685
{
2686+
*err = 0;
2687+
26692688
/* Leap from PSB to PSB, getting ip from FUP within PSB+ */
26702689
if (decoder->leap && !decoder->in_psb && decoder->packet.type != INTEL_PT_PSB) {
26712690
*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
26782697
return HOP_IGNORE;
26792698

26802699
case INTEL_PT_TIP_PGD:
2700+
decoder->pge = false;
26812701
if (!decoder->packet.count) {
26822702
intel_pt_set_nr(decoder);
26832703
return HOP_IGNORE;
@@ -2705,18 +2725,21 @@ static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, in
27052725
if (!decoder->packet.count)
27062726
return HOP_IGNORE;
27072727
intel_pt_set_ip(decoder);
2708-
if (intel_pt_fup_event(decoder))
2709-
return HOP_RETURN;
2710-
if (!decoder->branch_enable)
2728+
if (decoder->set_fup_mwait || decoder->set_fup_pwre)
2729+
*no_tip = true;
2730+
if (!decoder->branch_enable || !decoder->pge)
27112731
*no_tip = true;
27122732
if (*no_tip) {
27132733
decoder->state.type = INTEL_PT_INSTRUCTION;
27142734
decoder->state.from_ip = decoder->ip;
27152735
decoder->state.to_ip = 0;
2736+
intel_pt_fup_event(decoder);
27162737
return HOP_RETURN;
27172738
}
2739+
intel_pt_fup_event(decoder);
2740+
decoder->state.type |= INTEL_PT_INSTRUCTION | INTEL_PT_BRANCH;
27182741
*err = intel_pt_walk_fup_tip(decoder);
2719-
if (!*err)
2742+
if (!*err && decoder->state.to_ip)
27202743
decoder->pkt_state = INTEL_PT_STATE_RESAMPLE;
27212744
return HOP_RETURN;
27222745

@@ -2897,7 +2920,7 @@ static bool intel_pt_psb_with_fup(struct intel_pt_decoder *decoder, int *err)
28972920
{
28982921
struct intel_pt_psb_info data = { .fup = false };
28992922

2900-
if (!decoder->branch_enable || !decoder->pge)
2923+
if (!decoder->branch_enable)
29012924
return false;
29022925

29032926
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)
29242947
if (err)
29252948
return err;
29262949
next:
2950+
err = 0;
29272951
if (decoder->cyc_threshold) {
29282952
if (decoder->sample_cyc && last_packet_type != INTEL_PT_CYC)
29292953
decoder->sample_cyc = false;
@@ -2962,6 +2986,7 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder)
29622986

29632987
case INTEL_PT_TIP_PGE: {
29642988
decoder->pge = true;
2989+
decoder->overflow = false;
29652990
intel_pt_mtc_cyc_cnt_pge(decoder);
29662991
intel_pt_set_nr(decoder);
29672992
if (decoder->packet.count == 0) {
@@ -2999,7 +3024,7 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder)
29993024
break;
30003025
}
30013026
intel_pt_set_last_ip(decoder);
3002-
if (!decoder->branch_enable) {
3027+
if (!decoder->branch_enable || !decoder->pge) {
30033028
decoder->ip = decoder->last_ip;
30043029
if (intel_pt_fup_event(decoder))
30053030
return 0;
@@ -3467,10 +3492,10 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder)
34673492
decoder->set_fup_pwre = false;
34683493
decoder->set_fup_exstop = false;
34693494
decoder->set_fup_bep = false;
3495+
decoder->overflow = false;
34703496

34713497
if (!decoder->branch_enable) {
34723498
decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
3473-
decoder->overflow = false;
34743499
decoder->state.type = 0; /* Do not have a sample */
34753500
return 0;
34763501
}
@@ -3485,7 +3510,6 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder)
34853510
decoder->pkt_state = INTEL_PT_STATE_RESAMPLE;
34863511
else
34873512
decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
3488-
decoder->overflow = false;
34893513

34903514
decoder->state.from_ip = 0;
34913515
decoder->state.to_ip = decoder->ip;
@@ -3607,7 +3631,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder)
36073631
}
36083632

36093633
decoder->have_last_ip = true;
3610-
decoder->pkt_state = INTEL_PT_STATE_NO_IP;
3634+
decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
36113635

36123636
err = intel_pt_walk_psb(decoder);
36133637
if (err)
@@ -3704,7 +3728,8 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
37043728

37053729
if (err) {
37063730
decoder->state.err = intel_pt_ext_err(err);
3707-
decoder->state.from_ip = decoder->ip;
3731+
if (err != -EOVERFLOW)
3732+
decoder->state.from_ip = decoder->ip;
37083733
intel_pt_update_sample_time(decoder);
37093734
decoder->sample_tot_cyc_cnt = decoder->tot_cyc_cnt;
37103735
intel_pt_set_nr(decoder);

tools/perf/util/intel-pt.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2565,6 +2565,7 @@ static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp)
25652565
ptq->sync_switch = false;
25662566
intel_pt_next_tid(pt, ptq);
25672567
}
2568+
ptq->timestamp = state->est_timestamp;
25682569
if (pt->synth_opts.errors) {
25692570
err = intel_ptq_synth_error(ptq, state);
25702571
if (err)

tools/perf/util/perf_regs.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
2525
int i, idx = 0;
2626
u64 mask = regs->mask;
2727

28+
if ((u64)id >= PERF_SAMPLE_REGS_CACHE_SIZE)
29+
return -EINVAL;
30+
2831
if (regs->cache_mask & (1ULL << id))
2932
goto out;
3033

tools/perf/util/python.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name)
461461
struct tep_event *tp_format;
462462

463463
tp_format = trace_event__tp_format_id(evsel->core.attr.config);
464-
if (!tp_format)
464+
if (IS_ERR_OR_NULL(tp_format))
465465
return NULL;
466466

467467
evsel->tp_format = tp_format;

0 commit comments

Comments
 (0)