From 460c990c5d6a93df10d0b16480874c634c9b3884 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sat, 12 Apr 2008 16:59:49 +0000 Subject: [PATCH] The syscalls that were returning an address always copied back the full address back to userland, even if the provided buffer was smaller. Fixes a problem with Firefox, which is for some reason providing a buffer smaller than our sockaddr_in. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24948 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/fs/socket.cpp | 48 +++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/src/system/kernel/fs/socket.cpp b/src/system/kernel/fs/socket.cpp index 3c0e99722d..620178cb3c 100644 --- a/src/system/kernel/fs/socket.cpp +++ b/src/system/kernel/fs/socket.cpp @@ -111,6 +111,24 @@ prepare_userland_address_result(struct sockaddr* userAddress, } +static status_t +copy_address_to_userland(const void* address, socklen_t addressLength, + sockaddr* userAddress, socklen_t userAddressBufferSize, + socklen_t* userAddressLength) +{ + // copy address size and address back to userland + if (user_memcpy(userAddressLength, &addressLength, + sizeof(socklen_t)) != B_OK + || userAddress != NULL + && user_memcpy(userAddress, address, + min_c(addressLength, userAddressBufferSize)) != B_OK) { + return B_BAD_ADDRESS; + } + + return B_OK; +} + + static status_t prepare_userland_msghdr(const msghdr* userMessage, msghdr& message, iovec*& userVecs, MemoryDeleter& vecsDeleter, void*& userAddress, @@ -835,14 +853,13 @@ _user_accept(int socket, struct sockaddr *userAddress, SyscallRestartWrapper result; char address[MAX_SOCKET_ADDRESS_LEN]; + socklen_t userAddressBufferSize = addressLength; result = common_accept(socket, userAddress != NULL ? (sockaddr*)address : NULL, &addressLength, false); // copy address size and address back to userland - if (user_memcpy(_addressLength, &addressLength, - sizeof(socklen_t)) != B_OK - || userAddress != NULL - && user_memcpy(userAddress, address, addressLength) != B_OK) { + if (copy_address_to_userland(address, addressLength, userAddress, + userAddressBufferSize, _addressLength) != B_OK) { _user_close(result); return B_BAD_ADDRESS; } @@ -874,16 +891,15 @@ _user_recvfrom(int socket, void *data, size_t length, int flags, SyscallRestartWrapper result; char address[MAX_SOCKET_ADDRESS_LEN]; + socklen_t userAddressBufferSize = addressLength; result = common_recvfrom(socket, data, length, flags, userAddress != NULL ? (sockaddr*)address : NULL, &addressLength, false); if (result < (ssize_t)0) return result; // copy address size and address back to userland - if (user_memcpy(_addressLength, &addressLength, - sizeof(socklen_t)) != B_OK - || userAddress != NULL - && user_memcpy(userAddress, address, addressLength) != B_OK) { + if (copy_address_to_userland(address, addressLength, userAddress, + userAddressBufferSize, _addressLength) != B_OK) { return B_BAD_ADDRESS; } @@ -1103,16 +1119,15 @@ _user_getpeername(int socket, struct sockaddr *userAddress, // getpeername() char address[MAX_SOCKET_ADDRESS_LEN]; + socklen_t userAddressBufferSize = addressLength; error = common_getpeername(socket, (sockaddr*)address, &addressLength, false); if (error != (status_t)B_OK) return error; // copy address size and address back to userland - if (user_memcpy(_addressLength, &addressLength, - sizeof(socklen_t)) != B_OK - || userAddress != NULL - && user_memcpy(userAddress, address, addressLength) != B_OK) { + if (copy_address_to_userland(address, addressLength, userAddress, + userAddressBufferSize, _addressLength) != B_OK) { return B_BAD_ADDRESS; } @@ -1132,18 +1147,17 @@ _user_getsockname(int socket, struct sockaddr *userAddress, if (error != (status_t)B_OK) return error; - // getsocknam() + // getsockname() char address[MAX_SOCKET_ADDRESS_LEN]; + socklen_t userAddressBufferSize = addressLength; error = common_getsockname(socket, (sockaddr*)address, &addressLength, false); if (error != (status_t)B_OK) return error; // copy address size and address back to userland - if (user_memcpy(_addressLength, &addressLength, - sizeof(socklen_t)) != B_OK - || userAddress != NULL - && user_memcpy(userAddress, address, addressLength) != B_OK) { + if (copy_address_to_userland(address, addressLength, userAddress, + userAddressBufferSize, _addressLength) != B_OK) { return B_BAD_ADDRESS; }