Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Al Viro and committed by
Mauro Carvalho Chehab
a230e55d f34ec12a

+27 -7
+27 -7
drivers/media/dvb/ttpci/av7110_av.c
··· 965 965 966 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 969 int progressive = 0; 970 + int match = 0; 970 971 971 972 dprintk(2, "av7110:%p, \n", av7110); 972 973 ··· 976 975 return -EBUSY; 977 976 } 978 977 979 - for (i = 0; i < len - 5; i++) { 980 - /* get progressive flag from picture extension */ 981 - if (buf[i] == 0x00 && buf[i+1] == 0x00 && 982 - buf[i+2] == 0x01 && (unsigned char)buf[i+3] == 0xb5 && 983 - (buf[i+4] & 0xf0) == 0x10) 984 - progressive = buf[i+5] & 0x08; 978 + /* search in buf for instances of 00 00 01 b5 1? */ 979 + for (i = 0; i < len; i++) { 980 + unsigned char c; 981 + if (get_user(c, buf + i)) 982 + return -EFAULT; 983 + if (match == 5) { 984 + progressive = c & 0x08; 985 + match = 0; 986 + } 987 + if (c == 0x00) { 988 + match = (match == 1 || match == 2) ? 2 : 1; 989 + continue; 990 + } 991 + switch (match++) { 992 + case 2: if (c == 0x01) 993 + continue; 994 + break; 995 + case 3: if (c == 0xb5) 996 + continue; 997 + break; 998 + case 4: if ((c & 0xf0) == 0x10) 999 + continue; 1000 + break; 1001 + } 1002 + match = 0; 985 1003 } 986 1004 987 1005 /* setting n always > 1, fixes problems when playing stillframes