[x86] i915: Add mitigations for two hardware security flaws
This commit is contained in:
parent
c2443a2e97
commit
feec1caa94
|
@ -32,6 +32,20 @@ linux (4.19.67-2+deb10u2) UNRELEASED; urgency=medium
|
|||
- kvm: Add helper function for creating VM worker threads
|
||||
- kvm: x86: mmu: Recovery of shattered NX large pages
|
||||
- Documentation: Add ITLB_MULTIHIT documentation
|
||||
* [x86] i915: Mitigate local privilege escalation on gen9 (CVE-2019-0155):
|
||||
- drm/i915: Rename gen7 cmdparser tables
|
||||
- drm/i915: Disable Secure Batches for gen6+
|
||||
- drm/i915: Remove Master tables from cmdparser
|
||||
- drm/i915: Add support for mandatory cmdparsing
|
||||
- drm/i915: Support ro ppgtt mapped cmdparser shadow buffers
|
||||
- drm/i915: Allow parsing of unsized batches
|
||||
- drm/i915: Add gen9 BCS cmdparsing
|
||||
- drm/i915/cmdparser: Use explicit goto for error paths
|
||||
- drm/i915/cmdparser: Add support for backward jumps
|
||||
- drm/i915/cmdparser: Ignore Length operands during command matching
|
||||
* [x86] i915: Mitigate local denial-of-service on gen8/gen9 (CVE-2019-0154):
|
||||
- drm/i915: Lower RM timeout to avoid DSI hard hangs
|
||||
- drm/i915/gen8+: Add RC6 CTX corruption WA
|
||||
|
||||
-- Ben Hutchings <ben@decadent.org.uk> Sun, 20 Oct 2019 14:21:28 +0100
|
||||
|
||||
|
|
176
debian/patches/bugfix/x86/i915/0001-drm-i915-Rename-gen7-cmdparser-tables.patch
vendored
Normal file
176
debian/patches/bugfix/x86/i915/0001-drm-i915-Rename-gen7-cmdparser-tables.patch
vendored
Normal file
|
@ -0,0 +1,176 @@
|
|||
From: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Date: Fri, 20 Apr 2018 14:26:01 -0700
|
||||
Subject: drm/i915: Rename gen7 cmdparser tables
|
||||
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-0155
|
||||
|
||||
commit 0a2f661b6c21815a7fa60e30babe975fee8e73c6 upstream.
|
||||
|
||||
We're about to introduce some new tables for later gens, and the
|
||||
current naming for the gen7 tables will no longer make sense.
|
||||
|
||||
v2: rebase
|
||||
|
||||
Signed-off-by: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Cc: Tony Luck <tony.luck@intel.com>
|
||||
Cc: Dave Airlie <airlied@redhat.com>
|
||||
Cc: Takashi Iwai <tiwai@suse.de>
|
||||
Cc: Tyler Hicks <tyhicks@canonical.com>
|
||||
Signed-off-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
|
||||
Reviewed-by: Chris Wilson <chris.p.wilson@intel.com>
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_cmd_parser.c | 70 +++++++++++++-------------
|
||||
1 file changed, 35 insertions(+), 35 deletions(-)
|
||||
|
||||
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
|
||||
@@ -211,7 +211,7 @@ struct drm_i915_cmd_table {
|
||||
|
||||
/* Command Mask Fixed Len Action
|
||||
---------------------------------------------------------- */
|
||||
-static const struct drm_i915_cmd_descriptor common_cmds[] = {
|
||||
+static const struct drm_i915_cmd_descriptor gen7_common_cmds[] = {
|
||||
CMD( MI_NOOP, SMI, F, 1, S ),
|
||||
CMD( MI_USER_INTERRUPT, SMI, F, 1, R ),
|
||||
CMD( MI_WAIT_FOR_EVENT, SMI, F, 1, M ),
|
||||
@@ -244,7 +244,7 @@ static const struct drm_i915_cmd_descrip
|
||||
CMD( MI_BATCH_BUFFER_START, SMI, !F, 0xFF, S ),
|
||||
};
|
||||
|
||||
-static const struct drm_i915_cmd_descriptor render_cmds[] = {
|
||||
+static const struct drm_i915_cmd_descriptor gen7_render_cmds[] = {
|
||||
CMD( MI_FLUSH, SMI, F, 1, S ),
|
||||
CMD( MI_ARB_ON_OFF, SMI, F, 1, R ),
|
||||
CMD( MI_PREDICATE, SMI, F, 1, S ),
|
||||
@@ -328,7 +328,7 @@ static const struct drm_i915_cmd_descrip
|
||||
CMD( GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS, S3D, !F, 0x1FF, S ),
|
||||
};
|
||||
|
||||
-static const struct drm_i915_cmd_descriptor video_cmds[] = {
|
||||
+static const struct drm_i915_cmd_descriptor gen7_video_cmds[] = {
|
||||
CMD( MI_ARB_ON_OFF, SMI, F, 1, R ),
|
||||
CMD( MI_SET_APPID, SMI, F, 1, S ),
|
||||
CMD( MI_STORE_DWORD_IMM, SMI, !F, 0xFF, B,
|
||||
@@ -372,7 +372,7 @@ static const struct drm_i915_cmd_descrip
|
||||
CMD( MFX_WAIT, SMFX, F, 1, S ),
|
||||
};
|
||||
|
||||
-static const struct drm_i915_cmd_descriptor vecs_cmds[] = {
|
||||
+static const struct drm_i915_cmd_descriptor gen7_vecs_cmds[] = {
|
||||
CMD( MI_ARB_ON_OFF, SMI, F, 1, R ),
|
||||
CMD( MI_SET_APPID, SMI, F, 1, S ),
|
||||
CMD( MI_STORE_DWORD_IMM, SMI, !F, 0xFF, B,
|
||||
@@ -410,7 +410,7 @@ static const struct drm_i915_cmd_descrip
|
||||
}}, ),
|
||||
};
|
||||
|
||||
-static const struct drm_i915_cmd_descriptor blt_cmds[] = {
|
||||
+static const struct drm_i915_cmd_descriptor gen7_blt_cmds[] = {
|
||||
CMD( MI_DISPLAY_FLIP, SMI, !F, 0xFF, R ),
|
||||
CMD( MI_STORE_DWORD_IMM, SMI, !F, 0x3FF, B,
|
||||
.bits = {{
|
||||
@@ -463,35 +463,35 @@ static const struct drm_i915_cmd_descrip
|
||||
#undef B
|
||||
#undef M
|
||||
|
||||
-static const struct drm_i915_cmd_table gen7_render_cmds[] = {
|
||||
- { common_cmds, ARRAY_SIZE(common_cmds) },
|
||||
- { render_cmds, ARRAY_SIZE(render_cmds) },
|
||||
+static const struct drm_i915_cmd_table gen7_render_cmd_table[] = {
|
||||
+ { gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) },
|
||||
+ { gen7_render_cmds, ARRAY_SIZE(gen7_render_cmds) },
|
||||
};
|
||||
|
||||
-static const struct drm_i915_cmd_table hsw_render_ring_cmds[] = {
|
||||
- { common_cmds, ARRAY_SIZE(common_cmds) },
|
||||
- { render_cmds, ARRAY_SIZE(render_cmds) },
|
||||
+static const struct drm_i915_cmd_table hsw_render_ring_cmd_table[] = {
|
||||
+ { gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) },
|
||||
+ { gen7_render_cmds, ARRAY_SIZE(gen7_render_cmds) },
|
||||
{ hsw_render_cmds, ARRAY_SIZE(hsw_render_cmds) },
|
||||
};
|
||||
|
||||
-static const struct drm_i915_cmd_table gen7_video_cmds[] = {
|
||||
- { common_cmds, ARRAY_SIZE(common_cmds) },
|
||||
- { video_cmds, ARRAY_SIZE(video_cmds) },
|
||||
+static const struct drm_i915_cmd_table gen7_video_cmd_table[] = {
|
||||
+ { gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) },
|
||||
+ { gen7_video_cmds, ARRAY_SIZE(gen7_video_cmds) },
|
||||
};
|
||||
|
||||
-static const struct drm_i915_cmd_table hsw_vebox_cmds[] = {
|
||||
- { common_cmds, ARRAY_SIZE(common_cmds) },
|
||||
- { vecs_cmds, ARRAY_SIZE(vecs_cmds) },
|
||||
+static const struct drm_i915_cmd_table hsw_vebox_cmd_table[] = {
|
||||
+ { gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) },
|
||||
+ { gen7_vecs_cmds, ARRAY_SIZE(gen7_vecs_cmds) },
|
||||
};
|
||||
|
||||
-static const struct drm_i915_cmd_table gen7_blt_cmds[] = {
|
||||
- { common_cmds, ARRAY_SIZE(common_cmds) },
|
||||
- { blt_cmds, ARRAY_SIZE(blt_cmds) },
|
||||
+static const struct drm_i915_cmd_table gen7_blt_cmd_table[] = {
|
||||
+ { gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) },
|
||||
+ { gen7_blt_cmds, ARRAY_SIZE(gen7_blt_cmds) },
|
||||
};
|
||||
|
||||
-static const struct drm_i915_cmd_table hsw_blt_ring_cmds[] = {
|
||||
- { common_cmds, ARRAY_SIZE(common_cmds) },
|
||||
- { blt_cmds, ARRAY_SIZE(blt_cmds) },
|
||||
+static const struct drm_i915_cmd_table hsw_blt_ring_cmd_table[] = {
|
||||
+ { gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) },
|
||||
+ { gen7_blt_cmds, ARRAY_SIZE(gen7_blt_cmds) },
|
||||
{ hsw_blt_cmds, ARRAY_SIZE(hsw_blt_cmds) },
|
||||
};
|
||||
|
||||
@@ -871,12 +871,12 @@ void intel_engine_init_cmd_parser(struct
|
||||
switch (engine->id) {
|
||||
case RCS:
|
||||
if (IS_HASWELL(engine->i915)) {
|
||||
- cmd_tables = hsw_render_ring_cmds;
|
||||
+ cmd_tables = hsw_render_ring_cmd_table;
|
||||
cmd_table_count =
|
||||
- ARRAY_SIZE(hsw_render_ring_cmds);
|
||||
+ ARRAY_SIZE(hsw_render_ring_cmd_table);
|
||||
} else {
|
||||
- cmd_tables = gen7_render_cmds;
|
||||
- cmd_table_count = ARRAY_SIZE(gen7_render_cmds);
|
||||
+ cmd_tables = gen7_render_cmd_table;
|
||||
+ cmd_table_count = ARRAY_SIZE(gen7_render_cmd_table);
|
||||
}
|
||||
|
||||
if (IS_HASWELL(engine->i915)) {
|
||||
@@ -890,17 +890,17 @@ void intel_engine_init_cmd_parser(struct
|
||||
engine->get_cmd_length_mask = gen7_render_get_cmd_length_mask;
|
||||
break;
|
||||
case VCS:
|
||||
- cmd_tables = gen7_video_cmds;
|
||||
- cmd_table_count = ARRAY_SIZE(gen7_video_cmds);
|
||||
+ cmd_tables = gen7_video_cmd_table;
|
||||
+ cmd_table_count = ARRAY_SIZE(gen7_video_cmd_table);
|
||||
engine->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
|
||||
break;
|
||||
case BCS:
|
||||
if (IS_HASWELL(engine->i915)) {
|
||||
- cmd_tables = hsw_blt_ring_cmds;
|
||||
- cmd_table_count = ARRAY_SIZE(hsw_blt_ring_cmds);
|
||||
+ cmd_tables = hsw_blt_ring_cmd_table;
|
||||
+ cmd_table_count = ARRAY_SIZE(hsw_blt_ring_cmd_table);
|
||||
} else {
|
||||
- cmd_tables = gen7_blt_cmds;
|
||||
- cmd_table_count = ARRAY_SIZE(gen7_blt_cmds);
|
||||
+ cmd_tables = gen7_blt_cmd_table;
|
||||
+ cmd_table_count = ARRAY_SIZE(gen7_blt_cmd_table);
|
||||
}
|
||||
|
||||
if (IS_HASWELL(engine->i915)) {
|
||||
@@ -914,8 +914,8 @@ void intel_engine_init_cmd_parser(struct
|
||||
engine->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
|
||||
break;
|
||||
case VECS:
|
||||
- cmd_tables = hsw_vebox_cmds;
|
||||
- cmd_table_count = ARRAY_SIZE(hsw_vebox_cmds);
|
||||
+ cmd_tables = hsw_vebox_cmd_table;
|
||||
+ cmd_table_count = ARRAY_SIZE(hsw_vebox_cmd_table);
|
||||
/* VECS can use the same length_mask function as VCS */
|
||||
engine->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
|
||||
break;
|
93
debian/patches/bugfix/x86/i915/0002-drm-i915-Disable-Secure-Batches-for-gen6.patch
vendored
Normal file
93
debian/patches/bugfix/x86/i915/0002-drm-i915-Disable-Secure-Batches-for-gen6.patch
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
From: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Date: Fri, 8 Jun 2018 08:53:46 -0700
|
||||
Subject: drm/i915: Disable Secure Batches for gen6+
|
||||
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-0155
|
||||
|
||||
commit 44157641d448cbc0c4b73c5231d2b911f0cb0427 upstream.
|
||||
|
||||
Retroactively stop reporting support for secure batches
|
||||
through the api for gen6+ so that older binaries trigger
|
||||
the fallback path instead.
|
||||
|
||||
Older binaries use secure batches pre gen6 to access resources
|
||||
that are not available to normal usermode processes. However,
|
||||
all known userspace explicitly checks for HAS_SECURE_BATCHES
|
||||
before relying on the secure batch feature.
|
||||
|
||||
Since there are no known binaries relying on this for newer gens
|
||||
we can kill secure batches from gen6, via I915_PARAM_HAS_SECURE_BATCHES.
|
||||
|
||||
v2: rebase (Mika)
|
||||
v3: rebase (Mika)
|
||||
|
||||
Signed-off-by: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Cc: Tony Luck <tony.luck@intel.com>
|
||||
Cc: Dave Airlie <airlied@redhat.com>
|
||||
Cc: Takashi Iwai <tiwai@suse.de>
|
||||
Cc: Tyler Hicks <tyhicks@canonical.com>
|
||||
Signed-off-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
|
||||
Reviewed-by: Chris Wilson <chris.p.wilson@intel.com>
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_drv.c | 2 +-
|
||||
drivers/gpu/drm/i915/i915_drv.h | 2 ++
|
||||
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 12 ++++++++++--
|
||||
3 files changed, 13 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/gpu/drm/i915/i915_drv.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_drv.c
|
||||
@@ -351,7 +351,7 @@ static int i915_getparam_ioctl(struct dr
|
||||
value = HAS_LEGACY_SEMAPHORES(dev_priv);
|
||||
break;
|
||||
case I915_PARAM_HAS_SECURE_BATCHES:
|
||||
- value = capable(CAP_SYS_ADMIN);
|
||||
+ value = HAS_SECURE_BATCHES(dev_priv) && capable(CAP_SYS_ADMIN);
|
||||
break;
|
||||
case I915_PARAM_CMD_PARSER_VERSION:
|
||||
value = i915_cmd_parser_get_version(dev_priv);
|
||||
--- a/drivers/gpu/drm/i915/i915_drv.h
|
||||
+++ b/drivers/gpu/drm/i915/i915_drv.h
|
||||
@@ -2517,6 +2517,8 @@ intel_info(const struct drm_i915_private
|
||||
|
||||
#define HAS_LEGACY_SEMAPHORES(dev_priv) IS_GEN7(dev_priv)
|
||||
|
||||
+#define HAS_SECURE_BATCHES(dev_priv) (INTEL_GEN(dev_priv) < 6)
|
||||
+
|
||||
#define HAS_LLC(dev_priv) ((dev_priv)->info.has_llc)
|
||||
#define HAS_SNOOP(dev_priv) ((dev_priv)->info.has_snoop)
|
||||
#define HAS_EDRAM(dev_priv) (!!((dev_priv)->edram_cap & EDRAM_ENABLED))
|
||||
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
|
||||
@@ -2177,6 +2177,7 @@ i915_gem_do_execbuffer(struct drm_device
|
||||
struct drm_i915_gem_exec_object2 *exec,
|
||||
struct drm_syncobj **fences)
|
||||
{
|
||||
+ struct drm_i915_private *i915 = to_i915(dev);
|
||||
struct i915_execbuffer eb;
|
||||
struct dma_fence *in_fence = NULL;
|
||||
struct sync_file *out_fence = NULL;
|
||||
@@ -2187,7 +2188,7 @@ i915_gem_do_execbuffer(struct drm_device
|
||||
BUILD_BUG_ON(__EXEC_OBJECT_INTERNAL_FLAGS &
|
||||
~__EXEC_OBJECT_UNKNOWN_FLAGS);
|
||||
|
||||
- eb.i915 = to_i915(dev);
|
||||
+ eb.i915 = i915;
|
||||
eb.file = file;
|
||||
eb.args = args;
|
||||
if (DBG_FORCE_RELOC || !(args->flags & I915_EXEC_NO_RELOC))
|
||||
@@ -2209,8 +2210,15 @@ i915_gem_do_execbuffer(struct drm_device
|
||||
|
||||
eb.batch_flags = 0;
|
||||
if (args->flags & I915_EXEC_SECURE) {
|
||||
+ if (INTEL_GEN(i915) >= 11)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ /* Return -EPERM to trigger fallback code on old binaries. */
|
||||
+ if (!HAS_SECURE_BATCHES(i915))
|
||||
+ return -EPERM;
|
||||
+
|
||||
if (!drm_is_current_master(file) || !capable(CAP_SYS_ADMIN))
|
||||
- return -EPERM;
|
||||
+ return -EPERM;
|
||||
|
||||
eb.batch_flags |= I915_DISPATCH_SECURE;
|
||||
}
|
295
debian/patches/bugfix/x86/i915/0003-drm-i915-Remove-Master-tables-from-cmdparser.patch
vendored
Normal file
295
debian/patches/bugfix/x86/i915/0003-drm-i915-Remove-Master-tables-from-cmdparser.patch
vendored
Normal file
|
@ -0,0 +1,295 @@
|
|||
From: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Date: Fri, 8 Jun 2018 10:05:26 -0700
|
||||
Subject: drm/i915: Remove Master tables from cmdparser
|
||||
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-0155
|
||||
|
||||
commit 66d8aba1cd6db34af10de465c0d52af679288cb6 upstream.
|
||||
|
||||
The previous patch has killed support for secure batches
|
||||
on gen6+, and hence the cmdparsers master tables are
|
||||
now dead code. Remove them.
|
||||
|
||||
Signed-off-by: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Cc: Tony Luck <tony.luck@intel.com>
|
||||
Cc: Dave Airlie <airlied@redhat.com>
|
||||
Cc: Takashi Iwai <tiwai@suse.de>
|
||||
Cc: Tyler Hicks <tyhicks@canonical.com>
|
||||
Reviewed-by: Chris Wilson <chris.p.wilson@intel.com>
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_cmd_parser.c | 84 ++++++----------------
|
||||
drivers/gpu/drm/i915/i915_drv.h | 3 +-
|
||||
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 7 +-
|
||||
3 files changed, 26 insertions(+), 68 deletions(-)
|
||||
|
||||
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
|
||||
@@ -51,13 +51,11 @@
|
||||
* granting userspace undue privileges. There are three categories of privilege.
|
||||
*
|
||||
* First, commands which are explicitly defined as privileged or which should
|
||||
- * only be used by the kernel driver. The parser generally rejects such
|
||||
- * commands, though it may allow some from the drm master process.
|
||||
+ * only be used by the kernel driver. The parser rejects such commands
|
||||
*
|
||||
* Second, commands which access registers. To support correct/enhanced
|
||||
* userspace functionality, particularly certain OpenGL extensions, the parser
|
||||
- * provides a whitelist of registers which userspace may safely access (for both
|
||||
- * normal and drm master processes).
|
||||
+ * provides a whitelist of registers which userspace may safely access
|
||||
*
|
||||
* Third, commands which access privileged memory (i.e. GGTT, HWS page, etc).
|
||||
* The parser always rejects such commands.
|
||||
@@ -82,9 +80,9 @@
|
||||
* in the per-engine command tables.
|
||||
*
|
||||
* Other command table entries map fairly directly to high level categories
|
||||
- * mentioned above: rejected, master-only, register whitelist. The parser
|
||||
- * implements a number of checks, including the privileged memory checks, via a
|
||||
- * general bitmasking mechanism.
|
||||
+ * mentioned above: rejected, register whitelist. The parser implements a number
|
||||
+ * of checks, including the privileged memory checks, via a general bitmasking
|
||||
+ * mechanism.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -102,8 +100,6 @@ struct drm_i915_cmd_descriptor {
|
||||
* CMD_DESC_REJECT: The command is never allowed
|
||||
* CMD_DESC_REGISTER: The command should be checked against the
|
||||
* register whitelist for the appropriate ring
|
||||
- * CMD_DESC_MASTER: The command is allowed if the submitting process
|
||||
- * is the DRM master
|
||||
*/
|
||||
u32 flags;
|
||||
#define CMD_DESC_FIXED (1<<0)
|
||||
@@ -111,7 +107,6 @@ struct drm_i915_cmd_descriptor {
|
||||
#define CMD_DESC_REJECT (1<<2)
|
||||
#define CMD_DESC_REGISTER (1<<3)
|
||||
#define CMD_DESC_BITMASK (1<<4)
|
||||
-#define CMD_DESC_MASTER (1<<5)
|
||||
|
||||
/*
|
||||
* The command's unique identification bits and the bitmask to get them.
|
||||
@@ -207,14 +202,13 @@ struct drm_i915_cmd_table {
|
||||
#define R CMD_DESC_REJECT
|
||||
#define W CMD_DESC_REGISTER
|
||||
#define B CMD_DESC_BITMASK
|
||||
-#define M CMD_DESC_MASTER
|
||||
|
||||
/* Command Mask Fixed Len Action
|
||||
---------------------------------------------------------- */
|
||||
static const struct drm_i915_cmd_descriptor gen7_common_cmds[] = {
|
||||
CMD( MI_NOOP, SMI, F, 1, S ),
|
||||
CMD( MI_USER_INTERRUPT, SMI, F, 1, R ),
|
||||
- CMD( MI_WAIT_FOR_EVENT, SMI, F, 1, M ),
|
||||
+ CMD( MI_WAIT_FOR_EVENT, SMI, F, 1, R ),
|
||||
CMD( MI_ARB_CHECK, SMI, F, 1, S ),
|
||||
CMD( MI_REPORT_HEAD, SMI, F, 1, S ),
|
||||
CMD( MI_SUSPEND_FLUSH, SMI, F, 1, S ),
|
||||
@@ -311,7 +305,7 @@ static const struct drm_i915_cmd_descrip
|
||||
CMD( MI_URB_ATOMIC_ALLOC, SMI, F, 1, S ),
|
||||
CMD( MI_SET_APPID, SMI, F, 1, S ),
|
||||
CMD( MI_RS_CONTEXT, SMI, F, 1, S ),
|
||||
- CMD( MI_LOAD_SCAN_LINES_INCL, SMI, !F, 0x3F, M ),
|
||||
+ CMD( MI_LOAD_SCAN_LINES_INCL, SMI, !F, 0x3F, R ),
|
||||
CMD( MI_LOAD_SCAN_LINES_EXCL, SMI, !F, 0x3F, R ),
|
||||
CMD( MI_LOAD_REGISTER_REG, SMI, !F, 0xFF, W,
|
||||
.reg = { .offset = 1, .mask = 0x007FFFFC, .step = 1 } ),
|
||||
@@ -444,7 +438,7 @@ static const struct drm_i915_cmd_descrip
|
||||
};
|
||||
|
||||
static const struct drm_i915_cmd_descriptor hsw_blt_cmds[] = {
|
||||
- CMD( MI_LOAD_SCAN_LINES_INCL, SMI, !F, 0x3F, M ),
|
||||
+ CMD( MI_LOAD_SCAN_LINES_INCL, SMI, !F, 0x3F, R ),
|
||||
CMD( MI_LOAD_SCAN_LINES_EXCL, SMI, !F, 0x3F, R ),
|
||||
};
|
||||
|
||||
@@ -461,7 +455,6 @@ static const struct drm_i915_cmd_descrip
|
||||
#undef R
|
||||
#undef W
|
||||
#undef B
|
||||
-#undef M
|
||||
|
||||
static const struct drm_i915_cmd_table gen7_render_cmd_table[] = {
|
||||
{ gen7_common_cmds, ARRAY_SIZE(gen7_common_cmds) },
|
||||
@@ -610,47 +603,29 @@ static const struct drm_i915_reg_descrip
|
||||
REG64_IDX(RING_TIMESTAMP, BLT_RING_BASE),
|
||||
};
|
||||
|
||||
-static const struct drm_i915_reg_descriptor ivb_master_regs[] = {
|
||||
- REG32(FORCEWAKE_MT),
|
||||
- REG32(DERRMR),
|
||||
- REG32(GEN7_PIPE_DE_LOAD_SL(PIPE_A)),
|
||||
- REG32(GEN7_PIPE_DE_LOAD_SL(PIPE_B)),
|
||||
- REG32(GEN7_PIPE_DE_LOAD_SL(PIPE_C)),
|
||||
-};
|
||||
-
|
||||
-static const struct drm_i915_reg_descriptor hsw_master_regs[] = {
|
||||
- REG32(FORCEWAKE_MT),
|
||||
- REG32(DERRMR),
|
||||
-};
|
||||
-
|
||||
#undef REG64
|
||||
#undef REG32
|
||||
|
||||
struct drm_i915_reg_table {
|
||||
const struct drm_i915_reg_descriptor *regs;
|
||||
int num_regs;
|
||||
- bool master;
|
||||
};
|
||||
|
||||
static const struct drm_i915_reg_table ivb_render_reg_tables[] = {
|
||||
- { gen7_render_regs, ARRAY_SIZE(gen7_render_regs), false },
|
||||
- { ivb_master_regs, ARRAY_SIZE(ivb_master_regs), true },
|
||||
+ { gen7_render_regs, ARRAY_SIZE(gen7_render_regs) },
|
||||
};
|
||||
|
||||
static const struct drm_i915_reg_table ivb_blt_reg_tables[] = {
|
||||
- { gen7_blt_regs, ARRAY_SIZE(gen7_blt_regs), false },
|
||||
- { ivb_master_regs, ARRAY_SIZE(ivb_master_regs), true },
|
||||
+ { gen7_blt_regs, ARRAY_SIZE(gen7_blt_regs) },
|
||||
};
|
||||
|
||||
static const struct drm_i915_reg_table hsw_render_reg_tables[] = {
|
||||
- { gen7_render_regs, ARRAY_SIZE(gen7_render_regs), false },
|
||||
- { hsw_render_regs, ARRAY_SIZE(hsw_render_regs), false },
|
||||
- { hsw_master_regs, ARRAY_SIZE(hsw_master_regs), true },
|
||||
+ { gen7_render_regs, ARRAY_SIZE(gen7_render_regs) },
|
||||
+ { hsw_render_regs, ARRAY_SIZE(hsw_render_regs) },
|
||||
};
|
||||
|
||||
static const struct drm_i915_reg_table hsw_blt_reg_tables[] = {
|
||||
- { gen7_blt_regs, ARRAY_SIZE(gen7_blt_regs), false },
|
||||
- { hsw_master_regs, ARRAY_SIZE(hsw_master_regs), true },
|
||||
+ { gen7_blt_regs, ARRAY_SIZE(gen7_blt_regs) },
|
||||
};
|
||||
|
||||
static u32 gen7_render_get_cmd_length_mask(u32 cmd_header)
|
||||
@@ -1027,22 +1002,16 @@ __find_reg(const struct drm_i915_reg_des
|
||||
}
|
||||
|
||||
static const struct drm_i915_reg_descriptor *
|
||||
-find_reg(const struct intel_engine_cs *engine, bool is_master, u32 addr)
|
||||
+find_reg(const struct intel_engine_cs *engine, u32 addr)
|
||||
{
|
||||
const struct drm_i915_reg_table *table = engine->reg_tables;
|
||||
+ const struct drm_i915_reg_descriptor *reg = NULL;
|
||||
int count = engine->reg_table_count;
|
||||
|
||||
- for (; count > 0; ++table, --count) {
|
||||
- if (!table->master || is_master) {
|
||||
- const struct drm_i915_reg_descriptor *reg;
|
||||
-
|
||||
- reg = __find_reg(table->regs, table->num_regs, addr);
|
||||
- if (reg != NULL)
|
||||
- return reg;
|
||||
- }
|
||||
- }
|
||||
+ for (; !reg && (count > 0); ++table, --count)
|
||||
+ reg = __find_reg(table->regs, table->num_regs, addr);
|
||||
|
||||
- return NULL;
|
||||
+ return reg;
|
||||
}
|
||||
|
||||
/* Returns a vmap'd pointer to dst_obj, which the caller must unmap */
|
||||
@@ -1127,8 +1096,7 @@ unpin_src:
|
||||
|
||||
static bool check_cmd(const struct intel_engine_cs *engine,
|
||||
const struct drm_i915_cmd_descriptor *desc,
|
||||
- const u32 *cmd, u32 length,
|
||||
- const bool is_master)
|
||||
+ const u32 *cmd, u32 length)
|
||||
{
|
||||
if (desc->flags & CMD_DESC_SKIP)
|
||||
return true;
|
||||
@@ -1138,12 +1106,6 @@ static bool check_cmd(const struct intel
|
||||
return false;
|
||||
}
|
||||
|
||||
- if ((desc->flags & CMD_DESC_MASTER) && !is_master) {
|
||||
- DRM_DEBUG_DRIVER("CMD: Rejected master-only command: 0x%08X\n",
|
||||
- *cmd);
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
if (desc->flags & CMD_DESC_REGISTER) {
|
||||
/*
|
||||
* Get the distance between individual register offset
|
||||
@@ -1157,7 +1119,7 @@ static bool check_cmd(const struct intel
|
||||
offset += step) {
|
||||
const u32 reg_addr = cmd[offset] & desc->reg.mask;
|
||||
const struct drm_i915_reg_descriptor *reg =
|
||||
- find_reg(engine, is_master, reg_addr);
|
||||
+ find_reg(engine, reg_addr);
|
||||
|
||||
if (!reg) {
|
||||
DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (%s)\n",
|
||||
@@ -1244,7 +1206,6 @@ static bool check_cmd(const struct intel
|
||||
* @shadow_batch_obj: copy of the batch buffer in question
|
||||
* @batch_start_offset: byte offset in the batch at which execution starts
|
||||
* @batch_len: length of the commands in batch_obj
|
||||
- * @is_master: is the submitting process the drm master?
|
||||
*
|
||||
* Parses the specified batch buffer looking for privilege violations as
|
||||
* described in the overview.
|
||||
@@ -1256,8 +1217,7 @@ int intel_engine_cmd_parser(struct intel
|
||||
struct drm_i915_gem_object *batch_obj,
|
||||
struct drm_i915_gem_object *shadow_batch_obj,
|
||||
u32 batch_start_offset,
|
||||
- u32 batch_len,
|
||||
- bool is_master)
|
||||
+ u32 batch_len)
|
||||
{
|
||||
u32 *cmd, *batch_end;
|
||||
struct drm_i915_cmd_descriptor default_desc = noop_desc;
|
||||
@@ -1323,7 +1283,7 @@ int intel_engine_cmd_parser(struct intel
|
||||
break;
|
||||
}
|
||||
|
||||
- if (!check_cmd(engine, desc, cmd, length, is_master)) {
|
||||
+ if (!check_cmd(engine, desc, cmd, length)) {
|
||||
ret = -EACCES;
|
||||
break;
|
||||
}
|
||||
--- a/drivers/gpu/drm/i915/i915_drv.h
|
||||
+++ b/drivers/gpu/drm/i915/i915_drv.h
|
||||
@@ -3343,8 +3343,7 @@ int intel_engine_cmd_parser(struct intel
|
||||
struct drm_i915_gem_object *batch_obj,
|
||||
struct drm_i915_gem_object *shadow_batch_obj,
|
||||
u32 batch_start_offset,
|
||||
- u32 batch_len,
|
||||
- bool is_master);
|
||||
+ u32 batch_len);
|
||||
|
||||
/* i915_perf.c */
|
||||
extern void i915_perf_init(struct drm_i915_private *dev_priv);
|
||||
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
|
||||
@@ -1893,7 +1893,7 @@ static int i915_reset_gen7_sol_offsets(s
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static struct i915_vma *eb_parse(struct i915_execbuffer *eb, bool is_master)
|
||||
+static struct i915_vma *eb_parse(struct i915_execbuffer *eb)
|
||||
{
|
||||
struct drm_i915_gem_object *shadow_batch_obj;
|
||||
struct i915_vma *vma;
|
||||
@@ -1908,8 +1908,7 @@ static struct i915_vma *eb_parse(struct
|
||||
eb->batch->obj,
|
||||
shadow_batch_obj,
|
||||
eb->batch_start_offset,
|
||||
- eb->batch_len,
|
||||
- is_master);
|
||||
+ eb->batch_len);
|
||||
if (err) {
|
||||
if (err == -EACCES) /* unhandled chained batch */
|
||||
vma = NULL;
|
||||
@@ -2308,7 +2307,7 @@ i915_gem_do_execbuffer(struct drm_device
|
||||
if (eb_use_cmdparser(&eb)) {
|
||||
struct i915_vma *vma;
|
||||
|
||||
- vma = eb_parse(&eb, drm_is_current_master(file));
|
||||
+ vma = eb_parse(&eb);
|
||||
if (IS_ERR(vma)) {
|
||||
err = PTR_ERR(vma);
|
||||
goto err_vma;
|
110
debian/patches/bugfix/x86/i915/0004-drm-i915-Add-support-for-mandatory-cmdparsing.patch
vendored
Normal file
110
debian/patches/bugfix/x86/i915/0004-drm-i915-Add-support-for-mandatory-cmdparsing.patch
vendored
Normal file
|
@ -0,0 +1,110 @@
|
|||
From: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Date: Wed, 1 Aug 2018 09:33:59 -0700
|
||||
Subject: drm/i915: Add support for mandatory cmdparsing
|
||||
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-0155
|
||||
|
||||
commit 311a50e76a33d1e029563c24b2ff6db0c02b5afe upstream.
|
||||
|
||||
The existing cmdparser for gen7 can be bypassed by specifying
|
||||
batch_len=0 in the execbuf call. This is safe because bypassing
|
||||
simply reduces the cmd-set available.
|
||||
|
||||
In a later patch we will introduce cmdparsing for gen9, as a
|
||||
security measure, which must be strictly enforced since without
|
||||
it we are vulnerable to DoS attacks.
|
||||
|
||||
Introduce the concept of 'required' cmd parsing that cannot be
|
||||
bypassed by submitting zero-length bb's.
|
||||
|
||||
v2: rebase (Mika)
|
||||
v2: rebase (Mika)
|
||||
v3: fix conflict on engine flags (Mika)
|
||||
|
||||
Signed-off-by: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Cc: Tony Luck <tony.luck@intel.com>
|
||||
Cc: Dave Airlie <airlied@redhat.com>
|
||||
Cc: Takashi Iwai <tiwai@suse.de>
|
||||
Cc: Tyler Hicks <tyhicks@canonical.com>
|
||||
Signed-off-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
|
||||
Reviewed-by: Chris Wilson <chris.p.wilson@intel.com>
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_cmd_parser.c | 6 +++---
|
||||
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 3 ++-
|
||||
drivers/gpu/drm/i915/intel_ringbuffer.h | 17 ++++++++++++-----
|
||||
3 files changed, 17 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
|
||||
@@ -916,7 +916,7 @@ void intel_engine_init_cmd_parser(struct
|
||||
return;
|
||||
}
|
||||
|
||||
- engine->flags |= I915_ENGINE_NEEDS_CMD_PARSER;
|
||||
+ engine->flags |= I915_ENGINE_USING_CMD_PARSER;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -928,7 +928,7 @@ void intel_engine_init_cmd_parser(struct
|
||||
*/
|
||||
void intel_engine_cleanup_cmd_parser(struct intel_engine_cs *engine)
|
||||
{
|
||||
- if (!intel_engine_needs_cmd_parser(engine))
|
||||
+ if (!intel_engine_using_cmd_parser(engine))
|
||||
return;
|
||||
|
||||
fini_hash_table(engine);
|
||||
@@ -1317,7 +1317,7 @@ int i915_cmd_parser_get_version(struct d
|
||||
|
||||
/* If the command parser is not enabled, report 0 - unsupported */
|
||||
for_each_engine(engine, dev_priv, id) {
|
||||
- if (intel_engine_needs_cmd_parser(engine)) {
|
||||
+ if (intel_engine_using_cmd_parser(engine)) {
|
||||
active = true;
|
||||
break;
|
||||
}
|
||||
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
|
||||
@@ -309,7 +309,8 @@ static inline u64 gen8_noncanonical_addr
|
||||
|
||||
static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb)
|
||||
{
|
||||
- return intel_engine_needs_cmd_parser(eb->engine) && eb->batch_len;
|
||||
+ return intel_engine_requires_cmd_parser(eb->engine) ||
|
||||
+ (intel_engine_using_cmd_parser(eb->engine) && eb->batch_len);
|
||||
}
|
||||
|
||||
static int eb_create(struct i915_execbuffer *eb)
|
||||
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
|
||||
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
|
||||
@@ -584,9 +584,10 @@ struct intel_engine_cs {
|
||||
|
||||
struct intel_engine_hangcheck hangcheck;
|
||||
|
||||
-#define I915_ENGINE_NEEDS_CMD_PARSER BIT(0)
|
||||
-#define I915_ENGINE_SUPPORTS_STATS BIT(1)
|
||||
-#define I915_ENGINE_HAS_PREEMPTION BIT(2)
|
||||
+#define I915_ENGINE_USING_CMD_PARSER BIT(0)
|
||||
+#define I915_ENGINE_SUPPORTS_STATS BIT(1)
|
||||
+#define I915_ENGINE_HAS_PREEMPTION BIT(2)
|
||||
+#define I915_ENGINE_REQUIRES_CMD_PARSER BIT(3)
|
||||
unsigned int flags;
|
||||
|
||||
/*
|
||||
@@ -647,9 +648,15 @@ struct intel_engine_cs {
|
||||
};
|
||||
|
||||
static inline bool
|
||||
-intel_engine_needs_cmd_parser(const struct intel_engine_cs *engine)
|
||||
+intel_engine_using_cmd_parser(const struct intel_engine_cs *engine)
|
||||
{
|
||||
- return engine->flags & I915_ENGINE_NEEDS_CMD_PARSER;
|
||||
+ return engine->flags & I915_ENGINE_USING_CMD_PARSER;
|
||||
+}
|
||||
+
|
||||
+static inline bool
|
||||
+intel_engine_requires_cmd_parser(const struct intel_engine_cs *engine)
|
||||
+{
|
||||
+ return engine->flags & I915_ENGINE_REQUIRES_CMD_PARSER;
|
||||
}
|
||||
|
||||
static inline bool
|
198
debian/patches/bugfix/x86/i915/0005-drm-i915-Support-ro-ppgtt-mapped-cmdparser-shadow-bu.patch
vendored
Normal file
198
debian/patches/bugfix/x86/i915/0005-drm-i915-Support-ro-ppgtt-mapped-cmdparser-shadow-bu.patch
vendored
Normal file
|
@ -0,0 +1,198 @@
|
|||
From: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Date: Tue, 22 May 2018 13:59:06 -0700
|
||||
Subject: drm/i915: Support ro ppgtt mapped cmdparser shadow buffers
|
||||
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-0155
|
||||
|
||||
commit 4f7af1948abcb18b4772fe1bcd84d7d27d96258c upstream.
|
||||
|
||||
For Gen7, the original cmdparser motive was to permit limited
|
||||
use of register read/write instructions in unprivileged BB's.
|
||||
This worked by copying the user supplied bb to a kmd owned
|
||||
bb, and running it in secure mode, from the ggtt, only if
|
||||
the scanner finds no unsafe commands or registers.
|
||||
|
||||
For Gen8+ we can't use this same technique because running bb's
|
||||
from the ggtt also disables access to ppgtt space. But we also
|
||||
do not actually require 'secure' execution since we are only
|
||||
trying to reduce the available command/register set. Instead we
|
||||
will copy the user buffer to a kmd owned read-only bb in ppgtt,
|
||||
and run in the usual non-secure mode.
|
||||
|
||||
Note that ro pages are only supported by ppgtt (not ggtt), but
|
||||
luckily that's exactly what we need.
|
||||
|
||||
Add the required paths to map the shadow buffer to ppgtt ro for Gen8+
|
||||
|
||||
v2: IS_GEN7/IS_GEN (Mika)
|
||||
v3: rebase
|
||||
v4: rebase
|
||||
v5: rebase
|
||||
|
||||
Signed-off-by: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Cc: Tony Luck <tony.luck@intel.com>
|
||||
Cc: Dave Airlie <airlied@redhat.com>
|
||||
Cc: Takashi Iwai <tiwai@suse.de>
|
||||
Cc: Tyler Hicks <tyhicks@canonical.com>
|
||||
Signed-off-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
|
||||
Reviewed-by: Chris Wilson <chris.p.wilson@intel.com>
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_drv.h | 14 ++++++
|
||||
drivers/gpu/drm/i915/i915_gem.c | 16 +++++-
|
||||
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 57 +++++++++++++++-------
|
||||
3 files changed, 68 insertions(+), 19 deletions(-)
|
||||
|
||||
--- a/drivers/gpu/drm/i915/i915_drv.h
|
||||
+++ b/drivers/gpu/drm/i915/i915_drv.h
|
||||
@@ -2496,6 +2496,12 @@ intel_info(const struct drm_i915_private
|
||||
#define IS_GEN9_LP(dev_priv) (IS_GEN9(dev_priv) && IS_LP(dev_priv))
|
||||
#define IS_GEN9_BC(dev_priv) (IS_GEN9(dev_priv) && !IS_LP(dev_priv))
|
||||
|
||||
+/*
|
||||
+ * The Gen7 cmdparser copies the scanned buffer to the ggtt for execution
|
||||
+ * All later gens can run the final buffer from the ppgtt
|
||||
+ */
|
||||
+#define CMDPARSER_USES_GGTT(dev_priv) IS_GEN7(dev_priv)
|
||||
+
|
||||
#define ENGINE_MASK(id) BIT(id)
|
||||
#define RENDER_RING ENGINE_MASK(RCS)
|
||||
#define BSD_RING ENGINE_MASK(VCS)
|
||||
@@ -2946,6 +2952,14 @@ i915_gem_object_ggtt_pin(struct drm_i915
|
||||
u64 alignment,
|
||||
u64 flags);
|
||||
|
||||
+struct i915_vma * __must_check
|
||||
+i915_gem_object_pin(struct drm_i915_gem_object *obj,
|
||||
+ struct i915_address_space *vm,
|
||||
+ const struct i915_ggtt_view *view,
|
||||
+ u64 size,
|
||||
+ u64 alignment,
|
||||
+ u64 flags);
|
||||
+
|
||||
int i915_gem_object_unbind(struct drm_i915_gem_object *obj);
|
||||
void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
|
||||
|
||||
--- a/drivers/gpu/drm/i915/i915_gem.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_gem.c
|
||||
@@ -4414,6 +4414,20 @@ i915_gem_object_ggtt_pin(struct drm_i915
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
|
||||
struct i915_address_space *vm = &dev_priv->ggtt.vm;
|
||||
+
|
||||
+ return i915_gem_object_pin(obj, vm, view, size, alignment,
|
||||
+ flags | PIN_GLOBAL);
|
||||
+}
|
||||
+
|
||||
+struct i915_vma *
|
||||
+i915_gem_object_pin(struct drm_i915_gem_object *obj,
|
||||
+ struct i915_address_space *vm,
|
||||
+ const struct i915_ggtt_view *view,
|
||||
+ u64 size,
|
||||
+ u64 alignment,
|
||||
+ u64 flags)
|
||||
+{
|
||||
+ struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
|
||||
struct i915_vma *vma;
|
||||
int ret;
|
||||
|
||||
@@ -4477,7 +4491,7 @@ i915_gem_object_ggtt_pin(struct drm_i915
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
- ret = i915_vma_pin(vma, size, alignment, flags | PIN_GLOBAL);
|
||||
+ ret = i915_vma_pin(vma, size, alignment, flags);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
|
||||
@@ -1894,6 +1894,33 @@ static int i915_reset_gen7_sol_offsets(s
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static struct i915_vma *
|
||||
+shadow_batch_pin(struct i915_execbuffer *eb, struct drm_i915_gem_object *obj)
|
||||
+{
|
||||
+ struct drm_i915_private *dev_priv = eb->i915;
|
||||
+ struct i915_address_space *vm;
|
||||
+ u64 flags;
|
||||
+
|
||||
+ /*
|
||||
+ * PPGTT backed shadow buffers must be mapped RO, to prevent
|
||||
+ * post-scan tampering
|
||||
+ */
|
||||
+ if (CMDPARSER_USES_GGTT(dev_priv)) {
|
||||
+ flags = PIN_GLOBAL;
|
||||
+ vm = &dev_priv->ggtt.vm;
|
||||
+ eb->batch_flags |= I915_DISPATCH_SECURE;
|
||||
+ } else if (eb->vm->has_read_only) {
|
||||
+ flags = PIN_USER;
|
||||
+ vm = eb->vm;
|
||||
+ i915_gem_object_set_readonly(obj);
|
||||
+ } else {
|
||||
+ DRM_DEBUG("Cannot prevent post-scan tampering without RO capable vm\n");
|
||||
+ return ERR_PTR(-EINVAL);
|
||||
+ }
|
||||
+
|
||||
+ return i915_gem_object_pin(obj, vm, NULL, 0, 0, flags);
|
||||
+}
|
||||
+
|
||||
static struct i915_vma *eb_parse(struct i915_execbuffer *eb)
|
||||
{
|
||||
struct drm_i915_gem_object *shadow_batch_obj;
|
||||
@@ -1911,14 +1938,21 @@ static struct i915_vma *eb_parse(struct
|
||||
eb->batch_start_offset,
|
||||
eb->batch_len);
|
||||
if (err) {
|
||||
- if (err == -EACCES) /* unhandled chained batch */
|
||||
+ /*
|
||||
+ * Unsafe GGTT-backed buffers can still be submitted safely
|
||||
+ * as non-secure.
|
||||
+ * For PPGTT backing however, we have no choice but to forcibly
|
||||
+ * reject unsafe buffers
|
||||
+ */
|
||||
+ if (CMDPARSER_USES_GGTT(eb->i915) && (err == -EACCES))
|
||||
+ /* Execute original buffer non-secure */
|
||||
vma = NULL;
|
||||
else
|
||||
vma = ERR_PTR(err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
- vma = i915_gem_object_ggtt_pin(shadow_batch_obj, NULL, 0, 0, 0);
|
||||
+ vma = shadow_batch_pin(eb, shadow_batch_obj);
|
||||
if (IS_ERR(vma))
|
||||
goto out;
|
||||
|
||||
@@ -1927,7 +1961,9 @@ static struct i915_vma *eb_parse(struct
|
||||
__EXEC_OBJECT_HAS_PIN | __EXEC_OBJECT_HAS_REF;
|
||||
vma->exec_flags = &eb->flags[eb->buffer_count];
|
||||
eb->buffer_count++;
|
||||
-
|
||||
+ eb->batch_start_offset = 0;
|
||||
+ eb->batch = vma;
|
||||
+ /* eb->batch_len unchanged */
|
||||
out:
|
||||
i915_gem_object_unpin_pages(shadow_batch_obj);
|
||||
return vma;
|
||||
@@ -2313,21 +2349,6 @@ i915_gem_do_execbuffer(struct drm_device
|
||||
err = PTR_ERR(vma);
|
||||
goto err_vma;
|
||||
}
|
||||
-
|
||||
- if (vma) {
|
||||
- /*
|
||||
- * Batch parsed and accepted:
|
||||
- *
|
||||
- * Set the DISPATCH_SECURE bit to remove the NON_SECURE
|
||||
- * bit from MI_BATCH_BUFFER_START commands issued in
|
||||
- * the dispatch_execbuffer implementations. We
|
||||
- * specifically don't want that set on batches the
|
||||
- * command parser has accepted.
|
||||
- */
|
||||
- eb.batch_flags |= I915_DISPATCH_SECURE;
|
||||
- eb.batch_start_offset = 0;
|
||||
- eb.batch = vma;
|
||||
- }
|
||||
}
|
||||
|
||||
if (eb.batch_len == 0)
|
57
debian/patches/bugfix/x86/i915/0006-drm-i915-Allow-parsing-of-unsized-batches.patch
vendored
Normal file
57
debian/patches/bugfix/x86/i915/0006-drm-i915-Allow-parsing-of-unsized-batches.patch
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
From: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Date: Wed, 1 Aug 2018 09:45:50 -0700
|
||||
Subject: drm/i915: Allow parsing of unsized batches
|
||||
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-0155
|
||||
|
||||
commit 435e8fc059dbe0eec823a75c22da2972390ba9e0 upstream.
|
||||
|
||||
In "drm/i915: Add support for mandatory cmdparsing" we introduced the
|
||||
concept of mandatory parsing. This allows the cmdparser to be invoked
|
||||
even when user passes batch_len=0 to the execbuf ioctl's.
|
||||
|
||||
However, the cmdparser needs to know the extents of the buffer being
|
||||
scanned. Refactor the code to ensure the cmdparser uses the actual
|
||||
object size, instead of the incoming length, if user passes 0.
|
||||
|
||||
Signed-off-by: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Cc: Tony Luck <tony.luck@intel.com>
|
||||
Cc: Dave Airlie <airlied@redhat.com>
|
||||
Cc: Takashi Iwai <tiwai@suse.de>
|
||||
Cc: Tyler Hicks <tyhicks@canonical.com>
|
||||
Reviewed-by: Chris Wilson <chris.p.wilson@intel.com>
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 9 +++++----
|
||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
|
||||
@@ -310,7 +310,8 @@ static inline u64 gen8_noncanonical_addr
|
||||
static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb)
|
||||
{
|
||||
return intel_engine_requires_cmd_parser(eb->engine) ||
|
||||
- (intel_engine_using_cmd_parser(eb->engine) && eb->batch_len);
|
||||
+ (intel_engine_using_cmd_parser(eb->engine) &&
|
||||
+ eb->args->batch_len);
|
||||
}
|
||||
|
||||
static int eb_create(struct i915_execbuffer *eb)
|
||||
@@ -2341,6 +2342,9 @@ i915_gem_do_execbuffer(struct drm_device
|
||||
goto err_vma;
|
||||
}
|
||||
|
||||
+ if (eb.batch_len == 0)
|
||||
+ eb.batch_len = eb.batch->size - eb.batch_start_offset;
|
||||
+
|
||||
if (eb_use_cmdparser(&eb)) {
|
||||
struct i915_vma *vma;
|
||||
|
||||
@@ -2351,9 +2355,6 @@ i915_gem_do_execbuffer(struct drm_device
|
||||
}
|
||||
}
|
||||
|
||||
- if (eb.batch_len == 0)
|
||||
- eb.batch_len = eb.batch->size - eb.batch_start_offset;
|
||||
-
|
||||
/*
|
||||
* snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure
|
||||
* batch" bit. Hence we need to pin secure batches into the global gtt.
|
|
@ -0,0 +1,258 @@
|
|||
From: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Date: Mon, 23 Apr 2018 11:12:15 -0700
|
||||
Subject: drm/i915: Add gen9 BCS cmdparsing
|
||||
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-0155
|
||||
|
||||
commit 0f2f39758341df70202ae1c42d5a1e4ee392b6d3 upstream.
|
||||
|
||||
For gen9 we enable cmdparsing on the BCS ring, specifically
|
||||
to catch inadvertent accesses to sensitive registers
|
||||
|
||||
Unlike gen7/hsw, we use the parser only to block certain
|
||||
registers. We can rely on h/w to block restricted commands,
|
||||
so the command tables only provide enough info to allow the
|
||||
parser to delineate each command, and identify commands that
|
||||
access registers.
|
||||
|
||||
Note: This patch deliberately ignores checkpatch issues in
|
||||
favour of matching the style of the surrounding code. We'll
|
||||
correct the entire file in one go in a later patch.
|
||||
|
||||
Signed-off-by: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Cc: Tony Luck <tony.luck@intel.com>
|
||||
Cc: Dave Airlie <airlied@redhat.com>
|
||||
Cc: Takashi Iwai <tiwai@suse.de>
|
||||
Cc: Tyler Hicks <tyhicks@canonical.com>
|
||||
Signed-off-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
|
||||
Reviewed-by: Chris Wilson <chris.p.wilson@intel.com>
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_cmd_parser.c | 116 ++++++++++++++++++++++---
|
||||
drivers/gpu/drm/i915/i915_gem_gtt.c | 3 +-
|
||||
drivers/gpu/drm/i915/i915_reg.h | 4 +
|
||||
3 files changed, 112 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
|
||||
@@ -442,6 +442,47 @@ static const struct drm_i915_cmd_descrip
|
||||
CMD( MI_LOAD_SCAN_LINES_EXCL, SMI, !F, 0x3F, R ),
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * For Gen9 we can still rely on the h/w to enforce cmd security, and only
|
||||
+ * need to re-enforce the register access checks. We therefore only need to
|
||||
+ * teach the cmdparser how to find the end of each command, and identify
|
||||
+ * register accesses. The table doesn't need to reject any commands, and so
|
||||
+ * the only commands listed here are:
|
||||
+ * 1) Those that touch registers
|
||||
+ * 2) Those that do not have the default 8-bit length
|
||||
+ *
|
||||
+ * Note that the default MI length mask chosen for this table is 0xFF, not
|
||||
+ * the 0x3F used on older devices. This is because the vast majority of MI
|
||||
+ * cmds on Gen9 use a standard 8-bit Length field.
|
||||
+ * All the Gen9 blitter instructions are standard 0xFF length mask, and
|
||||
+ * none allow access to non-general registers, so in fact no BLT cmds are
|
||||
+ * included in the table at all.
|
||||
+ *
|
||||
+ */
|
||||
+static const struct drm_i915_cmd_descriptor gen9_blt_cmds[] = {
|
||||
+ CMD( MI_NOOP, SMI, F, 1, S ),
|
||||
+ CMD( MI_USER_INTERRUPT, SMI, F, 1, S ),
|
||||
+ CMD( MI_WAIT_FOR_EVENT, SMI, F, 1, S ),
|
||||
+ CMD( MI_FLUSH, SMI, F, 1, S ),
|
||||
+ CMD( MI_ARB_CHECK, SMI, F, 1, S ),
|
||||
+ CMD( MI_REPORT_HEAD, SMI, F, 1, S ),
|
||||
+ CMD( MI_ARB_ON_OFF, SMI, F, 1, S ),
|
||||
+ CMD( MI_SUSPEND_FLUSH, SMI, F, 1, S ),
|
||||
+ CMD( MI_LOAD_SCAN_LINES_INCL, SMI, !F, 0x3F, S ),
|
||||
+ CMD( MI_LOAD_SCAN_LINES_EXCL, SMI, !F, 0x3F, S ),
|
||||
+ CMD( MI_STORE_DWORD_IMM, SMI, !F, 0x3FF, S ),
|
||||
+ CMD( MI_LOAD_REGISTER_IMM(1), SMI, !F, 0xFF, W,
|
||||
+ .reg = { .offset = 1, .mask = 0x007FFFFC, .step = 2 } ),
|
||||
+ CMD( MI_UPDATE_GTT, SMI, !F, 0x3FF, S ),
|
||||
+ CMD( MI_STORE_REGISTER_MEM_GEN8, SMI, F, 4, W,
|
||||
+ .reg = { .offset = 1, .mask = 0x007FFFFC } ),
|
||||
+ CMD( MI_FLUSH_DW, SMI, !F, 0x3F, S ),
|
||||
+ CMD( MI_LOAD_REGISTER_MEM_GEN8, SMI, F, 4, W,
|
||||
+ .reg = { .offset = 1, .mask = 0x007FFFFC } ),
|
||||
+ CMD( MI_LOAD_REGISTER_REG, SMI, !F, 0xFF, W,
|
||||
+ .reg = { .offset = 1, .mask = 0x007FFFFC, .step = 1 } ),
|
||||
+};
|
||||
+
|
||||
static const struct drm_i915_cmd_descriptor noop_desc =
|
||||
CMD(MI_NOOP, SMI, F, 1, S);
|
||||
|
||||
@@ -488,6 +529,11 @@ static const struct drm_i915_cmd_table h
|
||||
{ hsw_blt_cmds, ARRAY_SIZE(hsw_blt_cmds) },
|
||||
};
|
||||
|
||||
+static const struct drm_i915_cmd_table gen9_blt_cmd_table[] = {
|
||||
+ { gen9_blt_cmds, ARRAY_SIZE(gen9_blt_cmds) },
|
||||
+};
|
||||
+
|
||||
+
|
||||
/*
|
||||
* Register whitelists, sorted by increasing register offset.
|
||||
*/
|
||||
@@ -603,6 +649,29 @@ static const struct drm_i915_reg_descrip
|
||||
REG64_IDX(RING_TIMESTAMP, BLT_RING_BASE),
|
||||
};
|
||||
|
||||
+static const struct drm_i915_reg_descriptor gen9_blt_regs[] = {
|
||||
+ REG64_IDX(RING_TIMESTAMP, RENDER_RING_BASE),
|
||||
+ REG64_IDX(RING_TIMESTAMP, BSD_RING_BASE),
|
||||
+ REG32(BCS_SWCTRL),
|
||||
+ REG64_IDX(RING_TIMESTAMP, BLT_RING_BASE),
|
||||
+ REG64_IDX(BCS_GPR, 0),
|
||||
+ REG64_IDX(BCS_GPR, 1),
|
||||
+ REG64_IDX(BCS_GPR, 2),
|
||||
+ REG64_IDX(BCS_GPR, 3),
|
||||
+ REG64_IDX(BCS_GPR, 4),
|
||||
+ REG64_IDX(BCS_GPR, 5),
|
||||
+ REG64_IDX(BCS_GPR, 6),
|
||||
+ REG64_IDX(BCS_GPR, 7),
|
||||
+ REG64_IDX(BCS_GPR, 8),
|
||||
+ REG64_IDX(BCS_GPR, 9),
|
||||
+ REG64_IDX(BCS_GPR, 10),
|
||||
+ REG64_IDX(BCS_GPR, 11),
|
||||
+ REG64_IDX(BCS_GPR, 12),
|
||||
+ REG64_IDX(BCS_GPR, 13),
|
||||
+ REG64_IDX(BCS_GPR, 14),
|
||||
+ REG64_IDX(BCS_GPR, 15),
|
||||
+};
|
||||
+
|
||||
#undef REG64
|
||||
#undef REG32
|
||||
|
||||
@@ -628,6 +697,10 @@ static const struct drm_i915_reg_table h
|
||||
{ gen7_blt_regs, ARRAY_SIZE(gen7_blt_regs) },
|
||||
};
|
||||
|
||||
+static const struct drm_i915_reg_table gen9_blt_reg_tables[] = {
|
||||
+ { gen9_blt_regs, ARRAY_SIZE(gen9_blt_regs) },
|
||||
+};
|
||||
+
|
||||
static u32 gen7_render_get_cmd_length_mask(u32 cmd_header)
|
||||
{
|
||||
u32 client = cmd_header >> INSTR_CLIENT_SHIFT;
|
||||
@@ -683,6 +756,17 @@ static u32 gen7_blt_get_cmd_length_mask(
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static u32 gen9_blt_get_cmd_length_mask(u32 cmd_header)
|
||||
+{
|
||||
+ u32 client = cmd_header >> INSTR_CLIENT_SHIFT;
|
||||
+
|
||||
+ if (client == INSTR_MI_CLIENT || client == INSTR_BC_CLIENT)
|
||||
+ return 0xFF;
|
||||
+
|
||||
+ DRM_DEBUG_DRIVER("CMD: Abnormal blt cmd length! 0x%08X\n", cmd_header);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static bool validate_cmds_sorted(const struct intel_engine_cs *engine,
|
||||
const struct drm_i915_cmd_table *cmd_tables,
|
||||
int cmd_table_count)
|
||||
@@ -840,7 +924,8 @@ void intel_engine_init_cmd_parser(struct
|
||||
int cmd_table_count;
|
||||
int ret;
|
||||
|
||||
- if (!IS_GEN7(engine->i915))
|
||||
+ if (!IS_GEN7(engine->i915) && !(IS_GEN9(engine->i915) &&
|
||||
+ engine->id == BCS))
|
||||
return;
|
||||
|
||||
switch (engine->id) {
|
||||
@@ -861,7 +946,6 @@ void intel_engine_init_cmd_parser(struct
|
||||
engine->reg_tables = ivb_render_reg_tables;
|
||||
engine->reg_table_count = ARRAY_SIZE(ivb_render_reg_tables);
|
||||
}
|
||||
-
|
||||
engine->get_cmd_length_mask = gen7_render_get_cmd_length_mask;
|
||||
break;
|
||||
case VCS:
|
||||
@@ -870,7 +954,16 @@ void intel_engine_init_cmd_parser(struct
|
||||
engine->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
|
||||
break;
|
||||
case BCS:
|
||||
- if (IS_HASWELL(engine->i915)) {
|
||||
+ engine->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
|
||||
+ if (IS_GEN9(engine->i915)) {
|
||||
+ cmd_tables = gen9_blt_cmd_table;
|
||||
+ cmd_table_count = ARRAY_SIZE(gen9_blt_cmd_table);
|
||||
+ engine->get_cmd_length_mask =
|
||||
+ gen9_blt_get_cmd_length_mask;
|
||||
+
|
||||
+ /* BCS Engine unsafe without parser */
|
||||
+ engine->flags |= I915_ENGINE_REQUIRES_CMD_PARSER;
|
||||
+ } else if (IS_HASWELL(engine->i915)) {
|
||||
cmd_tables = hsw_blt_ring_cmd_table;
|
||||
cmd_table_count = ARRAY_SIZE(hsw_blt_ring_cmd_table);
|
||||
} else {
|
||||
@@ -878,15 +971,17 @@ void intel_engine_init_cmd_parser(struct
|
||||
cmd_table_count = ARRAY_SIZE(gen7_blt_cmd_table);
|
||||
}
|
||||
|
||||
- if (IS_HASWELL(engine->i915)) {
|
||||
+ if (IS_GEN9(engine->i915)) {
|
||||
+ engine->reg_tables = gen9_blt_reg_tables;
|
||||
+ engine->reg_table_count =
|
||||
+ ARRAY_SIZE(gen9_blt_reg_tables);
|
||||
+ } else if (IS_HASWELL(engine->i915)) {
|
||||
engine->reg_tables = hsw_blt_reg_tables;
|
||||
engine->reg_table_count = ARRAY_SIZE(hsw_blt_reg_tables);
|
||||
} else {
|
||||
engine->reg_tables = ivb_blt_reg_tables;
|
||||
engine->reg_table_count = ARRAY_SIZE(ivb_blt_reg_tables);
|
||||
}
|
||||
-
|
||||
- engine->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
|
||||
break;
|
||||
case VECS:
|
||||
cmd_tables = hsw_vebox_cmd_table;
|
||||
@@ -1260,9 +1355,9 @@ int intel_engine_cmd_parser(struct intel
|
||||
}
|
||||
|
||||
/*
|
||||
- * If the batch buffer contains a chained batch, return an
|
||||
- * error that tells the caller to abort and dispatch the
|
||||
- * workload as a non-secure batch.
|
||||
+ * We don't try to handle BATCH_BUFFER_START because it adds
|
||||
+ * non-trivial complexity. Instead we abort the scan and return
|
||||
+ * and error to indicate that the batch is unsafe.
|
||||
*/
|
||||
if (desc->cmd.value == MI_BATCH_BUFFER_START) {
|
||||
ret = -EACCES;
|
||||
@@ -1342,6 +1437,7 @@ int i915_cmd_parser_get_version(struct d
|
||||
* the parser enabled.
|
||||
* 9. Don't whitelist or handle oacontrol specially, as ownership
|
||||
* for oacontrol state is moving to i915-perf.
|
||||
+ * 10. Support for Gen9 BCS Parsing
|
||||
*/
|
||||
- return 9;
|
||||
+ return 10;
|
||||
}
|
||||
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
|
||||
@@ -158,7 +158,8 @@ int intel_sanitize_enable_ppgtt(struct d
|
||||
if (enable_ppgtt == 0 && INTEL_GEN(dev_priv) < 9)
|
||||
return 0;
|
||||
|
||||
- if (enable_ppgtt == 1)
|
||||
+ /* Full PPGTT is required by the Gen9 cmdparser */
|
||||
+ if (enable_ppgtt == 1 && INTEL_GEN(dev_priv) != 9)
|
||||
return 1;
|
||||
|
||||
if (enable_ppgtt == 2 && has_full_ppgtt)
|
||||
--- a/drivers/gpu/drm/i915/i915_reg.h
|
||||
+++ b/drivers/gpu/drm/i915/i915_reg.h
|
||||
@@ -471,6 +471,10 @@ static inline bool i915_mmio_reg_valid(i
|
||||
*/
|
||||
#define BCS_SWCTRL _MMIO(0x22200)
|
||||
|
||||
+/* There are 16 GPR registers */
|
||||
+#define BCS_GPR(n) _MMIO(0x22600 + (n) * 8)
|
||||
+#define BCS_GPR_UDW(n) _MMIO(0x22600 + (n) * 8 + 4)
|
||||
+
|
||||
#define GPGPU_THREADS_DISPATCHED _MMIO(0x2290)
|
||||
#define GPGPU_THREADS_DISPATCHED_UDW _MMIO(0x2290 + 4)
|
||||
#define HS_INVOCATION_COUNT _MMIO(0x2300)
|
94
debian/patches/bugfix/x86/i915/0008-drm-i915-cmdparser-Use-explicit-goto-for-error-paths.patch
vendored
Normal file
94
debian/patches/bugfix/x86/i915/0008-drm-i915-cmdparser-Use-explicit-goto-for-error-paths.patch
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
From: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Date: Thu, 27 Sep 2018 10:23:17 -0700
|
||||
Subject: drm/i915/cmdparser: Use explicit goto for error paths
|
||||
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-0155
|
||||
|
||||
commit 0546a29cd884fb8184731c79ab008927ca8859d0 upstream.
|
||||
|
||||
In the next patch we will be adding a second valid
|
||||
termination condition which will require a small
|
||||
amount of refactoring to share logic with the BB_END
|
||||
case.
|
||||
|
||||
Refactor all error conditions to jump to a dedicated
|
||||
exit path, with 'break' reserved only for a successful
|
||||
parse.
|
||||
|
||||
Cc: Tony Luck <tony.luck@intel.com>
|
||||
Cc: Dave Airlie <airlied@redhat.com>
|
||||
Cc: Takashi Iwai <tiwai@suse.de>
|
||||
Cc: Tyler Hicks <tyhicks@canonical.com>
|
||||
Signed-off-by: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Reviewed-by: Chris Wilson <chris.p.wilson@intel.com>
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_cmd_parser.c | 25 +++++++++++++------------
|
||||
1 file changed, 13 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
|
||||
@@ -1337,21 +1337,15 @@ int intel_engine_cmd_parser(struct intel
|
||||
do {
|
||||
u32 length;
|
||||
|
||||
- if (*cmd == MI_BATCH_BUFFER_END) {
|
||||
- if (needs_clflush_after) {
|
||||
- void *ptr = page_mask_bits(shadow_batch_obj->mm.mapping);
|
||||
- drm_clflush_virt_range(ptr,
|
||||
- (void *)(cmd + 1) - ptr);
|
||||
- }
|
||||
+ if (*cmd == MI_BATCH_BUFFER_END)
|
||||
break;
|
||||
- }
|
||||
|
||||
desc = find_cmd(engine, *cmd, desc, &default_desc);
|
||||
if (!desc) {
|
||||
DRM_DEBUG_DRIVER("CMD: Unrecognized command: 0x%08X\n",
|
||||
*cmd);
|
||||
ret = -EINVAL;
|
||||
- break;
|
||||
+ goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1361,7 +1355,7 @@ int intel_engine_cmd_parser(struct intel
|
||||
*/
|
||||
if (desc->cmd.value == MI_BATCH_BUFFER_START) {
|
||||
ret = -EACCES;
|
||||
- break;
|
||||
+ goto err;
|
||||
}
|
||||
|
||||
if (desc->flags & CMD_DESC_FIXED)
|
||||
@@ -1375,22 +1369,29 @@ int intel_engine_cmd_parser(struct intel
|
||||
length,
|
||||
batch_end - cmd);
|
||||
ret = -EINVAL;
|
||||
- break;
|
||||
+ goto err;
|
||||
}
|
||||
|
||||
if (!check_cmd(engine, desc, cmd, length)) {
|
||||
ret = -EACCES;
|
||||
- break;
|
||||
+ goto err;
|
||||
}
|
||||
|
||||
cmd += length;
|
||||
if (cmd >= batch_end) {
|
||||
DRM_DEBUG_DRIVER("CMD: Got to the end of the buffer w/o a BBE cmd!\n");
|
||||
ret = -EINVAL;
|
||||
- break;
|
||||
+ goto err;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
+ if (needs_clflush_after) {
|
||||
+ void *ptr = page_mask_bits(shadow_batch_obj->mm.mapping);
|
||||
+
|
||||
+ drm_clflush_virt_range(ptr, (void *)(cmd + 1) - ptr);
|
||||
+ }
|
||||
+
|
||||
+err:
|
||||
i915_gem_object_unpin_map(shadow_batch_obj);
|
||||
return ret;
|
||||
}
|
404
debian/patches/bugfix/x86/i915/0009-drm-i915-cmdparser-Add-support-for-backward-jumps.patch
vendored
Normal file
404
debian/patches/bugfix/x86/i915/0009-drm-i915-cmdparser-Add-support-for-backward-jumps.patch
vendored
Normal file
|
@ -0,0 +1,404 @@
|
|||
From: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Date: Thu, 20 Sep 2018 09:58:36 -0700
|
||||
Subject: drm/i915/cmdparser: Add support for backward jumps
|
||||
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-0155
|
||||
|
||||
commit f8c08d8faee5567803c8c533865296ca30286bbf upstream.
|
||||
|
||||
To keep things manageable, the pre-gen9 cmdparser does not
|
||||
attempt to track any form of nested BB_START's. This did not
|
||||
prevent usermode from using nested starts, or even chained
|
||||
batches because the cmdparser is not strictly enforced pre gen9.
|
||||
|
||||
Instead, the existence of a nested BB_START would cause the batch
|
||||
to be emitted in insecure mode, and any privileged capabilities
|
||||
would not be available.
|
||||
|
||||
For Gen9, the cmdparser becomes mandatory (for BCS at least), and
|
||||
so not providing any form of nested BB_START support becomes
|
||||
overly restrictive. Any such batch will simply not run.
|
||||
|
||||
We make heavy use of backward jumps in igt, and it is much easier
|
||||
to add support for this restricted subset of nested jumps, than to
|
||||
rewrite the whole of our test suite to avoid them.
|
||||
|
||||
Add the required logic to support limited backward jumps, to
|
||||
instructions that have already been validated by the parser.
|
||||
|
||||
Note that it's not sufficient to simply approve any BB_START
|
||||
that jumps backwards in the buffer because this would allow an
|
||||
attacker to embed a rogue instruction sequence within the
|
||||
operand words of a harmless instruction (say LRI) and jump to
|
||||
that.
|
||||
|
||||
We introduce a bit array to track every instr offset successfully
|
||||
validated, and test the target of BB_START against this. If the
|
||||
target offset hits, it is re-written to the same offset in the
|
||||
shadow buffer and the BB_START cmd is allowed.
|
||||
|
||||
Note: This patch deliberately ignores checkpatch issues in the
|
||||
cmdtables, in order to match the style of the surrounding code.
|
||||
We'll correct the entire file in one go in a later patch.
|
||||
|
||||
v2: set dispatch secure late (Mika)
|
||||
v3: rebase (Mika)
|
||||
v4: Clear whitelist on each parse
|
||||
Minor review updates (Chris)
|
||||
v5: Correct backward jump batching
|
||||
v6: fix compilation error due to struct eb shuffle (Mika)
|
||||
|
||||
Cc: Tony Luck <tony.luck@intel.com>
|
||||
Cc: Dave Airlie <airlied@redhat.com>
|
||||
Cc: Takashi Iwai <tiwai@suse.de>
|
||||
Cc: Tyler Hicks <tyhicks@canonical.com>
|
||||
Signed-off-by: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Signed-off-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
|
||||
Reviewed-by: Chris Wilson <chris.p.wilson@intel.com>
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_cmd_parser.c | 151 +++++++++++++++++++--
|
||||
drivers/gpu/drm/i915/i915_drv.h | 9 +-
|
||||
drivers/gpu/drm/i915/i915_gem_context.c | 5 +
|
||||
drivers/gpu/drm/i915/i915_gem_context.h | 6 +
|
||||
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 34 +++--
|
||||
5 files changed, 179 insertions(+), 26 deletions(-)
|
||||
|
||||
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
|
||||
@@ -481,6 +481,19 @@ static const struct drm_i915_cmd_descrip
|
||||
.reg = { .offset = 1, .mask = 0x007FFFFC } ),
|
||||
CMD( MI_LOAD_REGISTER_REG, SMI, !F, 0xFF, W,
|
||||
.reg = { .offset = 1, .mask = 0x007FFFFC, .step = 1 } ),
|
||||
+
|
||||
+ /*
|
||||
+ * We allow BB_START but apply further checks. We just sanitize the
|
||||
+ * basic fields here.
|
||||
+ */
|
||||
+#define MI_BB_START_OPERAND_MASK GENMASK(SMI-1, 0)
|
||||
+#define MI_BB_START_OPERAND_EXPECT (MI_BATCH_PPGTT_HSW | 1)
|
||||
+ CMD( MI_BATCH_BUFFER_START_GEN8, SMI, !F, 0xFF, B,
|
||||
+ .bits = {{
|
||||
+ .offset = 0,
|
||||
+ .mask = MI_BB_START_OPERAND_MASK,
|
||||
+ .expected = MI_BB_START_OPERAND_EXPECT,
|
||||
+ }}, ),
|
||||
};
|
||||
|
||||
static const struct drm_i915_cmd_descriptor noop_desc =
|
||||
@@ -1292,15 +1305,113 @@ static bool check_cmd(const struct intel
|
||||
return true;
|
||||
}
|
||||
|
||||
+static int check_bbstart(const struct i915_gem_context *ctx,
|
||||
+ u32 *cmd, u32 offset, u32 length,
|
||||
+ u32 batch_len,
|
||||
+ u64 batch_start,
|
||||
+ u64 shadow_batch_start)
|
||||
+{
|
||||
+ u64 jump_offset, jump_target;
|
||||
+ u32 target_cmd_offset, target_cmd_index;
|
||||
+
|
||||
+ /* For igt compatibility on older platforms */
|
||||
+ if (CMDPARSER_USES_GGTT(ctx->i915)) {
|
||||
+ DRM_DEBUG("CMD: Rejecting BB_START for ggtt based submission\n");
|
||||
+ return -EACCES;
|
||||
+ }
|
||||
+
|
||||
+ if (length != 3) {
|
||||
+ DRM_DEBUG("CMD: Recursive BB_START with bad length(%u)\n",
|
||||
+ length);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ jump_target = *(u64*)(cmd+1);
|
||||
+ jump_offset = jump_target - batch_start;
|
||||
+
|
||||
+ /*
|
||||
+ * Any underflow of jump_target is guaranteed to be outside the range
|
||||
+ * of a u32, so >= test catches both too large and too small
|
||||
+ */
|
||||
+ if (jump_offset >= batch_len) {
|
||||
+ DRM_DEBUG("CMD: BB_START to 0x%llx jumps out of BB\n",
|
||||
+ jump_target);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * This cannot overflow a u32 because we already checked jump_offset
|
||||
+ * is within the BB, and the batch_len is a u32
|
||||
+ */
|
||||
+ target_cmd_offset = lower_32_bits(jump_offset);
|
||||
+ target_cmd_index = target_cmd_offset / sizeof(u32);
|
||||
+
|
||||
+ *(u64*)(cmd + 1) = shadow_batch_start + target_cmd_offset;
|
||||
+
|
||||
+ if (target_cmd_index == offset)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (ctx->jump_whitelist_cmds <= target_cmd_index) {
|
||||
+ DRM_DEBUG("CMD: Rejecting BB_START - truncated whitelist array\n");
|
||||
+ return -EINVAL;
|
||||
+ } else if (!test_bit(target_cmd_index, ctx->jump_whitelist)) {
|
||||
+ DRM_DEBUG("CMD: BB_START to 0x%llx not a previously executed cmd\n",
|
||||
+ jump_target);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void init_whitelist(struct i915_gem_context *ctx, u32 batch_len)
|
||||
+{
|
||||
+ const u32 batch_cmds = DIV_ROUND_UP(batch_len, sizeof(u32));
|
||||
+ const u32 exact_size = BITS_TO_LONGS(batch_cmds);
|
||||
+ u32 next_size = BITS_TO_LONGS(roundup_pow_of_two(batch_cmds));
|
||||
+ unsigned long *next_whitelist;
|
||||
+
|
||||
+ if (CMDPARSER_USES_GGTT(ctx->i915))
|
||||
+ return;
|
||||
+
|
||||
+ if (batch_cmds <= ctx->jump_whitelist_cmds) {
|
||||
+ memset(ctx->jump_whitelist, 0, exact_size * sizeof(u32));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+again:
|
||||
+ next_whitelist = kcalloc(next_size, sizeof(long), GFP_KERNEL);
|
||||
+ if (next_whitelist) {
|
||||
+ kfree(ctx->jump_whitelist);
|
||||
+ ctx->jump_whitelist = next_whitelist;
|
||||
+ ctx->jump_whitelist_cmds =
|
||||
+ next_size * BITS_PER_BYTE * sizeof(long);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (next_size > exact_size) {
|
||||
+ next_size = exact_size;
|
||||
+ goto again;
|
||||
+ }
|
||||
+
|
||||
+ DRM_DEBUG("CMD: Failed to extend whitelist. BB_START may be disallowed\n");
|
||||
+ memset(ctx->jump_whitelist, 0,
|
||||
+ BITS_TO_LONGS(ctx->jump_whitelist_cmds) * sizeof(u32));
|
||||
+
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
#define LENGTH_BIAS 2
|
||||
|
||||
/**
|
||||
* i915_parse_cmds() - parse a submitted batch buffer for privilege violations
|
||||
+ * @ctx: the context in which the batch is to execute
|
||||
* @engine: the engine on which the batch is to execute
|
||||
* @batch_obj: the batch buffer in question
|
||||
- * @shadow_batch_obj: copy of the batch buffer in question
|
||||
+ * @batch_start: Canonical base address of batch
|
||||
* @batch_start_offset: byte offset in the batch at which execution starts
|
||||
* @batch_len: length of the commands in batch_obj
|
||||
+ * @shadow_batch_obj: copy of the batch buffer in question
|
||||
+ * @shadow_batch_start: Canonical base address of shadow_batch_obj
|
||||
*
|
||||
* Parses the specified batch buffer looking for privilege violations as
|
||||
* described in the overview.
|
||||
@@ -1308,13 +1419,17 @@ static bool check_cmd(const struct intel
|
||||
* Return: non-zero if the parser finds violations or otherwise fails; -EACCES
|
||||
* if the batch appears legal but should use hardware parsing
|
||||
*/
|
||||
-int intel_engine_cmd_parser(struct intel_engine_cs *engine,
|
||||
+
|
||||
+int intel_engine_cmd_parser(struct i915_gem_context *ctx,
|
||||
+ struct intel_engine_cs *engine,
|
||||
struct drm_i915_gem_object *batch_obj,
|
||||
- struct drm_i915_gem_object *shadow_batch_obj,
|
||||
+ u64 batch_start,
|
||||
u32 batch_start_offset,
|
||||
- u32 batch_len)
|
||||
+ u32 batch_len,
|
||||
+ struct drm_i915_gem_object *shadow_batch_obj,
|
||||
+ u64 shadow_batch_start)
|
||||
{
|
||||
- u32 *cmd, *batch_end;
|
||||
+ u32 *cmd, *batch_end, offset = 0;
|
||||
struct drm_i915_cmd_descriptor default_desc = noop_desc;
|
||||
const struct drm_i915_cmd_descriptor *desc = &default_desc;
|
||||
bool needs_clflush_after = false;
|
||||
@@ -1328,6 +1443,8 @@ int intel_engine_cmd_parser(struct intel
|
||||
return PTR_ERR(cmd);
|
||||
}
|
||||
|
||||
+ init_whitelist(ctx, batch_len);
|
||||
+
|
||||
/*
|
||||
* We use the batch length as size because the shadow object is as
|
||||
* large or larger and copy_batch() will write MI_NOPs to the extra
|
||||
@@ -1348,16 +1465,6 @@ int intel_engine_cmd_parser(struct intel
|
||||
goto err;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * We don't try to handle BATCH_BUFFER_START because it adds
|
||||
- * non-trivial complexity. Instead we abort the scan and return
|
||||
- * and error to indicate that the batch is unsafe.
|
||||
- */
|
||||
- if (desc->cmd.value == MI_BATCH_BUFFER_START) {
|
||||
- ret = -EACCES;
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
if (desc->flags & CMD_DESC_FIXED)
|
||||
length = desc->length.fixed;
|
||||
else
|
||||
@@ -1377,7 +1484,21 @@ int intel_engine_cmd_parser(struct intel
|
||||
goto err;
|
||||
}
|
||||
|
||||
+ if (desc->cmd.value == MI_BATCH_BUFFER_START) {
|
||||
+ ret = check_bbstart(ctx, cmd, offset, length,
|
||||
+ batch_len, batch_start,
|
||||
+ shadow_batch_start);
|
||||
+
|
||||
+ if (ret)
|
||||
+ goto err;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (ctx->jump_whitelist_cmds > offset)
|
||||
+ set_bit(offset, ctx->jump_whitelist);
|
||||
+
|
||||
cmd += length;
|
||||
+ offset += length;
|
||||
if (cmd >= batch_end) {
|
||||
DRM_DEBUG_DRIVER("CMD: Got to the end of the buffer w/o a BBE cmd!\n");
|
||||
ret = -EINVAL;
|
||||
--- a/drivers/gpu/drm/i915/i915_drv.h
|
||||
+++ b/drivers/gpu/drm/i915/i915_drv.h
|
||||
@@ -3353,11 +3353,14 @@ const char *i915_cache_level_str(struct
|
||||
int i915_cmd_parser_get_version(struct drm_i915_private *dev_priv);
|
||||
void intel_engine_init_cmd_parser(struct intel_engine_cs *engine);
|
||||
void intel_engine_cleanup_cmd_parser(struct intel_engine_cs *engine);
|
||||
-int intel_engine_cmd_parser(struct intel_engine_cs *engine,
|
||||
+int intel_engine_cmd_parser(struct i915_gem_context *cxt,
|
||||
+ struct intel_engine_cs *engine,
|
||||
struct drm_i915_gem_object *batch_obj,
|
||||
- struct drm_i915_gem_object *shadow_batch_obj,
|
||||
+ u64 user_batch_start,
|
||||
u32 batch_start_offset,
|
||||
- u32 batch_len);
|
||||
+ u32 batch_len,
|
||||
+ struct drm_i915_gem_object *shadow_batch_obj,
|
||||
+ u64 shadow_batch_start);
|
||||
|
||||
/* i915_perf.c */
|
||||
extern void i915_perf_init(struct drm_i915_private *dev_priv);
|
||||
--- a/drivers/gpu/drm/i915/i915_gem_context.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
|
||||
@@ -124,6 +124,8 @@ static void i915_gem_context_free(struct
|
||||
|
||||
i915_ppgtt_put(ctx->ppgtt);
|
||||
|
||||
+ kfree(ctx->jump_whitelist);
|
||||
+
|
||||
for (n = 0; n < ARRAY_SIZE(ctx->__engine); n++) {
|
||||
struct intel_context *ce = &ctx->__engine[n];
|
||||
|
||||
@@ -339,6 +341,9 @@ __create_hw_context(struct drm_i915_priv
|
||||
else
|
||||
ctx->ggtt_offset_bias = I915_GTT_PAGE_SIZE;
|
||||
|
||||
+ ctx->jump_whitelist = NULL;
|
||||
+ ctx->jump_whitelist_cmds = 0;
|
||||
+
|
||||
return ctx;
|
||||
|
||||
err_pid:
|
||||
--- a/drivers/gpu/drm/i915/i915_gem_context.h
|
||||
+++ b/drivers/gpu/drm/i915/i915_gem_context.h
|
||||
@@ -183,6 +183,12 @@ struct i915_gem_context {
|
||||
/** remap_slice: Bitmask of cache lines that need remapping */
|
||||
u8 remap_slice;
|
||||
|
||||
+ /** jump_whitelist: Bit array for tracking cmds during cmdparsing */
|
||||
+ unsigned long *jump_whitelist;
|
||||
+
|
||||
+ /** jump_whitelist_cmds: No of cmd slots available */
|
||||
+ u32 jump_whitelist_cmds;
|
||||
+
|
||||
/** handles_vma: rbtree to look up our context specific obj/vma for
|
||||
* the user handle. (user handles are per fd, but the binding is
|
||||
* per vm, which may be one per context or shared with the global GTT)
|
||||
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
|
||||
@@ -1909,7 +1909,6 @@ shadow_batch_pin(struct i915_execbuffer
|
||||
if (CMDPARSER_USES_GGTT(dev_priv)) {
|
||||
flags = PIN_GLOBAL;
|
||||
vm = &dev_priv->ggtt.vm;
|
||||
- eb->batch_flags |= I915_DISPATCH_SECURE;
|
||||
} else if (eb->vm->has_read_only) {
|
||||
flags = PIN_USER;
|
||||
vm = eb->vm;
|
||||
@@ -1926,6 +1925,8 @@ static struct i915_vma *eb_parse(struct
|
||||
{
|
||||
struct drm_i915_gem_object *shadow_batch_obj;
|
||||
struct i915_vma *vma;
|
||||
+ u64 batch_start;
|
||||
+ u64 shadow_batch_start;
|
||||
int err;
|
||||
|
||||
shadow_batch_obj = i915_gem_batch_pool_get(&eb->engine->batch_pool,
|
||||
@@ -1933,12 +1934,27 @@ static struct i915_vma *eb_parse(struct
|
||||
if (IS_ERR(shadow_batch_obj))
|
||||
return ERR_CAST(shadow_batch_obj);
|
||||
|
||||
- err = intel_engine_cmd_parser(eb->engine,
|
||||
+ vma = shadow_batch_pin(eb, shadow_batch_obj);
|
||||
+ if (IS_ERR(vma))
|
||||
+ goto out;
|
||||
+
|
||||
+ batch_start = gen8_canonical_addr(eb->batch->node.start) +
|
||||
+ eb->batch_start_offset;
|
||||
+
|
||||
+ shadow_batch_start = gen8_canonical_addr(vma->node.start);
|
||||
+
|
||||
+ err = intel_engine_cmd_parser(eb->ctx,
|
||||
+ eb->engine,
|
||||
eb->batch->obj,
|
||||
- shadow_batch_obj,
|
||||
+ batch_start,
|
||||
eb->batch_start_offset,
|
||||
- eb->batch_len);
|
||||
+ eb->batch_len,
|
||||
+ shadow_batch_obj,
|
||||
+ shadow_batch_start);
|
||||
+
|
||||
if (err) {
|
||||
+ i915_vma_unpin(vma);
|
||||
+
|
||||
/*
|
||||
* Unsafe GGTT-backed buffers can still be submitted safely
|
||||
* as non-secure.
|
||||
@@ -1950,12 +1966,9 @@ static struct i915_vma *eb_parse(struct
|
||||
vma = NULL;
|
||||
else
|
||||
vma = ERR_PTR(err);
|
||||
- goto out;
|
||||
- }
|
||||
|
||||
- vma = shadow_batch_pin(eb, shadow_batch_obj);
|
||||
- if (IS_ERR(vma))
|
||||
goto out;
|
||||
+ }
|
||||
|
||||
eb->vma[eb->buffer_count] = i915_vma_get(vma);
|
||||
eb->flags[eb->buffer_count] =
|
||||
@@ -1964,7 +1977,12 @@ static struct i915_vma *eb_parse(struct
|
||||
eb->buffer_count++;
|
||||
eb->batch_start_offset = 0;
|
||||
eb->batch = vma;
|
||||
+
|
||||
/* eb->batch_len unchanged */
|
||||
+
|
||||
+ if (CMDPARSER_USES_GGTT(eb->i915))
|
||||
+ eb->batch_flags |= I915_DISPATCH_SECURE;
|
||||
+
|
||||
out:
|
||||
i915_gem_object_unpin_pages(shadow_batch_obj);
|
||||
return vma;
|
37
debian/patches/bugfix/x86/i915/0010-drm-i915-cmdparser-Ignore-Length-operands-during-com.patch
vendored
Normal file
37
debian/patches/bugfix/x86/i915/0010-drm-i915-cmdparser-Ignore-Length-operands-during-com.patch
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
From: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Date: Thu, 20 Sep 2018 09:45:10 -0700
|
||||
Subject: drm/i915/cmdparser: Ignore Length operands during command matching
|
||||
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-0155
|
||||
|
||||
commit 926abff21a8f29ef159a3ac893b05c6e50e043c3 upstream.
|
||||
|
||||
Some of the gen instruction macros (e.g. MI_DISPLAY_FLIP) have the
|
||||
length directly encoded in them. Since these are used directly in
|
||||
the tables, the Length becomes part of the comparison used for
|
||||
matching during parsing. Thus, if the cmd being parsed has a
|
||||
different length to that in the table, it is not matched and the
|
||||
cmd is accepted via the default variable length path.
|
||||
|
||||
Fix by masking out everything except the Opcode in the cmd tables
|
||||
|
||||
Cc: Tony Luck <tony.luck@intel.com>
|
||||
Cc: Dave Airlie <airlied@redhat.com>
|
||||
Cc: Takashi Iwai <tiwai@suse.de>
|
||||
Cc: Tyler Hicks <tyhicks@canonical.com>
|
||||
Signed-off-by: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
Reviewed-by: Chris Wilson <chris.p.wilson@intel.com>
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_cmd_parser.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
|
||||
@@ -187,7 +187,7 @@ struct drm_i915_cmd_table {
|
||||
#define CMD(op, opm, f, lm, fl, ...) \
|
||||
{ \
|
||||
.flags = (fl) | ((f) ? CMD_DESC_FIXED : 0), \
|
||||
- .cmd = { (op), ~0u << (opm) }, \
|
||||
+ .cmd = { (op & ~0u << (opm)), ~0u << (opm) }, \
|
||||
.length = { (lm) }, \
|
||||
__VA_ARGS__ \
|
||||
}
|
72
debian/patches/bugfix/x86/i915/0011-drm-i915-Lower-RM-timeout-to-avoid-DSI-hard-hangs.patch
vendored
Normal file
72
debian/patches/bugfix/x86/i915/0011-drm-i915-Lower-RM-timeout-to-avoid-DSI-hard-hangs.patch
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
From: Uma Shankar <uma.shankar@intel.com>
|
||||
Date: Tue, 7 Aug 2018 21:15:35 +0530
|
||||
Subject: drm/i915: Lower RM timeout to avoid DSI hard hangs
|
||||
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-0154
|
||||
|
||||
commit 1d85a299c4db57c55e0229615132c964d17aa765 upstream.
|
||||
|
||||
In BXT/APL, device 2 MMIO reads from MIPI controller requires its PLL
|
||||
to be turned ON. When MIPI PLL is turned off (MIPI Display is not
|
||||
active or connected), and someone (host or GT engine) tries to read
|
||||
MIPI registers, it causes hard hang. This is a hardware restriction
|
||||
or limitation.
|
||||
|
||||
Driver by itself doesn't read MIPI registers when MIPI display is off.
|
||||
But any userspace application can submit unprivileged batch buffer for
|
||||
execution. In that batch buffer there can be mmio reads. And these
|
||||
reads are allowed even for unprivileged applications. If these
|
||||
register reads are for MIPI DSI controller and MIPI display is not
|
||||
active during that time, then the MMIO read operation causes system
|
||||
hard hang and only way to recover is hard reboot. A genuine
|
||||
process/application won't submit batch buffer like this and doesn't
|
||||
cause any issue. But on a compromised system, a malign userspace
|
||||
process/app can generate such batch buffer and can trigger system
|
||||
hard hang (denial of service attack).
|
||||
|
||||
The fix is to lower the internal MMIO timeout value to an optimum
|
||||
value of 950us as recommended by hardware team. If the timeout is
|
||||
beyond 1ms (which will hit for any value we choose if MMIO READ on a
|
||||
DSI specific register is performed without PLL ON), it causes the
|
||||
system hang. But if the timeout value is lower than it will be below
|
||||
the threshold (even if timeout happens) and system will not get into
|
||||
a hung state. This will avoid a system hang without losing any
|
||||
programming or GT interrupts, taking the worst case of lowest CDCLK
|
||||
frequency and early DC5 abort into account.
|
||||
|
||||
Signed-off-by: Uma Shankar <uma.shankar@intel.com>
|
||||
Reviewed-by: Jon Bloomfield <jon.bloomfield@intel.com>
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_reg.h | 4 ++++
|
||||
drivers/gpu/drm/i915/intel_pm.c | 8 ++++++++
|
||||
2 files changed, 12 insertions(+)
|
||||
|
||||
--- a/drivers/gpu/drm/i915/i915_reg.h
|
||||
+++ b/drivers/gpu/drm/i915/i915_reg.h
|
||||
@@ -7009,6 +7009,10 @@ enum {
|
||||
#define SKL_CSR_DC5_DC6_COUNT _MMIO(0x8002C)
|
||||
#define BXT_CSR_DC3_DC5_COUNT _MMIO(0x80038)
|
||||
|
||||
+/* Display Internal Timeout Register */
|
||||
+#define RM_TIMEOUT _MMIO(0x42060)
|
||||
+#define MMIO_TIMEOUT_US(us) ((us) << 0)
|
||||
+
|
||||
/* interrupts */
|
||||
#define DE_MASTER_IRQ_CONTROL (1 << 31)
|
||||
#define DE_SPRITEB_FLIP_DONE (1 << 29)
|
||||
--- a/drivers/gpu/drm/i915/intel_pm.c
|
||||
+++ b/drivers/gpu/drm/i915/intel_pm.c
|
||||
@@ -114,6 +114,14 @@ static void bxt_init_clock_gating(struct
|
||||
*/
|
||||
I915_WRITE(GEN9_CLKGATE_DIS_0, I915_READ(GEN9_CLKGATE_DIS_0) |
|
||||
PWM1_GATING_DIS | PWM2_GATING_DIS);
|
||||
+
|
||||
+ /*
|
||||
+ * Lower the display internal timeout.
|
||||
+ * This is needed to avoid any hard hangs when DSI port PLL
|
||||
+ * is off and a MMIO access is attempted by any privilege
|
||||
+ * application, using batch buffers or any other means.
|
||||
+ */
|
||||
+ I915_WRITE(RM_TIMEOUT, MMIO_TIMEOUT_US(950));
|
||||
}
|
||||
|
||||
static void glk_init_clock_gating(struct drm_i915_private *dev_priv)
|
282
debian/patches/bugfix/x86/i915/0012-drm-i915-gen8-Add-RC6-CTX-corruption-WA.patch
vendored
Normal file
282
debian/patches/bugfix/x86/i915/0012-drm-i915-gen8-Add-RC6-CTX-corruption-WA.patch
vendored
Normal file
|
@ -0,0 +1,282 @@
|
|||
From: Imre Deak <imre.deak@intel.com>
|
||||
Date: Mon, 9 Jul 2018 18:24:27 +0300
|
||||
Subject: drm/i915/gen8+: Add RC6 CTX corruption WA
|
||||
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-0154
|
||||
|
||||
commit 7e34f4e4aad3fd34c02b294a3cf2321adf5b4438 upstream.
|
||||
|
||||
In some circumstances the RC6 context can get corrupted. We can detect
|
||||
this and take the required action, that is disable RC6 and runtime PM.
|
||||
The HW recovers from the corrupted state after a system suspend/resume
|
||||
cycle, so detect the recovery and re-enable RC6 and runtime PM.
|
||||
|
||||
v2: rebase (Mika)
|
||||
v3:
|
||||
- Move intel_suspend_gt_powersave() to the end of the GEM suspend
|
||||
sequence.
|
||||
- Add commit message.
|
||||
v4:
|
||||
- Rebased on intel_uncore_forcewake_put(i915->uncore, ...) API
|
||||
change.
|
||||
v5: rebased on gem/gt split (Mika)
|
||||
|
||||
Signed-off-by: Imre Deak <imre.deak@intel.com>
|
||||
Signed-off-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_drv.c | 3 +
|
||||
drivers/gpu/drm/i915/i915_drv.h | 7 +-
|
||||
drivers/gpu/drm/i915/i915_gem.c | 8 +++
|
||||
drivers/gpu/drm/i915/i915_reg.h | 2 +
|
||||
drivers/gpu/drm/i915/intel_drv.h | 3 +
|
||||
drivers/gpu/drm/i915/intel_pm.c | 107 ++++++++++++++++++++++++++++++-
|
||||
6 files changed, 126 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/gpu/drm/i915/i915_drv.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_drv.c
|
||||
@@ -1621,6 +1621,7 @@ static int i915_drm_suspend_late(struct
|
||||
i915_gem_suspend_late(dev_priv);
|
||||
|
||||
intel_display_set_init_power(dev_priv, false);
|
||||
+ i915_rc6_ctx_wa_suspend(dev_priv);
|
||||
intel_uncore_suspend(dev_priv);
|
||||
|
||||
/*
|
||||
@@ -1847,6 +1848,8 @@ static int i915_drm_resume_early(struct
|
||||
else
|
||||
intel_display_set_init_power(dev_priv, true);
|
||||
|
||||
+ i915_rc6_ctx_wa_resume(dev_priv);
|
||||
+
|
||||
intel_engines_sanitize(dev_priv);
|
||||
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
--- a/drivers/gpu/drm/i915/i915_drv.h
|
||||
+++ b/drivers/gpu/drm/i915/i915_drv.h
|
||||
@@ -801,6 +801,7 @@ struct intel_rps {
|
||||
|
||||
struct intel_rc6 {
|
||||
bool enabled;
|
||||
+ bool ctx_corrupted;
|
||||
u64 prev_hw_residency[4];
|
||||
u64 cur_residency[4];
|
||||
};
|
||||
@@ -2557,10 +2558,12 @@ intel_info(const struct drm_i915_private
|
||||
/* Early gen2 have a totally busted CS tlb and require pinned batches. */
|
||||
#define HAS_BROKEN_CS_TLB(dev_priv) (IS_I830(dev_priv) || IS_I845G(dev_priv))
|
||||
|
||||
+#define NEEDS_RC6_CTX_CORRUPTION_WA(dev_priv) \
|
||||
+ (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) == 9)
|
||||
+
|
||||
/* WaRsDisableCoarsePowerGating:skl,cnl */
|
||||
#define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \
|
||||
- (IS_CANNONLAKE(dev_priv) || \
|
||||
- IS_SKL_GT3(dev_priv) || IS_SKL_GT4(dev_priv))
|
||||
+ (IS_CANNONLAKE(dev_priv) || INTEL_GEN(dev_priv) == 9)
|
||||
|
||||
#define HAS_GMBUS_IRQ(dev_priv) (INTEL_GEN(dev_priv) >= 4)
|
||||
#define HAS_GMBUS_BURST_READ(dev_priv) (INTEL_GEN(dev_priv) >= 10 || \
|
||||
--- a/drivers/gpu/drm/i915/i915_gem.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_gem.c
|
||||
@@ -174,6 +174,11 @@ static u32 __i915_gem_park(struct drm_i9
|
||||
if (INTEL_GEN(i915) >= 6)
|
||||
gen6_rps_idle(i915);
|
||||
|
||||
+ if (NEEDS_RC6_CTX_CORRUPTION_WA(i915)) {
|
||||
+ i915_rc6_ctx_wa_check(i915);
|
||||
+ intel_uncore_forcewake_put(i915, FORCEWAKE_ALL);
|
||||
+ }
|
||||
+
|
||||
intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ);
|
||||
|
||||
intel_runtime_pm_put(i915);
|
||||
@@ -220,6 +225,9 @@ void i915_gem_unpark(struct drm_i915_pri
|
||||
*/
|
||||
intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
|
||||
|
||||
+ if (NEEDS_RC6_CTX_CORRUPTION_WA(i915))
|
||||
+ intel_uncore_forcewake_get(i915, FORCEWAKE_ALL);
|
||||
+
|
||||
i915->gt.awake = true;
|
||||
if (unlikely(++i915->gt.epoch == 0)) /* keep 0 as invalid */
|
||||
i915->gt.epoch = 1;
|
||||
--- a/drivers/gpu/drm/i915/i915_reg.h
|
||||
+++ b/drivers/gpu/drm/i915/i915_reg.h
|
||||
@@ -387,6 +387,8 @@ static inline bool i915_mmio_reg_valid(i
|
||||
#define ECOCHK_PPGTT_WT_HSW (0x2 << 3)
|
||||
#define ECOCHK_PPGTT_WB_HSW (0x3 << 3)
|
||||
|
||||
+#define GEN8_RC6_CTX_INFO _MMIO(0x8504)
|
||||
+
|
||||
#define GAC_ECO_BITS _MMIO(0x14090)
|
||||
#define ECOBITS_SNB_BIT (1 << 13)
|
||||
#define ECOBITS_PPGTT_CACHE64B (3 << 8)
|
||||
--- a/drivers/gpu/drm/i915/intel_drv.h
|
||||
+++ b/drivers/gpu/drm/i915/intel_drv.h
|
||||
@@ -2064,6 +2064,9 @@ void intel_sanitize_gt_powersave(struct
|
||||
void intel_enable_gt_powersave(struct drm_i915_private *dev_priv);
|
||||
void intel_disable_gt_powersave(struct drm_i915_private *dev_priv);
|
||||
void intel_suspend_gt_powersave(struct drm_i915_private *dev_priv);
|
||||
+bool i915_rc6_ctx_wa_check(struct drm_i915_private *i915);
|
||||
+void i915_rc6_ctx_wa_suspend(struct drm_i915_private *i915);
|
||||
+void i915_rc6_ctx_wa_resume(struct drm_i915_private *i915);
|
||||
void gen6_rps_busy(struct drm_i915_private *dev_priv);
|
||||
void gen6_rps_reset_ei(struct drm_i915_private *dev_priv);
|
||||
void gen6_rps_idle(struct drm_i915_private *dev_priv);
|
||||
--- a/drivers/gpu/drm/i915/intel_pm.c
|
||||
+++ b/drivers/gpu/drm/i915/intel_pm.c
|
||||
@@ -8196,6 +8196,95 @@ static void intel_init_emon(struct drm_i
|
||||
dev_priv->ips.corr = (lcfuse & LCFUSE_HIV_MASK);
|
||||
}
|
||||
|
||||
+static bool i915_rc6_ctx_corrupted(struct drm_i915_private *dev_priv)
|
||||
+{
|
||||
+ return !I915_READ(GEN8_RC6_CTX_INFO);
|
||||
+}
|
||||
+
|
||||
+static void i915_rc6_ctx_wa_init(struct drm_i915_private *i915)
|
||||
+{
|
||||
+ if (!NEEDS_RC6_CTX_CORRUPTION_WA(i915))
|
||||
+ return;
|
||||
+
|
||||
+ if (i915_rc6_ctx_corrupted(i915)) {
|
||||
+ DRM_INFO("RC6 context corrupted, disabling runtime power management\n");
|
||||
+ i915->gt_pm.rc6.ctx_corrupted = true;
|
||||
+ intel_runtime_pm_get(i915);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void i915_rc6_ctx_wa_cleanup(struct drm_i915_private *i915)
|
||||
+{
|
||||
+ if (i915->gt_pm.rc6.ctx_corrupted) {
|
||||
+ intel_runtime_pm_put(i915);
|
||||
+ i915->gt_pm.rc6.ctx_corrupted = false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * i915_rc6_ctx_wa_suspend - system suspend sequence for the RC6 CTX WA
|
||||
+ * @i915: i915 device
|
||||
+ *
|
||||
+ * Perform any steps needed to clean up the RC6 CTX WA before system suspend.
|
||||
+ */
|
||||
+void i915_rc6_ctx_wa_suspend(struct drm_i915_private *i915)
|
||||
+{
|
||||
+ if (i915->gt_pm.rc6.ctx_corrupted)
|
||||
+ intel_runtime_pm_put(i915);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * i915_rc6_ctx_wa_resume - system resume sequence for the RC6 CTX WA
|
||||
+ * @i915: i915 device
|
||||
+ *
|
||||
+ * Perform any steps needed to re-init the RC6 CTX WA after system resume.
|
||||
+ */
|
||||
+void i915_rc6_ctx_wa_resume(struct drm_i915_private *i915)
|
||||
+{
|
||||
+ if (!i915->gt_pm.rc6.ctx_corrupted)
|
||||
+ return;
|
||||
+
|
||||
+ if (i915_rc6_ctx_corrupted(i915)) {
|
||||
+ intel_runtime_pm_get(i915);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ DRM_INFO("RC6 context restored, re-enabling runtime power management\n");
|
||||
+ i915->gt_pm.rc6.ctx_corrupted = false;
|
||||
+}
|
||||
+
|
||||
+static void intel_disable_rc6(struct drm_i915_private *dev_priv);
|
||||
+
|
||||
+/**
|
||||
+ * i915_rc6_ctx_wa_check - check for a new RC6 CTX corruption
|
||||
+ * @i915: i915 device
|
||||
+ *
|
||||
+ * Check if an RC6 CTX corruption has happened since the last check and if so
|
||||
+ * disable RC6 and runtime power management.
|
||||
+ *
|
||||
+ * Return false if no context corruption has happened since the last call of
|
||||
+ * this function, true otherwise.
|
||||
+*/
|
||||
+bool i915_rc6_ctx_wa_check(struct drm_i915_private *i915)
|
||||
+{
|
||||
+ if (!NEEDS_RC6_CTX_CORRUPTION_WA(i915))
|
||||
+ return false;
|
||||
+
|
||||
+ if (i915->gt_pm.rc6.ctx_corrupted)
|
||||
+ return false;
|
||||
+
|
||||
+ if (!i915_rc6_ctx_corrupted(i915))
|
||||
+ return false;
|
||||
+
|
||||
+ DRM_NOTE("RC6 context corruption, disabling runtime power management\n");
|
||||
+
|
||||
+ intel_disable_rc6(i915);
|
||||
+ i915->gt_pm.rc6.ctx_corrupted = true;
|
||||
+ intel_runtime_pm_get_noresume(i915);
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
void intel_init_gt_powersave(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct intel_rps *rps = &dev_priv->gt_pm.rps;
|
||||
@@ -8211,6 +8300,8 @@ void intel_init_gt_powersave(struct drm_
|
||||
|
||||
mutex_lock(&dev_priv->pcu_lock);
|
||||
|
||||
+ i915_rc6_ctx_wa_init(dev_priv);
|
||||
+
|
||||
/* Initialize RPS limits (for userspace) */
|
||||
if (IS_CHERRYVIEW(dev_priv))
|
||||
cherryview_init_gt_powersave(dev_priv);
|
||||
@@ -8257,6 +8348,8 @@ void intel_cleanup_gt_powersave(struct d
|
||||
if (IS_VALLEYVIEW(dev_priv))
|
||||
valleyview_cleanup_gt_powersave(dev_priv);
|
||||
|
||||
+ i915_rc6_ctx_wa_cleanup(dev_priv);
|
||||
+
|
||||
if (!HAS_RC6(dev_priv))
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
}
|
||||
@@ -8301,7 +8394,7 @@ static inline void intel_disable_llc_pst
|
||||
i915->gt_pm.llc_pstate.enabled = false;
|
||||
}
|
||||
|
||||
-static void intel_disable_rc6(struct drm_i915_private *dev_priv)
|
||||
+static void __intel_disable_rc6(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
lockdep_assert_held(&dev_priv->pcu_lock);
|
||||
|
||||
@@ -8320,6 +8413,13 @@ static void intel_disable_rc6(struct drm
|
||||
dev_priv->gt_pm.rc6.enabled = false;
|
||||
}
|
||||
|
||||
+static void intel_disable_rc6(struct drm_i915_private *dev_priv)
|
||||
+{
|
||||
+ mutex_lock(&dev_priv->pcu_lock);
|
||||
+ __intel_disable_rc6(dev_priv);
|
||||
+ mutex_unlock(&dev_priv->pcu_lock);
|
||||
+}
|
||||
+
|
||||
static void intel_disable_rps(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
lockdep_assert_held(&dev_priv->pcu_lock);
|
||||
@@ -8345,7 +8445,7 @@ void intel_disable_gt_powersave(struct d
|
||||
{
|
||||
mutex_lock(&dev_priv->pcu_lock);
|
||||
|
||||
- intel_disable_rc6(dev_priv);
|
||||
+ __intel_disable_rc6(dev_priv);
|
||||
intel_disable_rps(dev_priv);
|
||||
if (HAS_LLC(dev_priv))
|
||||
intel_disable_llc_pstate(dev_priv);
|
||||
@@ -8372,6 +8472,9 @@ static void intel_enable_rc6(struct drm_
|
||||
if (dev_priv->gt_pm.rc6.enabled)
|
||||
return;
|
||||
|
||||
+ if (dev_priv->gt_pm.rc6.ctx_corrupted)
|
||||
+ return;
|
||||
+
|
||||
if (IS_CHERRYVIEW(dev_priv))
|
||||
cherryview_enable_rc6(dev_priv);
|
||||
else if (IS_VALLEYVIEW(dev_priv))
|
|
@ -284,6 +284,18 @@ bugfix/x86/itlb_multihit/0023-KVM-vmx-svm-always-run-with-EFER.NXE-1-when-shadow
|
|||
bugfix/x86/itlb_multihit/0024-kvm-mmu-ITLB_MULTIHIT-mitigation.patch
|
||||
bugfix/x86/itlb_multihit/0025-kvm-Add-helper-function-for-creating-VM-worker-threa.patch
|
||||
bugfix/x86/itlb_multihit/0026-kvm-x86-mmu-Recovery-of-shattered-NX-large-pages.patch
|
||||
bugfix/x86/i915/0001-drm-i915-Rename-gen7-cmdparser-tables.patch
|
||||
bugfix/x86/i915/0002-drm-i915-Disable-Secure-Batches-for-gen6.patch
|
||||
bugfix/x86/i915/0003-drm-i915-Remove-Master-tables-from-cmdparser.patch
|
||||
bugfix/x86/i915/0004-drm-i915-Add-support-for-mandatory-cmdparsing.patch
|
||||
bugfix/x86/i915/0005-drm-i915-Support-ro-ppgtt-mapped-cmdparser-shadow-bu.patch
|
||||
bugfix/x86/i915/0006-drm-i915-Allow-parsing-of-unsized-batches.patch
|
||||
bugfix/x86/i915/0007-drm-i915-Add-gen9-BCS-cmdparsing.patch
|
||||
bugfix/x86/i915/0008-drm-i915-cmdparser-Use-explicit-goto-for-error-paths.patch
|
||||
bugfix/x86/i915/0009-drm-i915-cmdparser-Add-support-for-backward-jumps.patch
|
||||
bugfix/x86/i915/0010-drm-i915-cmdparser-Ignore-Length-operands-during-com.patch
|
||||
bugfix/x86/i915/0011-drm-i915-Lower-RM-timeout-to-avoid-DSI-hard-hangs.patch
|
||||
bugfix/x86/i915/0012-drm-i915-gen8-Add-RC6-CTX-corruption-WA.patch
|
||||
|
||||
# ABI maintenance
|
||||
debian/abi/powerpc-avoid-abi-change-for-disabling-tm.patch
|
||||
|
|
Loading…
Reference in New Issue