aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorMaya Erez <qca_merez@qca.qualcomm.com>2016-11-28 06:49:01 -0500
committerKalle Valo <kvalo@qca.qualcomm.com>2016-12-01 06:20:31 -0500
commit1db226ffe1c2ab900cffb1d71f042e565f77775d (patch)
tree6c8ff295e6baff3146b4d740ed8bab5b9603f864 /drivers/net/wireless/ath
parentbb6743f7c2ffc467002dfe24bea5dedc96c7da04 (diff)
wil6210: validate wil_pmc_alloc parameters
num_descriptors and descriptor_size needs to be checked for: 1) not being negative values 2) no overflow occurs when these are multiplied together as done in wil_pmc_read. An overflow of two signed integers is undefined behavior. Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/wil6210/pmc.c55
1 files changed, 49 insertions, 6 deletions
diff --git a/drivers/net/wireless/ath/wil6210/pmc.c b/drivers/net/wireless/ath/wil6210/pmc.c
index 5ca0307a3274..b9faae0278c9 100644
--- a/drivers/net/wireless/ath/wil6210/pmc.c
+++ b/drivers/net/wireless/ath/wil6210/pmc.c
@@ -54,6 +54,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil,
54 struct pmc_ctx *pmc = &wil->pmc; 54 struct pmc_ctx *pmc = &wil->pmc;
55 struct device *dev = wil_to_dev(wil); 55 struct device *dev = wil_to_dev(wil);
56 struct wmi_pmc_cmd pmc_cmd = {0}; 56 struct wmi_pmc_cmd pmc_cmd = {0};
57 int last_cmd_err = -ENOMEM;
57 58
58 mutex_lock(&pmc->lock); 59 mutex_lock(&pmc->lock);
59 60
@@ -62,6 +63,29 @@ void wil_pmc_alloc(struct wil6210_priv *wil,
62 wil_err(wil, "%s: ERROR pmc is already allocated\n", __func__); 63 wil_err(wil, "%s: ERROR pmc is already allocated\n", __func__);
63 goto no_release_err; 64 goto no_release_err;
64 } 65 }
66 if ((num_descriptors <= 0) || (descriptor_size <= 0)) {
67 wil_err(wil,
68 "Invalid params num_descriptors(%d), descriptor_size(%d)\n",
69 num_descriptors, descriptor_size);
70 last_cmd_err = -EINVAL;
71 goto no_release_err;
72 }
73
74 if (num_descriptors > (1 << WIL_RING_SIZE_ORDER_MAX)) {
75 wil_err(wil,
76 "num_descriptors(%d) exceeds max ring size %d\n",
77 num_descriptors, 1 << WIL_RING_SIZE_ORDER_MAX);
78 last_cmd_err = -EINVAL;
79 goto no_release_err;
80 }
81
82 if (num_descriptors > INT_MAX / descriptor_size) {
83 wil_err(wil,
84 "Overflow in num_descriptors(%d)*descriptor_size(%d)\n",
85 num_descriptors, descriptor_size);
86 last_cmd_err = -EINVAL;
87 goto no_release_err;
88 }
65 89
66 pmc->num_descriptors = num_descriptors; 90 pmc->num_descriptors = num_descriptors;
67 pmc->descriptor_size = descriptor_size; 91 pmc->descriptor_size = descriptor_size;
@@ -189,7 +213,7 @@ release_pmc_skb_list:
189 pmc->descriptors = NULL; 213 pmc->descriptors = NULL;
190 214
191no_release_err: 215no_release_err:
192 pmc->last_cmd_status = -ENOMEM; 216 pmc->last_cmd_status = last_cmd_err;
193 mutex_unlock(&pmc->lock); 217 mutex_unlock(&pmc->lock);
194} 218}
195 219
@@ -295,7 +319,7 @@ ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count,
295 size_t retval = 0; 319 size_t retval = 0;
296 unsigned long long idx; 320 unsigned long long idx;
297 loff_t offset; 321 loff_t offset;
298 size_t pmc_size = pmc->descriptor_size * pmc->num_descriptors; 322 size_t pmc_size;
299 323
300 mutex_lock(&pmc->lock); 324 mutex_lock(&pmc->lock);
301 325
@@ -306,6 +330,8 @@ ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count,
306 return -EPERM; 330 return -EPERM;
307 } 331 }
308 332
333 pmc_size = pmc->descriptor_size * pmc->num_descriptors;
334
309 wil_dbg_misc(wil, 335 wil_dbg_misc(wil,
310 "%s: size %u, pos %lld\n", 336 "%s: size %u, pos %lld\n",
311 __func__, (unsigned)count, *f_pos); 337 __func__, (unsigned)count, *f_pos);
@@ -345,7 +371,18 @@ loff_t wil_pmc_llseek(struct file *filp, loff_t off, int whence)
345 loff_t newpos; 371 loff_t newpos;
346 struct wil6210_priv *wil = filp->private_data; 372 struct wil6210_priv *wil = filp->private_data;
347 struct pmc_ctx *pmc = &wil->pmc; 373 struct pmc_ctx *pmc = &wil->pmc;
348 size_t pmc_size = pmc->descriptor_size * pmc->num_descriptors; 374 size_t pmc_size;
375
376 mutex_lock(&pmc->lock);
377
378 if (!wil_is_pmc_allocated(pmc)) {
379 wil_err(wil, "error, pmc is not allocated!\n");
380 pmc->last_cmd_status = -EPERM;
381 mutex_unlock(&pmc->lock);
382 return -EPERM;
383 }
384
385 pmc_size = pmc->descriptor_size * pmc->num_descriptors;
349 386
350 switch (whence) { 387 switch (whence) {
351 case 0: /* SEEK_SET */ 388 case 0: /* SEEK_SET */
@@ -361,15 +398,21 @@ loff_t wil_pmc_llseek(struct file *filp, loff_t off, int whence)
361 break; 398 break;
362 399
363 default: /* can't happen */ 400 default: /* can't happen */
364 return -EINVAL; 401 newpos = -EINVAL;
402 goto out;
365 } 403 }
366 404
367 if (newpos < 0) 405 if (newpos < 0) {
368 return -EINVAL; 406 newpos = -EINVAL;
407 goto out;
408 }
369 if (newpos > pmc_size) 409 if (newpos > pmc_size)
370 newpos = pmc_size; 410 newpos = pmc_size;
371 411
372 filp->f_pos = newpos; 412 filp->f_pos = newpos;
373 413
414out:
415 mutex_unlock(&pmc->lock);
416
374 return newpos; 417 return newpos;
375} 418}