Skip to content

Commit 182f9aa

Browse files
[libc] Fix unpoisoning for recvfrom (#117366)
Turns out there were also errors in the recvfrom unpoisoning logic. This patch fixes those.
1 parent 89614ce commit 182f9aa

File tree

2 files changed

+19
-6
lines changed

2 files changed

+19
-6
lines changed

libc/src/sys/socket/linux/recvfrom.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,26 @@ namespace LIBC_NAMESPACE_DECL {
2323

2424
LLVM_LIBC_FUNCTION(ssize_t, recvfrom,
2525
(int sockfd, void *buf, size_t len, int flags,
26-
struct sockaddr *__restrict dest_addr,
26+
sockaddr *__restrict src_addr,
2727
socklen_t *__restrict addrlen)) {
28+
// addrlen is a value-result argument. If it's not null, it passes the max
29+
// size of the buffer src_addr to the syscall. After the syscall, it's updated
30+
// to the actual size of the source address. This may be larger than the
31+
// buffer, in which case the buffer contains a truncated result.
32+
size_t srcaddr_sz;
33+
if (src_addr)
34+
srcaddr_sz = *addrlen;
35+
(void)srcaddr_sz; // prevent "set but not used" warning
36+
2837
#ifdef SYS_recvfrom
2938
ssize_t ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(
30-
SYS_recvfrom, sockfd, buf, len, flags, dest_addr, addrlen);
39+
SYS_recvfrom, sockfd, buf, len, flags, src_addr, addrlen);
3140
#elif defined(SYS_socketcall)
3241
unsigned long sockcall_args[6] = {static_cast<unsigned long>(sockfd),
3342
reinterpret_cast<unsigned long>(buf),
3443
static_cast<unsigned long>(len),
3544
static_cast<unsigned long>(flags),
36-
reinterpret_cast<unsigned long>(dest_addr),
45+
reinterpret_cast<unsigned long>(src_addr),
3746
static_cast<unsigned long>(addrlen)};
3847
ssize_t ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(
3948
SYS_socketcall, SYS_RECVFROM, sockcall_args);
@@ -46,8 +55,13 @@ LLVM_LIBC_FUNCTION(ssize_t, recvfrom,
4655
}
4756

4857
MSAN_UNPOISON(buf, ret);
49-
MSAN_UNPOISON(addrlen, sizeof(socklen_t));
5058

59+
if (src_addr) {
60+
size_t min_src_addr_size = (*addrlen < srcaddr_sz) ? *addrlen : srcaddr_sz;
61+
(void)min_src_addr_size; // prevent "set but not used" warning
62+
63+
MSAN_UNPOISON(src_addr, min_src_addr_size);
64+
}
5165
return ret;
5266
}
5367

libc/src/sys/socket/recvfrom.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818
namespace LIBC_NAMESPACE_DECL {
1919

2020
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
21-
struct sockaddr *__restrict address,
22-
socklen_t *__restrict addrlen);
21+
sockaddr *__restrict src_addr, socklen_t *__restrict addrlen);
2322

2423
} // namespace LIBC_NAMESPACE_DECL
2524

0 commit comments

Comments
 (0)