aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2008-11-13 15:03:28 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-11-14 11:24:45 -0500
commit494264379d186bf806613d27aafb7d88d42f4212 (patch)
tree681aeb1444d7e1b2d994d5045644a0c8ec44e342 /drivers/media/video
parent81cb5c4f7fbe6971d9c61401bc47193290fd59b7 (diff)
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>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/tvaudio.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 5ec369d54e6e..55b39b9a33d9 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -154,7 +154,7 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
154{ 154{
155 unsigned char buffer[2]; 155 unsigned char buffer[2];
156 156
157 if (-1 == subaddr) { 157 if (subaddr < 0) {
158 v4l_dbg(1, debug, chip->c, "%s: chip_write: 0x%x\n", 158 v4l_dbg(1, debug, chip->c, "%s: chip_write: 0x%x\n",
159 chip->c->name, val); 159 chip->c->name, val);
160 chip->shadow.bytes[1] = val; 160 chip->shadow.bytes[1] = val;
@@ -165,6 +165,13 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
165 return -1; 165 return -1;
166 } 166 }
167 } else { 167 } else {
168 if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
169 v4l_info(chip->c,
170 "Tried to access a non-existent register: %d\n",
171 subaddr);
172 return -EINVAL;
173 }
174
168 v4l_dbg(1, debug, chip->c, "%s: chip_write: reg%d=0x%x\n", 175 v4l_dbg(1, debug, chip->c, "%s: chip_write: reg%d=0x%x\n",
169 chip->c->name, subaddr, val); 176 chip->c->name, subaddr, val);
170 chip->shadow.bytes[subaddr+1] = val; 177 chip->shadow.bytes[subaddr+1] = val;
@@ -179,12 +186,20 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
179 return 0; 186 return 0;
180} 187}
181 188
182static int chip_write_masked(struct CHIPSTATE *chip, int subaddr, int val, int mask) 189static int chip_write_masked(struct CHIPSTATE *chip,
190 int subaddr, int val, int mask)
183{ 191{
184 if (mask != 0) { 192 if (mask != 0) {
185 if (-1 == subaddr) { 193 if (subaddr < 0) {
186 val = (chip->shadow.bytes[1] & ~mask) | (val & mask); 194 val = (chip->shadow.bytes[1] & ~mask) | (val & mask);
187 } else { 195 } else {
196 if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
197 v4l_info(chip->c,
198 "Tried to access a non-existent register: %d\n",
199 subaddr);
200 return -EINVAL;
201 }
202
188 val = (chip->shadow.bytes[subaddr+1] & ~mask) | (val & mask); 203 val = (chip->shadow.bytes[subaddr+1] & ~mask) | (val & mask);
189 } 204 }
190 } 205 }
@@ -230,6 +245,15 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
230 if (0 == cmd->count) 245 if (0 == cmd->count)
231 return 0; 246 return 0;
232 247
248 if (cmd->count + cmd->bytes[0] - 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
249 v4l_info(chip->c,
250 "Tried to access a non-existent register range: %d to %d\n",
251 cmd->bytes[0] + 1, cmd->bytes[0] + cmd->count - 1);
252 return -EINVAL;
253 }
254
255 /* FIXME: it seems that the shadow bytes are wrong bellow !*/
256
233 /* update our shadow register set; print bytes if (debug > 0) */ 257 /* update our shadow register set; print bytes if (debug > 0) */
234 v4l_dbg(1, debug, chip->c, "%s: chip_cmd(%s): reg=%d, data:", 258 v4l_dbg(1, debug, chip->c, "%s: chip_cmd(%s): reg=%d, data:",
235 chip->c->name, name,cmd->bytes[0]); 259 chip->c->name, name,cmd->bytes[0]);