Skip to content

Commit

Permalink
added strace exclude filter feature
Browse files Browse the repository at this point in the history
  • Loading branch information
salsal97 committed Aug 24, 2022
1 parent 85ece7c commit 27cc84c
Show file tree
Hide file tree
Showing 10 changed files with 242 additions and 42 deletions.
33 changes: 28 additions & 5 deletions doc/user-getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,20 +65,43 @@ Options:
multiplier suffix: k 1024, m 1024*1024, or
g 1024*1024*1024. Ignored if smaller than the
existing default thread stack size
--app-config-path <json> -- specifies the configuration json file for
running an unsigned binary. The file can be
the same one used for the signing process.
--app-config-path <json>
-- specifies the configuration json file for
running an unsigned binary. The file can be
the same one used for the signing process.
--host-to-enc-uid-map <host-uid:enc-uid[,host-uid2:enc-uid2,...]>
-- comma separated list of uid mappings between
the host and the enclave
the host and the enclave
--host-to-enc-gid-map <host-gid:enc-gid[,host-gid2:enc-gid2,...]>
-- comma separated list of gid mappings between
the host and the enclave
the host and the enclave
--unhandled-syscall-enosys <true/false>
-- flag indicating if the app must exit when
it encounters an unimplemented syscall
'true' implies the syscall would not terminate
and instead return ENOSYS.
--strace
-- Use this option to display the system call traces of
the execution
--strace-failing
-- When specified, all syscalls that fail will be logged.
Other syscalls will not be logged, unless specified via
filter (see below). Set a breakpoint in _strace_failure_hook
to stop execution whenever a syscall fails. Use breakpoint
conditions to control the behavior of the breakpoint.
E.g: Use syscall number as a condition in the breakpoint
--strace-filter 'SYS_name1:SYS_name2:...'
-- Specify the set of syscalls to be traced. When filters
are specified, only those syscalls specified in the filter
will be traced, in addition to failing syscalls if
specified as described above.
E.g: To trace open and mprotect syscalls, specify
--strace-filter 'SYS_open:SYS_mprotect'
--strace-exclude-filter 'SYS_name1:SYS_name2:...'
-- Specify a set of syscalls to exclude from the strace log.
All other syscalls will be logged in the strace.
E.g: To exclude open and mprotect syscalls, specify
--strace-exclude-filter 'SYS_open:SYS_mprotect'
```
You can also specify many other parameters in a configuration file, conventionally called `config.json`, you will also use this configuration file to package your application.
Expand Down
2 changes: 2 additions & 0 deletions tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ endif

DIRS += appenv
DIRS += go
DIRS += strace


.PHONY: $(DIRS)

Expand Down
7 changes: 7 additions & 0 deletions tests/strace/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
1
2
3
test1.txt
test2.txt
test3.txt
test4.txt
51 changes: 51 additions & 0 deletions tests/strace/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
TOP=$(abspath ../..)
include $(TOP)/defs.mak

APPDIR = appdir
CFLAGS = -fPIC
LDFLAGS = -Wl,-rpath=$(MUSL_LIB)

all:
$(MAKE) myst
$(MAKE) rootfs

rootfs: strace.c
mkdir -p $(APPDIR)/bin
$(CC) $(CFLAGS) -o $(APPDIR)/bin/strace strace.c $(LDFLAGS)
$(MYST) mkcpio $(APPDIR) rootfs

OPTS =

ifdef PERF
OPTS += --perf
endif

OPTS += --thread-stack-size=1048576

tests: all test1 test2 test3 test4
echo " === passed test strace"

test1:
-$(MYST_EXEC) rootfs /bin/strace --strace-filter=SYS_invali $(OPTS) 2> test1.txt || $(RUNTEST) diff test1.txt test1.expected.txt
echo "=== test1 passed"

test2:
-$(MYST_EXEC) rootfs /bin/strace --strace-filter=SYS_mmap --strace-exclude-filter=SYS_ioctl $(OPTS) 2> test2.txt || $(RUNTEST) diff test2.txt test2.expected.txt
echo "=== test2 passed"

test3:
$(MYST_EXEC) rootfs /bin/strace --strace-filter=SYS_close:SYS_open $(OPTS) 2> test3.txt
cat test3.txt | grep "SYS_" > 1 && cat test3.txt | grep -E '(SYS_close|SYS_open)' > 2 && $(RUNTEST) diff 1 2
echo "=== test3 passed"

test4:
$(MYST_EXEC) rootfs /bin/strace --strace-exclude-filter 'SYS_open:SYS_close' $(OPTS) 2> test4.txt
cat test4.txt | grep -v "SYS_open" > 3 && $(RUNTEST) diff 3 test4.txt
cat test4.txt | grep -v "SYS_close" > 3 && $(RUNTEST) diff 3 test4.txt
echo "=== test4 passed"

myst:
$(MAKE) -C $(TOP)/tools/myst

clean:
rm -rf $(APPDIR) rootfs export ramfs 1 2 3 test1.txt text2.txt test3.txt test4.txt
25 changes: 25 additions & 0 deletions tests/strace/strace.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

void foofoo()
{
}

int main(int argc, const char* argv[])
{
char buf[PATH_MAX];

foofoo();

getcwd(buf, sizeof(buf));
assert(strcmp(buf, "/") == 0);

return 0;
}
2 changes: 2 additions & 0 deletions tests/strace/test1.expected.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Unknown syscall SYS_invali specified in --strace-filter or --strace-exclude-filter
Aborted (core dumped)
2 changes: 2 additions & 0 deletions tests/strace/test2.expected.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Cannot specify both --strace-filter and --strace-exclude-filter
Aborted (core dumped)
33 changes: 28 additions & 5 deletions tools/myst/host/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,20 +371,43 @@ Options:\n\
main thread, where <size> may have a\n\
multiplier suffix: k 1024, m 1024*1024, or\n\
g 1024*1024*1024\n\
--app-config-path <json> -- specifies the configuration json file for\n\
running an unsigned binary. The file can be\n\
the same one used for the signing process.\n\
--app-config-path <json>\n\
-- specifies the configuration json file for\n\
running an unsigned binary. The file can be\n\
the same one used for the signing process.\n\
--host-to-enc-uid-map <host-uid:enc-uid[,host-uid2:enc-uid2,...]>\n\
-- comma separated list of uid mappings between\n\
the host and the enclave\n\
the host and the enclave\n\
--host-to-enc-gid-map <host-gid:enc-gid[,host-gid2:enc-gid2,...]>\n\
-- comma separated list of gid mappings between\n\
the host and the enclave\n\
the host and the enclave\n\
--unhandled-syscall-enosys <true/false>\n\
-- flag indicating if the app must exit when\n\
it encounters an unimplemented syscall\n\
'true' implies the syscall would not terminate\n\
and instead return ENOSYS.\n\
--strace \n\
-- Use this option to display the system call traces of \n\
the execution\n\
--strace-failing\n\
-- When specified, all syscalls that fail will be logged.\n\
Other syscalls will not be logged, unless specified via \n\
filter (see below). Set a breakpoint in _strace_failure_hook \n\
to stop execution whenever a syscall fails. Use breakpoint \n\
conditions to control the behavior of the breakpoint.\n\
E.g: Use syscall number as a condition in the breakpoint\n\
--strace-filter 'SYS_name1:SYS_name2:...'\n\
-- Specify the set of syscalls to be traced. When filters \n\
are specified, only those syscalls specified in the filter \n\
will be traced, in addition to failing syscalls if\n\
specified as described above.\n\
E.g: To trace open and mprotect syscalls, specify\n\
--strace-filter 'SYS_open:SYS_mprotect'\n\
--strace-exclude-filter 'SYS_name1:SYS_name2:...'\n\
-- Specify a set of syscalls to exclude from the strace log. \n\
All other syscalls will be logged in the strace. \n\
E.g: To exclude open and mprotect syscalls, specify\n\
--strace-exclude-filter 'SYS_open:SYS_mprotect'\n\
\n"

int exec_action(int argc, const char* argv[], const char* envp[])
Expand Down
33 changes: 28 additions & 5 deletions tools/myst/host/exec_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,20 +68,43 @@ Options:\n\
main thread, where <size> may have a\n\
multiplier suffix: k 1024, m 1024*1024, or\n\
g 1024*1024*1024\n\
--app-config-path <json> -- specifies the configuration json file for\n\
running an unsigned binary. The file can be\n\
the same one used for the signing process.\n\
--app-config-path <json>\n\
-- specifies the configuration json file for\n\
running an unsigned binary. The file can be\n\
the same one used for the signing process.\n\
--host-to-enc-uid-map <host-uid:enc-uid[,host-uid2:enc-uid2,...]>\n\
-- comma separated list of uid mappings between\n\
the host and the enclave\n\
the host and the enclave\n\
--host-to-enc-gid-map <host-gid:enc-gid[,host-gid2:enc-gid2,...]>\n\
-- comma separated list of gid mappings between\n\
the host and the enclave\n\
the host and the enclave\n\
--unhandled-syscall-enosys <true/false>\n\
-- flag indicating if the app must exit when\n\
it encounters an unimplemented syscall\n\
'true' implies the syscall would not terminate\n\
and instead return ENOSYS.\n\
--strace \n\
-- Use this option to display the system call traces of \n\
the execution\n\
--strace-failing\n\
-- When specified, all syscalls that fail will be logged.\n\
Other syscalls will not be logged, unless specified via \n\
filter (see below). Set a breakpoint in _strace_failure_hook \n\
to stop execution whenever a syscall fails. Use breakpoint \n\
conditions to control the behavior of the breakpoint.\n\
E.g: Use syscall number as a condition in the breakpoint\n\
--strace-filter 'SYS_name1:SYS_name2:...'\n\
-- Specify the set of syscalls to be traced. When filters \n\
are specified, only those syscalls specified in the filter \n\
will be traced, in addition to failing syscalls if\n\
specified as described above.\n\
E.g: To trace open and mprotect syscalls, specify\n\
--strace-filter 'SYS_open:SYS_mprotect'\n\
--strace-exclude-filter 'SYS_name1:SYS_name2:...'\n\
-- Specify a set of syscalls to exclude from the strace log. \n\
All other syscalls will be logged in the strace. \n\
E.g: To exclude open and mprotect syscalls, specify\n\
--strace-exclude-filter 'SYS_open:SYS_mprotect'\n\
\n\
"

Expand Down
96 changes: 69 additions & 27 deletions tools/myst/host/strace.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,49 @@
#include <myst/strings.h>
#include <myst/syscall.h>

int myst_set_strace_filter(
int num_tokens,
char** tokens,
myst_strace_config_t* strace_config,
bool include)
{
for (size_t i = 0; i < MYST_MAX_SYSCALLS; ++i)
{
strace_config->trace[i] = !include;
}

for (size_t i = 0; i < num_tokens; ++i)
{
const char* name = tokens[i];
long num = myst_syscall_num(name);
if (num >= 0)
{
if (num < MYST_MAX_SYSCALLS)
strace_config->trace[num] = include;
else
{
fprintf(
stderr,
"Syscall %s exceeds trace array. Fix "
"myst_syscall_config_t\n",
name);
abort();
}
}
else
{
fprintf(
stderr,
"Unknown syscall %s specified in --strace-filter or "
"--strace-exclude-filter \n",
name);
abort();
}
}
strace_config->filter = 1;
return 0;
}

int myst_parse_strace_config(
int* argc,
const char** argv,
Expand All @@ -17,6 +60,7 @@ int myst_parse_strace_config(
const char* filter = NULL;
char** tokens = NULL;
size_t num_tokens = 0;
bool filter_flag = 0;

if (cli_getopt(argc, argv, "--strace-failing", NULL) == 0)
{
Expand All @@ -31,35 +75,33 @@ int myst_parse_strace_config(
fprintf(stderr, "Invalid strace-filter '%s' specified.\n", filter);
abort();
}
for (size_t i = 0; i < num_tokens; ++i)

ret = myst_set_strace_filter(num_tokens, tokens, strace_config, 1);
filter_flag = true;
}

if (cli_getopt(argc, argv, "--strace-exclude-filter", &filter) == 0 &&
filter)
{
if (filter_flag)
{
const char* name = tokens[i];
long num = myst_syscall_num(name);
if (num >= 0)
{
if (num < MYST_MAX_SYSCALLS)
strace_config->trace[num] = 1;
else
{
fprintf(
stderr,
"Syscall %s exceeds trace array. Fix "
"myst_syscall_config_t\n",
name);
abort();
}
}
else
{
fprintf(
stderr,
"Unknown syscall %s specified in --strace=filter\n",
name);
abort();
}
fprintf(
stderr,
"Cannot specify both --strace-filter and "
"--strace-exclude-filter\n");
abort();
}
strace_config->filter = 1;
ret = 0;

if (myst_strsplit(filter, ":", &tokens, &num_tokens) != 0)
{
fprintf(
stderr,
"Invalid strace-exclude-filter '%s' specified.\n",
filter);
abort();
}

ret = myst_set_strace_filter(num_tokens, tokens, strace_config, 0);
}

if (tokens)
Expand Down

0 comments on commit 27cc84c

Please sign in to comment.