summaryrefslogtreecommitdiff
path: root/net/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/socket.c')
-rw-r--r--net/socket.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/net/socket.c b/net/socket.c
index bac335ecee4c..e8892b218708 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -276,28 +276,41 @@ int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *k
static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
void __user *uaddr, int __user *ulen)
{
- int err;
int len;
BUG_ON(klen > sizeof(struct sockaddr_storage));
- err = get_user(len, ulen);
- if (err)
- return err;
+
+ if (can_do_masked_user_access())
+ ulen = masked_user_access_begin(ulen);
+ else if (!user_access_begin(ulen, 4))
+ return -EFAULT;
+
+ unsafe_get_user(len, ulen, efault_end);
+
if (len > klen)
len = klen;
- if (len < 0)
- return -EINVAL;
+ /*
+ * "fromlen shall refer to the value before truncation.."
+ * 1003.1g
+ */
+ if (len >= 0)
+ unsafe_put_user(klen, ulen, efault_end);
+
+ user_access_end();
+
if (len) {
+ if (len < 0)
+ return -EINVAL;
if (audit_sockaddr(klen, kaddr))
return -ENOMEM;
if (copy_to_user(uaddr, kaddr, len))
return -EFAULT;
}
- /*
- * "fromlen shall refer to the value before truncation.."
- * 1003.1g
- */
- return __put_user(klen, ulen);
+ return 0;
+
+efault_end:
+ user_access_end();
+ return -EFAULT;
}
static struct kmem_cache *sock_inode_cachep __ro_after_init;