I'm trying to track down an issue with Launchpad Enhanced were it fails to download its updates (Bug #17443). It appears that the issue stems from recv being called with a buffer from a different process, so as a result the call fails. I put together a hack that gets around the problem ( http://bugs.winehq.org/show_bug.cgi?id=17443#c2), but I'm having difficulty figuring out exactly why this is happening in the first place. Does anyone know if this is a known difference between Windows and Linux or if there is something else strange going on?
Erich Hoover ehoover@mines.edu
On Sun, Jun 21, 2009 at 1:06 AM, Erich Hooverehoover@mines.edu wrote:
I'm trying to track down an issue with Launchpad Enhanced were it fails to download its updates (Bug #17443). It appears that the issue stems from recv being called with a buffer from a different process, so as a result the call fails. I put together a hack that gets around the problem (http://bugs.winehq.org/show_bug.cgi?id=17443#c2), but I'm having difficulty figuring out exactly why this is happening in the first place. Does anyone know if this is a known difference between Windows and Linux or if there is something else strange going on?
If recv() fails with EFAULT, why doesn't the memcpy() in your patch raise SIGSEGV instead?
Maybe the memory is writable but not readable, and WSARecvFrom()/recv() is reading it while memcpy() is not?
Maybe the memory is from a DIB section which Wine lazily mprotects and the kernel isn't raising SIGSEGV for the protection to be reapplied? Does simply zero-filling buf before calling WSARecvFrom() help?
Erich Hoover ehoover@mines.edu
Damjan Jovanovic
On Sun, Jun 21, 2009 at 1:36 AM, Damjan Jovanovic damjan.jov@gmail.comwrote:
On Sun, Jun 21, 2009 at 1:06 AM, Erich Hooverehoover@mines.edu wrote:
I'm trying to track down an issue with Launchpad Enhanced were it fails
to
download its updates (Bug #17443). It appears that the issue stems from recv being called with a buffer from a different process, so as a result
the
call fails. I put together a hack that gets around the problem (http://bugs.winehq.org/show_bug.cgi?id=17443#c2), but I'm having
difficulty
figuring out exactly why this is happening in the first place. Does
anyone
know if this is a known difference between Windows and Linux or if there
is
something else strange going on?
If recv() fails with EFAULT, why doesn't the memcpy() in your patch raise SIGSEGV instead?
While I realize now that I didn't exactly state this, that's why I thought the issue I was encountering was strange.
Maybe the memory is writable but not readable, and WSARecvFrom()/recv() is reading it while memcpy() is not?
Maybe the memory is from a DIB section which Wine lazily mprotects and the kernel isn't raising SIGSEGV for the protection to be reapplied? Does simply zero-filling buf before calling WSARecvFrom() help?
The memory should be a buffer from the calling application that it is using temporarily to store update data before saving it to the hard-disk. Yes, oddly enough zero-filling the buffer before calling WSARecvFrom() also fixes the problem.
So, where exactly should I be looking to find the real problem? As far as I can tell the memory for the buffer is being allocated immediate prior to the call and the request is for read/write access: 0009:Call KERNEL32.VirtualAlloc(01b85000,00040000,00001000,00000004) ret=79e74a2b 0009:Ret KERNEL32.VirtualAlloc() retval=01b85000 ret=79e74a2b 0009:Call ws2_32.recv(00000380,01ba4fc1,000178d0,00000000) ret=0036a287 ...
Erich Hoover ehoover@mines.edu
On Sun, Jun 21, 2009 at 10:23 AM, Erich Hoover ehoover@mines.edu wrote:
On Sun, Jun 21, 2009 at 1:36 AM, Damjan Jovanovic damjan.jov@gmail.comwrote:
...
Maybe the memory is writable but not readable, and
WSARecvFrom()/recv() is reading it while memcpy() is not?
Maybe the memory is from a DIB section which Wine lazily mprotects and the kernel isn't raising SIGSEGV for the protection to be reapplied? Does simply zero-filling buf before calling WSARecvFrom() help?
The memory should be a buffer from the calling application that it is using temporarily to store update data before saving it to the hard-disk. Yes, oddly enough zero-filling the buffer before calling WSARecvFrom() also fixes the problem.
So, where exactly should I be looking to find the real problem? As far as I can tell the memory for the buffer is being allocated immediate prior to the call and the request is for read/write access: 0009:Call KERNEL32.VirtualAlloc(01b85000,00040000,00001000,00000004) ret=79e74a2b 0009:Ret KERNEL32.VirtualAlloc() retval=01b85000 ret=79e74a2b 0009:Call ws2_32.recv(00000380,01ba4fc1,000178d0,00000000) ret=0036a287 ...
After looking over the documentation for VirtualAlloc, it appears that Wine should be zeroing the returned memory if MEM_COMMIT is specified. Making this change (rather than playing around in the socket code) also fixes the problem (see attached patch). Do you think this step occurs if write access isn't specified?
Erich Hoover ehoover@mines.edu
On Sun, Jun 21, 2009 at 1:03 PM, Erich Hoover ehoover@mines.edu wrote:
On Sun, Jun 21, 2009 at 10:23 AM, Erich Hoover ehoover@mines.edu wrote:
On Sun, Jun 21, 2009 at 1:36 AM, Damjan Jovanovic damjan.jov@gmail.comwrote:
...
Maybe the memory is writable but not readable, and
WSARecvFrom()/recv() is reading it while memcpy() is not?
Maybe the memory is from a DIB section which Wine lazily mprotects and the kernel isn't raising SIGSEGV for the protection to be reapplied? Does simply zero-filling buf before calling WSARecvFrom() help?
The memory should be a buffer from the calling application that it is using temporarily to store update data before saving it to the hard-disk. Yes, oddly enough zero-filling the buffer before calling WSARecvFrom() also fixes the problem.
So, where exactly should I be looking to find the real problem? As far as I can tell the memory for the buffer is being allocated immediate prior to the call and the request is for read/write access: 0009:Call KERNEL32.VirtualAlloc(01b85000,00040000,00001000,00000004) ret=79e74a2b 0009:Ret KERNEL32.VirtualAlloc() retval=01b85000 ret=79e74a2b 0009:Call ws2_32.recv(00000380,01ba4fc1,000178d0,00000000) ret=0036a287 ...
After looking over the documentation for VirtualAlloc, it appears that Wine should be zeroing the returned memory if MEM_COMMIT is specified. Making this change (rather than playing around in the socket code) also fixes the problem (see attached patch). Do you think this step occurs if write access isn't specified?
Erich Hoover ehoover@mines.edu
Any thoughts on this? Is there anything a "+relay" wouldn't catch that could occur between the call to KERNEL32.VirtualAlloc and the call to ws2_32.recv? This behavior (the memory area having to be cleared before the recv call) seems a tad on the odd side.
Erich Hoover ehoover@mines.edu
On Fri, Jun 26, 2009 at 2:19 AM, Erich Hooverehoover@mines.edu wrote:
On Sun, Jun 21, 2009 at 1:03 PM, Erich Hoover ehoover@mines.edu wrote:
On Sun, Jun 21, 2009 at 10:23 AM, Erich Hoover ehoover@mines.edu wrote:
On Sun, Jun 21, 2009 at 1:36 AM, Damjan Jovanovic damjan.jov@gmail.com wrote:
...
Maybe the memory is writable but not readable, and WSARecvFrom()/recv() is reading it while memcpy() is not?
Maybe the memory is from a DIB section which Wine lazily mprotects and the kernel isn't raising SIGSEGV for the protection to be reapplied? Does simply zero-filling buf before calling WSARecvFrom() help?
The memory should be a buffer from the calling application that it is using temporarily to store update data before saving it to the hard-disk. Yes, oddly enough zero-filling the buffer before calling WSARecvFrom() also fixes the problem.
So, where exactly should I be looking to find the real problem? As far as I can tell the memory for the buffer is being allocated immediate prior to the call and the request is for read/write access: 0009:Call KERNEL32.VirtualAlloc(01b85000,00040000,00001000,00000004) ret=79e74a2b 0009:Ret KERNEL32.VirtualAlloc() retval=01b85000 ret=79e74a2b 0009:Call ws2_32.recv(00000380,01ba4fc1,000178d0,00000000) ret=0036a287 ...
After looking over the documentation for VirtualAlloc, it appears that Wine should be zeroing the returned memory if MEM_COMMIT is specified. Making this change (rather than playing around in the socket code) also fixes the problem (see attached patch). Do you think this step occurs if write access isn't specified?
Erich Hoover ehoover@mines.edu
Any thoughts on this? Is there anything a "+relay" wouldn't catch that could occur between the call to KERNEL32.VirtualAlloc and the call to ws2_32.recv? This behavior (the memory area having to be cleared before the recv call) seems a tad on the odd side.
All that zeroing the memory area does is commit the memory, so the future recv() works.
But is the problem that VirtualAlloc() doesn't already do this, or that WSARecvFrom() doesn't do it? Who does it in Windows?
The fact MEM_COMMIT is specified seems to imply that VirtualAlloc() should do the committing, but some tests on Windows with that exact same VirtualAlloc() and a VirtualQuery() after to check would help.
I really hope that it's a VirtualAlloc() bug in Wine - we make tonnes of system calls all over the place assuming the memory passed is already committed...
Erich Hoover ehoover@mines.edu
Damjan Jovanovic