linux-user: check some parameters for some socket syscalls.
This patch is fixing following issues :
- commit 8fea36025b
was applied to
do_getsockname instead of do_accept.
- Some syscalls were not checking properly the memory addresses passed
as argument
- Add check before syscalls made for cases like do_getpeername() where
we're using the address parameter after doing the syscall
- Fix do_accept to return EINVAL instead of EFAULT when parameters
invalid to match with linux behaviour
Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org>
Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
This commit is contained in:
parent
fd4d81dd04
commit
917507b01e
@ -1498,13 +1498,17 @@ static abi_long do_bind(int sockfd, abi_ulong target_addr,
|
|||||||
socklen_t addrlen)
|
socklen_t addrlen)
|
||||||
{
|
{
|
||||||
void *addr;
|
void *addr;
|
||||||
|
abi_long ret;
|
||||||
|
|
||||||
if (addrlen < 0)
|
if (addrlen < 0)
|
||||||
return -TARGET_EINVAL;
|
return -TARGET_EINVAL;
|
||||||
|
|
||||||
addr = alloca(addrlen+1);
|
addr = alloca(addrlen+1);
|
||||||
|
|
||||||
target_to_host_sockaddr(addr, target_addr, addrlen);
|
ret = target_to_host_sockaddr(addr, target_addr, addrlen);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
return get_errno(bind(sockfd, addr, addrlen));
|
return get_errno(bind(sockfd, addr, addrlen));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1513,13 +1517,17 @@ static abi_long do_connect(int sockfd, abi_ulong target_addr,
|
|||||||
socklen_t addrlen)
|
socklen_t addrlen)
|
||||||
{
|
{
|
||||||
void *addr;
|
void *addr;
|
||||||
|
abi_long ret;
|
||||||
|
|
||||||
if (addrlen < 0)
|
if (addrlen < 0)
|
||||||
return -TARGET_EINVAL;
|
return -TARGET_EINVAL;
|
||||||
|
|
||||||
addr = alloca(addrlen);
|
addr = alloca(addrlen);
|
||||||
|
|
||||||
target_to_host_sockaddr(addr, target_addr, addrlen);
|
ret = target_to_host_sockaddr(addr, target_addr, addrlen);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
return get_errno(connect(sockfd, addr, addrlen));
|
return get_errno(connect(sockfd, addr, addrlen));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1543,8 +1551,12 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
|
|||||||
if (msgp->msg_name) {
|
if (msgp->msg_name) {
|
||||||
msg.msg_namelen = tswap32(msgp->msg_namelen);
|
msg.msg_namelen = tswap32(msgp->msg_namelen);
|
||||||
msg.msg_name = alloca(msg.msg_namelen);
|
msg.msg_name = alloca(msg.msg_namelen);
|
||||||
target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
|
ret = target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
|
||||||
msg.msg_namelen);
|
msg.msg_namelen);
|
||||||
|
if (ret) {
|
||||||
|
unlock_user_struct(msgp, target_msg, send ? 0 : 1);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
msg.msg_name = NULL;
|
msg.msg_name = NULL;
|
||||||
msg.msg_namelen = 0;
|
msg.msg_namelen = 0;
|
||||||
@ -1586,12 +1598,19 @@ static abi_long do_accept(int fd, abi_ulong target_addr,
|
|||||||
void *addr;
|
void *addr;
|
||||||
abi_long ret;
|
abi_long ret;
|
||||||
|
|
||||||
|
if (target_addr == 0)
|
||||||
|
return get_errno(accept(fd, NULL, NULL));
|
||||||
|
|
||||||
|
/* linux returns EINVAL if addrlen pointer is invalid */
|
||||||
if (get_user_u32(addrlen, target_addrlen_addr))
|
if (get_user_u32(addrlen, target_addrlen_addr))
|
||||||
return -TARGET_EFAULT;
|
return -TARGET_EINVAL;
|
||||||
|
|
||||||
if (addrlen < 0)
|
if (addrlen < 0)
|
||||||
return -TARGET_EINVAL;
|
return -TARGET_EINVAL;
|
||||||
|
|
||||||
|
if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
|
||||||
addr = alloca(addrlen);
|
addr = alloca(addrlen);
|
||||||
|
|
||||||
ret = get_errno(accept(fd, addr, &addrlen));
|
ret = get_errno(accept(fd, addr, &addrlen));
|
||||||
@ -1617,6 +1636,9 @@ static abi_long do_getpeername(int fd, abi_ulong target_addr,
|
|||||||
if (addrlen < 0)
|
if (addrlen < 0)
|
||||||
return -TARGET_EINVAL;
|
return -TARGET_EINVAL;
|
||||||
|
|
||||||
|
if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
|
||||||
addr = alloca(addrlen);
|
addr = alloca(addrlen);
|
||||||
|
|
||||||
ret = get_errno(getpeername(fd, addr, &addrlen));
|
ret = get_errno(getpeername(fd, addr, &addrlen));
|
||||||
@ -1636,15 +1658,15 @@ static abi_long do_getsockname(int fd, abi_ulong target_addr,
|
|||||||
void *addr;
|
void *addr;
|
||||||
abi_long ret;
|
abi_long ret;
|
||||||
|
|
||||||
if (target_addr == 0)
|
|
||||||
return get_errno(accept(fd, NULL, NULL));
|
|
||||||
|
|
||||||
if (get_user_u32(addrlen, target_addrlen_addr))
|
if (get_user_u32(addrlen, target_addrlen_addr))
|
||||||
return -TARGET_EFAULT;
|
return -TARGET_EFAULT;
|
||||||
|
|
||||||
if (addrlen < 0)
|
if (addrlen < 0)
|
||||||
return -TARGET_EINVAL;
|
return -TARGET_EINVAL;
|
||||||
|
|
||||||
|
if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
|
||||||
addr = alloca(addrlen);
|
addr = alloca(addrlen);
|
||||||
|
|
||||||
ret = get_errno(getsockname(fd, addr, &addrlen));
|
ret = get_errno(getsockname(fd, addr, &addrlen));
|
||||||
@ -1688,7 +1710,11 @@ static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
|
|||||||
return -TARGET_EFAULT;
|
return -TARGET_EFAULT;
|
||||||
if (target_addr) {
|
if (target_addr) {
|
||||||
addr = alloca(addrlen);
|
addr = alloca(addrlen);
|
||||||
target_to_host_sockaddr(addr, target_addr, addrlen);
|
ret = target_to_host_sockaddr(addr, target_addr, addrlen);
|
||||||
|
if (ret) {
|
||||||
|
unlock_user(host_msg, msg, 0);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
|
ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
|
||||||
} else {
|
} else {
|
||||||
ret = get_errno(send(fd, host_msg, len, flags));
|
ret = get_errno(send(fd, host_msg, len, flags));
|
||||||
|
Loading…
Reference in New Issue
Block a user