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 1498 socklen_t addrlen)
1499 1499 {
1500 1500 void *addr;
  1501 + abi_long ret;
1501 1502  
1502 1503 if (addrlen < 0)
1503 1504 return -TARGET_EINVAL;
1504 1505  
1505 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 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 1517 socklen_t addrlen)
1514 1518 {
1515 1519 void *addr;
  1520 + abi_long ret;
1516 1521  
1517 1522 if (addrlen < 0)
1518 1523 return -TARGET_EINVAL;
1519 1524  
1520 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 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 1551 if (msgp->msg_name) {
1544 1552 msg.msg_namelen = tswap32(msgp->msg_namelen);
1545 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 1555 msg.msg_namelen);
  1556 + if (ret) {
  1557 + unlock_user_struct(msgp, target_msg, send ? 0 : 1);
  1558 + return ret;
  1559 + }
1548 1560 } else {
1549 1561 msg.msg_name = NULL;
1550 1562 msg.msg_namelen = 0;
... ... @@ -1586,12 +1598,19 @@ static abi_long do_accept(int fd, abi_ulong target_addr,
1586 1598 void *addr;
1587 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 1605 if (get_user_u32(addrlen, target_addrlen_addr))
1590   - return -TARGET_EFAULT;
  1606 + return -TARGET_EINVAL;
1591 1607  
1592 1608 if (addrlen < 0)
1593 1609 return -TARGET_EINVAL;
1594 1610  
  1611 + if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
  1612 + return -TARGET_EINVAL;
  1613 +
1595 1614 addr = alloca(addrlen);
1596 1615  
1597 1616 ret = get_errno(accept(fd, addr, &addrlen));
... ... @@ -1617,6 +1636,9 @@ static abi_long do_getpeername(int fd, abi_ulong target_addr,
1617 1636 if (addrlen < 0)
1618 1637 return -TARGET_EINVAL;
1619 1638  
  1639 + if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
  1640 + return -TARGET_EFAULT;
  1641 +
1620 1642 addr = alloca(addrlen);
1621 1643  
1622 1644 ret = get_errno(getpeername(fd, addr, &addrlen));
... ... @@ -1636,15 +1658,15 @@ static abi_long do_getsockname(int fd, abi_ulong target_addr,
1636 1658 void *addr;
1637 1659 abi_long ret;
1638 1660  
1639   - if (target_addr == 0)
1640   - return get_errno(accept(fd, NULL, NULL));
1641   -
1642 1661 if (get_user_u32(addrlen, target_addrlen_addr))
1643 1662 return -TARGET_EFAULT;
1644 1663  
1645 1664 if (addrlen < 0)
1646 1665 return -TARGET_EINVAL;
1647 1666  
  1667 + if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
  1668 + return -TARGET_EFAULT;
  1669 +
1648 1670 addr = alloca(addrlen);
1649 1671  
1650 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 1710 return -TARGET_EFAULT;
1689 1711 if (target_addr) {
1690 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 1718 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1693 1719 } else {
1694 1720 ret = get_errno(send(fd, host_msg, len, flags));
... ...