i965: fix problem with constant out of bounds access (v3)
authorDave Airlie <airlied@gmail.com>
Thu, 30 May 2013 10:21:56 +0000 (20:21 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 4 Jun 2013 03:50:20 +0000 (13:50 +1000)
Okay I now understand why Frank would want to run away, this is
my attempt at fixing the CVE out of bounds access to constants
outside the range. This attempt converts any illegal constants
to constant 0 as per the GL spec, and is undefined behaviour.

A future patch should add some debug for users to find this out,
but this needs to be backported to stable branches.

CVE-2013-1872

v2: drop the last hunk which was a separate fix (now in master).
hopefully fix the indentations.

v3: don't fail piglit, the whole 8/16 dispatch stuff was over
my head, and I spent a while figuring it out, but this one is
definitely safe, one piglit pass extra on my Ironlake.

NOTE: This is a candidate for stable branches.

Signed-off-by: Dave Airlie <airlied@redhat.com>
src/mesa/drivers/dri/i965/brw_fs.cpp
src/mesa/drivers/dri/i965/brw_fs.h
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp

index baaa25c13473171ae963b150c021cd92f908653b..7f8edff57eca24918439ac36a08a746195e49858 100644 (file)
@@ -818,6 +818,7 @@ fs_visitor::import_uniforms(fs_visitor *v)
                           import_uniforms_callback,
                           variable_ht);
    this->params_remap = v->params_remap;
+   this->nr_params_remap = v->nr_params_remap;
 }
 
 /* Our support for uniforms is piggy-backed on the struct
@@ -1490,6 +1491,7 @@ fs_visitor::remove_dead_constants()
 {
    if (dispatch_width == 8) {
       this->params_remap = ralloc_array(mem_ctx, int, c->prog_data.nr_params);
+      this->nr_params_remap = c->prog_data.nr_params;
 
       for (unsigned int i = 0; i < c->prog_data.nr_params; i++)
         this->params_remap[i] = -1;
@@ -1504,7 +1506,14 @@ fs_visitor::remove_dead_constants()
            if (inst->src[i].file != UNIFORM)
               continue;
 
-           assert(constant_nr < (int)c->prog_data.nr_params);
+           /* Section 5.11 of the OpenGL 4.3 spec says:
+            *
+            *     "Out-of-bounds reads return undefined values, which include
+            *     values from other variables of the active program or zero."
+            */
+           if (constant_nr < 0 || constant_nr >= (int)c->prog_data.nr_params) {
+              constant_nr = 0;
+           }
 
            /* For now, set this to non-negative.  We'll give it the
             * actual new number in a moment, in order to keep the
@@ -1552,6 +1561,10 @@ fs_visitor::remove_dead_constants()
         if (inst->src[i].file != UNIFORM)
            continue;
 
+        /* as above alias to 0 */
+        if (constant_nr < 0 || constant_nr >= (int)this->nr_params_remap) {
+           constant_nr = 0;
+        }
         assert(this->params_remap[constant_nr] != -1);
         inst->src[i].reg = this->params_remap[constant_nr];
         inst->src[i].reg_offset = 0;
index 3d44daf8545aad138948a5406d165d812cd9dfd0..762e2508d22e97be46cd4775e2362058f9e9da36 100644 (file)
@@ -440,6 +440,7 @@ public:
     * uniform index.
     */
    int *params_remap;
+   int nr_params_remap;
 
    struct hash_table *variable_ht;
    fs_reg frag_depth;
index 79c5a11f507b1b275b5d1e9184e5ea947cd36d2a..9bb15d037c164c13a267113e03a1c43c2b3f02e3 100644 (file)
@@ -2464,6 +2464,7 @@ fs_visitor::fs_visitor(struct brw_context *brw,
    this->live_intervals_valid = false;
 
    this->params_remap = NULL;
+   this->nr_params_remap = 0;
 
    this->force_uncompressed_stack = 0;
    this->force_sechalf_stack = 0;