summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorLuca Dariz <luca@orpolo.org>2024-01-11 22:09:04 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2024-01-13 22:51:50 +0100
commitf8bd1c487d1d60342c1aaaeb955b25ac39286d9f (patch)
treec2e1bca963f4feb6667ab1281bf8c4102adc2216 /tests
parenta42040231e574f7ea52be341d6c212cba9411e72 (diff)
add syscall tests
Message-ID: <20240111210907.419689-8-luca@orpolo.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/test-syscalls.c166
-rw-r--r--tests/user-qemu.mk3
2 files changed, 168 insertions, 1 deletions
diff --git a/tests/test-syscalls.c b/tests/test-syscalls.c
new file mode 100644
index 00000000..be4df8c3
--- /dev/null
+++ b/tests/test-syscalls.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2024 Free Software Foundation
+ *
+ * This program is free software ; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation ; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY ; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with the program ; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <syscalls.h>
+#include <testlib.h>
+
+#include <mach/exception.h>
+#include <mach/mig_errors.h>
+#include <mach/vm_param.h>
+
+#include <mach.user.h>
+#include <mach_port.user.h>
+#include <exc.server.h>
+
+
+static struct {
+ mach_port_t exception_port;
+ mach_port_t thread;
+ mach_port_t task;
+ integer_t exception;
+ integer_t code;
+ integer_t subcode;
+} last_exc;
+kern_return_t catch_exception_raise(mach_port_t exception_port,
+ mach_port_t thread, mach_port_t task,
+ integer_t exception, integer_t code,
+ long_integer_t subcode)
+{
+ printf("received catch_exception_raise(%u %u %u %d %d %d)\n",
+ exception_port, thread, task, exception, code, subcode);
+ last_exc.exception_port = exception_port;
+ last_exc.thread = thread;
+ last_exc.task = task;
+ last_exc.exception = exception;
+ last_exc.code = code;
+ last_exc.subcode = subcode;
+ return KERN_SUCCESS;
+}
+
+static char simple_request_data[PAGE_SIZE];
+static char simple_reply_data[PAGE_SIZE];
+int simple_msg_server(boolean_t (*demuxer) (mach_msg_header_t *request,
+ mach_msg_header_t *reply),
+ mach_port_t rcv_port_name,
+ int num_msgs)
+{
+ int midx = 0, mok = 0;
+ int ret;
+ mig_reply_header_t *request = (mig_reply_header_t*)simple_request_data;
+ mig_reply_header_t *reply = (mig_reply_header_t*)simple_reply_data;
+ while ((midx - num_msgs) < 0)
+ {
+ ret = mach_msg(&request->Head, MACH_RCV_MSG, 0, PAGE_SIZE,
+ rcv_port_name, 0, MACH_PORT_NULL);
+ switch (ret)
+ {
+ case MACH_MSG_SUCCESS:
+ if ((*demuxer)(&request->Head, &reply->Head))
+ mok++; // TODO send reply
+ else
+ FAILURE("demuxer didn't handle the message");
+ break;
+ default:
+ ASSERT_RET(ret, "receiving in msg_server");
+ break;
+ }
+ midx++;
+ }
+ if (mok != midx)
+ FAILURE("wrong number of message received");
+ return mok != midx;
+}
+
+
+void test_syscall_bad_arg_on_stack(void *arg)
+{
+ /* mach_msg() has 7 arguments, so the last one should be always
+ passed on the stack on x86. Here we make ESP/RSP point to the
+ wrong place to test the access check */
+#ifdef __x86_64__
+ asm volatile("movq $0x123,%rsp;" \
+ "movq $-25,%rax;" \
+ "syscall;" \
+ );
+#else
+ asm volatile("mov $0x123,%esp;" \
+ "mov $-25,%eax;" \
+ "lcall $0x7,$0x0;" \
+ );
+#endif
+ FAILURE("we shouldn't be here!");
+}
+
+void test_bad_syscall_num(void *arg)
+{
+#ifdef __x86_64__
+ asm volatile("movq $0x123456,%rax;" \
+ "syscall;" \
+ );
+#else
+ asm volatile("mov $0x123456,%eax;" \
+ "lcall $0x7,$0x0;" \
+ );
+#endif
+ FAILURE("we shouldn't be here!");
+}
+
+
+int main(int argc, char *argv[], int envc, char *envp[])
+{
+ int err;
+ mach_port_t excp;
+
+ err = mach_port_allocate(mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &excp);
+ ASSERT_RET(err, "creating exception port");
+
+ err = mach_port_insert_right(mach_task_self(), excp, excp,
+ MACH_MSG_TYPE_MAKE_SEND);
+ ASSERT_RET(err, "inserting send right into exception port");
+
+ err = task_set_special_port(mach_task_self(), TASK_EXCEPTION_PORT, excp);
+ ASSERT_RET(err, "setting task exception port");
+
+ /* FIXME: receiving an exception with small size causes GP on 64 bit userspace */
+ /* mig_reply_header_t msg; */
+ /* err = mach_msg(&msg.Head, /\* The header *\/ */
+ /* MACH_RCV_MSG, */
+ /* 0, */
+ /* sizeof (msg), /\* Max receive Size *\/ */
+ /* excp, */
+ /* 1000, */
+ /* MACH_PORT_NULL); */
+
+ // FIXME: maybe MIG should provide this prototype?
+ boolean_t exc_server
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
+
+ memset(&last_exc, 0, sizeof(last_exc));
+ test_thread_start(mach_task_self(), test_bad_syscall_num, NULL);
+ ASSERT_RET(simple_msg_server(exc_server, excp, 1), "error in exc server");
+ ASSERT((last_exc.exception == EXC_BAD_INSTRUCTION) && (last_exc.code == EXC_I386_INVOP),
+ "bad exception for test_bad_syscall_num()");
+
+ memset(&last_exc, 0, sizeof(last_exc));
+ test_thread_start(mach_task_self(), test_syscall_bad_arg_on_stack, NULL);
+ ASSERT_RET(simple_msg_server(exc_server, excp, 1), "error in exc server");
+ ASSERT((last_exc.exception == EXC_BAD_ACCESS) && (last_exc.code == KERN_INVALID_ADDRESS),
+ "bad exception for test_syscall_bad_arg_on_stack()");
+
+ return 0;
+}
diff --git a/tests/user-qemu.mk b/tests/user-qemu.mk
index 8f10ba36..c11f7ded 100644
--- a/tests/user-qemu.mk
+++ b/tests/user-qemu.mk
@@ -200,7 +200,8 @@ USER_TESTS := \
tests/test-mach_host \
tests/test-gsync \
tests/test-mach_port \
- tests/test-vm
+ tests/test-vm \
+ tests/test-syscalls
USER_TESTS_CLEAN = $(subst tests/,clean-,$(USER_TESTS))