Commit 917507b01efea8017bfcb4188ac696612e363e72

Authored by Arnaud Patard
Committed by Riku Voipio
1 parent fd4d81dd

linux-user: check some parameters for some socket syscalls.

This patch is fixing following issues :

- commit 8fea3602 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>
Showing 1 changed file with 34 additions and 8 deletions
linux-user/syscall.c
@@ -1498,13 +1498,17 @@ static abi_long do_bind(int sockfd, abi_ulong target_addr, @@ -1498,13 +1498,17 @@ static abi_long do_bind(int sockfd, abi_ulong target_addr,
1498 socklen_t addrlen) 1498 socklen_t addrlen)
1499 { 1499 {
1500 void *addr; 1500 void *addr;
  1501 + abi_long ret;
1501 1502
1502 if (addrlen < 0) 1503 if (addrlen < 0)
1503 return -TARGET_EINVAL; 1504 return -TARGET_EINVAL;
1504 1505
1505 addr = alloca(addrlen+1); 1506 addr = alloca(addrlen+1);
1506 1507
1507 - target_to_host_sockaddr(addr, target_addr, addrlen); 1508 + ret = target_to_host_sockaddr(addr, target_addr, addrlen);
  1509 + if (ret)
  1510 + return ret;
  1511 +
1508 return get_errno(bind(sockfd, addr, addrlen)); 1512 return get_errno(bind(sockfd, addr, addrlen));
1509 } 1513 }
1510 1514
@@ -1513,13 +1517,17 @@ static abi_long do_connect(int sockfd, abi_ulong target_addr, @@ -1513,13 +1517,17 @@ static abi_long do_connect(int sockfd, abi_ulong target_addr,
1513 socklen_t addrlen) 1517 socklen_t addrlen)
1514 { 1518 {
1515 void *addr; 1519 void *addr;
  1520 + abi_long ret;
1516 1521
1517 if (addrlen < 0) 1522 if (addrlen < 0)
1518 return -TARGET_EINVAL; 1523 return -TARGET_EINVAL;
1519 1524
1520 addr = alloca(addrlen); 1525 addr = alloca(addrlen);
1521 1526
1522 - target_to_host_sockaddr(addr, target_addr, addrlen); 1527 + ret = target_to_host_sockaddr(addr, target_addr, addrlen);
  1528 + if (ret)
  1529 + return ret;
  1530 +
1523 return get_errno(connect(sockfd, addr, addrlen)); 1531 return get_errno(connect(sockfd, addr, addrlen));
1524 } 1532 }
1525 1533
@@ -1543,8 +1551,12 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, @@ -1543,8 +1551,12 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1543 if (msgp->msg_name) { 1551 if (msgp->msg_name) {
1544 msg.msg_namelen = tswap32(msgp->msg_namelen); 1552 msg.msg_namelen = tswap32(msgp->msg_namelen);
1545 msg.msg_name = alloca(msg.msg_namelen); 1553 msg.msg_name = alloca(msg.msg_namelen);
1546 - target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name), 1554 + ret = target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
1547 msg.msg_namelen); 1555 msg.msg_namelen);
  1556 + if (ret) {
  1557 + unlock_user_struct(msgp, target_msg, send ? 0 : 1);
  1558 + return ret;
  1559 + }
1548 } else { 1560 } else {
1549 msg.msg_name = NULL; 1561 msg.msg_name = NULL;
1550 msg.msg_namelen = 0; 1562 msg.msg_namelen = 0;
@@ -1586,12 +1598,19 @@ static abi_long do_accept(int fd, abi_ulong target_addr, @@ -1586,12 +1598,19 @@ static abi_long do_accept(int fd, abi_ulong target_addr,
1586 void *addr; 1598 void *addr;
1587 abi_long ret; 1599 abi_long ret;
1588 1600
  1601 + if (target_addr == 0)
  1602 + return get_errno(accept(fd, NULL, NULL));
  1603 +
  1604 + /* linux returns EINVAL if addrlen pointer is invalid */
1589 if (get_user_u32(addrlen, target_addrlen_addr)) 1605 if (get_user_u32(addrlen, target_addrlen_addr))
1590 - return -TARGET_EFAULT; 1606 + return -TARGET_EINVAL;
1591 1607
1592 if (addrlen < 0) 1608 if (addrlen < 0)
1593 return -TARGET_EINVAL; 1609 return -TARGET_EINVAL;
1594 1610
  1611 + if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
  1612 + return -TARGET_EINVAL;
  1613 +
1595 addr = alloca(addrlen); 1614 addr = alloca(addrlen);
1596 1615
1597 ret = get_errno(accept(fd, addr, &addrlen)); 1616 ret = get_errno(accept(fd, addr, &addrlen));
@@ -1617,6 +1636,9 @@ static abi_long do_getpeername(int fd, abi_ulong target_addr, @@ -1617,6 +1636,9 @@ static abi_long do_getpeername(int fd, abi_ulong target_addr,
1617 if (addrlen < 0) 1636 if (addrlen < 0)
1618 return -TARGET_EINVAL; 1637 return -TARGET_EINVAL;
1619 1638
  1639 + if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
  1640 + return -TARGET_EFAULT;
  1641 +
1620 addr = alloca(addrlen); 1642 addr = alloca(addrlen);
1621 1643
1622 ret = get_errno(getpeername(fd, addr, &addrlen)); 1644 ret = get_errno(getpeername(fd, addr, &addrlen));
@@ -1636,15 +1658,15 @@ static abi_long do_getsockname(int fd, abi_ulong target_addr, @@ -1636,15 +1658,15 @@ static abi_long do_getsockname(int fd, abi_ulong target_addr,
1636 void *addr; 1658 void *addr;
1637 abi_long ret; 1659 abi_long ret;
1638 1660
1639 - if (target_addr == 0)  
1640 - return get_errno(accept(fd, NULL, NULL));  
1641 -  
1642 if (get_user_u32(addrlen, target_addrlen_addr)) 1661 if (get_user_u32(addrlen, target_addrlen_addr))
1643 return -TARGET_EFAULT; 1662 return -TARGET_EFAULT;
1644 1663
1645 if (addrlen < 0) 1664 if (addrlen < 0)
1646 return -TARGET_EINVAL; 1665 return -TARGET_EINVAL;
1647 1666
  1667 + if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
  1668 + return -TARGET_EFAULT;
  1669 +
1648 addr = alloca(addrlen); 1670 addr = alloca(addrlen);
1649 1671
1650 ret = get_errno(getsockname(fd, addr, &addrlen)); 1672 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, @@ -1688,7 +1710,11 @@ static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1688 return -TARGET_EFAULT; 1710 return -TARGET_EFAULT;
1689 if (target_addr) { 1711 if (target_addr) {
1690 addr = alloca(addrlen); 1712 addr = alloca(addrlen);
1691 - target_to_host_sockaddr(addr, target_addr, addrlen); 1713 + ret = target_to_host_sockaddr(addr, target_addr, addrlen);
  1714 + if (ret) {
  1715 + unlock_user(host_msg, msg, 0);
  1716 + return ret;
  1717 + }
1692 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen)); 1718 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1693 } else { 1719 } else {
1694 ret = get_errno(send(fd, host_msg, len, flags)); 1720 ret = get_errno(send(fd, host_msg, len, flags));