From f0018aca1df36a04e8364dcd39e3013cda54f850 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Tue, 15 Sep 2020 15:43:23 -0400 Subject: [PATCH] UserspaceEmulator: Intercept sendto() With this, `ue /bin/ntpquery` can be used to test sendto() and recvfrom() in ue. (It eventually hits an unimplemented FILD_RM64, but not before doing emulated network i/o and printing response details.) --- DevTools/UserspaceEmulator/Emulator.cpp | 16 ++++++++++++++++ DevTools/UserspaceEmulator/Emulator.h | 1 + 2 files changed, 17 insertions(+) diff --git a/DevTools/UserspaceEmulator/Emulator.cpp b/DevTools/UserspaceEmulator/Emulator.cpp index 72b37b1fd3..db6c46689a 100644 --- a/DevTools/UserspaceEmulator/Emulator.cpp +++ b/DevTools/UserspaceEmulator/Emulator.cpp @@ -354,6 +354,8 @@ u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3) return virt$listen(arg1, arg2); case SC_select: return virt$select(arg1); + case SC_sendto: + return virt$sendto(arg1); case SC_recvfrom: return virt$recvfrom(arg1); case SC_kill: @@ -619,6 +621,20 @@ int Emulator::virt$recvfrom(FlatPtr params_addr) return rc; } +int Emulator::virt$sendto(FlatPtr params_addr) +{ + Syscall::SC_sendto_params params; + mmu().copy_from_vm(¶ms, params_addr, sizeof(params)); + + auto buffer = mmu().copy_buffer_from_vm((FlatPtr)params.data.data, params.data.size); + + sockaddr_storage address; + if (params.addr) + mmu().copy_from_vm(&address, (FlatPtr)params.addr, min(sizeof(address), (size_t)params.addr_length)); + + return sendto(params.sockfd, buffer.data(), buffer.size(), params.flags, params.addr ? (struct sockaddr*)&address : nullptr, params.addr_length); +} + int Emulator::virt$select(FlatPtr params_addr) { Syscall::SC_select_params params; diff --git a/DevTools/UserspaceEmulator/Emulator.h b/DevTools/UserspaceEmulator/Emulator.h index f92a996809..b914ad9513 100644 --- a/DevTools/UserspaceEmulator/Emulator.h +++ b/DevTools/UserspaceEmulator/Emulator.h @@ -132,6 +132,7 @@ private: int virt$accept(int sockfd, FlatPtr address, FlatPtr address_length); int virt$bind(int sockfd, FlatPtr address, socklen_t address_length); int virt$recvfrom(FlatPtr); + int virt$sendto(FlatPtr); int virt$connect(int sockfd, FlatPtr address, socklen_t address_size); void virt$exit(int); ssize_t virt$getrandom(FlatPtr buffer, size_t buffer_size, unsigned int flags);