Commit 5925f447 authored by Jon Bloomfield's avatar Jon Bloomfield Committed by Stefan Bader

UBUNTU: SAUCE: i915_bpo: drm/i915: Support ro ppgtt mapped cmdparser shadow buffers

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+
Signed-off-by: default avatarJon Bloomfield <jon.bloomfield@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>

CVE-2019-0155

[tjaalton: backport to i915_bpo
 - dev_priv doesn't have gtt, use ggtt instead]
Signed-off-by: default avatarTimo Aaltonen <timo.aaltonen@canonical.com>
Signed-off-by: default avatarStefan Bader <stefan.bader@canonical.com>
parent 61e5d0c0
......@@ -2656,6 +2656,12 @@ struct drm_i915_cmd_table {
#define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay)
#define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical)
/*
* 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)
/* Early gen2 have a totally busted CS tlb and require pinned batches. */
#define HAS_BROKEN_CS_TLB(dev) (IS_I830(dev) || IS_845G(dev))
......
......@@ -1173,10 +1173,41 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev,
return 0;
}
static struct i915_vma*
shadow_batch_pin(struct drm_i915_gem_object *obj, struct i915_address_space *vm)
{
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
struct i915_address_space *pin_vm = vm;
u64 flags;
int ret;
/*
* PPGTT backed shadow buffers must be mapped RO, to prevent
* post-scan tampering
*/
if (CMDPARSER_USES_GGTT(dev_priv)) {
flags = PIN_GLOBAL;
pin_vm = &dev_priv->ggtt.base;
} else if (vm->has_read_only) {
flags = PIN_USER;
obj->gt_ro = 1;
} else {
DRM_DEBUG("Cannot prevent post-scan tampering without RO capable vm\n");
return ERR_PTR(-EINVAL);
}
ret = i915_gem_object_pin(obj, pin_vm, 0, flags);
if (ret)
return ERR_PTR(ret);
else
return i915_gem_obj_to_vma(obj, pin_vm);
}
static struct drm_i915_gem_object*
i915_gem_execbuffer_parse(struct intel_engine_cs *engine,
struct drm_i915_gem_exec_object2 *shadow_exec_entry,
struct eb_vmas *eb,
struct i915_address_space *vm,
struct drm_i915_gem_object *batch_obj,
u32 batch_start_offset,
u32 batch_len)
......@@ -1198,15 +1229,16 @@ i915_gem_execbuffer_parse(struct intel_engine_cs *engine,
if (ret)
goto err;
ret = i915_gem_obj_ggtt_pin(shadow_batch_obj, 0, 0);
if (ret)
vma = shadow_batch_pin(shadow_batch_obj, vm);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
goto err;
}
i915_gem_object_unpin_pages(shadow_batch_obj);
memset(shadow_exec_entry, 0, sizeof(*shadow_exec_entry));
vma = i915_gem_obj_to_ggtt(shadow_batch_obj);
vma->exec_entry = shadow_exec_entry;
vma->exec_entry->flags = __EXEC_OBJECT_HAS_PIN;
drm_gem_object_reference(&shadow_batch_obj->base);
......@@ -1218,7 +1250,14 @@ i915_gem_execbuffer_parse(struct intel_engine_cs *engine,
err:
i915_gem_object_unpin_pages(shadow_batch_obj);
if (ret == -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(batch_obj->base.dev) && (ret == -EACCES))
return batch_obj;
else
return ERR_PTR(ret);
......@@ -1566,7 +1605,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
parsed_batch_obj = i915_gem_execbuffer_parse(engine,
&shadow_exec_entry,
eb,
eb, vm,
batch_obj,
args->batch_start_offset,
args->batch_len);
......@@ -1579,18 +1618,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
* parsed_batch_obj == batch_obj means batch not fully parsed:
* Accept, but don't promote to secure.
*/
if (parsed_batch_obj != batch_obj) {
/*
* 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.
*/
dispatch_flags |= I915_DISPATCH_SECURE;
if (CMDPARSER_USES_GGTT(dev_priv))
dispatch_flags |= I915_DISPATCH_SECURE;
params->args_batch_start_offset = 0;
batch_obj = parsed_batch_obj;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment