Skip to content

Commit 9c6256a

Browse files
Xiao Hangregkh
authored andcommitted
usb: misc: ftdi-elan: Fix off-by-one memory corruptions
This patch fixes fives off-by-one bugs in the ftdi-elan driver code. The bug can be triggered by plugging a USB adapter for CardBus 3G cards (model U132 manufactured by Elan Digital Systems, Ltd), causing a kernel panic. The fix was tested on Ubuntu 14.04.4 with 4.7.0-rc14.2.0-27-generic+ and 4.4.0-22-generic+ kernel. In the ftdi_elan_synchronize function, an off-by-one memory corruption occurs when packet_bytes is equal or bigger than m. After having read m bytes, that is bytes_read is equal to m, " ..\x00" is still copied to the stack variable causing an out bounds write of 4 bytes, which overwrites the stack canary and results in a kernel panic. This off-by-one requires physical access to the machine. It is not exploitable since we have no control on the overwritten data. Similar off-by-one bugs have been observed in 4 other functions: ftdi_elan_stuck_waiting, ftdi_elan_read, ftdi_elan_edset_output and ftdi_elan_flush_input_fifo. Reported-by: Alex Palesandro <[email protected]> Signed-off-by: Xiao Han <[email protected]> Tested-by: Paul Chaignon <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 2832493 commit 9c6256a

File tree

1 file changed

+5
-5
lines changed

1 file changed

+5
-5
lines changed

drivers/usb/misc/ftdi-elan.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,7 @@ static ssize_t ftdi_elan_read(struct file *file, char __user *buffer,
665665
{
666666
char data[30 *3 + 4];
667667
char *d = data;
668-
int m = (sizeof(data) - 1) / 3;
668+
int m = (sizeof(data) - 1) / 3 - 1;
669669
int bytes_read = 0;
670670
int retry_on_empty = 10;
671671
int retry_on_timeout = 5;
@@ -1684,7 +1684,7 @@ wait:if (ftdi->disconnected > 0) {
16841684
int i = 0;
16851685
char data[30 *3 + 4];
16861686
char *d = data;
1687-
int m = (sizeof(data) - 1) / 3;
1687+
int m = (sizeof(data) - 1) / 3 - 1;
16881688
int l = 0;
16891689
struct u132_target *target = &ftdi->target[ed];
16901690
struct u132_command *command = &ftdi->command[
@@ -1876,7 +1876,7 @@ more:{
18761876
if (packet_bytes > 2) {
18771877
char diag[30 *3 + 4];
18781878
char *d = diag;
1879-
int m = (sizeof(diag) - 1) / 3;
1879+
int m = (sizeof(diag) - 1) / 3 - 1;
18801880
char *b = ftdi->bulk_in_buffer;
18811881
int bytes_read = 0;
18821882
diag[0] = 0;
@@ -2053,7 +2053,7 @@ static int ftdi_elan_synchronize(struct usb_ftdi *ftdi)
20532053
if (packet_bytes > 2) {
20542054
char diag[30 *3 + 4];
20552055
char *d = diag;
2056-
int m = (sizeof(diag) - 1) / 3;
2056+
int m = (sizeof(diag) - 1) / 3 - 1;
20572057
char *b = ftdi->bulk_in_buffer;
20582058
int bytes_read = 0;
20592059
unsigned char c = 0;
@@ -2155,7 +2155,7 @@ more:{
21552155
if (packet_bytes > 2) {
21562156
char diag[30 *3 + 4];
21572157
char *d = diag;
2158-
int m = (sizeof(diag) - 1) / 3;
2158+
int m = (sizeof(diag) - 1) / 3 - 1;
21592159
char *b = ftdi->bulk_in_buffer;
21602160
int bytes_read = 0;
21612161
diag[0] = 0;

0 commit comments

Comments
 (0)