Skip to content

Commit 44744bb

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: "A kprobes and a perf compat ioctl fix" * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf: Handle compat ioctl kprobes: Skip kretprobe hit in NMI context to avoid deadlock
2 parents 959dc25 + b3f2078 commit 44744bb

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

kernel/events/core.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <linux/cgroup.h>
4242
#include <linux/module.h>
4343
#include <linux/mman.h>
44+
#include <linux/compat.h>
4445

4546
#include "internal.h"
4647

@@ -3717,6 +3718,26 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
37173718
return 0;
37183719
}
37193720

3721+
#ifdef CONFIG_COMPAT
3722+
static long perf_compat_ioctl(struct file *file, unsigned int cmd,
3723+
unsigned long arg)
3724+
{
3725+
switch (_IOC_NR(cmd)) {
3726+
case _IOC_NR(PERF_EVENT_IOC_SET_FILTER):
3727+
case _IOC_NR(PERF_EVENT_IOC_ID):
3728+
/* Fix up pointer size (usually 4 -> 8 in 32-on-64-bit case */
3729+
if (_IOC_SIZE(cmd) == sizeof(compat_uptr_t)) {
3730+
cmd &= ~IOCSIZE_MASK;
3731+
cmd |= sizeof(void *) << IOCSIZE_SHIFT;
3732+
}
3733+
break;
3734+
}
3735+
return perf_ioctl(file, cmd, arg);
3736+
}
3737+
#else
3738+
# define perf_compat_ioctl NULL
3739+
#endif
3740+
37203741
int perf_event_task_enable(void)
37213742
{
37223743
struct perf_event *event;
@@ -4222,7 +4243,7 @@ static const struct file_operations perf_fops = {
42224243
.read = perf_read,
42234244
.poll = perf_poll,
42244245
.unlocked_ioctl = perf_ioctl,
4225-
.compat_ioctl = perf_ioctl,
4246+
.compat_ioctl = perf_compat_ioctl,
42264247
.mmap = perf_mmap,
42274248
.fasync = perf_fasync,
42284249
};

kernel/kprobes.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1778,7 +1778,18 @@ static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs)
17781778
unsigned long hash, flags = 0;
17791779
struct kretprobe_instance *ri;
17801780

1781-
/*TODO: consider to only swap the RA after the last pre_handler fired */
1781+
/*
1782+
* To avoid deadlocks, prohibit return probing in NMI contexts,
1783+
* just skip the probe and increase the (inexact) 'nmissed'
1784+
* statistical counter, so that the user is informed that
1785+
* something happened:
1786+
*/
1787+
if (unlikely(in_nmi())) {
1788+
rp->nmissed++;
1789+
return 0;
1790+
}
1791+
1792+
/* TODO: consider to only swap the RA after the last pre_handler fired */
17821793
hash = hash_ptr(current, KPROBE_HASH_BITS);
17831794
raw_spin_lock_irqsave(&rp->lock, flags);
17841795
if (!hlist_empty(&rp->free_instances)) {

0 commit comments

Comments
 (0)