aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/cw1200
diff options
context:
space:
mode:
authorSolomon Peachy <pizza@shaftnet.org>2013-06-04 23:37:05 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-06-10 14:41:25 -0400
commitaa63e18e3ddad4eb15d4af34ae66e7f4dcc7a6d0 (patch)
tree4fd3cb8439a8efc71e4b768257dbaea6f8dddbec /drivers/net/wireless/cw1200
parentcc2588eabbe46820a86e55fccec8b741e15f647f (diff)
cw1200: Sanity-check arguments in copy_from_user()
The optional debugfs interface to the vendor's engineering tools wasn't bounds checking at all, which made it trivial to perform a buffer overflow if this interface was compiled in and then explicitly enabled at runtime. This patch checks both the length supplied as part of the data to ensure it is sane, and also the amount of data compared to the remaining buffer space. If either is too large, fail immediately. (This bug was spotted by Dan Carpenter <dan.carpenter@oracle.com>) Signed-off-by: Solomon Peachy <pizza@shaftnet.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/cw1200')
-rw-r--r--drivers/net/wireless/cw1200/debug.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/net/wireless/cw1200/debug.c b/drivers/net/wireless/cw1200/debug.c
index eb40c9c61a51..1596b7042cbd 100644
--- a/drivers/net/wireless/cw1200/debug.c
+++ b/drivers/net/wireless/cw1200/debug.c
@@ -397,13 +397,13 @@ struct etf_req_msg;
397static int etf_request(struct cw1200_common *priv, 397static int etf_request(struct cw1200_common *priv,
398 struct etf_req_msg *msg, u32 len); 398 struct etf_req_msg *msg, u32 len);
399 399
400#define MAX_RX_SZE 2600 400#define MAX_RX_SIZE 2600
401 401
402struct etf_in_state { 402struct etf_in_state {
403 struct cw1200_common *priv; 403 struct cw1200_common *priv;
404 u32 total_len; 404 u16 total_len;
405 u8 buf[MAX_RX_SZE]; 405 u16 written;
406 u32 written; 406 u8 buf[MAX_RX_SIZE];
407}; 407};
408 408
409static int cw1200_etf_in_open(struct inode *inode, struct file *file) 409static int cw1200_etf_in_open(struct inode *inode, struct file *file)
@@ -448,6 +448,11 @@ static ssize_t cw1200_etf_in_write(struct file *file,
448 return -EFAULT; 448 return -EFAULT;
449 } 449 }
450 450
451 if (etf->total_len > MAX_RX_SIZE) {
452 pr_err("requested length > MAX_RX_SIZE\n");
453 return -EINVAL;
454 }
455
451 written += sizeof(etf->total_len); 456 written += sizeof(etf->total_len);
452 count -= sizeof(etf->total_len); 457 count -= sizeof(etf->total_len);
453 } 458 }
@@ -455,6 +460,11 @@ static ssize_t cw1200_etf_in_write(struct file *file,
455 if (!count) 460 if (!count)
456 goto done; 461 goto done;
457 462
463 if (count > (etf->total_len - written)) {
464 pr_err("Tried to write > MAX_RX_SIZE\n");
465 return -EINVAL;
466 }
467
458 if (copy_from_user(etf->buf + etf->written, user_buf + written, 468 if (copy_from_user(etf->buf + etf->written, user_buf + written,
459 count)) { 469 count)) {
460 pr_err("copy_from_user (payload %zu) failed\n", count); 470 pr_err("copy_from_user (payload %zu) failed\n", count);