]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
2 .32 radeon patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Tue, 9 Mar 2010 00:08:28 +0000 (16:08 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 9 Mar 2010 00:08:28 +0000 (16:08 -0800)
queue-2.6.32/drm-radeon-kms-r600-r700-don-t-test-ib-if-ib-initialization-fails.patch [new file with mode: 0644]
queue-2.6.32/drm-radeon-r6xx-r7xx-possible-security-issue-system-ram-access.patch [new file with mode: 0644]
queue-2.6.32/series

diff --git a/queue-2.6.32/drm-radeon-kms-r600-r700-don-t-test-ib-if-ib-initialization-fails.patch b/queue-2.6.32/drm-radeon-kms-r600-r700-don-t-test-ib-if-ib-initialization-fails.patch
new file mode 100644 (file)
index 0000000..0d3cecf
--- /dev/null
@@ -0,0 +1,68 @@
+From e3dae5087754984ed7e6daf4fbb742ff026aadd5 Mon Sep 17 00:00:00 2001
+From: Jerome Glisse <jglisse@redhat.com>
+Date: Sun, 14 Feb 2010 19:31:58 +0000
+Subject: drm/radeon/kms: r600/r700 don't test ib if ib initialization fails
+
+From: Jerome Glisse <jglisse@redhat.com>
+
+commit db96380ea26fcc31ab37189aedeabd12894b1431 upstream
+
+If ib initialization failed don't try to test ib as it will result
+in an oops (accessing NULL ib buffer ptr).
+
+[bwh: Adjusted context for 2.6.32]
+Signed-off-by: Jerome Glisse <jglisse@redhat.com>
+Signed-off-by: Dave Airlie <airlied@linux.ie>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/radeon/r600.c  |   13 +++++++------
+ drivers/gpu/drm/radeon/rv770.c |   13 +++++++------
+ 2 files changed, 14 insertions(+), 12 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/r600.c
++++ b/drivers/gpu/drm/radeon/r600.c
+@@ -1686,13 +1686,14 @@ int r600_init(struct radeon_device *rdev
+       if (rdev->accel_working) {
+               r = radeon_ib_pool_init(rdev);
+               if (r) {
+-                      DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r);
+-                      rdev->accel_working = false;
+-              }
+-              r = r600_ib_test(rdev);
+-              if (r) {
+-                      DRM_ERROR("radeon: failled testing IB (%d).\n", r);
++                      dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
+                       rdev->accel_working = false;
++              } else {
++                      r = r600_ib_test(rdev);
++                      if (r) {
++                              dev_err(rdev->dev, "IB test failed (%d).\n", r);
++                              rdev->accel_working = false;
++                      }
+               }
+       }
+       return 0;
+--- a/drivers/gpu/drm/radeon/rv770.c
++++ b/drivers/gpu/drm/radeon/rv770.c
+@@ -1034,13 +1034,14 @@ int rv770_init(struct radeon_device *rde
+       if (rdev->accel_working) {
+               r = radeon_ib_pool_init(rdev);
+               if (r) {
+-                      DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r);
+-                      rdev->accel_working = false;
+-              }
+-              r = r600_ib_test(rdev);
+-              if (r) {
+-                      DRM_ERROR("radeon: failled testing IB (%d).\n", r);
++                      dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
+                       rdev->accel_working = false;
++              } else {
++                      r = r600_ib_test(rdev);
++                      if (r) {
++                              dev_err(rdev->dev, "IB test failed (%d).\n", r);
++                              rdev->accel_working = false;
++                      }
+               }
+       }
+       return 0;
diff --git a/queue-2.6.32/drm-radeon-r6xx-r7xx-possible-security-issue-system-ram-access.patch b/queue-2.6.32/drm-radeon-r6xx-r7xx-possible-security-issue-system-ram-access.patch
new file mode 100644 (file)
index 0000000..bbd8ce2
--- /dev/null
@@ -0,0 +1,256 @@
+From ceb0297d3da7ecf44bccec2c4520c8710612c238 Mon Sep 17 00:00:00 2001
+From: Jerome Glisse <jglisse@redhat.com>
+Date: Sun, 14 Feb 2010 19:33:18 +0000
+Subject: drm/radeon: r6xx/r7xx possible security issue, system ram access
+
+From: Jerome Glisse <jglisse@redhat.com>
+
+commit c8c15ff1e90bfc4a2db1ba77a01b3b2783e723fc upstream
+
+This patch workaround a possible security issue which can allow
+user to abuse drm on r6xx/r7xx hw to access any system ram memory.
+This patch doesn't break userspace, it detect "valid" old use of
+CB_COLOR[0-7]_FRAG & CB_COLOR[0-7]_TILE registers and overwritte
+the address these registers are pointing to with the one of the
+last color buffer. This workaround will work for old mesa &
+xf86-video-ati and any old user which did use similar register
+programming pattern as those (we expect that there is no others
+user of those ioctl except possibly a malicious one). This patch
+add a warning if it detects such usage, warning encourage people
+to update their mesa & xf86-video-ati. New userspace will submit
+proper relocation.
+
+Fix for xf86-video-ati / mesa (this kernel patch is enough to
+prevent abuse, fix for userspace are to set proper cs stream and
+avoid kernel warning) :
+http://cgit.freedesktop.org/xorg/driver/xf86-video-ati/commit/?id=95d63e408cc88b6934bec84a0b1ef94dfe8bee7b
+http://cgit.freedesktop.org/mesa/mesa/commit/?id=46dc6fd3ed5ef96cda53641a97bc68c3bc104a9f
+
+Abusing this register to perform system ram memory is not easy,
+here is outline on how it could be achieve. First attacker must
+have access to the drm device and be able to submit command stream
+throught cs ioctl. Then attacker must build a proper command stream
+for r6xx/r7xx hw which will abuse the FRAG or TILE buffer to
+overwrite the GPU GART which is in VRAM. To achieve so attacker
+as to setup CB_COLOR[0-7]_FRAG or CB_COLOR[0-7]_TILE to point
+to the GPU GART, then it has to find a way to write predictable
+value into those buffer (with little cleverness i believe this
+can be done but this is an hard task). Once attacker have such
+program it can overwritte GPU GART to program GPU gart to point
+anywhere in system memory. It then can reusse same method as he
+used to reprogram GART to overwritte the system ram through the
+GART mapping. In the process the attacker has to be carefull to
+not overwritte any sensitive area of the GART table, like ring
+or IB gart entry as it will more then likely lead to GPU lockup.
+Bottom line is that i think it's very hard to use this flaw
+to get system ram access but in theory one can achieve so.
+
+Side note: I am not aware of anyone ever using the GPU as an
+attack vector, nevertheless we take great care in the opensource
+driver to try to detect and forbid malicious use of GPU. I don't
+think the closed source driver are as cautious as we are.
+
+[bwh: Adjusted context for 2.6.32]
+Signed-off-by: Jerome Glisse <jglisse@redhat.com>
+Signed-off-by: Dave Airlie <airlied@linux.ie>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/radeon/r600_cs.c   |   83 +++++++++++++++++++++++++++++++++++++
+ drivers/gpu/drm/radeon/r600d.h     |   26 +++++++++++
+ drivers/gpu/drm/radeon/radeon.h    |    1 
+ drivers/gpu/drm/radeon/radeon_cs.c |    1 
+ 4 files changed, 111 insertions(+)
+
+--- a/drivers/gpu/drm/radeon/r600_cs.c
++++ b/drivers/gpu/drm/radeon/r600_cs.c
+@@ -36,6 +36,10 @@ static int r600_cs_packet_next_reloc_nom
+ typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**);
+ static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm;
++struct r600_cs_track {
++      u32     cb_color0_base_last;
++};
++
+ /**
+  * r600_cs_packet_parse() - parse cp packet and point ib index to next packet
+  * @parser:   parser structure holding parsing context.
+@@ -177,6 +181,28 @@ static int r600_cs_packet_next_reloc_nom
+ }
+ /**
++ * r600_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc
++ * @parser:           parser structure holding parsing context.
++ *
++ * Check next packet is relocation packet3, do bo validation and compute
++ * GPU offset using the provided start.
++ **/
++static inline int r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p)
++{
++      struct radeon_cs_packet p3reloc;
++      int r;
++
++      r = r600_cs_packet_parse(p, &p3reloc, p->idx);
++      if (r) {
++              return 0;
++      }
++      if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
++              return 0;
++      }
++      return 1;
++}
++
++/**
+  * r600_cs_packet_next_vline() - parse userspace VLINE packet
+  * @parser:           parser structure holding parsing context.
+  *
+@@ -337,6 +363,7 @@ static int r600_packet3_check(struct rad
+                               struct radeon_cs_packet *pkt)
+ {
+       struct radeon_cs_reloc *reloc;
++      struct r600_cs_track *track;
+       volatile u32 *ib;
+       unsigned idx;
+       unsigned i;
+@@ -344,6 +371,7 @@ static int r600_packet3_check(struct rad
+       int r;
+       u32 idx_value;
++      track = (struct r600_cs_track *)p->track;
+       ib = p->ib->ptr;
+       idx = pkt->idx + 1;
+       idx_value = radeon_get_ib_value(p, idx);
+@@ -503,9 +531,60 @@ static int r600_packet3_check(struct rad
+               for (i = 0; i < pkt->count; i++) {
+                       reg = start_reg + (4 * i);
+                       switch (reg) {
++                      /* This register were added late, there is userspace
++                       * which does provide relocation for those but set
++                       * 0 offset. In order to avoid breaking old userspace
++                       * we detect this and set address to point to last
++                       * CB_COLOR0_BASE, note that if userspace doesn't set
++                       * CB_COLOR0_BASE before this register we will report
++                       * error. Old userspace always set CB_COLOR0_BASE
++                       * before any of this.
++                       */
++                      case R_0280E0_CB_COLOR0_FRAG:
++                      case R_0280E4_CB_COLOR1_FRAG:
++                      case R_0280E8_CB_COLOR2_FRAG:
++                      case R_0280EC_CB_COLOR3_FRAG:
++                      case R_0280F0_CB_COLOR4_FRAG:
++                      case R_0280F4_CB_COLOR5_FRAG:
++                      case R_0280F8_CB_COLOR6_FRAG:
++                      case R_0280FC_CB_COLOR7_FRAG:
++                      case R_0280C0_CB_COLOR0_TILE:
++                      case R_0280C4_CB_COLOR1_TILE:
++                      case R_0280C8_CB_COLOR2_TILE:
++                      case R_0280CC_CB_COLOR3_TILE:
++                      case R_0280D0_CB_COLOR4_TILE:
++                      case R_0280D4_CB_COLOR5_TILE:
++                      case R_0280D8_CB_COLOR6_TILE:
++                      case R_0280DC_CB_COLOR7_TILE:
++                              if (!r600_cs_packet_next_is_pkt3_nop(p)) {
++                                      if (!track->cb_color0_base_last) {
++                                              dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
++                                              return -EINVAL;
++                                      }
++                                      ib[idx+1+i] = track->cb_color0_base_last;
++                                      printk_once(KERN_WARNING "You have old & broken userspace "
++                                              "please consider updating mesa & xf86-video-ati\n");
++                              } else {
++                                      r = r600_cs_packet_next_reloc(p, &reloc);
++                                      if (r) {
++                                              dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
++                                              return -EINVAL;
++                                      }
++                                      ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
++                              }
++                              break;
+                       case DB_DEPTH_BASE:
+                       case DB_HTILE_DATA_BASE:
+                       case CB_COLOR0_BASE:
++                              r = r600_cs_packet_next_reloc(p, &reloc);
++                              if (r) {
++                                      DRM_ERROR("bad SET_CONTEXT_REG "
++                                                      "0x%04X\n", reg);
++                                      return -EINVAL;
++                              }
++                              ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
++                              track->cb_color0_base_last = ib[idx+1+i];
++                              break;
+                       case CB_COLOR1_BASE:
+                       case CB_COLOR2_BASE:
+                       case CB_COLOR3_BASE:
+@@ -678,8 +757,11 @@ static int r600_packet3_check(struct rad
+ int r600_cs_parse(struct radeon_cs_parser *p)
+ {
+       struct radeon_cs_packet pkt;
++      struct r600_cs_track *track;
+       int r;
++      track = kzalloc(sizeof(*track), GFP_KERNEL);
++      p->track = track;
+       do {
+               r = r600_cs_packet_parse(p, &pkt, p->idx);
+               if (r) {
+@@ -757,6 +839,7 @@ int r600_cs_legacy(struct drm_device *de
+       /* initialize parser */
+       memset(&parser, 0, sizeof(struct radeon_cs_parser));
+       parser.filp = filp;
++      parser.dev = &dev->pdev->dev;
+       parser.rdev = NULL;
+       parser.family = family;
+       parser.ib = &fake_ib;
+--- a/drivers/gpu/drm/radeon/r600d.h
++++ b/drivers/gpu/drm/radeon/r600d.h
+@@ -674,4 +674,30 @@
+ #define               S_000E60_SOFT_RESET_TSC(x)              (((x) & 1) << 16)
+ #define               S_000E60_SOFT_RESET_VMC(x)              (((x) & 1) << 17)
++#define R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL         0x5480
++
++#define R_0280E0_CB_COLOR0_FRAG                      0x0280E0
++#define   S_0280E0_BASE_256B(x)                        (((x) & 0xFFFFFFFF) << 0)
++#define   G_0280E0_BASE_256B(x)                        (((x) >> 0) & 0xFFFFFFFF)
++#define   C_0280E0_BASE_256B                           0x00000000
++#define R_0280E4_CB_COLOR1_FRAG                      0x0280E4
++#define R_0280E8_CB_COLOR2_FRAG                      0x0280E8
++#define R_0280EC_CB_COLOR3_FRAG                      0x0280EC
++#define R_0280F0_CB_COLOR4_FRAG                      0x0280F0
++#define R_0280F4_CB_COLOR5_FRAG                      0x0280F4
++#define R_0280F8_CB_COLOR6_FRAG                      0x0280F8
++#define R_0280FC_CB_COLOR7_FRAG                      0x0280FC
++#define R_0280C0_CB_COLOR0_TILE                      0x0280C0
++#define   S_0280C0_BASE_256B(x)                        (((x) & 0xFFFFFFFF) << 0)
++#define   G_0280C0_BASE_256B(x)                        (((x) >> 0) & 0xFFFFFFFF)
++#define   C_0280C0_BASE_256B                           0x00000000
++#define R_0280C4_CB_COLOR1_TILE                      0x0280C4
++#define R_0280C8_CB_COLOR2_TILE                      0x0280C8
++#define R_0280CC_CB_COLOR3_TILE                      0x0280CC
++#define R_0280D0_CB_COLOR4_TILE                      0x0280D0
++#define R_0280D4_CB_COLOR5_TILE                      0x0280D4
++#define R_0280D8_CB_COLOR6_TILE                      0x0280D8
++#define R_0280DC_CB_COLOR7_TILE                      0x0280DC
++
++
+ #endif
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -448,6 +448,7 @@ struct radeon_cs_chunk {
+ };
+ struct radeon_cs_parser {
++      struct device           *dev;
+       struct radeon_device    *rdev;
+       struct drm_file         *filp;
+       /* chunks */
+--- a/drivers/gpu/drm/radeon/radeon_cs.c
++++ b/drivers/gpu/drm/radeon/radeon_cs.c
+@@ -230,6 +230,7 @@ int radeon_cs_ioctl(struct drm_device *d
+       memset(&parser, 0, sizeof(struct radeon_cs_parser));
+       parser.filp = filp;
+       parser.rdev = rdev;
++      parser.dev = rdev->dev;
+       r = radeon_cs_parser_init(&parser, data);
+       if (r) {
+               DRM_ERROR("Failed to initialize parser !\n");
index affa774ab60c6a2659e1a4c31a2c42c8b6446d71..64358db03670651b6c7d8ac441378612a00b2fc1 100644 (file)
@@ -44,3 +44,5 @@ ipv6-conntrack-add-member-of-user-to-nf_ct_frag6_queue-structure.patch
 drivers-net-ks8851_mll-ethernet-network-driver.patch
 sky2-fix-transmit-dma-map-leakage.patch
 drm-radeon-kms-forbid-creation-of-framebuffer-with-no-valid-gem-object.patch
+drm-radeon-kms-r600-r700-don-t-test-ib-if-ib-initialization-fails.patch
+drm-radeon-r6xx-r7xx-possible-security-issue-system-ram-access.patch