diff options
author | Al Viro <viro@ftp.linux.org.uk> | 2008-05-20 23:30:41 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-06-05 05:35:47 -0400 |
commit | a230e55d92347e09d9ba2e97096df114b2dfaf2d (patch) | |
tree | 757a051bf453b408a64ae33bbb5aaea352e15e9d /drivers/media/dvb/ttpci | |
parent | f34ec12a17984d7df784bf49caf64f5f743e5e10 (diff) |
V4L/DVB (7957): fix the roothole in av7110_av.c
direct dereferencing from user-supplied address
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Reviewed-by: Oliver Endriss <o.endriss@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/dvb/ttpci')
-rw-r--r-- | drivers/media/dvb/ttpci/av7110_av.c | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c index 3e6b650fbb81..ec55a968f204 100644 --- a/drivers/media/dvb/ttpci/av7110_av.c +++ b/drivers/media/dvb/ttpci/av7110_av.c | |||
@@ -965,8 +965,9 @@ static u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x | |||
965 | 965 | ||
966 | static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len, int nonblock) | 966 | static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len, int nonblock) |
967 | { | 967 | { |
968 | int i, n; | 968 | unsigned i, n; |
969 | int progressive = 0; | 969 | int progressive = 0; |
970 | int match = 0; | ||
970 | 971 | ||
971 | dprintk(2, "av7110:%p, \n", av7110); | 972 | dprintk(2, "av7110:%p, \n", av7110); |
972 | 973 | ||
@@ -975,12 +976,31 @@ static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len | |||
975 | return -EBUSY; | 976 | return -EBUSY; |
976 | } | 977 | } |
977 | 978 | ||
978 | for (i = 0; i < len - 5; i++) { | 979 | /* search in buf for instances of 00 00 01 b5 1? */ |
979 | /* get progressive flag from picture extension */ | 980 | for (i = 0; i < len; i++) { |
980 | if (buf[i] == 0x00 && buf[i+1] == 0x00 && | 981 | unsigned char c; |
981 | buf[i+2] == 0x01 && (unsigned char)buf[i+3] == 0xb5 && | 982 | if (get_user(c, buf + i)) |
982 | (buf[i+4] & 0xf0) == 0x10) | 983 | return -EFAULT; |
983 | progressive = buf[i+5] & 0x08; | 984 | if (match == 5) { |
985 | progressive = c & 0x08; | ||
986 | match = 0; | ||
987 | } | ||
988 | if (c == 0x00) { | ||
989 | match = (match == 1 || match == 2) ? 2 : 1; | ||
990 | continue; | ||
991 | } | ||
992 | switch (match++) { | ||
993 | case 2: if (c == 0x01) | ||
994 | continue; | ||
995 | break; | ||
996 | case 3: if (c == 0xb5) | ||
997 | continue; | ||
998 | break; | ||
999 | case 4: if ((c & 0xf0) == 0x10) | ||
1000 | continue; | ||
1001 | break; | ||
1002 | } | ||
1003 | match = 0; | ||
984 | } | 1004 | } |
985 | 1005 | ||
986 | /* setting n always > 1, fixes problems when playing stillframes | 1006 | /* setting n always > 1, fixes problems when playing stillframes |