[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] Fix for accept
From: |
Pablo Virolainen |
Subject: |
Re: [Qemu-devel] Fix for accept |
Date: |
Fri, 14 Jul 2006 10:48:42 +0300 |
User-agent: |
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.13) Gecko/20060427 Debian/1.7.13-0ubuntu5.10 |
Fabrice Bellard wrote:
> Hi,
>
> OK for the bug report, but the fix is not correct because the problem
> is generic. [get|put]_user() and the other functions should be used
> everywhere to communicate with the "user" space and to generate the
> -EFAULT error if the address is not correct. For that purpose the host
> signal SIGSEGV can be catched and asm macros can be used to see if it
> is an expected seg fault (in this case [get|put]_user must return an
> error code) or if it is a QEMU bug. Note that exactly the same system
> is used inside the Linux kernel and I don't think it is necessary to
> invent something else.
>
> Regards,
>
> Fabrice.
Hello,
So I should write something like following instead?
if (!get_user(addrlen,&target_addrlen)) {
return -EFAULT
}
The code seems to assume target_sockaddr == sockaddr, so why allocate
temporary buffer and then do copying?
One could implement SOCKOP_[accept|getsockname|getpeername] with same
code. Perhaps something like
static long do_socketcall_helper(target_ulong vptr,
int (*func)(int,struct sockaddr*,socklen_t*))
{
const int n = sizeof(target_ulong);
if (access_ok(VERIFY_READ,vptr,n*3)) {
int ret;
int sockfd=tgetl(vptr);
target_ulong target_addr = tgetl(vptr + n);
target_ulong target_addrlen = tgetl(vptr + 2 * n);
struct sockaddr *addr=(struct sockaddr *)target_addr;
socklen_t addrlen;
if (!get_user(addrlen,&target_addrlen) ||
!acces_ok(VERIFY_WRITE,target_addrlen,4)) {
return -EFAULT;
}
ret=get_errno(func(sockfd, addr, &addrlen));
if (!is_error(ret)) {
host_to_target_sockaddr(target_addr, addr, addrlen);
tput32(target_addrlen, addrlen);
}
return ret;
}
return -EFAULT;
}
....
case SOCKOP_accept:
ret = do_socketcall_helper(vptr,accept);
break;
case SOCKOP_getsockname:
ret = do_socketcall_helper(vptr,getsockname);
break;
case SOCKOP_getpeername:
ret = do_socketcall_helper(vptr,getpeername);
break;
Pablo