Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 3821

kernel-2.6.18-194.11.1.el5.src.rpm

From: Mauro Carvalho Chehab <mchehab@redhat.com>
Date: Mon, 17 Nov 2008 19:48:11 -0200
Subject: [video] avoid writing outside shadow.bytes array
Message-id: 20081117194811.3ed9bc08@pedra.chehab.org
O-Subject: [PATCH RHEL 5.4] Avoid writing outside shadow.bytes[] array
Bugzilla: 471844
RH-Acked-by: Pete Zaitcev <zaitcev@redhat.com>

Bugzilla 471844

Upstream changeset 494264379d186bf806613d27aafb7d88d42f4212

This basically backports a patch that I did for tvaudio module already
upstream, in order to avoid the risk of writing outside a shadow array.

V4L/DVB (9621): Avoid writing outside shadow.bytes[] array

There were no check about the limits of shadow.bytes array. This offers
a risk of writing values outside the limits, overriding other data
areas.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

Cheers,
Mauro

diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 936e3f7..1da5cbd 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -159,7 +159,7 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
 {
 	unsigned char buffer[2];
 
-	if (-1 == subaddr) {
+	if (subaddr < 0) {
 		v4l_dbg(1, debug, &chip->c, "%s: chip_write: 0x%x\n",
 			chip->c.name, val);
 		chip->shadow.bytes[1] = val;
@@ -170,6 +170,13 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
 			return -1;
 		}
 	} else {
+		if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
+			v4l_info(&chip->c,
+				"Tried to access a non-existent register: %d\n",
+				subaddr);
+			return -EINVAL;
+		}
+
 		v4l_dbg(1, debug, &chip->c, "%s: chip_write: reg%d=0x%x\n",
 			chip->c.name, subaddr, val);
 		chip->shadow.bytes[subaddr+1] = val;
@@ -184,12 +191,20 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
 	return 0;
 }
 
-static int chip_write_masked(struct CHIPSTATE *chip, int subaddr, int val, int mask)
+static int chip_write_masked(struct CHIPSTATE *chip,
+			     int subaddr, int val, int mask)
 {
 	if (mask != 0) {
-		if (-1 == subaddr) {
+		if (subaddr < 0) {
 			val = (chip->shadow.bytes[1] & ~mask) | (val & mask);
 		} else {
+			if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
+				v4l_info(&chip->c,
+					"Tried to access a non-existent register: %d\n",
+					subaddr);
+				return -EINVAL;
+			}
+
 			val = (chip->shadow.bytes[subaddr+1] & ~mask) | (val & mask);
 		}
 	}
@@ -235,6 +250,13 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
 	if (0 == cmd->count)
 		return 0;
 
+	if (cmd->count + cmd->bytes[0] - 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
+		v4l_info(&chip->c,
+			 "Tried to access a non-existent register range: %d to %d\n",
+			 cmd->bytes[0] + 1, cmd->bytes[0] + cmd->count - 1);
+		return -EINVAL;
+	}
+
 	/* update our shadow register set; print bytes if (debug > 0) */
 	v4l_dbg(1, debug, &chip->c, "%s: chip_cmd(%s): reg=%d, data:",
 		chip->c.name, name,cmd->bytes[0]);