Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions src/glibc/lind_syscall/addr_translation.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
#include <stddef.h>
#include <errno.h>

// When we want the argument to be translated, the cageid supplied must have the MSB set to 1.
// These masks help check this.
#define LIND_ARG_TRANSLATE_FLAG (1ULL << 63)
#define LIND_ARG_CAGEID_MASK (~LIND_ARG_TRANSLATE_FLAG)

#ifdef __cplusplus
extern "C"
{
Expand Down Expand Up @@ -45,7 +50,9 @@ extern "C"
static inline uint64_t
__lind_translate_uaddr_to_host (const uint64_t uaddr, const uint64_t cageid)
{
if (cageid == __lind_cageid)
uint64_t __cageid = cageid & LIND_ARG_CAGEID_MASK;

if (__cageid == __lind_cageid && ((cageid & LIND_ARG_TRANSLATE_FLAG) != 0))
return __lind_base + uaddr;

return uaddr;
Expand All @@ -57,8 +64,16 @@ extern "C"

// Converts (uaddr, cageid) pair to host address.
// Useful when address space (cage vs host) is ambigious.
//
// This is called by copy data where the arguments are already addresses
// so we implicitly update the cageid argument before passing it to the helper.
#define TRANSLATE_UADDR_TO_HOST(uaddr, cageid) \
__lind_translate_uaddr_to_host ((uaddr), (cageid))
__lind_translate_uaddr_to_host ((uaddr), (cageid | LIND_ARG_TRANSLATE_FLAG)), (cageid)

// This is used by make_threei_call, we do not modify the flag before checking if translation
// is needed. We do modify the cage on output so that other threei/lind calls see a correct cageid
#define TRANSLATE_ARG_TO_HOST(uaddr, cageid) \
__lind_translate_uaddr_to_host ((uaddr), (cageid)), (cageid & LIND_ARG_CAGEID_MASK)

/* Translate an array of guest iovec structures to host layout.
Each iov_base is a wasm32 guest pointer; we split the translated
Expand Down
17 changes: 9 additions & 8 deletions src/glibc/lind_syscall/lind_syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,13 @@ int make_threei_call (unsigned int callnumber,
int ret = __lind_make_syscall_trampoline(callnumber,
callname,
self_cageid, target_cageid,
arg1, arg1cageid,
arg2, arg2cageid,
arg3, arg3cageid,
arg4, arg4cageid,
arg5, arg5cageid,
arg6, arg6cageid);
TRANSLATE_ARG_TO_HOST(arg1, arg1cageid),
TRANSLATE_ARG_TO_HOST(arg2, arg2cageid),
TRANSLATE_ARG_TO_HOST(arg3, arg3cageid),
TRANSLATE_ARG_TO_HOST(arg4, arg4cageid),
TRANSLATE_ARG_TO_HOST(arg5, arg5cageid),
TRANSLATE_ARG_TO_HOST(arg6, arg6cageid));

// if translate_errno is not enabled, we do not do any further process to errno handling and directly return the result
if(translate_errno == TRANSLATE_ERRNO_OFF) return ret;
// handle the errno
Expand Down Expand Up @@ -155,8 +156,8 @@ int copy_data_between_cages(uint64_t thiscage, uint64_t targetcage, uint64_t src
NOTUSED, // callname is not used in the trampoline
thiscage, // self_cageid
thiscage, // target_cageid. Self_cageid and target_cageid are the same to adapt with regular make_syscall lookup logic in 3i
TRANSLATE_UADDR_TO_HOST(srcaddr, srccage), srccage,
TRANSLATE_UADDR_TO_HOST(destaddr, destcage), destcage,
TRANSLATE_UADDR_TO_HOST(srcaddr, srccage),
TRANSLATE_UADDR_TO_HOST(destaddr, destcage),
len, NOTUSED,
copytype, NOTUSED,
NOTUSED, NOTUSED, NOTUSED, NOTUSED,
Expand Down
13 changes: 13 additions & 0 deletions tests/grate-tests/diff-cage-args.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main() {
int fd = open("redirected.txt", O_RDONLY, 0);
printf("Hello world. FD=%d\n", fd);

char buf[11];
int ret = read(1, buf, 10);

printf("Goodbye world! ret=%d buf=%s\n", ret, buf);
}
136 changes: 136 additions & 0 deletions tests/grate-tests/diff-cage-args_grate.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#include <errno.h>
#include <lind_syscall.h>

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

// Dispatcher function
int pass_fptr_to_wt(uint64_t fn_ptr_uint, uint64_t cageid, uint64_t arg1,
uint64_t arg1cage, uint64_t arg2, uint64_t arg2cage,
uint64_t arg3, uint64_t arg3cage, uint64_t arg4,
uint64_t arg4cage, uint64_t arg5, uint64_t arg5cage,
uint64_t arg6, uint64_t arg6cage) {
if (fn_ptr_uint == 0) {
fprintf(stderr,
"[Grate|diff-cage-args] Invalid function ptr\n");
assert(0);
}

printf("[Grate|diff-cage-args] Handling function ptr: %llu from cage: "
"%llu\n",
fn_ptr_uint, cageid);

int (*fn)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
uint64_t) =
(int (*)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
uint64_t))(uintptr_t)fn_ptr_uint;

return fn(cageid, arg1, arg1cage, arg2, arg2cage, arg3, arg3cage, arg4,
arg4cage, arg5, arg5cage, arg6, arg6cage);
}

int read_grate(uint64_t grateid, uint64_t arg1, uint64_t arg1cage,
uint64_t arg2, uint64_t arg2cage, uint64_t arg3,
uint64_t arg3cage, uint64_t arg4, uint64_t arg4cage,
uint64_t arg5, uint64_t arg5cage, uint64_t arg6,
uint64_t arg6cage) {
int thiscage = getpid();
int cageid = arg1cage;

int fd = (int)arg1;
int count = (size_t)arg3;

ssize_t ret = 4321;

char buf[11] = "helloworld";

copy_data_between_cages(thiscage, arg2cage, (uint64_t)buf, thiscage,
arg2, arg2cage, count,
0 // Use copytype 0 so read exactly count
// bytes instead of stopping at '\0'
);

return ret;
}

int open_grate(uint64_t cageid, uint64_t arg1, uint64_t arg1cage, uint64_t arg2,
uint64_t arg2cage, uint64_t arg3, uint64_t arg3cage,
uint64_t arg4, uint64_t arg4cage, uint64_t arg5,
uint64_t arg5cage, uint64_t arg6, uint64_t arg6cage) {
printf(
"[Grate|diff-cage-args] In open_grate %d handler for cage: %llu\n",
getpid(), cageid);

int self_grate_id = getpid();

// Overwrite the path supplied to open with a different path.
char new_path[20] = "/tmp/redirected.txt";

int ret = make_threei_call(
2, 0, self_grate_id, arg1cage,
// We need to modify the cageid here to indicate that we want the
// address translated.
(uint64_t)&new_path, self_grate_id | (1ULL << 63), arg2, arg2cage,
arg3, arg3cage, arg4, arg4cage, arg5, arg5cage, arg6, arg6cage,
0 // we will handle the errno in this grate instead of translating
// it to
);

return ret;
}

// Main function will always be same in all grates
int main(int argc, char *argv[]) {
// Should be at least one input (at least one grate file and one cage
// file)
if (argc < 2) {
fprintf(stderr, "Usage: %s <cage_file> <grate_file>\n",
argv[0]);
assert(0);
}

int grateid = getpid();

pid_t pid = fork();
if (pid < 0) {
perror("fork failed");
assert(0);
} else if (pid == 0) {
int cageid = getpid();

// This is to test whether we can use arg, argcage from
// different cages.
uint64_t fn_ptr_addr = (uint64_t)(uintptr_t)&open_grate;
int ret = register_handler(cageid, 2, grateid, fn_ptr_addr);

// This is to check copy_data for regression.
fn_ptr_addr = (uint64_t)(uintptr_t)&read_grate;
ret = register_handler(cageid, 0, grateid, fn_ptr_addr);

if (execv(argv[1], &argv[1]) == -1) {
perror("execv failed");
assert(0);
}
}

int status;
int failed = 0;
while (wait(&status) > 0) {
if (status != 0) {
fprintf(stderr,
"[Grate|diff-cage-args] FAIL: child exited "
"with status %d\n",
status);
assert(0);
}
}

printf("[Grate|diff-cage-args] PASS\n");
return 0;
}
Loading