aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ali Polatel <alip@exherbo.org> 2010-01-16 15:15:33 +0200
committerAvatar Ali Polatel <alip@exherbo.org> 2010-01-16 15:15:33 +0200
commit8560474e95138666cab40b29bfdccfe07b29df39 (patch)
treee40b09ab7dc0605f461823b3b179b58f9df52968
parent01bd93fa4ed1a5703b4e009dda88b16a91a9473b (diff)
downloadsydbox-8560474e95138666cab40b29bfdccfe07b29df39.tar.gz
sydbox-8560474e95138666cab40b29bfdccfe07b29df39.tar.xz
Denying syscalls don't work on FreeBSD
-rw-r--r--src/syd-trace-freebsd.c18
-rw-r--r--src/syd-trace-freebsd.h2
-rw-r--r--tests/unit/test-trace-freebsd.c94
3 files changed, 106 insertions, 8 deletions
diff --git a/src/syd-trace-freebsd.c b/src/syd-trace-freebsd.c
index 4f4fb4b..9072b58 100644
--- a/src/syd-trace-freebsd.c
+++ b/src/syd-trace-freebsd.c
@@ -93,11 +93,25 @@ int trace_kill(pid_t pid)
return 0;
}
-int trace_syscall(pid_t pid, int data, bool entry)
+int trace_syscall(pid_t pid, int data, int call)
{
int save_errno;
- if (G_UNLIKELY(0 > ptrace(entry ? PT_TO_SCE : PT_TO_SCX, pid, (caddr_t)1, data))) {
+ switch (call) {
+ case -1:
+ call = PT_SYSCALL;
+ break;
+ case 0:
+ call = PT_TO_SCX;
+ break;
+ case 1:
+ call = PT_TO_SCE;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ if (G_UNLIKELY(0 > ptrace(call, pid, (caddr_t)1, data))) {
save_errno = errno;
g_info("failed to resume child %i: %s", pid, g_strerror(errno));
errno = save_errno;
diff --git a/src/syd-trace-freebsd.h b/src/syd-trace-freebsd.h
index 6b853c6..1f8ea3f 100644
--- a/src/syd-trace-freebsd.h
+++ b/src/syd-trace-freebsd.h
@@ -65,7 +65,7 @@ int trace_kill(pid_t pid);
* Restarts the child and arranges it to stop at the next system call.
* Returns 0 on success, -1 on failure and sets errno accordingly.
*/
-int trace_syscall(pid_t pid, int data, bool entry);
+int trace_syscall(pid_t pid, int data, int call);
/**
* Get the system call number and place it in scno.
diff --git a/tests/unit/test-trace-freebsd.c b/tests/unit/test-trace-freebsd.c
index 3387a3d..5df3887 100644
--- a/tests/unit/test-trace-freebsd.c
+++ b/tests/unit/test-trace-freebsd.c
@@ -22,12 +22,14 @@
#endif // HAVE_CONFIG_H
#include <errno.h>
+#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
+#include <sys/syscall.h>
#include <unistd.h>
#include <glib.h>
@@ -92,7 +94,7 @@ static void test2(void)
XFAIL_UNLESS(WIFSTOPPED(status), "child didn't stop by sending itself SIGSTOP\n");
/* Resume the child, it will stop at the next system call. */
- XFAIL_IF(0 > trace_syscall(pid, 0, true), "failed to resume child: %s\n", g_strerror(errno));
+ XFAIL_IF(0 > trace_syscall(pid, 0, -1), "failed to resume child: %s\n", g_strerror(errno));
waitpid(pid, &status, 0);
XFAIL_UNLESS(WIFSTOPPED(status), "child didn't stop by sending itself SIGTRAP\n");
@@ -167,6 +169,85 @@ static void test4(void)
}
}
+static void test6(void)
+{
+ int ret, status;
+ long sno;
+ pid_t pid;
+
+ pid = fork();
+ if (0 > pid)
+ XFAIL("fork() failed: %s\n", g_strerror(errno));
+ else if (0 == pid) { // child
+ if (0 > trace_me()) {
+ g_printerr("trace_me() failed: %s\n", g_strerror(errno));
+ _exit(EXIT_FAILURE);
+ }
+ kill(getpid(), SIGSTOP);
+ open("/dev/null", O_RDONLY);
+ pause();
+ }
+ else { // parent
+ waitpid(pid, &status, 0);
+
+ XFAIL_UNLESS(WIFSTOPPED(status), "child didn't stop by sending itself SIGSTOP\n");
+
+ /* Resume the child and it will stop at the next system call */
+ XFAIL_IF(0 > trace_syscall(pid, 0, -1), "trace_syscall() failed: %s\n", g_strerror(errno));
+ waitpid(pid, &status, 0);
+ XFAIL_UNLESS(WIFSTOPPED(status), "child didn't stop by sending itself SIGTRAP\n");
+
+ /* Check the system call number */
+ XFAIL_IF(0 > trace_get_syscall(pid, &sno), "failed to get system call: %s\n", g_strerror(errno));
+ XFAIL_UNLESS(SYS_open == sno, "expected SYS_open, got %d\n", sno);
+
+ trace_kill(pid);
+ }
+}
+
+static void test7(void)
+{
+ int ret, status;
+ long sno;
+ pid_t pid;
+
+ pid = fork();
+ if (0 > pid)
+ XFAIL("fork() failed: %s\n", g_strerror(errno));
+ else if (0 == pid) { // child
+ if (0 > trace_me()) {
+ g_printerr("trace_me() failed: %s\n", g_strerror(errno));
+ _exit(EXIT_FAILURE);
+ }
+ kill(getpid(), SIGSTOP);
+ open("/dev/null", O_RDONLY);
+ pause();
+ }
+ else { // parent
+ waitpid(pid, &status, 0);
+
+ XFAIL_UNLESS(WIFSTOPPED(status), "child didn't stop by sending itself SIGSTOP\n");
+
+ /* Resume the child and it will stop at the next system call */
+ XFAIL_IF(0 > trace_syscall(pid, 0, -1), "trace_syscall() failed: %s\n", g_strerror(errno));
+ waitpid(pid, &status, 0);
+ XFAIL_UNLESS(WIFSTOPPED(status), "child didn't stop by sending itself SIGTRAP\n");
+
+ XFAIL_IF(0 > trace_set_syscall(pid, 0xbadca11), "failed to set system call: %s", g_strerror(errno));
+
+ /* Resume the child and it will stop at the end of the system call */
+ XFAIL_IF(0 > trace_syscall(pid, 0, -1), "trace_syscall() failed: %s\n", g_strerror(errno));
+ waitpid(pid, &status, 0);
+ XFAIL_UNLESS(WIFSTOPPED(status), "child didn't stop by sending itself SIGTRAP\n");
+
+ /* Check the system call number */
+ XFAIL_IF(0 > trace_get_syscall(pid, &sno), "failed to get system call: %s\n", g_strerror(errno));
+ XFAIL_UNLESS(SYS_getpid == sno, "expected 0xbadca11, got %d\n", sno);
+
+ trace_kill(pid);
+ }
+}
+
static void no_log(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
{
}
@@ -180,11 +261,14 @@ int main(int argc, char **argv)
g_log_set_default_handler(no_log, NULL);
- g_test_add_func("/trace/freebsd/event/stop", test1);
- g_test_add_func("/trace/freebsd/event/trap", test2);
- g_test_add_func("/trace/freebsd/event/genuine", test3);
- g_test_add_func("/trace/freebsd/event/exit/normal", test4);
+ g_test_add_func("/trace/event/stop", test1);
+ g_test_add_func("/trace/event/trap", test2);
+ g_test_add_func("/trace/event/genuine", test3);
+ g_test_add_func("/trace/event/exit/normal", test4);
/* TODO: g_test_add_func("/trace/freebsd/event/exit/signal", test5); */
+ g_test_add_func("/trace/syscall/get", test6);
+ g_test_add_func("/trace/syscall/set", test7);
+
return g_test_run();
}