From: Alex T. <al...@cl...> - 2004-01-07 19:36:54
|
please, consider applying. changes: - large strucures kmalloc'ed rather than placing in stack - lost acx100_lock in some error paths fixed btw, I've observed hungs several times upon card ejecting from pcmcia socket. don't know was it hardware related or just deadlock. any ideas? thanks, Alex PS. please, CC me Index: acx100/src/acx100_ioctl.c =================================================================== --- acx100.orig/src/acx100_ioctl.c 2003-11-16 15:59:53.000000000 +0300 +++ acx100/src/acx100_ioctl.c 2004-01-07 16:30:45.000000000 +0300 @@ -354,11 +354,14 @@ { wlandevice_t *wlandev = (wlandevice_t *) dev->priv; unsigned long flags; + int ret = 0; acx100_lock(wlandev, &flags); - if (wlandev->macmode != WLAN_MACMODE_ESS_AP /* 3 */ ) - return -EOPNOTSUPP; + if (wlandev->macmode != WLAN_MACMODE_ESS_AP /* 3 */ ) { + ret = -EOPNOTSUPP; + goto out; + } wlandev->unknown0x2350 = ISTATUS_5_UNKNOWN; acx100_scan_chan(wlandev); @@ -376,12 +379,6 @@ } if (dwrq->flags == SIOCGIWAPLIST) { - /* The variables being used in this ioctl, - * despite being localised in local brackets, - * still take up a lot of stack space, - * thus still possibly leading to IRQ handler - * stack overflow. They should probably be - * dynamically allocated instead. */ struct ap { int size; char essid[32]; @@ -390,10 +387,16 @@ int var_71c; int var_718; - } var_74c[IW_MAX_AP]; - + }; + struct ap *var_74c; int i = 0; + var_74c = kmalloc(sizeof(struct ap) * IW_MAX_AP, GFP_USER); + if (!var_74c) { + ret = -ENOMEM; + goto out; + } + if (wlandev->iStable != 0) { for (; i < wlandev->iStable; i++) { @@ -417,19 +420,23 @@ dwrq->length = wlandev->iStable * sizeof(struct ap); /* FIXME memcpy? */ - if (copy_to_user - (dwrq->pointer, &var_74c, - dwrq->length) != 0) { - return -EFAULT; - } + if (copy_to_user (dwrq->pointer, &var_74c, dwrq->length) != 0) + ret = -EFAULT; + kfree(var_74c); } else if (dwrq->pointer != 0) { struct ap_addr { sa_family_t sa_family; char sa_data[6]; - } var_94c[IW_MAX_AP]; + }; + struct ap_addr *var_94c; + var_94c = kmalloc(sizeof(struct ap_addr)*IW_MAX_AP, GFP_USER); + if (!var_94c) { + ret = -ENOMEM; + goto out; + } if (wlandev->iStable != 0) { int i; @@ -446,17 +453,16 @@ dwrq->length = wlandev->iStable; /* FIXME memcpy? */ - if (copy_to_user - (dwrq->pointer, &var_94c, - wlandev->iStable * sizeof(struct ap_addr)) != 0) { - acx100_unlock(wlandev, &flags); - return -EFAULT; - } + if (copy_to_user(dwrq->pointer, &var_94c, + wlandev->iStable * sizeof(struct ap_addr)) != 0) + ret = -EFAULT; + kfree(var_94c); } +out: acx100_unlock(wlandev, &flags); - return 0; + return ret; } static inline int acx100_ioctl_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) @@ -1305,6 +1311,7 @@ } wlandev->set_mask |= GETSET_RETRY; printk("new retry limits: short %ld long %ld\n", wlandev->short_retry, wlandev->long_retry); + acx100_unlock(wlandev, &flags); return -EINPROGRESS; } else if (vwrq->flags & IW_RETRY_LIFETIME) { /* TODO: support IW_RETRY_LIFETIME */ Index: acx100/src/acx100_helper.c =================================================================== --- acx100.orig/src/acx100_helper.c 2003-11-16 16:12:28.000000000 +0300 +++ acx100/src/acx100_helper.c 2004-01-07 13:42:35.000000000 +0300 @@ -325,7 +325,7 @@ { int res1, res2; firmware_image_t* apfw_image; - char filename[PATH_MAX]; + char *filename; FN_ENTER; if (!firmware_dir) @@ -335,12 +335,16 @@ acxlog(L_STD, "ERROR: no directory for firmware file specified, ABORTING. Make sure to set module parameter 'firmware_dir'! (specified as absolute path!)\n"); return 0; } + filename = kmalloc(PATH_MAX, GFP_USER); + if (!filename) + return -ENOMEM; sprintf(filename,"%s/WLANGEN.BIN", firmware_dir); apfw_image = acx100_read_fw( filename ); if (!apfw_image) { acxlog(L_STD, "acx100_read_fw failed.\n"); + kfree(filename); return 0; } @@ -353,6 +357,7 @@ acxlog(L_DEBUG | L_INIT, "acx100_write_fw (firmware): %d, acx100_validate_fw: %d\n", res1, res2); FN_EXIT(1, res1 && res2); + kfree(filename); return (res1 && res2); } @@ -382,16 +387,21 @@ int acx100_load_radio(wlandevice_t *wlandev) { UINT32 offset; - memmap_t mm; int res1, res2; firmware_image_t *radio_image=0; radioinit_t radioinit; - char filename[PATH_MAX]; + char *filename; acx100_interrogate(wlandev, &mm, ACX100_RID_MEMORY_MAP); offset = mm.m.ip.CodeEnd; + filename = kmalloc(PATH_MAX, GFP_USER); + if (!filename) { + acxlog(L_STD, "ALERT: can't allocate filename\n"); + return 0; + } + sprintf(filename,"%s/RADIO%02x.BIN", firmware_dir, wlandev->radio_type); radio_image = acx100_read_fw(filename); @@ -404,6 +414,7 @@ if ( !radio_image ) { acxlog(L_STD,"WARNING: no suitable radio module (%s) found to load. No problem in case of older combined firmware, FATAL when using new separated firmware.\n",filename); + kfree(filename); return 1; /* Doesn't need to be fatal, we might be using a combined image */ } @@ -424,6 +435,7 @@ /* will take a moment so let's have a big timeout */ acx100_issue_cmd(wlandev, ACX100_CMD_RADIOINIT, &radioinit, sizeof(radioinit), 120000); + kfree(filename); if (!acx100_interrogate(wlandev, &mm, ACX100_RID_MEMORY_MAP)) { acxlog(L_STD, "Error reading memory map\n"); |