From: Kulikov Vasiliy Date: Fri, 23 Jul 2010 06:36:15 +0000 (+0000) Subject: net: s2io: fix buffer overflow X-Git-Tag: v2.6.36-rc1~571^2~109 X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=commitdiff_plain;h=9c1797808996eef47a7954ec580c6db7de1fff76 net: s2io: fix buffer overflow vpd_data[] is allocated as kmalloc(256, GFP_KERNEL), so if cnt = 255 then (cnt + 3) overflows 256. memset() is executed without checking. vpd_data[cnt+2] must be less than 256-cnt-2 as the latter is number of vpd_data[] elements to copy. Do not fill with zero the beginning of nic->serial_num as it will be filled with vpd_data[]. String in product_name[] should be terminated by '\0'. Signed-off-by: Kulikov Vasiliy Signed-off-by: David S. Miller --- diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index b8b85843c614..18bc5b718bbb 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -5796,7 +5796,7 @@ static void s2io_vpd_read(struct s2io_nic *nic) { u8 *vpd_data; u8 data; - int i = 0, cnt, fail = 0; + int i = 0, cnt, len, fail = 0; int vpd_addr = 0x80; struct swStat *swstats = &nic->mac_control.stats_info->sw_stat; @@ -5837,20 +5837,28 @@ static void s2io_vpd_read(struct s2io_nic *nic) if (!fail) { /* read serial number of adapter */ - for (cnt = 0; cnt < 256; cnt++) { + for (cnt = 0; cnt < 252; cnt++) { if ((vpd_data[cnt] == 'S') && - (vpd_data[cnt+1] == 'N') && - (vpd_data[cnt+2] < VPD_STRING_LEN)) { - memset(nic->serial_num, 0, VPD_STRING_LEN); - memcpy(nic->serial_num, &vpd_data[cnt + 3], - vpd_data[cnt+2]); - break; + (vpd_data[cnt+1] == 'N')) { + len = vpd_data[cnt+2]; + if (len < min(VPD_STRING_LEN, 256-cnt-2)) { + memcpy(nic->serial_num, + &vpd_data[cnt + 3], + len); + memset(nic->serial_num+len, + 0, + VPD_STRING_LEN-len); + break; + } } } } - if ((!fail) && (vpd_data[1] < VPD_STRING_LEN)) - memcpy(nic->product_name, &vpd_data[3], vpd_data[1]); + if ((!fail) && (vpd_data[1] < VPD_STRING_LEN)) { + len = vpd_data[1]; + memcpy(nic->product_name, &vpd_data[3], len); + nic->product_name[len] = 0; + } kfree(vpd_data); swstats->mem_freed += 256; }