Skip to content

Commit c3bf8a1

Browse files
committed
Merge tag 'perf_urgent_for_v5.17_rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Borislav Petkov: - Intel/PT: filters could crash the kernel - Intel: default disable the PMU for SMM, some new-ish EFI firmware has started using CPL3 and the PMU CPL filters don't discriminate against SMM, meaning that CPL3 (userspace only) events now also count EFI/SMM cycles. - Fixup for perf_event_attr::sig_data * tag 'perf_urgent_for_v5.17_rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf/x86/intel/pt: Fix crash with stop filters in single-range mode perf: uapi: Document perf_event_attr::sig_data truncation on 32 bit architectures selftests/perf_events: Test modification of perf_event_attr::sig_data perf: Copy perf_event_attr::sig_data on modification x86/perf: Default set FREEZE_ON_SMI for all
2 parents aeabe1e + 1d90934 commit c3bf8a1

File tree

5 files changed

+43
-10
lines changed

5 files changed

+43
-10
lines changed

arch/x86/events/intel/core.c

+13
Original file line numberDiff line numberDiff line change
@@ -4703,6 +4703,19 @@ static __initconst const struct x86_pmu intel_pmu = {
47034703
.lbr_read = intel_pmu_lbr_read_64,
47044704
.lbr_save = intel_pmu_lbr_save,
47054705
.lbr_restore = intel_pmu_lbr_restore,
4706+
4707+
/*
4708+
* SMM has access to all 4 rings and while traditionally SMM code only
4709+
* ran in CPL0, 2021-era firmware is starting to make use of CPL3 in SMM.
4710+
*
4711+
* Since the EVENTSEL.{USR,OS} CPL filtering makes no distinction
4712+
* between SMM or not, this results in what should be pure userspace
4713+
* counters including SMM data.
4714+
*
4715+
* This is a clear privilege issue, therefore globally disable
4716+
* counting SMM by default.
4717+
*/
4718+
.attr_freeze_on_smi = 1,
47064719
};
47074720

47084721
static __init void intel_clovertown_quirk(void)

arch/x86/events/intel/pt.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -897,8 +897,9 @@ static void pt_handle_status(struct pt *pt)
897897
* means we are already losing data; need to let the decoder
898898
* know.
899899
*/
900-
if (!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries) ||
901-
buf->output_off == pt_buffer_region_size(buf)) {
900+
if (!buf->single &&
901+
(!intel_pt_validate_hw_cap(PT_CAP_topa_multiple_entries) ||
902+
buf->output_off == pt_buffer_region_size(buf))) {
902903
perf_aux_output_flag(&pt->handle,
903904
PERF_AUX_FLAG_TRUNCATED);
904905
advance++;

include/uapi/linux/perf_event.h

+2
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,8 @@ struct perf_event_attr {
465465
/*
466466
* User provided data if sigtrap=1, passed back to user via
467467
* siginfo_t::si_perf_data, e.g. to permit user to identify the event.
468+
* Note, siginfo_t::si_perf_data is long-sized, and sig_data will be
469+
* truncated accordingly on 32 bit architectures.
468470
*/
469471
__u64 sig_data;
470472
};

kernel/events/core.c

+16
Original file line numberDiff line numberDiff line change
@@ -3238,6 +3238,15 @@ static int perf_event_modify_breakpoint(struct perf_event *bp,
32383238
return err;
32393239
}
32403240

3241+
/*
3242+
* Copy event-type-independent attributes that may be modified.
3243+
*/
3244+
static void perf_event_modify_copy_attr(struct perf_event_attr *to,
3245+
const struct perf_event_attr *from)
3246+
{
3247+
to->sig_data = from->sig_data;
3248+
}
3249+
32413250
static int perf_event_modify_attr(struct perf_event *event,
32423251
struct perf_event_attr *attr)
32433252
{
@@ -3260,10 +3269,17 @@ static int perf_event_modify_attr(struct perf_event *event,
32603269
WARN_ON_ONCE(event->ctx->parent_ctx);
32613270

32623271
mutex_lock(&event->child_mutex);
3272+
/*
3273+
* Event-type-independent attributes must be copied before event-type
3274+
* modification, which will validate that final attributes match the
3275+
* source attributes after all relevant attributes have been copied.
3276+
*/
3277+
perf_event_modify_copy_attr(&event->attr, attr);
32633278
err = func(event, attr);
32643279
if (err)
32653280
goto out;
32663281
list_for_each_entry(child, &event->child_list, child_list) {
3282+
perf_event_modify_copy_attr(&child->attr, attr);
32673283
err = func(child, attr);
32683284
if (err)
32693285
goto out;

tools/testing/selftests/perf_events/sigtrap_threads.c

+9-8
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,10 @@ static struct {
4444
} ctx;
4545

4646
/* Unique value to check si_perf_data is correctly set from perf_event_attr::sig_data. */
47-
#define TEST_SIG_DATA(addr) (~(unsigned long)(addr))
47+
#define TEST_SIG_DATA(addr, id) (~(unsigned long)(addr) + id)
4848

49-
static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr)
49+
static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr,
50+
unsigned long id)
5051
{
5152
struct perf_event_attr attr = {
5253
.type = PERF_TYPE_BREAKPOINT,
@@ -60,7 +61,7 @@ static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr)
6061
.inherit_thread = 1, /* ... but only cloned with CLONE_THREAD. */
6162
.remove_on_exec = 1, /* Required by sigtrap. */
6263
.sigtrap = 1, /* Request synchronous SIGTRAP on event. */
63-
.sig_data = TEST_SIG_DATA(addr),
64+
.sig_data = TEST_SIG_DATA(addr, id),
6465
};
6566
return attr;
6667
}
@@ -110,7 +111,7 @@ FIXTURE(sigtrap_threads)
110111

111112
FIXTURE_SETUP(sigtrap_threads)
112113
{
113-
struct perf_event_attr attr = make_event_attr(false, &ctx.iterate_on);
114+
struct perf_event_attr attr = make_event_attr(false, &ctx.iterate_on, 0);
114115
struct sigaction action = {};
115116
int i;
116117

@@ -165,7 +166,7 @@ TEST_F(sigtrap_threads, enable_event)
165166
EXPECT_EQ(ctx.tids_want_signal, 0);
166167
EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on);
167168
EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT);
168-
EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on));
169+
EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 0));
169170

170171
/* Check enabled for parent. */
171172
ctx.iterate_on = 0;
@@ -175,7 +176,7 @@ TEST_F(sigtrap_threads, enable_event)
175176
/* Test that modification propagates to all inherited events. */
176177
TEST_F(sigtrap_threads, modify_and_enable_event)
177178
{
178-
struct perf_event_attr new_attr = make_event_attr(true, &ctx.iterate_on);
179+
struct perf_event_attr new_attr = make_event_attr(true, &ctx.iterate_on, 42);
179180

180181
EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &new_attr), 0);
181182
run_test_threads(_metadata, self);
@@ -184,7 +185,7 @@ TEST_F(sigtrap_threads, modify_and_enable_event)
184185
EXPECT_EQ(ctx.tids_want_signal, 0);
185186
EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on);
186187
EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT);
187-
EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on));
188+
EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 42));
188189

189190
/* Check enabled for parent. */
190191
ctx.iterate_on = 0;
@@ -204,7 +205,7 @@ TEST_F(sigtrap_threads, signal_stress)
204205
EXPECT_EQ(ctx.tids_want_signal, 0);
205206
EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on);
206207
EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT);
207-
EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on));
208+
EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 0));
208209
}
209210

210211
TEST_HARNESS_MAIN

0 commit comments

Comments
 (0)