qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2] Add getsockopt for settable SOL_IPV6 options


From: Laurent Vivier
Subject: Re: [Qemu-devel] [PATCH v2] Add getsockopt for settable SOL_IPV6 options
Date: Thu, 13 Dec 2018 14:57:51 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0

On 13/12/2018 14:37, address@hidden wrote:
> From: Tom Deseyn <address@hidden>
> 
> Signed-off-by: Tom Deseyn <address@hidden>
> ---

Please add here an history of the changes between the version 1 and 2:

v2: ?????

>  linux-user/syscall.c | 38 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 38 insertions(+)
> 
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 280137da8c..ad52cfbd54 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -2352,6 +2352,44 @@ static abi_long do_getsockopt(int sockfd, int level, 
> int optname,
>              break;
>          }
>          break;
> +    case SOL_IPV6:
> +        switch (optname) {
> +        case IPV6_MTU_DISCOVER:
> +        case IPV6_MTU:
> +        case IPV6_V6ONLY:
> +        case IPV6_RECVPKTINFO:
> +        case IPV6_UNICAST_HOPS:
> +        case IPV6_MULTICAST_HOPS:
> +        case IPV6_MULTICAST_LOOP:
> +        case IPV6_RECVERR:
> +        case IPV6_RECVHOPLIMIT:
> +        case IPV6_2292HOPLIMIT:
> +        case IPV6_CHECKSUM:
> +            if (get_user_u32(len, optlen))
> +                return -TARGET_EFAULT;
> +            if (len < 0)
> +                return -TARGET_EINVAL;
> +            lv = sizeof(lv);
> +            ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
> +            if (ret < 0)
> +                return ret;
> +            if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
> +                len = 1;
> +                if (put_user_u32(len, optlen)
> +                    || put_user_u8(val, optval_addr))
> +                    return -TARGET_EFAULT;
> +            } else {
> +                if (len > sizeof(int))
> +                    len = sizeof(int);
> +                if (put_user_u32(len, optlen)
> +                    || put_user_u32(val, optval_addr))
> +                    return -TARGET_EFAULT;
> +            }

This way to compute the size of the result is good for SOL_IP, but not
for SOL_IPV6, in kernel do_ip_getsockopt() we have:

       if (len < sizeof(int) && len > 0 && val >= 0 && val <= 255) {
                unsigned char ucval = (unsigned char)val;
                len = 1;
                if (put_user(len, optlen))
                        return -EFAULT;
                if (copy_to_user(optval, &ucval, 1))
                        return -EFAULT;
        } else {
                len = min_t(unsigned int, sizeof(int), len);
                if (put_user(len, optlen))
                        return -EFAULT;
                if (copy_to_user(optval, &val, len))
                        return -EFAULT;
        }

Whereas in kernel do_ipv6_getsockopt():

        default:
                return -ENOPROTOOPT;
        }
        len = min_t(unsigned int, sizeof(int), len);
        if (put_user(len, optlen))
                return -EFAULT;
        if (copy_to_user(optval, &val, len))
                return -EFAULT;
        return 0;


So in QEMU for SOL_IPV6 to mimic this I think you should use something like:

    len = min(lv, sizeof(val));
    if (put_user_u32(len, optlen) {
         return -TARGET_EFAULT;
    }
    target_addr =  lock_user(VERIFY_WRITE, optval_addr, len, 0);
    tswap32s(&val);
    memcpy(target_addr, &val, len);
    unlock_user(target_addr, optval_addr, len);

Thanks,
Laurent



reply via email to

[Prev in Thread] Current Thread [Next in Thread]