In preparation for sharing the implementation of sock_get_timeout.
Unified · Split
| @@ -1648,68 +1648,59 @@ static int vsock_connectible_getsockopt(struct socket *sock, · 1647 unmodified lines | ||
| 1648 | 1648 | char __user *optval, |
| 1649 | 1649 | int __user *optlen) |
| 1650 | 1650 | { |
| 1651 | − int err; | |
| 1651 | + struct sock *sk = sock->sk; | |
| 1652 | + struct vsock_sock *vsk = vsock_sk(sk); | |
| 1653 | + | |
| 1654 | + union { | |
| 1655 | + u64 val64; | |
| 1656 | + struct __kernel_old_timeval tm; | |
| 1657 | + } v; | |
| 1658 | + | |
| 1659 | + int lv = sizeof(v.val64); | |
| 1652 | 1660 | int len; |
| 1653 | − struct sock *sk; | |
| 1654 | − struct vsock_sock *vsk; | |
| 1655 | − u64 val; | |
| 1656 | 1661 | |
| 1657 | 1662 | if (level != AF_VSOCK) |
| 1658 | 1663 | return -ENOPROTOOPT; |
| 1659 | 1664 | |
| 1660 | − err = get_user(len, optlen); | |
| 1661 | − if (err != 0) | |
| 1662 | − return err; | |
| 1663 | − | |
| 1664 | −#define COPY_OUT(_v) \ | |
| 1665 | − do { \ | |
| 1666 | − if (len < sizeof(_v)) \ | |
| 1667 | − return -EINVAL; \ | |
| 1668 | − \ | |
| 1669 | − len = sizeof(_v); \ | |
| 1670 | − if (copy_to_user(optval, &_v, len) != 0) \ | |
| 1671 | − return -EFAULT; \ | |
| 1672 | − \ | |
| 1673 | − } while (0) | |
| 1665 | + if (get_user(len, optlen)) | |
| 1666 | + return -EFAULT; | |
| 1674 | 1667 | |
| 1675 | − err = 0; | |
| 1676 | − sk = sock->sk; | |
| 1677 | − vsk = vsock_sk(sk); | |
| 1668 | + memset(&v, 0, sizeof(v)); | |
| 1678 | 1669 | |
| 1679 | 1670 | switch (optname) { |
| 1680 | 1671 | case SO_VM_SOCKETS_BUFFER_SIZE: |
| 1681 | − val = vsk->buffer_size; | |
| 1682 | − COPY_OUT(val); | |
| 1672 | + v.val64 = vsk->buffer_size; | |
| 1683 | 1673 | break; |
| 1684 | 1674 | |
| 1685 | 1675 | case SO_VM_SOCKETS_BUFFER_MAX_SIZE: |
| 1686 | − val = vsk->buffer_max_size; | |
| 1687 | − COPY_OUT(val); | |
| 1676 | + v.val64 = vsk->buffer_max_size; | |
| 1688 | 1677 | break; |
| 1689 | 1678 | |
| 1690 | 1679 | case SO_VM_SOCKETS_BUFFER_MIN_SIZE: |
| 1691 | − val = vsk->buffer_min_size; | |
| 1692 | − COPY_OUT(val); | |
| 1680 | + v.val64 = vsk->buffer_min_size; | |
| 1693 | 1681 | break; |
| 1694 | 1682 | |
| 1695 | − case SO_VM_SOCKETS_CONNECT_TIMEOUT: { | |
| 1696 | − struct __kernel_old_timeval tv; | |
| 1697 | − tv.tv_sec = vsk->connect_timeout / HZ; | |
| 1698 | − tv.tv_usec = | |
| 1683 | + case SO_VM_SOCKETS_CONNECT_TIMEOUT: | |
| 1684 | + lv = sizeof(v.tm); | |
| 1685 | + v.tm.tv_sec = vsk->connect_timeout / HZ; | |
| 1686 | + v.tm.tv_usec = | |
| 1699 | 1687 | (vsk->connect_timeout - |
| 1700 | − tv.tv_sec * HZ) * (1000000 / HZ); | |
| 1701 | − COPY_OUT(tv); | |
| 1688 | + v.tm.tv_sec * HZ) * (1000000 / HZ); | |
| 1702 | 1689 | break; |
| 1703 | − } | |
| 1690 | + | |
| 1704 | 1691 | default: |
| 1705 | 1692 | return -ENOPROTOOPT; |
| 1706 | 1693 | } |
| 1707 | 1694 | |
| 1708 | − err = put_user(len, optlen); | |
| 1709 | − if (err != 0) | |
| 1695 | + if (len < lv) | |
| 1696 | + return -EINVAL; | |
| 1697 | + if (len > lv) | |
| 1698 | + len = lv; | |
| 1699 | + if (copy_to_user(optval, &v, len)) | |
| 1710 | 1700 | return -EFAULT; |
| 1711 | 1701 | |
| 1712 | −#undef COPY_OUT | |
| 1702 | + if (put_user(len, optlen)) | |
| 1703 | + return -EFAULT; | |
| 1713 | 1704 | |
| 1714 | 1705 | return 0; |
| 1715 | 1706 | } |