[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