Commit aa63e18e authored by Solomon Peachy's avatar Solomon Peachy Committed by John W. Linville

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: default avatarSolomon Peachy <pizza@shaftnet.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent cc2588ea
...@@ -397,13 +397,13 @@ struct etf_req_msg; ...@@ -397,13 +397,13 @@ struct etf_req_msg;
static int etf_request(struct cw1200_common *priv, static int etf_request(struct cw1200_common *priv,
struct etf_req_msg *msg, u32 len); struct etf_req_msg *msg, u32 len);
#define MAX_RX_SZE 2600 #define MAX_RX_SIZE 2600
struct etf_in_state { struct etf_in_state {
struct cw1200_common *priv; struct cw1200_common *priv;
u32 total_len; u16 total_len;
u8 buf[MAX_RX_SZE]; u16 written;
u32 written; u8 buf[MAX_RX_SIZE];
}; };
static int cw1200_etf_in_open(struct inode *inode, struct file *file) static 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,6 +448,11 @@ static ssize_t cw1200_etf_in_write(struct file *file,
return -EFAULT; return -EFAULT;
} }
if (etf->total_len > MAX_RX_SIZE) {
pr_err("requested length > MAX_RX_SIZE\n");
return -EINVAL;
}
written += sizeof(etf->total_len); written += sizeof(etf->total_len);
count -= sizeof(etf->total_len); count -= sizeof(etf->total_len);
} }
...@@ -455,6 +460,11 @@ static ssize_t cw1200_etf_in_write(struct file *file, ...@@ -455,6 +460,11 @@ static ssize_t cw1200_etf_in_write(struct file *file,
if (!count) if (!count)
goto done; goto done;
if (count > (etf->total_len - written)) {
pr_err("Tried to write > MAX_RX_SIZE\n");
return -EINVAL;
}
if (copy_from_user(etf->buf + etf->written, user_buf + written, if (copy_from_user(etf->buf + etf->written, user_buf + written,
count)) { count)) {
pr_err("copy_from_user (payload %zu) failed\n", count); pr_err("copy_from_user (payload %zu) failed\n", count);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment