From: Greg Kroah-Hartman Date: Tue, 9 Mar 2010 00:08:28 +0000 (-0800) Subject: 2 .32 radeon patches X-Git-Tag: v2.6.32.10~28 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c328dc7b1963bf0a1d81ebf5689fa4678255298f;p=thirdparty%2Fkernel%2Fstable-queue.git 2 .32 radeon patches --- 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 index 00000000000..0d3cecf9c59 --- /dev/null +++ b/queue-2.6.32/drm-radeon-kms-r600-r700-don-t-test-ib-if-ib-initialization-fails.patch @@ -0,0 +1,68 @@ +From e3dae5087754984ed7e6daf4fbb742ff026aadd5 Mon Sep 17 00:00:00 2001 +From: Jerome Glisse +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 + +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 +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..bbd8ce2ffd9 --- /dev/null +++ b/queue-2.6.32/drm-radeon-r6xx-r7xx-possible-security-issue-system-ram-access.patch @@ -0,0 +1,256 @@ +From ceb0297d3da7ecf44bccec2c4520c8710612c238 Mon Sep 17 00:00:00 2001 +From: Jerome Glisse +Date: Sun, 14 Feb 2010 19:33:18 +0000 +Subject: drm/radeon: r6xx/r7xx possible security issue, system ram access + +From: Jerome Glisse + +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 +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + 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"); diff --git a/queue-2.6.32/series b/queue-2.6.32/series index affa774ab60..64358db0367 100644 --- a/queue-2.6.32/series +++ b/queue-2.6.32/series @@ -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