mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
net: wireless: bcmdhd: Fix memory corruption in wl_android_get_rssi()
In case of FW problem wldev_get_ssid() doesn't return error and ssid structure has garbage. Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
This commit is contained in:
@@ -149,22 +149,25 @@ static int wl_android_get_link_speed(struct net_device *net, char *command, int
|
||||
|
||||
static int wl_android_get_rssi(struct net_device *net, char *command, int total_len)
|
||||
{
|
||||
wlc_ssid_t ssid;
|
||||
wlc_ssid_t ssid = {0};
|
||||
int rssi;
|
||||
int bytes_written;
|
||||
int bytes_written = 0;
|
||||
int error;
|
||||
|
||||
error = wldev_get_rssi(net, &rssi);
|
||||
if (error)
|
||||
return -1;
|
||||
|
||||
error = wldev_get_ssid(net, &ssid);
|
||||
if (error)
|
||||
return -1;
|
||||
memcpy(command, ssid.SSID, ssid.SSID_len);
|
||||
bytes_written = ssid.SSID_len;
|
||||
if ((ssid.SSID_len == 0) || (ssid.SSID_len > DOT11_MAX_SSID_LEN)) {
|
||||
DHD_ERROR(("%s: wldev_get_ssid failed\n", __FUNCTION__));
|
||||
} else {
|
||||
memcpy(command, ssid.SSID, ssid.SSID_len);
|
||||
bytes_written = ssid.SSID_len;
|
||||
}
|
||||
bytes_written += snprintf(&command[bytes_written], total_len, " rssi %d", rssi);
|
||||
DHD_INFO(("%s: command result is %s \n", __FUNCTION__, command));
|
||||
DHD_INFO(("%s: command result is %s (%d)\n", __FUNCTION__, command, bytes_written));
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
@@ -367,24 +370,26 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
|
||||
int ret = 0;
|
||||
char *command = NULL;
|
||||
int bytes_written = 0;
|
||||
android_wifi_priv_cmd *priv_cmd;
|
||||
android_wifi_priv_cmd priv_cmd;
|
||||
|
||||
net_os_wake_lock(net);
|
||||
|
||||
priv_cmd = (android_wifi_priv_cmd*)ifr->ifr_data;
|
||||
if (!priv_cmd)
|
||||
{
|
||||
if (!ifr->ifr_data) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
command = kmalloc(priv_cmd->total_len, GFP_KERNEL);
|
||||
if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
|
||||
ret = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
command = kmalloc(priv_cmd.total_len, GFP_KERNEL);
|
||||
if (!command)
|
||||
{
|
||||
DHD_ERROR(("%s: failed to allocate memory\n", __FUNCTION__));
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
if (copy_from_user(command, priv_cmd->buf, priv_cmd->total_len)) {
|
||||
if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) {
|
||||
ret = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
@@ -396,7 +401,7 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
|
||||
bytes_written = wl_android_wifi_on(net);
|
||||
}
|
||||
else if (strnicmp(command, CMD_SETFWPATH, strlen(CMD_SETFWPATH)) == 0) {
|
||||
bytes_written = wl_android_set_fwpath(net, command, priv_cmd->total_len);
|
||||
bytes_written = wl_android_set_fwpath(net, command, priv_cmd.total_len);
|
||||
}
|
||||
|
||||
if (!g_wifi_on) {
|
||||
@@ -416,10 +421,10 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
|
||||
/* TBD: SCAN-PASSIVE */
|
||||
}
|
||||
else if (strnicmp(command, CMD_RSSI, strlen(CMD_RSSI)) == 0) {
|
||||
bytes_written = wl_android_get_rssi(net, command, priv_cmd->total_len);
|
||||
bytes_written = wl_android_get_rssi(net, command, priv_cmd.total_len);
|
||||
}
|
||||
else if (strnicmp(command, CMD_LINKSPEED, strlen(CMD_LINKSPEED)) == 0) {
|
||||
bytes_written = wl_android_get_link_speed(net, command, priv_cmd->total_len);
|
||||
bytes_written = wl_android_get_link_speed(net, command, priv_cmd.total_len);
|
||||
}
|
||||
else if (strnicmp(command, CMD_RXFILTER_START, strlen(CMD_RXFILTER_START)) == 0) {
|
||||
bytes_written = net_os_set_packet_filter(net, 1);
|
||||
@@ -445,14 +450,14 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
|
||||
/* TBD: BTCOEXMODE */
|
||||
}
|
||||
else if (strnicmp(command, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) {
|
||||
bytes_written = wl_android_set_suspendopt(net, command, priv_cmd->total_len);
|
||||
bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len);
|
||||
}
|
||||
else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) {
|
||||
uint band = *(command + strlen(CMD_SETBAND) + 1) - '0';
|
||||
bytes_written = wldev_set_band(net, band);
|
||||
}
|
||||
else if (strnicmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) {
|
||||
bytes_written = wl_android_get_band(net, command, priv_cmd->total_len);
|
||||
bytes_written = wl_android_get_band(net, command, priv_cmd.total_len);
|
||||
}
|
||||
else if (strnicmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) {
|
||||
char *country_code = command + strlen(CMD_COUNTRY) + 1;
|
||||
@@ -463,7 +468,7 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
|
||||
bytes_written = dhd_dev_pno_reset(net);
|
||||
}
|
||||
else if (strnicmp(command, CMD_PNOSETUP_SET, strlen(CMD_PNOSETUP_SET)) == 0) {
|
||||
bytes_written = wl_android_set_pno_setup(net, command, priv_cmd->total_len);
|
||||
bytes_written = wl_android_set_pno_setup(net, command, priv_cmd.total_len);
|
||||
}
|
||||
else if (strnicmp(command, CMD_PNOENABLE_SET, strlen(CMD_PNOENABLE_SET)) == 0) {
|
||||
uint pfn_enabled = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0';
|
||||
@@ -471,7 +476,7 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
|
||||
}
|
||||
#endif
|
||||
else if (strnicmp(command, CMD_P2P_DEV_ADDR, strlen(CMD_P2P_DEV_ADDR)) == 0) {
|
||||
bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd->total_len);
|
||||
bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
|
||||
} else {
|
||||
DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command));
|
||||
snprintf(command, 3, "OK");
|
||||
@@ -479,9 +484,14 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
|
||||
}
|
||||
|
||||
if (bytes_written > 0) {
|
||||
bytes_written++;
|
||||
priv_cmd->used_len = bytes_written;
|
||||
if (copy_to_user(priv_cmd->buf, command, bytes_written)) {
|
||||
if (bytes_written > priv_cmd.total_len) {
|
||||
DHD_ERROR(("%s: bytes_written = %d\n", __FUNCTION__, bytes_written));
|
||||
bytes_written = priv_cmd.total_len;
|
||||
} else {
|
||||
bytes_written++;
|
||||
}
|
||||
priv_cmd.used_len = bytes_written;
|
||||
if (copy_to_user(priv_cmd.buf, command, bytes_written)) {
|
||||
DHD_ERROR(("%s: failed to copy data to user buffer\n", __FUNCTION__));
|
||||
ret = -EFAULT;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user