summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYing Xue <ying.xue@windriver.com>2013-10-18 07:23:14 +0200
committerJiri Slaby <jslaby@suse.cz>2014-08-26 14:12:22 +0200
commit56cf7e077c081a5874dcbd722cbae771bb5177fc (patch)
tree8365150d373462d14a0d9937485ad30a02e3d579
parente0c516a109e873556edd487912c62bc39ad5c9ce (diff)
tipc: don't use memcpy to copy from user space
commit 5c0a0fc81f4dc786b42c4fc9c7c72ba635406ab5 upstream. tipc_msg_build() calls skb_copy_to_linear_data_offset() to copy data from user space to kernel space. However, the latter function does in its turn call memcpy() to perform the actual copying. This poses an obvious security and robustness risk, since memcpy() never makes any validity check on the pointer it is copying from. To correct this, we the replace the offending function call with a call to memcpy_fromiovecend(), which uses copy_from_user() to perform the copying. Signed-off-by: Ying Xue <ying.xue@windriver.com> Reviewed-by: Paul Gortmaker <paul.gortmaker@windriver.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
-rw-r--r--net/tipc/msg.c22
1 files changed, 9 insertions, 13 deletions
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index ced60e2fc4f7..1e76d91e5691 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -76,10 +76,11 @@ int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect,
u32 num_sect, unsigned int total_len, int max_size,
struct sk_buff **buf)
{
- int dsz, sz, hsz, pos, res, cnt;
+ int dsz, sz, hsz;
+ unsigned char *to;
dsz = total_len;
- pos = hsz = msg_hdr_sz(hdr);
+ hsz = msg_hdr_sz(hdr);
sz = hsz + dsz;
msg_set_size(hdr, sz);
if (unlikely(sz > max_size)) {
@@ -91,16 +92,11 @@ int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect,
if (!(*buf))
return -ENOMEM;
skb_copy_to_linear_data(*buf, hdr, hsz);
- for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) {
- skb_copy_to_linear_data_offset(*buf, pos,
- msg_sect[cnt].iov_base,
- msg_sect[cnt].iov_len);
- pos += msg_sect[cnt].iov_len;
+ to = (*buf)->data + hsz;
+ if (total_len && memcpy_fromiovecend(to, msg_sect, 0, dsz)) {
+ kfree_skb(*buf);
+ *buf = NULL;
+ return -EFAULT;
}
- if (likely(res))
- return dsz;
-
- kfree_skb(*buf);
- *buf = NULL;
- return -EFAULT;
+ return dsz;
}