aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/s2io.c
diff options
context:
space:
mode:
authorKulikov Vasiliy <segooon@gmail.com>2010-07-23 02:36:15 -0400
committerDavid S. Miller <davem@davemloft.net>2010-07-23 16:05:13 -0400
commit9c1797808996eef47a7954ec580c6db7de1fff76 (patch)
tree1a15655cf586c34a0b9d33ff5f591dd15e279107 /drivers/net/s2io.c
parent50a749c1f2fc8f03232c174c9dbc78a78f9bebfd (diff)
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 <segooon@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/s2io.c')
-rw-r--r--drivers/net/s2io.c28
1 files changed, 18 insertions, 10 deletions
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)
5796{ 5796{
5797 u8 *vpd_data; 5797 u8 *vpd_data;
5798 u8 data; 5798 u8 data;
5799 int i = 0, cnt, fail = 0; 5799 int i = 0, cnt, len, fail = 0;
5800 int vpd_addr = 0x80; 5800 int vpd_addr = 0x80;
5801 struct swStat *swstats = &nic->mac_control.stats_info->sw_stat; 5801 struct swStat *swstats = &nic->mac_control.stats_info->sw_stat;
5802 5802
@@ -5837,20 +5837,28 @@ static void s2io_vpd_read(struct s2io_nic *nic)
5837 5837
5838 if (!fail) { 5838 if (!fail) {
5839 /* read serial number of adapter */ 5839 /* read serial number of adapter */
5840 for (cnt = 0; cnt < 256; cnt++) { 5840 for (cnt = 0; cnt < 252; cnt++) {
5841 if ((vpd_data[cnt] == 'S') && 5841 if ((vpd_data[cnt] == 'S') &&
5842 (vpd_data[cnt+1] == 'N') && 5842 (vpd_data[cnt+1] == 'N')) {
5843 (vpd_data[cnt+2] < VPD_STRING_LEN)) { 5843 len = vpd_data[cnt+2];
5844 memset(nic->serial_num, 0, VPD_STRING_LEN); 5844 if (len < min(VPD_STRING_LEN, 256-cnt-2)) {
5845 memcpy(nic->serial_num, &vpd_data[cnt + 3], 5845 memcpy(nic->serial_num,
5846 vpd_data[cnt+2]); 5846 &vpd_data[cnt + 3],
5847 break; 5847 len);
5848 memset(nic->serial_num+len,
5849 0,
5850 VPD_STRING_LEN-len);
5851 break;
5852 }
5848 } 5853 }
5849 } 5854 }
5850 } 5855 }
5851 5856
5852 if ((!fail) && (vpd_data[1] < VPD_STRING_LEN)) 5857 if ((!fail) && (vpd_data[1] < VPD_STRING_LEN)) {
5853 memcpy(nic->product_name, &vpd_data[3], vpd_data[1]); 5858 len = vpd_data[1];
5859 memcpy(nic->product_name, &vpd_data[3], len);
5860 nic->product_name[len] = 0;
5861 }
5854 kfree(vpd_data); 5862 kfree(vpd_data);
5855 swstats->mem_freed += 256; 5863 swstats->mem_freed += 256;
5856} 5864}