DivestOS/Patches/Linux_CVEs/CVE-2014-0972/ANY/0001.patch
2017-11-07 17:32:46 -05:00

182 lines
6.0 KiB
Diff

From 7613c9d520ee4d227e635f6db0270d4cf26102bc Mon Sep 17 00:00:00 2001
From: Jordan Crouse <jcrouse@codeaurora.org>
Date: Mon, 21 Apr 2014 15:04:54 -0600
Subject: msm: kgsl: Protect CP_STATE_DEBUG_INDEX
Put CP_STATE_DEBUG_INDEX and CP_STATE_DEBUG_DATA under protection
to keep it from being written from an IB1. Doing so however opens
up a subtle "feature" in the microcode: memory read opcodes turn off
protected mode in the microcode to do the read and then turns it
back on regardless of the initial state. This is a problem if the
memory read happens while protected mode is turned off and then we
try to access a protected register which then complains and goes boom.
To account for this irregularity explicitly turn back off protected
mode in all the places where we know this will be a problem.
Change-Id: Ic0dedbad1397ca9b80132241ac006560a615e042
Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
---
drivers/gpu/msm/adreno.c | 24 +++++++++++++-----------
drivers/gpu/msm/adreno.h | 10 ++++++++++
drivers/gpu/msm/adreno_a3xx.c | 1 +
drivers/gpu/msm/kgsl_iommu.c | 16 ++++++++++++++++
4 files changed, 40 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 4b21218..9bd07c6 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1150,9 +1150,7 @@ static int adreno_iommu_setstate(struct kgsl_device *device,
uint32_t flags)
{
phys_addr_t pt_val;
- unsigned int link[230];
- unsigned int *cmds = &link[0];
- int sizedwords = 0;
+ unsigned int *link = NULL, *cmds;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
int num_iommu_units;
struct kgsl_context *context;
@@ -1170,6 +1168,14 @@ static int adreno_iommu_setstate(struct kgsl_device *device,
if (context)
adreno_ctx = ADRENO_CONTEXT(context);
+ link = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (link == NULL) {
+ result = -ENOMEM;
+ goto done;
+ }
+
+ cmds = link;
+
result = kgsl_mmu_enable_clk(&device->mmu, KGSL_IOMMU_CONTEXT_USER);
if (result)
@@ -1192,17 +1198,11 @@ static int adreno_iommu_setstate(struct kgsl_device *device,
cmds += _adreno_iommu_setstate_v1(device, cmds, pt_val,
num_iommu_units, flags);
- sizedwords += (cmds - &link[0]);
- if (sizedwords == 0) {
- KGSL_DRV_ERR(device, "no commands generated\n");
- BUG();
- }
/* invalidate all base pointers */
*cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
*cmds++ = 0x7fff;
- sizedwords += 2;
- if (sizedwords > (ARRAY_SIZE(link))) {
+ if ((unsigned int) (cmds - link) > (PAGE_SIZE / sizeof(unsigned int))) {
KGSL_DRV_ERR(device, "Temp command buffer overflow\n");
BUG();
}
@@ -1211,7 +1211,8 @@ static int adreno_iommu_setstate(struct kgsl_device *device,
* use the global timestamp for iommu clock disablement
*/
result = adreno_ringbuffer_issuecmds(device, adreno_ctx,
- KGSL_CMD_FLAGS_PMODE, &link[0], sizedwords);
+ KGSL_CMD_FLAGS_PMODE, link,
+ (unsigned int)(cmds - link));
/*
* On error disable the IOMMU clock right away otherwise turn it off
@@ -1225,6 +1226,7 @@ static int adreno_iommu_setstate(struct kgsl_device *device,
KGSL_IOMMU_CONTEXT_USER);
done:
+ kfree(link);
kgsl_context_put(context);
return result;
}
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 8e162ca..0b793fa 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -805,6 +805,11 @@ static inline int adreno_add_read_cmds(struct kgsl_device *device,
*cmds++ = val;
*cmds++ = 0xFFFFFFFF;
*cmds++ = 0xFFFFFFFF;
+
+ /* WAIT_REG_MEM turns back on protected mode - push it off */
+ *cmds++ = cp_type3_packet(CP_SET_PROTECTED_MODE, 1);
+ *cmds++ = 0;
+
cmds += __adreno_add_idle_indirect_cmds(cmds, nop_gpuaddr);
return cmds - start;
}
@@ -850,6 +855,11 @@ static inline int adreno_wait_reg_mem(unsigned int *cmds, unsigned int addr,
*cmds++ = val; /* ref val */
*cmds++ = mask;
*cmds++ = interval;
+
+ /* WAIT_REG_MEM turns back on protected mode - push it off */
+ *cmds++ = cp_type3_packet(CP_SET_PROTECTED_MODE, 1);
+ *cmds++ = 0;
+
return cmds - start;
}
/*
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 70ba50e..873a5c9 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2038,6 +2038,7 @@ static void a3xx_protect_init(struct kgsl_device *device)
/* CP registers */
adreno_set_protected_registers(device, &index, 0x1C0, 5);
+ adreno_set_protected_registers(device, &index, 0x1EC, 1);
adreno_set_protected_registers(device, &index, 0x1F6, 1);
adreno_set_protected_registers(device, &index, 0x1F8, 2);
adreno_set_protected_registers(device, &index, 0x45E, 2);
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index dba23b0..68b3420 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -1036,6 +1036,10 @@ static unsigned int kgsl_iommu_sync_lock(struct kgsl_mmu *mmu,
*cmds++ = 0x1;
*cmds++ = 0x1;
+ /* WAIT_REG_MEM turns back on protected mode - push it off */
+ *cmds++ = cp_type3_packet(CP_SET_PROTECTED_MODE, 1);
+ *cmds++ = 0;
+
*cmds++ = cp_type3_packet(CP_MEM_WRITE, 2);
*cmds++ = lock_vars->turn;
*cmds++ = 0;
@@ -1050,11 +1054,19 @@ static unsigned int kgsl_iommu_sync_lock(struct kgsl_mmu *mmu,
*cmds++ = 0x1;
*cmds++ = 0x1;
+ /* WAIT_REG_MEM turns back on protected mode - push it off */
+ *cmds++ = cp_type3_packet(CP_SET_PROTECTED_MODE, 1);
+ *cmds++ = 0;
+
*cmds++ = cp_type3_packet(CP_TEST_TWO_MEMS, 3);
*cmds++ = lock_vars->flag[PROC_APPS];
*cmds++ = lock_vars->turn;
*cmds++ = 0;
+ /* TEST_TWO_MEMS turns back on protected mode - push it off */
+ *cmds++ = cp_type3_packet(CP_SET_PROTECTED_MODE, 1);
+ *cmds++ = 0;
+
cmds += adreno_add_idle_cmds(adreno_dev, cmds);
return cmds - start;
@@ -1092,6 +1104,10 @@ static unsigned int kgsl_iommu_sync_unlock(struct kgsl_mmu *mmu,
*cmds++ = 0x1;
*cmds++ = 0x1;
+ /* WAIT_REG_MEM turns back on protected mode - push it off */
+ *cmds++ = cp_type3_packet(CP_SET_PROTECTED_MODE, 1);
+ *cmds++ = 0;
+
cmds += adreno_add_idle_cmds(adreno_dev, cmds);
return cmds - start;
--
cgit v1.1