Skip to content

Commit 59b4d55

Browse files
authored
Merge pull request #1245 from robgjansen/name-lookup-syscall
Add a shadow-specific name lookup syscall Added a shadow-specific syscall to perform hostname to address lookups. The new syscall takes precedence over scanning the /etc/hosts file. Scanning the hosts file is still done as a fallback in case the new syscall fails. This was done primarily to support phold experiments that make lots of getaddrinfo calls where we need the work performed to be constant no matter the number of hosts we run in the experiment. Also refactored the shadow-specific syscall handling code into a single module, so that the syscalls go through the syscall handler. This means we can count the frequency with which shadow-specific syscalls are made (using the --enable-syscall-counters option). Closes #1094
2 parents 3b4a87c + b070c01 commit 59b4d55

19 files changed

Lines changed: 325 additions & 28 deletions

src/main/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ set(shadow_srcs
119119
host/syscall/poll.c
120120
host/syscall/process.c
121121
host/syscall/random.c
122+
host/syscall/shadow.c
122123
host/syscall/signal.c
123124
host/syscall/socket.c
124125
host/syscall/sysinfo.c

src/main/bindings/rust/wrapper.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,46 @@ pub struct _Thread {
286286
_unused: [u8; 0],
287287
}
288288
pub type Thread = _Thread;
289+
#[repr(C)]
290+
#[derive(Debug, Copy, Clone)]
291+
pub struct _ShMemBlock {
292+
pub p: *mut ::std::os::raw::c_void,
293+
pub nbytes: size_t,
294+
}
295+
#[test]
296+
fn bindgen_test_layout__ShMemBlock() {
297+
assert_eq!(
298+
::std::mem::size_of::<_ShMemBlock>(),
299+
16usize,
300+
concat!("Size of: ", stringify!(_ShMemBlock))
301+
);
302+
assert_eq!(
303+
::std::mem::align_of::<_ShMemBlock>(),
304+
8usize,
305+
concat!("Alignment of ", stringify!(_ShMemBlock))
306+
);
307+
assert_eq!(
308+
unsafe { &(*(::std::ptr::null::<_ShMemBlock>())).p as *const _ as usize },
309+
0usize,
310+
concat!(
311+
"Offset of field: ",
312+
stringify!(_ShMemBlock),
313+
"::",
314+
stringify!(p)
315+
)
316+
);
317+
assert_eq!(
318+
unsafe { &(*(::std::ptr::null::<_ShMemBlock>())).nbytes as *const _ as usize },
319+
8usize,
320+
concat!(
321+
"Offset of field: ",
322+
stringify!(_ShMemBlock),
323+
"::",
324+
stringify!(nbytes)
325+
)
326+
);
327+
}
328+
pub type ShMemBlock = _ShMemBlock;
289329
extern "C" {
290330
pub fn thread_ref(thread: *mut Thread);
291331
}
@@ -393,6 +433,12 @@ extern "C" {
393433
extern "C" {
394434
pub fn thread_isLeader(thread: *mut Thread) -> bool;
395435
}
436+
extern "C" {
437+
pub fn thread_getIPCBlock(thread: *mut Thread) -> *mut ShMemBlock;
438+
}
439+
extern "C" {
440+
pub fn thread_getShMBlock(thread: *mut Thread) -> *mut ShMemBlock;
441+
}
396442
#[repr(C)]
397443
#[derive(Debug, Copy, Clone)]
398444
pub struct _Timer {

src/main/host/process.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,11 @@ void process_setMemoryManager(Process* proc, MemoryManager* memoryManager) {
796796
proc->memoryManager = memoryManager;
797797
}
798798

799+
InterposeMethod process_getInterposeMethod(Process* proc) {
800+
MAGIC_ASSERT(proc);
801+
return proc->interposeMethod;
802+
}
803+
799804
PluginPhysicalPtr process_getPhysicalAddress(Process* proc, PluginVirtualPtr vPtr) {
800805
// We currently don't keep a true system-wide virtual <-> physical address
801806
// mapping. Instead we simply assume that no shadow processes map the same

src/main/host/process.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,7 @@ void process_flushPtrs(Process* proc, Thread* thread);
130130
MemoryManager* process_getMemoryManager(Process* proc);
131131
void process_setMemoryManager(Process* proc, MemoryManager* memoryManager);
132132

133+
// Returns the interpose method used by this process.
134+
InterposeMethod process_getInterposeMethod(Process* proc);
135+
133136
#endif /* SHD_PROCESS_H_ */

src/main/host/syscall/shadow.c

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* The Shadow Simulator
3+
* See LICENSE for licensing information
4+
*/
5+
6+
#include "main/host/syscall/shadow.h"
7+
8+
#include <errno.h>
9+
#include <stdarg.h>
10+
#include <stdlib.h>
11+
12+
#include "main/core/worker.h"
13+
#include "main/host/syscall/protected.h"
14+
#include "main/host/syscall_types.h"
15+
#include "main/host/thread_ptrace.h"
16+
#include "main/routing/address.h"
17+
#include "main/shmem/shmem_allocator.h"
18+
#include "support/logger/logger.h"
19+
20+
SysCallReturn syscallhandler_shadow_hostname_to_addr_ipv4(SysCallHandler* sys,
21+
const SysCallArgs* args) {
22+
utility_assert(sys && args);
23+
PluginPtr name_ptr = args->args[0].as_ptr;
24+
size_t name_len = args->args[1].as_u64;
25+
PluginPtr addr_ptr = args->args[2].as_ptr;
26+
size_t addr_len = args->args[3].as_u64;
27+
28+
debug("Handling custom syscall shadow_hostname_to_addr_ipv4");
29+
30+
if (!name_ptr.val || !addr_ptr.val || addr_len < sizeof(uint32_t)) {
31+
debug("Invalid argument detected, returning EINVAL");
32+
return (SysCallReturn){.state = SYSCALL_DONE, .retval.as_i64 = -EINVAL};
33+
}
34+
35+
const char* name = process_getReadablePtr(sys->process, sys->thread, name_ptr, name_len);
36+
37+
debug("Looking up name %s", name);
38+
Address* address = worker_resolveNameToAddress(name);
39+
40+
if (address) {
41+
debug("Found address %s for name %s", address_toString(address), name);
42+
43+
uint32_t ip = address_toNetworkIP(address);
44+
uint32_t* addr = process_getWriteablePtr(sys->process, sys->thread, addr_ptr, addr_len);
45+
*addr = ip;
46+
47+
return (SysCallReturn){.state = SYSCALL_DONE, .retval.as_i64 = 0};
48+
} else {
49+
debug("Unable to find address for name %s", name);
50+
// return EFAULT like gethostname
51+
return (SysCallReturn){.state = SYSCALL_DONE, .retval.as_i64 = -EFAULT};
52+
}
53+
}
54+
55+
SysCallReturn syscallhandler_shadow_set_ptrace_allow_native_syscalls(SysCallHandler* sys,
56+
const SysCallArgs* args) {
57+
utility_assert(sys && args);
58+
59+
InterposeMethod imethod = process_getInterposeMethod(sys->process);
60+
61+
if (imethod == INTERPOSE_PTRACE || imethod == INTERPOSE_HYBRID) {
62+
bool is_allowed = args->args[0].as_i64;
63+
debug("shadow_set_ptrace_allow_native_syscalls is_allowed=%d", is_allowed);
64+
65+
threadptrace_setAllowNativeSyscalls(sys->thread, is_allowed);
66+
67+
return (SysCallReturn){.state = SYSCALL_DONE, .retval.as_i64 = 0};
68+
} else {
69+
debug("shadow_set_ptrace_allow_native_syscalls not supported for interpose method %d",
70+
(int)imethod);
71+
return (SysCallReturn){.state = SYSCALL_DONE, .retval.as_i64 = 0};
72+
}
73+
}
74+
75+
static SysCallReturn _syscallhandler_get_shmem_block(SysCallHandler* sys, const SysCallArgs* args,
76+
ShMemBlock* block) {
77+
if (!block) {
78+
return (SysCallReturn){.state = SYSCALL_DONE, .retval.as_i64 = -ENODEV};
79+
}
80+
81+
PluginPtr shm_blk_pptr = args->args[0].as_ptr;
82+
83+
ShMemBlockSerialized* shm_blk_ptr =
84+
process_getWriteablePtr(sys->process, sys->thread, shm_blk_pptr, sizeof(*shm_blk_ptr));
85+
*shm_blk_ptr = shmemallocator_globalBlockSerialize(block);
86+
87+
return (SysCallReturn){.state = SYSCALL_DONE, .retval.as_i64 = 0};
88+
}
89+
90+
SysCallReturn syscallhandler_shadow_get_ipc_blk(SysCallHandler* sys, const SysCallArgs* args) {
91+
utility_assert(sys && args);
92+
debug("handling shadow_get_ipc_blk syscall");
93+
return _syscallhandler_get_shmem_block(sys, args, thread_getIPCBlock(sys->thread));
94+
}
95+
96+
SysCallReturn syscallhandler_shadow_get_shm_blk(SysCallHandler* sys, const SysCallArgs* args) {
97+
utility_assert(sys && args);
98+
debug("handling shadow_get_shm_blk syscall");
99+
return _syscallhandler_get_shmem_block(sys, args, thread_getShMBlock(sys->thread));
100+
}

src/main/host/syscall/shadow.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* The Shadow Simulator
3+
* See LICENSE for licensing information
4+
*/
5+
6+
#ifndef SRC_MAIN_HOST_SYSCALL_CUSTOM_H_
7+
#define SRC_MAIN_HOST_SYSCALL_CUSTOM_H_
8+
9+
#include "main/host/syscall/protected.h"
10+
11+
// Handle the custom shadow-specific syscalls defined in syscall_numbers.h
12+
SYSCALL_HANDLER(shadow_set_ptrace_allow_native_syscalls);
13+
SYSCALL_HANDLER(shadow_get_ipc_blk);
14+
SYSCALL_HANDLER(shadow_get_shm_blk);
15+
SYSCALL_HANDLER(shadow_hostname_to_addr_ipv4);
16+
17+
#endif /* SRC_MAIN_HOST_SYSCALL_CUSTOM_H_ */

src/main/host/syscall_handler.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "main/host/syscall/process.h"
3333
#include "main/host/syscall/protected.h"
3434
#include "main/host/syscall/random.h"
35+
#include "main/host/syscall/shadow.h"
3536
#include "main/host/syscall/signal.h"
3637
#include "main/host/syscall/socket.h"
3738
#include "main/host/syscall/sysinfo.h"
@@ -40,8 +41,10 @@
4041
#include "main/host/syscall/uio.h"
4142
#include "main/host/syscall/unistd.h"
4243
#include "main/host/syscall_handler.h"
44+
#include "main/host/syscall_numbers.h"
4345
#include "main/host/syscall_types.h"
4446
#include "main/host/thread.h"
47+
#include "shim/shim_event.h"
4548
#include "support/logger/logger.h"
4649

4750
// this is not defined on Ubuntu 16.04
@@ -367,6 +370,10 @@ SysCallReturn syscallhandler_make_syscall(SysCallHandler* sys,
367370
HANDLE(recvfrom);
368371
HANDLE(renameat);
369372
HANDLE(renameat2);
373+
HANDLE(shadow_set_ptrace_allow_native_syscalls);
374+
HANDLE(shadow_get_ipc_blk);
375+
HANDLE(shadow_get_shm_blk);
376+
HANDLE(shadow_hostname_to_addr_ipv4);
370377
HANDLE(sendto);
371378
HANDLE(setsockopt);
372379
HANDLE(set_robust_list);

src/main/host/syscall_numbers.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* The Shadow Simulator
3+
* See LICENSE for licensing information
4+
*/
5+
6+
#ifndef SRC_MAIN_HOST_SYSCALL_NUMBERS_H_
7+
#define SRC_MAIN_HOST_SYSCALL_NUMBERS_H_
8+
9+
#include <stdbool.h>
10+
11+
typedef enum {
12+
SYS_shadow_min = 1000,
13+
SYS_shadow_set_ptrace_allow_native_syscalls = 1000,
14+
SYS_shadow_get_ipc_blk = 1001,
15+
SYS_shadow_get_shm_blk = 1002,
16+
SYS_shadow_hostname_to_addr_ipv4 = 1003,
17+
SYS_shadow_max = 1003,
18+
} ShadowSyscallNum;
19+
20+
static inline bool syscall_num_is_shadow(long n) {
21+
return n >= SYS_shadow_min && n <= SYS_shadow_max;
22+
};
23+
24+
#endif /* SRC_MAIN_HOST_SYSCALL_NUMBERS_H_ */

src/main/host/thread.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,18 @@ void thread_flushPtrs(Thread* thread) {
149149
thread->methods.flushPtrs(thread);
150150
}
151151

152+
ShMemBlock* thread_getIPCBlock(Thread* thread) {
153+
MAGIC_ASSERT(thread);
154+
utility_assert(thread->methods.getIPCBlock);
155+
return thread->methods.getIPCBlock(thread);
156+
}
157+
158+
ShMemBlock* thread_getShMBlock(Thread* thread) {
159+
MAGIC_ASSERT(thread);
160+
utility_assert(thread->methods.getShMBlock);
161+
return thread->methods.getShMBlock(thread);
162+
}
163+
152164
long thread_nativeSyscall(Thread* thread, long n, ...) {
153165
MAGIC_ASSERT(thread);
154166
utility_assert(thread->methods.nativeSyscall);

src/main/host/thread.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
typedef struct _Thread Thread;
1515

1616
#include "main/host/syscall_types.h"
17+
#include "main/shmem/shmem_allocator.h"
1718

1819
void thread_ref(Thread* thread);
1920
void thread_unref(Thread* thread);
@@ -116,4 +117,10 @@ PluginVirtualPtr thread_getTidAddress(Thread* thread);
116117
// Typically this is true for the first thread created in a process.
117118
bool thread_isLeader(Thread* thread);
118119

120+
// Returns the block used for IPC, or NULL if no such block is is used.
121+
ShMemBlock* thread_getIPCBlock(Thread* thread);
122+
123+
// Returns the block used for shared state, or NULL if no such block is is used.
124+
ShMemBlock* thread_getShMBlock(Thread* thread);
125+
119126
#endif /* SRC_MAIN_HOST_SHD_THREAD_H_ */

0 commit comments

Comments
 (0)