Skip to content

Commit c4ff10e

Browse files
committed
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Ingo Molnar: "Misc fixes: a BTS fix, a PT NMI handling fix, a PMU sysfs fix and an SRCU annotation" * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf/core: Add SRCU annotation for pmus list walk perf/x86/intel: Fix PT PMI handling perf/x86/intel/bts: Fix the use of page_private() perf/x86: Fix potential out-of-bounds access
2 parents 6c1c79a + 9f0bff1 commit c4ff10e

File tree

3 files changed

+27
-10
lines changed

3 files changed

+27
-10
lines changed

arch/x86/events/core.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ int x86_add_exclusive(unsigned int what)
376376
* LBR and BTS are still mutually exclusive.
377377
*/
378378
if (x86_pmu.lbr_pt_coexist && what == x86_lbr_exclusive_pt)
379-
return 0;
379+
goto out;
380380

381381
if (!atomic_inc_not_zero(&x86_pmu.lbr_exclusive[what])) {
382382
mutex_lock(&pmc_reserve_mutex);
@@ -388,6 +388,7 @@ int x86_add_exclusive(unsigned int what)
388388
mutex_unlock(&pmc_reserve_mutex);
389389
}
390390

391+
out:
391392
atomic_inc(&active_events);
392393
return 0;
393394

@@ -398,11 +399,15 @@ int x86_add_exclusive(unsigned int what)
398399

399400
void x86_del_exclusive(unsigned int what)
400401
{
402+
atomic_dec(&active_events);
403+
404+
/*
405+
* See the comment in x86_add_exclusive().
406+
*/
401407
if (x86_pmu.lbr_pt_coexist && what == x86_lbr_exclusive_pt)
402408
return;
403409

404410
atomic_dec(&x86_pmu.lbr_exclusive[what]);
405-
atomic_dec(&active_events);
406411
}
407412

408413
int x86_setup_perfctr(struct perf_event *event)
@@ -1642,9 +1647,12 @@ static struct attribute_group x86_pmu_format_group __ro_after_init = {
16421647

16431648
ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr, char *page)
16441649
{
1645-
struct perf_pmu_events_attr *pmu_attr = \
1650+
struct perf_pmu_events_attr *pmu_attr =
16461651
container_of(attr, struct perf_pmu_events_attr, attr);
1647-
u64 config = x86_pmu.event_map(pmu_attr->id);
1652+
u64 config = 0;
1653+
1654+
if (pmu_attr->id < x86_pmu.max_events)
1655+
config = x86_pmu.event_map(pmu_attr->id);
16481656

16491657
/* string trumps id */
16501658
if (pmu_attr->event_str)
@@ -1713,6 +1721,9 @@ is_visible(struct kobject *kobj, struct attribute *attr, int idx)
17131721
{
17141722
struct perf_pmu_events_attr *pmu_attr;
17151723

1724+
if (idx >= x86_pmu.max_events)
1725+
return 0;
1726+
17161727
pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr.attr);
17171728
/* str trumps id */
17181729
return pmu_attr->event_str || x86_pmu.event_map(idx) ? attr->mode : 0;

arch/x86/events/intel/bts.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,17 @@ struct bts_buffer {
6363

6464
static struct pmu bts_pmu;
6565

66+
static int buf_nr_pages(struct page *page)
67+
{
68+
if (!PagePrivate(page))
69+
return 1;
70+
71+
return 1 << page_private(page);
72+
}
73+
6674
static size_t buf_size(struct page *page)
6775
{
68-
return 1 << (PAGE_SHIFT + page_private(page));
76+
return buf_nr_pages(page) * PAGE_SIZE;
6977
}
7078

7179
static void *
@@ -83,9 +91,7 @@ bts_buffer_setup_aux(struct perf_event *event, void **pages,
8391
/* count all the high order buffers */
8492
for (pg = 0, nbuf = 0; pg < nr_pages;) {
8593
page = virt_to_page(pages[pg]);
86-
if (WARN_ON_ONCE(!PagePrivate(page) && nr_pages > 1))
87-
return NULL;
88-
pg += 1 << page_private(page);
94+
pg += buf_nr_pages(page);
8995
nbuf++;
9096
}
9197

@@ -109,7 +115,7 @@ bts_buffer_setup_aux(struct perf_event *event, void **pages,
109115
unsigned int __nr_pages;
110116

111117
page = virt_to_page(pages[pg]);
112-
__nr_pages = PagePrivate(page) ? 1 << page_private(page) : 1;
118+
__nr_pages = buf_nr_pages(page);
113119
buf->buf[nbuf].page = page;
114120
buf->buf[nbuf].offset = offset;
115121
buf->buf[nbuf].displacement = (pad ? BTS_RECORD_SIZE - pad : 0);

kernel/events/core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10523,7 +10523,7 @@ static struct pmu *perf_init_event(struct perf_event *event)
1052310523
goto unlock;
1052410524
}
1052510525

10526-
list_for_each_entry_rcu(pmu, &pmus, entry) {
10526+
list_for_each_entry_rcu(pmu, &pmus, entry, lockdep_is_held(&pmus_srcu)) {
1052710527
ret = perf_try_init_event(pmu, event);
1052810528
if (!ret)
1052910529
goto unlock;

0 commit comments

Comments
 (0)