Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit efbbba4a authored by Sarada Prasanna Garnayak's avatar Sarada Prasanna Garnayak Committed by Gerrit - the friendly Code Review server
Browse files

wcnss: fix the potential buffer overflow in wlan ctrl data process



Validate the userspace wlan control cmd data, info and length
before copy into wcnss driver buffer. Avoid unnecessary string
manipulation and use kernel defined format specifier to print
wlan MAC address.

CRs-Fixed: 2149331
Change-Id: Ib59fdcc0e6b84cdd73972dcb62b2c05e4741f5f7
Signed-off-by: default avatarYuanyuan Liu <yuanliu@codeaurora.org>
Signed-off-by: default avatarSarada Prasanna Garnayak <sgarna@codeaurora.org>
parent 12638d67
Loading
Loading
Loading
Loading
+37 −46
Original line number Diff line number Diff line
@@ -187,6 +187,7 @@ static DEFINE_SPINLOCK(reg_spinlock);
#define WCNSS_MAX_BUILD_VER_LEN		256
#define WCNSS_MAX_CMD_LEN		(128)
#define WCNSS_MIN_CMD_LEN		(3)
#define WCNSS_CMD_INFO_LEN		2

/* control messages from userspace */
#define WCNSS_USR_CTRL_MSG_START  0x00000000
@@ -194,7 +195,6 @@ static DEFINE_SPINLOCK(reg_spinlock);
#define WCNSS_USR_WLAN_MAC_ADDR   (WCNSS_USR_CTRL_MSG_START + 3)

#define MAC_ADDRESS_STR "%02x:%02x:%02x:%02x:%02x:%02x"
#define SHOW_MAC_ADDRESS_STR	"%02x:%02x:%02x:%02x:%02x:%02x\n"
#define WCNSS_USER_MAC_ADDR_LENGTH	18

/* message types */
@@ -457,11 +457,7 @@ static ssize_t wcnss_wlan_macaddr_store(struct device *dev,
		       (char *)&macAddr[index], sizeof(char));
	}

	pr_info("%s: Write MAC Addr:" MAC_ADDRESS_STR "\n", __func__,
		penv->wlan_nv_macAddr[0], penv->wlan_nv_macAddr[1],
		penv->wlan_nv_macAddr[2], penv->wlan_nv_macAddr[3],
		penv->wlan_nv_macAddr[4], penv->wlan_nv_macAddr[5]);

	pr_info("%s: Write MAC Addr: %pM\n", __func__, penv->wlan_nv_macAddr);
	return count;
}

@@ -471,10 +467,7 @@ static ssize_t wcnss_wlan_macaddr_show(struct device *dev,
	if (!penv)
		return -ENODEV;

	return scnprintf(buf, PAGE_SIZE, SHOW_MAC_ADDRESS_STR,
		penv->wlan_nv_macAddr[0], penv->wlan_nv_macAddr[1],
		penv->wlan_nv_macAddr[2], penv->wlan_nv_macAddr[3],
		penv->wlan_nv_macAddr[4], penv->wlan_nv_macAddr[5]);
	return scnprintf(buf, PAGE_SIZE, "%pM\n", penv->wlan_nv_macAddr);
}

static DEVICE_ATTR(wcnss_mac_addr, S_IRUSR | S_IWUSR,
@@ -1663,10 +1656,8 @@ int wcnss_get_wlan_mac_address(char mac_addr[WLAN_MAC_ADDR_SIZE])
		return -ENODEV;

	memcpy(mac_addr, penv->wlan_nv_macAddr, WLAN_MAC_ADDR_SIZE);
	pr_debug("%s: Get MAC Addr:" MAC_ADDRESS_STR "\n", __func__,
		penv->wlan_nv_macAddr[0], penv->wlan_nv_macAddr[1],
		penv->wlan_nv_macAddr[2], penv->wlan_nv_macAddr[3],
		penv->wlan_nv_macAddr[4], penv->wlan_nv_macAddr[5]);
	pr_debug("%s: Get MAC Addr: %pM\n", __func__, penv->wlan_nv_macAddr);

	return 0;
}
EXPORT_SYMBOL(wcnss_get_wlan_mac_address);
@@ -2649,57 +2640,57 @@ static int wcnss_ctrl_open(struct inode *inode, struct file *file)
	return rc;
}


void process_usr_ctrl_cmd(u8 *buf, size_t len)
static ssize_t wcnss_ctrl_write(struct file *fp, const char __user
			*user_buffer, size_t count, loff_t *position)
{
	u16 cmd = buf[0] << 8 | buf[1];
	int rc = 0;
	u16 cmd;
	u8 buf[WCNSS_MAX_CMD_LEN];

	switch (cmd) {
	if (!penv || !penv->ctrl_device_opened ||
	    WCNSS_MAX_CMD_LEN < count || WCNSS_MIN_CMD_LEN > count)
		return -EFAULT;

	mutex_lock(&penv->ctrl_lock);
	rc = copy_from_user(buf, user_buffer, count);
	if (rc) {
		pr_err("%s: Failed to copy ctrl data\n", __func__);
		goto exit;
	}

	cmd = buf[0] << 8 | buf[1];
	switch (cmd) {
	case WCNSS_USR_HAS_CAL_DATA:
		if (1 < buf[2])
			pr_err("%s: Invalid data for cal %d\n", __func__,
				buf[2]);
		if (buf[2] > 1) {
			pr_err("%s: Invalid cal data %d\n", __func__, buf[2]);
			rc = -EINVAL;
			goto exit;
		}
		has_calibrated_data = buf[2];
		break;

	case WCNSS_USR_WLAN_MAC_ADDR:
		if ((count - WCNSS_CMD_INFO_LEN) != WLAN_MAC_ADDR_SIZE) {
			pr_err("%s: Invalid Mac addr %d\n", __func__, buf[2]);
			rc = -EINVAL;
			goto exit;
		}

		memcpy(&penv->wlan_nv_macAddr, &buf[2],
		       sizeof(penv->wlan_nv_macAddr));

		pr_debug("%s: MAC Addr:" MAC_ADDRESS_STR "\n", __func__,
			penv->wlan_nv_macAddr[0], penv->wlan_nv_macAddr[1],
			penv->wlan_nv_macAddr[2], penv->wlan_nv_macAddr[3],
			penv->wlan_nv_macAddr[4], penv->wlan_nv_macAddr[5]);
		pr_debug("%s:MAC Addr: %pM\n", __func__, penv->wlan_nv_macAddr);
		break;

	default:
		pr_err("%s: Invalid command %d\n", __func__, cmd);
		rc = -EINVAL;
		break;
	}
}

static ssize_t wcnss_ctrl_write(struct file *fp, const char __user
			*user_buffer, size_t count, loff_t *position)
{
	int rc = 0;
	u8 buf[WCNSS_MAX_CMD_LEN];

	if (!penv || !penv->ctrl_device_opened || WCNSS_MAX_CMD_LEN < count
			|| WCNSS_MIN_CMD_LEN > count)
		return -EFAULT;

	mutex_lock(&penv->ctrl_lock);
	rc = copy_from_user(buf, user_buffer, count);
	if (0 == rc)
		process_usr_ctrl_cmd(buf, count);

exit:
	mutex_unlock(&penv->ctrl_lock);

	return rc;
}


static const struct file_operations wcnss_ctrl_fops = {
	.owner = THIS_MODULE,
	.open = wcnss_ctrl_open,