ws2_32: Lock the user output buffer during receives.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2017-10-03 13:36:40 +02:00
parent c583953b95
commit dc203dd833
4 changed files with 39 additions and 6 deletions

View file

@ -1480,6 +1480,9 @@
@ cdecl wine_server_send_fd(long)
@ cdecl __wine_make_process_system()
# Virtual memory
@ cdecl __wine_locked_recvmsg(long ptr long)
# Version
@ cdecl wine_get_version() NTDLL_wine_get_version
@ cdecl wine_get_build_id() NTDLL_wine_get_build_id

View file

@ -32,6 +32,9 @@
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
@ -1904,6 +1907,36 @@ ssize_t virtual_locked_pread( int fd, void *addr, size_t size, off_t offset )
}
/***********************************************************************
* __wine_locked_recvmsg
*/
ssize_t CDECL __wine_locked_recvmsg( int fd, struct msghdr *hdr, int flags )
{
sigset_t sigset;
size_t i;
BOOL has_write_watch = FALSE;
int err = EFAULT;
ssize_t ret = recvmsg( fd, hdr, flags );
if (ret != -1 || errno != EFAULT) return ret;
server_enter_uninterrupted_section( &csVirtual, &sigset );
for (i = 0; i < hdr->msg_iovlen; i++)
if (check_write_access( hdr->msg_iov[i].iov_base, hdr->msg_iov[i].iov_len, &has_write_watch ))
break;
if (i == hdr->msg_iovlen)
{
ret = recvmsg( fd, hdr, flags );
err = errno;
}
if (has_write_watch)
while (i--) update_write_watches( hdr->msg_iov[i].iov_base, hdr->msg_iov[i].iov_len, 0 );
server_leave_uninterrupted_section( &csVirtual, &sigset );
errno = err;
return ret;
}
/***********************************************************************
* virtual_is_valid_code_address

View file

@ -241,6 +241,8 @@ static struct interface_filter generic_interface_filter = {
};
#endif /* LINUX_BOUND_IF */
extern ssize_t CDECL __wine_locked_recvmsg( int fd, struct msghdr *hdr, int flags );
/*
* The actual definition of WSASendTo, wrapped in a different function name
* so that internal calls from ws2_32 itself will not trigger programs like
@ -2356,7 +2358,7 @@ static int WS2_recv( int fd, struct ws2_async *wsa, int flags )
hdr.msg_flags = 0;
#endif
while ((n = recvmsg(fd, &hdr, flags)) == -1)
while ((n = __wine_locked_recvmsg( fd, &hdr, flags )) == -1)
{
if (errno != EINTR)
return -1;

View file

@ -6962,13 +6962,10 @@ static void test_write_watch(void)
send(src, "test message", sizeof("test message"), 0);
ret = GetOverlappedResult( (HANDLE)dest, &ov, &bytesReturned, TRUE );
todo_wine
{
ok( ret, "GetOverlappedResult failed %u\n", GetLastError() );
ok( bytesReturned == sizeof("test message"), "wrong size %u\n", bytesReturned );
ok( !memcmp( base, "test ", 5 ), "wrong data %s\n", base );
ok( !memcmp( base + 0x4000, "message", 8 ), "wrong data %s\n", base + 0x4000 );
}
count = 64;
ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
@ -6984,7 +6981,6 @@ static void test_write_watch(void)
bufs[1].len = 0x4000;
bufs[1].buf = base + 0x2000;
ret = WSARecvFrom( dest, bufs, 2, NULL, &flags, &addr, &addr_len, &ov, NULL);
todo_wine
ok(ret == SOCKET_ERROR && GetLastError() == ERROR_IO_PENDING,
"WSARecv failed - %d error %d\n", ret, GetLastError());
@ -6992,7 +6988,6 @@ static void test_write_watch(void)
ret = pGetWriteWatch( WRITE_WATCH_FLAG_RESET, base, size, results, &count, &pagesize );
ok( !ret, "GetWriteWatch failed %u\n", GetLastError() );
ok( count == 5, "wrong count %lu\n", count );
todo_wine
ok( !base[0], "data set\n" );
send(src, "test message", sizeof("test message"), 0);