From f0fc86966253ad244f53841e3d8db2cf9f862019 Mon Sep 17 00:00:00 2001
From: Al Viro <viro@zeniv.linux.org.uk>
Date: Thu, 24 Dec 2015 00:10:20 -0500
Subject: [PATCH] switch wireless debugfs ->write() instances to
 memdup_user_nul()

again, it only parses the contents of the copied buffer, so
get_zeroed_page() might as well had been kmalloc(), which makes
it open-coded memdup_user_nul()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 drivers/net/wireless/libertas/debugfs.c | 181 +++++++++---------------
 drivers/net/wireless/mwifiex/debugfs.c  |  82 ++++-------
 2 files changed, 89 insertions(+), 174 deletions(-)

diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index 26cbf1dcc662..faed1823c58e 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -56,19 +56,15 @@ static ssize_t lbs_sleepparams_write(struct file *file,
 				loff_t *ppos)
 {
 	struct lbs_private *priv = file->private_data;
-	ssize_t buf_size, ret;
+	ssize_t ret;
 	struct sleep_params sp;
 	int p1, p2, p3, p4, p5, p6;
-	unsigned long addr = get_zeroed_page(GFP_KERNEL);
-	char *buf = (char *)addr;
-	if (!buf)
-		return -ENOMEM;
+	char *buf;
+
+	buf = memdup_user_nul(user_buf, min(count, len - 1));
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
 
-	buf_size = min(count, len - 1);
-	if (copy_from_user(buf, user_buf, buf_size)) {
-		ret = -EFAULT;
-		goto out_unlock;
-	}
 	ret = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6);
 	if (ret != 6) {
 		ret = -EINVAL;
@@ -88,7 +84,7 @@ static ssize_t lbs_sleepparams_write(struct file *file,
 		ret = -EINVAL;
 
 out_unlock:
-	free_page(addr);
+	kfree(buf);
 	return ret;
 }
 
@@ -125,18 +121,14 @@ static ssize_t lbs_host_sleep_write(struct file *file,
 				loff_t *ppos)
 {
 	struct lbs_private *priv = file->private_data;
-	ssize_t buf_size, ret;
+	ssize_t ret;
 	int host_sleep;
-	unsigned long addr = get_zeroed_page(GFP_KERNEL);
-	char *buf = (char *)addr;
-	if (!buf)
-		return -ENOMEM;
+	char *buf;
+
+	buf = memdup_user_nul(user_buf, min(count, len - 1));
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
 
-	buf_size = min(count, len - 1);
-	if (copy_from_user(buf, user_buf, buf_size)) {
-		ret = -EFAULT;
-		goto out_unlock;
-	}
 	ret = sscanf(buf, "%d", &host_sleep);
 	if (ret != 1) {
 		ret = -EINVAL;
@@ -162,7 +154,7 @@ static ssize_t lbs_host_sleep_write(struct file *file,
 		ret = count;
 
 out_unlock:
-	free_page(addr);
+	kfree(buf);
 	return ret;
 }
 
@@ -281,21 +273,15 @@ static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask,
 	struct cmd_ds_802_11_subscribe_event *events;
 	struct mrvl_ie_thresholds *tlv;
 	struct lbs_private *priv = file->private_data;
-	ssize_t buf_size;
 	int value, freq, new_mask;
 	uint16_t curr_mask;
 	char *buf;
 	int ret;
 
-	buf = (char *)get_zeroed_page(GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
+	buf = memdup_user_nul(userbuf, min(count, len - 1));
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
 
-	buf_size = min(count, len - 1);
-	if (copy_from_user(buf, userbuf, buf_size)) {
-		ret = -EFAULT;
-		goto out_page;
-	}
 	ret = sscanf(buf, "%d %d %d", &value, &freq, &new_mask);
 	if (ret != 3) {
 		ret = -EINVAL;
@@ -343,7 +329,7 @@ static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask,
  out_events:
 	kfree(events);
  out_page:
-	free_page((unsigned long)buf);
+	kfree(buf);
 	return ret;
 }
 
@@ -472,22 +458,15 @@ static ssize_t lbs_rdmac_write(struct file *file,
 				    size_t count, loff_t *ppos)
 {
 	struct lbs_private *priv = file->private_data;
-	ssize_t res, buf_size;
-	unsigned long addr = get_zeroed_page(GFP_KERNEL);
-	char *buf = (char *)addr;
-	if (!buf)
-		return -ENOMEM;
+	char *buf;
+
+	buf = memdup_user_nul(userbuf, min(count, len - 1));
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
 
-	buf_size = min(count, len - 1);
-	if (copy_from_user(buf, userbuf, buf_size)) {
-		res = -EFAULT;
-		goto out_unlock;
-	}
 	priv->mac_offset = simple_strtoul(buf, NULL, 16);
-	res = count;
-out_unlock:
-	free_page(addr);
-	return res;
+	kfree(buf);
+	return count;
 }
 
 static ssize_t lbs_wrmac_write(struct file *file,
@@ -496,18 +475,14 @@ static ssize_t lbs_wrmac_write(struct file *file,
 {
 
 	struct lbs_private *priv = file->private_data;
-	ssize_t res, buf_size;
+	ssize_t res;
 	u32 offset, value;
-	unsigned long addr = get_zeroed_page(GFP_KERNEL);
-	char *buf = (char *)addr;
-	if (!buf)
-		return -ENOMEM;
+	char *buf;
+
+	buf = memdup_user_nul(userbuf, min(count, len - 1));
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
 
-	buf_size = min(count, len - 1);
-	if (copy_from_user(buf, userbuf, buf_size)) {
-		res = -EFAULT;
-		goto out_unlock;
-	}
 	res = sscanf(buf, "%x %x", &offset, &value);
 	if (res != 2) {
 		res = -EFAULT;
@@ -520,7 +495,7 @@ static ssize_t lbs_wrmac_write(struct file *file,
 	if (!res)
 		res = count;
 out_unlock:
-	free_page(addr);
+	kfree(buf);
 	return res;
 }
 
@@ -554,22 +529,16 @@ static ssize_t lbs_rdbbp_write(struct file *file,
 				    size_t count, loff_t *ppos)
 {
 	struct lbs_private *priv = file->private_data;
-	ssize_t res, buf_size;
-	unsigned long addr = get_zeroed_page(GFP_KERNEL);
-	char *buf = (char *)addr;
-	if (!buf)
-		return -ENOMEM;
+	char *buf;
+
+	buf = memdup_user_nul(userbuf, min(count, len - 1));
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
 
-	buf_size = min(count, len - 1);
-	if (copy_from_user(buf, userbuf, buf_size)) {
-		res = -EFAULT;
-		goto out_unlock;
-	}
 	priv->bbp_offset = simple_strtoul(buf, NULL, 16);
-	res = count;
-out_unlock:
-	free_page(addr);
-	return res;
+	kfree(buf);
+
+	return count;
 }
 
 static ssize_t lbs_wrbbp_write(struct file *file,
@@ -578,18 +547,14 @@ static ssize_t lbs_wrbbp_write(struct file *file,
 {
 
 	struct lbs_private *priv = file->private_data;
-	ssize_t res, buf_size;
+	ssize_t res;
 	u32 offset, value;
-	unsigned long addr = get_zeroed_page(GFP_KERNEL);
-	char *buf = (char *)addr;
-	if (!buf)
-		return -ENOMEM;
+	char *buf;
+
+	buf = memdup_user_nul(userbuf, min(count, len - 1));
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
 
-	buf_size = min(count, len - 1);
-	if (copy_from_user(buf, userbuf, buf_size)) {
-		res = -EFAULT;
-		goto out_unlock;
-	}
 	res = sscanf(buf, "%x %x", &offset, &value);
 	if (res != 2) {
 		res = -EFAULT;
@@ -602,7 +567,7 @@ static ssize_t lbs_wrbbp_write(struct file *file,
 	if (!res)
 		res = count;
 out_unlock:
-	free_page(addr);
+	kfree(buf);
 	return res;
 }
 
@@ -636,22 +601,15 @@ static ssize_t lbs_rdrf_write(struct file *file,
 				    size_t count, loff_t *ppos)
 {
 	struct lbs_private *priv = file->private_data;
-	ssize_t res, buf_size;
-	unsigned long addr = get_zeroed_page(GFP_KERNEL);
-	char *buf = (char *)addr;
-	if (!buf)
-		return -ENOMEM;
+	char *buf;
+
+	buf = memdup_user_nul(userbuf, min(count, len - 1));
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
 
-	buf_size = min(count, len - 1);
-	if (copy_from_user(buf, userbuf, buf_size)) {
-		res = -EFAULT;
-		goto out_unlock;
-	}
 	priv->rf_offset = simple_strtoul(buf, NULL, 16);
-	res = count;
-out_unlock:
-	free_page(addr);
-	return res;
+	kfree(buf);
+	return count;
 }
 
 static ssize_t lbs_wrrf_write(struct file *file,
@@ -660,18 +618,14 @@ static ssize_t lbs_wrrf_write(struct file *file,
 {
 
 	struct lbs_private *priv = file->private_data;
-	ssize_t res, buf_size;
+	ssize_t res;
 	u32 offset, value;
-	unsigned long addr = get_zeroed_page(GFP_KERNEL);
-	char *buf = (char *)addr;
-	if (!buf)
-		return -ENOMEM;
+	char *buf;
+
+	buf = memdup_user_nul(userbuf, min(count, len - 1));
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
 
-	buf_size = min(count, len - 1);
-	if (copy_from_user(buf, userbuf, buf_size)) {
-		res = -EFAULT;
-		goto out_unlock;
-	}
 	res = sscanf(buf, "%x %x", &offset, &value);
 	if (res != 2) {
 		res = -EFAULT;
@@ -684,7 +638,7 @@ static ssize_t lbs_wrrf_write(struct file *file,
 	if (!res)
 		res = count;
 out_unlock:
-	free_page(addr);
+	kfree(buf);
 	return res;
 }
 
@@ -915,16 +869,9 @@ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf,
 	if (cnt == 0)
 		return 0;
 
-	pdata = kmalloc(cnt + 1, GFP_KERNEL);
-	if (pdata == NULL)
-		return 0;
-
-	if (copy_from_user(pdata, buf, cnt)) {
-		lbs_deb_debugfs("Copy from user failed\n");
-		kfree(pdata);
-		return 0;
-	}
-	pdata[cnt] = '\0';
+	pdata = memdup_user_nul(buf, cnt);
+	if (IS_ERR(pdata))
+		return PTR_ERR(pdata);
 
 	p0 = pdata;
 	for (i = 0; i < num_of_items; i++) {
diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c
index 9824d8dd2b44..241e1c3fbf08 100644
--- a/drivers/net/wireless/mwifiex/debugfs.c
+++ b/drivers/net/wireless/mwifiex/debugfs.c
@@ -447,20 +447,13 @@ static ssize_t
 mwifiex_regrdwr_write(struct file *file,
 		      const char __user *ubuf, size_t count, loff_t *ppos)
 {
-	unsigned long addr = get_zeroed_page(GFP_KERNEL);
-	char *buf = (char *) addr;
-	size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
+	char *buf;
 	int ret;
 	u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX;
 
-	if (!buf)
-		return -ENOMEM;
-
-
-	if (copy_from_user(buf, ubuf, buf_size)) {
-		ret = -EFAULT;
-		goto done;
-	}
+	buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
 
 	sscanf(buf, "%u %x %x", &reg_type, &reg_offset, &reg_value);
 
@@ -474,7 +467,7 @@ mwifiex_regrdwr_write(struct file *file,
 		ret = count;
 	}
 done:
-	free_page(addr);
+	kfree(buf);
 	return ret;
 }
 
@@ -572,17 +565,11 @@ mwifiex_debug_mask_write(struct file *file, const char __user *ubuf,
 	int ret;
 	unsigned long debug_mask;
 	struct mwifiex_private *priv = (void *)file->private_data;
-	unsigned long addr = get_zeroed_page(GFP_KERNEL);
-	char *buf = (void *)addr;
-	size_t buf_size = min(count, (size_t)(PAGE_SIZE - 1));
+	char *buf;
 
-	if (!buf)
-		return -ENOMEM;
-
-	if (copy_from_user(buf, ubuf, buf_size)) {
-		ret = -EFAULT;
-		goto done;
-	}
+	buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
 
 	if (kstrtoul(buf, 0, &debug_mask)) {
 		ret = -EINVAL;
@@ -592,7 +579,7 @@ mwifiex_debug_mask_write(struct file *file, const char __user *ubuf,
 	priv->adapter->debug_mask = debug_mask;
 	ret = count;
 done:
-	free_page(addr);
+	kfree(buf);
 	return ret;
 }
 
@@ -609,17 +596,11 @@ mwifiex_memrw_write(struct file *file, const char __user *ubuf, size_t count,
 	struct mwifiex_ds_mem_rw mem_rw;
 	u16 cmd_action;
 	struct mwifiex_private *priv = (void *)file->private_data;
-	unsigned long addr = get_zeroed_page(GFP_KERNEL);
-	char *buf = (void *)addr;
-	size_t buf_size = min(count, (size_t)(PAGE_SIZE - 1));
-
-	if (!buf)
-		return -ENOMEM;
+	char *buf;
 
-	if (copy_from_user(buf, ubuf, buf_size)) {
-		ret = -EFAULT;
-		goto done;
-	}
+	buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
 
 	ret = sscanf(buf, "%c %x %x", &cmd, &mem_rw.addr, &mem_rw.value);
 	if (ret != 3) {
@@ -645,7 +626,7 @@ mwifiex_memrw_write(struct file *file, const char __user *ubuf, size_t count,
 		ret = count;
 
 done:
-	free_page(addr);
+	kfree(buf);
 	return ret;
 }
 
@@ -686,20 +667,13 @@ static ssize_t
 mwifiex_rdeeprom_write(struct file *file,
 		       const char __user *ubuf, size_t count, loff_t *ppos)
 {
-	unsigned long addr = get_zeroed_page(GFP_KERNEL);
-	char *buf = (char *) addr;
-	size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
+	char *buf;
 	int ret = 0;
 	int offset = -1, bytes = -1;
 
-	if (!buf)
-		return -ENOMEM;
-
-
-	if (copy_from_user(buf, ubuf, buf_size)) {
-		ret = -EFAULT;
-		goto done;
-	}
+	buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
 
 	sscanf(buf, "%d %d", &offset, &bytes);
 
@@ -712,7 +686,7 @@ mwifiex_rdeeprom_write(struct file *file,
 		ret = count;
 	}
 done:
-	free_page(addr);
+	kfree(buf);
 	return ret;
 }
 
@@ -771,21 +745,15 @@ mwifiex_hscfg_write(struct file *file, const char __user *ubuf,
 		    size_t count, loff_t *ppos)
 {
 	struct mwifiex_private *priv = (void *)file->private_data;
-	unsigned long addr = get_zeroed_page(GFP_KERNEL);
-	char *buf = (char *)addr;
-	size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
+	char *buf;
 	int ret, arg_num;
 	struct mwifiex_ds_hs_cfg hscfg;
 	int conditions = HS_CFG_COND_DEF;
 	u32 gpio = HS_CFG_GPIO_DEF, gap = HS_CFG_GAP_DEF;
 
-	if (!buf)
-		return -ENOMEM;
-
-	if (copy_from_user(buf, ubuf, buf_size)) {
-		ret = -EFAULT;
-		goto done;
-	}
+	buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1)));
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
 
 	arg_num = sscanf(buf, "%d %x %x", &conditions, &gpio, &gap);
 
@@ -823,7 +791,7 @@ mwifiex_hscfg_write(struct file *file, const char __user *ubuf,
 	priv->adapter->hs_enabling = false;
 	ret = count;
 done:
-	free_page(addr);
+	kfree(buf);
 	return ret;
 }
 
-- 
2.30.9