Commit 6e7fc4c8 authored by Tad's avatar Tad
Browse files

Import many patches from debian/retired [1/x]

Imported in reverse up to CVE-2015-8950
Using cip-kernel-sec scripts

There are some mangled commits in CIP.txt with brackets that will need to be fixed in the scripts

scripts/import_debian.py
+    their_issues.update((os.path.basename(name), name) for name in
+                        glob.glob(IMPORT_DIR + '/retired/CVE-*')
parent 97a1b1ba
This source diff could not be displayed because it is too large. You can view the blob instead.
From a142e9641dcbead2c8845c949ad518acac96ed28 Mon Sep 17 00:00:00 2001
From: Marek Szyprowski <m.szyprowski@samsung.com>
Date: Thu, 23 Apr 2015 12:46:16 +0100
Subject: arm64: dma-mapping: always clear allocated buffers
[ Upstream commit 6829e274a623187c24f7cfc0e3d35f25d087fcc5 ]
Buffers allocated by dma_alloc_coherent() are always zeroed on Alpha,
ARM (32bit), MIPS, PowerPC, x86/x86_64 and probably other architectures.
It turned out that some drivers rely on this 'feature'. Allocated buffer
might be also exposed to userspace with dma_mmap() call, so clearing it
is desired from security point of view to avoid exposing random memory
to userspace. This patch unifies dma_alloc_coherent() behavior on ARM64
architecture with other implementations by unconditionally zeroing
allocated buffer.
Cc: <stable@vger.kernel.org> # v3.14+
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
---
arch/arm64/mm/dma-mapping.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index df34a70caca19..6efbb52cb92ee 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -67,8 +67,7 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page, gfp_t flags)
*ret_page = phys_to_page(phys);
ptr = (void *)val;
- if (flags & __GFP_ZERO)
- memset(ptr, 0, size);
+ memset(ptr, 0, size);
}
return ptr;
@@ -113,8 +112,7 @@ static void *__dma_alloc_coherent(struct device *dev, size_t size,
*dma_handle = phys_to_dma(dev, page_to_phys(page));
addr = page_address(page);
- if (flags & __GFP_ZERO)
- memset(addr, 0, size);
+ memset(addr, 0, size);
return addr;
} else {
return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
--
cgit 1.2.3-1.el7
......@@ -20,7 +20,7 @@ Signed-off-by: Will Deacon <will.deacon@arm.com>
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index ef7d112f5ce0..e0f14ee26b68 100644
index ef7d112f5ce0d..e0f14ee26b681 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -67,8 +67,7 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page, gfp_t flags)
......@@ -44,5 +44,5 @@ index ef7d112f5ce0..e0f14ee26b68 100644
} else {
return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
--
cgit 1.2-0.3.lf.el7
cgit 1.2.3-1.el7
From e00f6efe21bd34a7dd1cc3520f6155180e3d8125 Mon Sep 17 00:00:00 2001
From: "Suzuki K. Poulose" <suzuki.poulose@arm.com>
Date: Tue, 17 Mar 2015 18:14:59 +0000
Subject: arm64: perf: reject groups spanning multiple HW PMUs
commit 8fff105e13041e49b82f92eef034f363a6b1c071 upstream.
The perf core implicitly rejects events spanning multiple HW PMUs, as in
these cases the event->ctx will differ. However this validation is
performed after pmu::event_init() is called in perf_init_event(), and
thus pmu::event_init() may be called with a group leader from a
different HW PMU.
The ARM64 PMU driver does not take this fact into account, and when
validating groups assumes that it can call to_arm_pmu(event->pmu) for
any HW event. When the event in question is from another HW PMU this is
wrong, and results in dereferencing garbage.
This patch updates the ARM64 PMU driver to first test for and reject
events from other PMUs, moving the to_arm_pmu and related logic after
this test. Fixes a crash triggered by perf_fuzzer on Linux-4.0-rc2, with
a CCI PMU present:
Bad mode in Synchronous Abort handler detected, code 0x86000006 -- IABT (current EL)
CPU: 0 PID: 1371 Comm: perf_fuzzer Not tainted 3.19.0+ #249
Hardware name: V2F-1XV7 Cortex-A53x2 SMM (DT)
task: ffffffc07c73a280 ti: ffffffc07b0a0000 task.ti: ffffffc07b0a0000
PC is at 0x0
LR is at validate_event+0x90/0xa8
pc : [<0000000000000000>] lr : [<ffffffc000090228>] pstate: 00000145
sp : ffffffc07b0a3ba0
[< (null)>] (null)
[<ffffffc0000907d8>] armpmu_event_init+0x174/0x3cc
[<ffffffc00015d870>] perf_try_init_event+0x34/0x70
[<ffffffc000164094>] perf_init_event+0xe0/0x10c
[<ffffffc000164348>] perf_event_alloc+0x288/0x358
[<ffffffc000164c5c>] SyS_perf_event_open+0x464/0x98c
Code: bad PC value
Also cleans up the code to use the arm_pmu only when we know
that we are dealing with an arm pmu event.
Cc: Will Deacon <will.deacon@arm.com>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Peter Ziljstra (Intel) <peterz@infradead.org>
Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/arm64/kernel/perf_event.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index aa29ecb4f8004..78a5894b16212 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -316,22 +316,31 @@ out:
}
static int
-validate_event(struct pmu_hw_events *hw_events,
- struct perf_event *event)
+validate_event(struct pmu *pmu, struct pmu_hw_events *hw_events,
+ struct perf_event *event)
{
- struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+ struct arm_pmu *armpmu;
struct hw_perf_event fake_event = event->hw;
struct pmu *leader_pmu = event->group_leader->pmu;
if (is_software_event(event))
return 1;
+ /*
+ * Reject groups spanning multiple HW PMUs (e.g. CPU + CCI). The
+ * core perf code won't check that the pmu->ctx == leader->ctx
+ * until after pmu->event_init(event).
+ */
+ if (event->pmu != pmu)
+ return 0;
+
if (event->pmu != leader_pmu || event->state < PERF_EVENT_STATE_OFF)
return 1;
if (event->state == PERF_EVENT_STATE_OFF && !event->attr.enable_on_exec)
return 1;
+ armpmu = to_arm_pmu(event->pmu);
return armpmu->get_event_idx(hw_events, &fake_event) >= 0;
}
@@ -349,15 +358,15 @@ validate_group(struct perf_event *event)
memset(fake_used_mask, 0, sizeof(fake_used_mask));
fake_pmu.used_mask = fake_used_mask;
- if (!validate_event(&fake_pmu, leader))
+ if (!validate_event(event->pmu, &fake_pmu, leader))
return -EINVAL;
list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
- if (!validate_event(&fake_pmu, sibling))
+ if (!validate_event(event->pmu, &fake_pmu, sibling))
return -EINVAL;
}
- if (!validate_event(&fake_pmu, event))
+ if (!validate_event(event->pmu, &fake_pmu, event))
return -EINVAL;
return 0;
--
cgit 1.2.3-1.el7
......@@ -49,7 +49,7 @@ Signed-off-by: Will Deacon <will.deacon@arm.com>
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index 25a5308744b1..68a74151fa6c 100644
index 25a5308744b1c..68a74151fa6cf 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -322,22 +322,31 @@ out:
......@@ -107,5 +107,5 @@ index 25a5308744b1..68a74151fa6c 100644
return 0;
--
cgit 1.2-0.3.lf.el7
cgit 1.2.3-1.el7
From ee79b622f43bab46bd6ff778b3cd2e4af4784bc2 Mon Sep 17 00:00:00 2001
From: Jaganath Kanakkassery <jaganath.k@samsung.com>
Date: Wed, 14 Dec 2016 13:24:54 +0100
Subject: Bluetooth: Fix potential NULL dereference in RFCOMM bind callback
[ Upstream commit 951b6a0717db97ce420547222647bcc40bf1eacd ]
addr can be NULL and it should not be dereferenced before NULL checking.
Signed-off-by: Jaganath Kanakkassery <jaganath.k@samsung.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
---
net/bluetooth/rfcomm/sock.c | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 8bbbb5ec468c3..bcb3160fefb4c 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -334,16 +334,19 @@ static int rfcomm_sock_create(struct net *net, struct socket *sock,
static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
{
- struct sockaddr_rc *sa = (struct sockaddr_rc *) addr;
+ struct sockaddr_rc sa;
struct sock *sk = sock->sk;
- int chan = sa->rc_channel;
- int err = 0;
-
- BT_DBG("sk %p %pMR", sk, &sa->rc_bdaddr);
+ int len, err = 0;
if (!addr || addr->sa_family != AF_BLUETOOTH)
return -EINVAL;
+ memset(&sa, 0, sizeof(sa));
+ len = min_t(unsigned int, sizeof(sa), addr_len);
+ memcpy(&sa, addr, len);
+
+ BT_DBG("sk %p %pMR", sk, &sa.rc_bdaddr);
+
lock_sock(sk);
if (sk->sk_state != BT_OPEN) {
@@ -358,12 +361,13 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr
write_lock(&rfcomm_sk_list.lock);
- if (chan && __rfcomm_get_listen_sock_by_addr(chan, &sa->rc_bdaddr)) {
+ if (sa.rc_channel &&
+ __rfcomm_get_listen_sock_by_addr(sa.rc_channel, &sa.rc_bdaddr)) {
err = -EADDRINUSE;
} else {
/* Save source address */
- bacpy(&rfcomm_pi(sk)->src, &sa->rc_bdaddr);
- rfcomm_pi(sk)->channel = chan;
+ bacpy(&rfcomm_pi(sk)->src, &sa.rc_bdaddr);
+ rfcomm_pi(sk)->channel = sa.rc_channel;
sk->sk_state = BT_BOUND;
}
--
cgit 1.2.3-1.el7
......@@ -12,7 +12,7 @@ Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index b2338e971b33..7511df72347f 100644
index b2338e971b335..7511df72347f3 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -334,16 +334,19 @@ static int rfcomm_sock_create(struct net *net, struct socket *sock,
......@@ -58,5 +58,5 @@ index b2338e971b33..7511df72347f 100644
}
--
cgit 1.2-0.3.lf.el7
cgit 1.2.3-1.el7
From a4896e11679432f30433f415a5f31d5ebbbf8b66 Mon Sep 17 00:00:00 2001
From: Lukas Czerner <lczerner@redhat.com>
Date: Sat, 17 Oct 2015 22:57:06 -0400
Subject: ext4: fix potential use after free in __ext4_journal_stop
commit 6934da9238da947628be83635e365df41064b09b upstream.
There is a use-after-free possibility in __ext4_journal_stop() in the
case that we free the handle in the first jbd2_journal_stop() because
we're referencing handle->h_err afterwards. This was introduced in
9705acd63b125dee8b15c705216d7186daea4625 and it is wrong. Fix it by
storing the handle->h_err value beforehand and avoid referencing
potentially freed handle.
Fixes: 9705acd63b125dee8b15c705216d7186daea4625
Signed-off-by: Lukas Czerner <lczerner@redhat.com>
Reviewed-by: Andreas Dilger <adilger@dilger.ca>
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/ext4/ext4_jbd2.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
index d418431818187..e770c1ee4613e 100644
--- a/fs/ext4/ext4_jbd2.c
+++ b/fs/ext4/ext4_jbd2.c
@@ -88,13 +88,13 @@ int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle)
return 0;
}
+ err = handle->h_err;
if (!handle->h_transaction) {
- err = jbd2_journal_stop(handle);
- return handle->h_err ? handle->h_err : err;
+ rc = jbd2_journal_stop(handle);
+ return err ? err : rc;
}
sb = handle->h_transaction->t_journal->j_private;
- err = handle->h_err;
rc = jbd2_journal_stop(handle);
if (!err)
--
cgit 1.2.3-1.el7
......@@ -19,7 +19,7 @@ Cc: stable@vger.kernel.org
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
index d41843181818..e770c1ee4613 100644
index d418431818187..e770c1ee4613e 100644
--- a/fs/ext4/ext4_jbd2.c
+++ b/fs/ext4/ext4_jbd2.c
@@ -88,13 +88,13 @@ int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle)
......@@ -40,5 +40,5 @@ index d41843181818..e770c1ee4613 100644
if (!err)
--
cgit 1.2-0.3.lf.el7
cgit 1.2.3-1.el7
From dda50d926e8a3f215857ab7091cd6b11d588881a Mon Sep 17 00:00:00 2001
From: Calvin Owens <calvinowens@fb.com>
Date: Fri, 30 Oct 2015 16:57:00 -0700
Subject: sg: Fix double-free when drives detach during SG_IO
commit f3951a3709ff50990bf3e188c27d346792103432 upstream.
In sg_common_write(), we free the block request and return -ENODEV if
the device is detached in the middle of the SG_IO ioctl().
Unfortunately, sg_finish_rem_req() also tries to free srp->rq, so we
end up freeing rq->cmd in the already free rq object, and then free
the object itself out from under the current user.
This ends up corrupting random memory via the list_head on the rq
object. The most common crash trace I saw is this:
------------[ cut here ]------------
kernel BUG at block/blk-core.c:1420!
Call Trace:
[<ffffffff81281eab>] blk_put_request+0x5b/0x80
[<ffffffffa0069e5b>] sg_finish_rem_req+0x6b/0x120 [sg]
[<ffffffffa006bcb9>] sg_common_write.isra.14+0x459/0x5a0 [sg]
[<ffffffff8125b328>] ? selinux_file_alloc_security+0x48/0x70
[<ffffffffa006bf95>] sg_new_write.isra.17+0x195/0x2d0 [sg]
[<ffffffffa006cef4>] sg_ioctl+0x644/0xdb0 [sg]
[<ffffffff81170f80>] do_vfs_ioctl+0x90/0x520
[<ffffffff81258967>] ? file_has_perm+0x97/0xb0
[<ffffffff811714a1>] SyS_ioctl+0x91/0xb0
[<ffffffff81602afb>] tracesys+0xdd/0xe2
RIP [<ffffffff81281e04>] __blk_put_request+0x154/0x1a0
The solution is straightforward: just set srp->rq to NULL in the
failure branch so that sg_finish_rem_req() doesn't attempt to re-free
it.
Additionally, since sg_rq_end_io() will never be called on the object
when this happens, we need to free memory backing ->cmd if it isn't
embedded in the object itself.
KASAN was extremely helpful in finding the root cause of this bug.
Signed-off-by: Calvin Owens <calvinowens@fb.com>
Acked-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
drivers/scsi/sg.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 291791a9be8b0..0b27d293dd837 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -769,8 +769,14 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
return k; /* probably out of space --> ENOMEM */
}
if (sdp->detached) {
- if (srp->bio)
+ if (srp->bio) {
+ if (srp->rq->cmd != srp->rq->__cmd)
+ kfree(srp->rq->cmd);
+
blk_end_request_all(srp->rq, -EIO);
+ srp->rq = NULL;
+ }
+
sg_finish_rem_req(srp);
return -ENODEV;
}
--
cgit 1.2.3-1.el7
From 6d523f23bb2dadfebcda1636ee2d534259566c6c Mon Sep 17 00:00:00 2001
From: Calvin Owens <calvinowens@fb.com>
Date: Fri, 30 Oct 2015 16:57:00 -0700
Subject: sg: Fix double-free when drives detach during SG_IO
commit f3951a3709ff50990bf3e188c27d346792103432 upstream.
In sg_common_write(), we free the block request and return -ENODEV if
the device is detached in the middle of the SG_IO ioctl().
Unfortunately, sg_finish_rem_req() also tries to free srp->rq, so we
end up freeing rq->cmd in the already free rq object, and then free
the object itself out from under the current user.
This ends up corrupting random memory via the list_head on the rq
object. The most common crash trace I saw is this:
------------[ cut here ]------------
kernel BUG at block/blk-core.c:1420!
Call Trace:
[<ffffffff81281eab>] blk_put_request+0x5b/0x80
[<ffffffffa0069e5b>] sg_finish_rem_req+0x6b/0x120 [sg]
[<ffffffffa006bcb9>] sg_common_write.isra.14+0x459/0x5a0 [sg]
[<ffffffff8125b328>] ? selinux_file_alloc_security+0x48/0x70
[<ffffffffa006bf95>] sg_new_write.isra.17+0x195/0x2d0 [sg]
[<ffffffffa006cef4>] sg_ioctl+0x644/0xdb0 [sg]
[<ffffffff81170f80>] do_vfs_ioctl+0x90/0x520
[<ffffffff81258967>] ? file_has_perm+0x97/0xb0
[<ffffffff811714a1>] SyS_ioctl+0x91/0xb0
[<ffffffff81602afb>] tracesys+0xdd/0xe2
RIP [<ffffffff81281e04>] __blk_put_request+0x154/0x1a0
The solution is straightforward: just set srp->rq to NULL in the
failure branch so that sg_finish_rem_req() doesn't attempt to re-free
it.
Additionally, since sg_rq_end_io() will never be called on the object
when this happens, we need to free memory backing ->cmd if it isn't
embedded in the object itself.
KASAN was extremely helpful in finding the root cause of this bug.
Signed-off-by: Calvin Owens <calvinowens@fb.com>
Acked-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/scsi/sg.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index e50adf7102298..71b30e18f2f00 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -791,8 +791,14 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
return k; /* probably out of space --> ENOMEM */
}
if (atomic_read(&sdp->detaching)) {
- if (srp->bio)
+ if (srp->bio) {
+ if (srp->rq->cmd != srp->rq->__cmd)
+ kfree(srp->rq->cmd);
+
blk_end_request_all(srp->rq, -EIO);
+ srp->rq = NULL;
+ }
+
sg_finish_rem_req(srp);
return -ENODEV;
}
--
cgit 1.2.3-1.el7
......@@ -46,7 +46,7 @@ Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 9d7b7db75e4b..503ab8b46c0b 100644
index 9d7b7db75e4b9..503ab8b46c0b4 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -787,8 +787,14 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
......@@ -66,5 +66,5 @@ index 9d7b7db75e4b..503ab8b46c0b 100644
return -ENODEV;
}
--
cgit 1.2-0.3.lf.el7
cgit 1.2.3-1.el7
diff --git a/kernel/events/core.c b/kernel/events/core.c
index e9018fe..382bad3 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5349,7 +5349,6 @@
int err = 0;
mutex_lock(&swhash->hlist_mutex);
-
if (!swevent_hlist_deref(swhash) && cpu_online(cpu)) {
struct swevent_hlist *hlist;
@@ -7436,12 +7435,6 @@
static void perf_event_exit_cpu(int cpu)
{
- struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
-
- mutex_lock(&swhash->hlist_mutex);
- swevent_hlist_release(swhash);
- mutex_unlock(&swhash->hlist_mutex);
-
perf_event_exit_cpu_context(cpu);
}
#else
ZGlmZiAtLWdpdCBhL2tlcm5lbC9ldmVudHMvY29yZS5jIGIva2VybmVsL2V2ZW50cy9jb3JlLmMKaW5kZXggZTkwMThmZS4uMzgyYmFkMyAxMDA2NDQKLS0tIGEva2VybmVsL2V2ZW50cy9jb3JlLmMKKysrIGIva2VybmVsL2V2ZW50cy9jb3JlLmMKQEAgLTUzNDksNyArNTM0OSw2IEBACiAJaW50IGVyciA9IDA7CiAKIAltdXRleF9sb2NrKCZzd2hhc2gtPmhsaXN0X211dGV4KTsKLQogCWlmICghc3dldmVudF9obGlzdF9kZXJlZihzd2hhc2gpICYmIGNwdV9vbmxpbmUoY3B1KSkgewogCQlzdHJ1Y3Qgc3dldmVudF9obGlzdCAqaGxpc3Q7CiAKQEAgLTc0MzYsMTIgKzc0MzUsNiBAQAogCiBzdGF0aWMgdm9pZCBwZXJmX2V2ZW50X2V4aXRfY3B1KGludCBjcHUpCiB7Ci0Jc3RydWN0IHN3ZXZlbnRfaHRhYmxlICpzd2hhc2ggPSAmcGVyX2NwdShzd2V2ZW50X2h0YWJsZSwgY3B1KTsKLQotCW11dGV4X2xvY2soJnN3aGFzaC0+aGxpc3RfbXV0ZXgpOwotCXN3ZXZlbnRfaGxpc3RfcmVsZWFzZShzd2hhc2gpOwotCW11dGV4X3VubG9jaygmc3doYXNoLT5obGlzdF9tdXRleCk7Ci0KIAlwZXJmX2V2ZW50X2V4aXRfY3B1X2NvbnRleHQoY3B1KTsKIH0KICNlbHNlCg==
\ No newline at end of file
From 6ee649ba055c71907226820070cde13079d3d49d Mon Sep 17 00:00:00 2001
From: Peter Zijlstra <peterz@infradead.org>
Date: Tue, 15 Dec 2015 13:49:05 +0100
Subject: perf: Fix race in swevent hash
commit 12ca6ad2e3a896256f086497a7c7406a547ee373 upstream.
There's a race on CPU unplug where we free the swevent hash array
while it can still have events on. This will result in a
use-after-free which is BAD.
Simply do not free the hash array on unplug. This leaves the thing
around and no use-after-free takes place.
When the last swevent dies, we do a for_each_possible_cpu() iteration
anyway to clean these up, at which time we'll free it, so no leakage
will occur.
Reported-by: Sasha Levin <sasha.levin@oracle.com>
Tested-by: Sasha Levin <sasha.levin@oracle.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/events/core.c | 20 +-------------------
1 file changed, 1 insertion(+), 19 deletions(-)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 3964293d1540f..4886c0e97bbde 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5851,9 +5851,6 @@ struct swevent_htable {
/* Recursion avoidance in each contexts */
int recursion[PERF_NR_CONTEXTS];
-
- /* Keeps track of cpu being initialized/exited */
- bool online;
};
static DEFINE_PER_CPU(struct swevent_htable, swevent_htable);
@@ -6111,14 +6108,8 @@ static int perf_swevent_add(struct perf_event *event, int flags)
hwc->state = !(flags & PERF_EF_START);
head = find_swevent_head(swhash, event);
- if (!head) {
- /*
- * We can race with cpu hotplug code. Do not
- * WARN if the cpu just got unplugged.
- */
- WARN_ON_ONCE(swhash->online);
+ if (WARN_ON_ONCE(!head))
return -EINVAL;
- }
hlist_add_head_rcu(&event->hlist_entry, head);
@@ -6185,7 +6176,6 @@ static int swevent_hlist_get_cpu(struct perf_event *event, int cpu)
int err = 0;
mutex_lock(&swhash->hlist_mutex);
-
if (!swevent_hlist_deref(swhash) && cpu_online(cpu)) {
struct swevent_hlist *hlist;
@@ -8342,7 +8332,6 @@ static void perf_event_init_cpu(int cpu)
struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
mutex_lock(&swhash->hlist_mutex);
- swhash->online = true;
if (swhash->hlist_refcount > 0) {
struct swevent_hlist *hlist;
@@ -8395,14 +8384,7 @@ static void perf_event_exit_cpu_context(int cpu)
static void perf_event_exit_cpu(int cpu)
{
- struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
-
perf_event_exit_cpu_context(cpu);
-
- mutex_lock(&swhash->hlist_mutex);