aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Bugaev <bugaevc@gmail.com>2024-03-27 19:18:36 +0300
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2024-03-27 19:56:53 +0100
commit2fb1f4ccbb369c06ef80dc0fe5798b239383fa4c (patch)
treeb03ad80da0e1297994feb48e3fa3131eb3f0e5a6
parentb5a1c677cae00261962ccfc31f33bc826539fc23 (diff)
downloadgnumach-2fb1f4ccbb369c06ef80dc0fe5798b239383fa4c.tar.gz
gnumach-2fb1f4ccbb369c06ef80dc0fe5798b239383fa4c.tar.bz2
gnumach-2fb1f4ccbb369c06ef80dc0fe5798b239383fa4c.zip
tests: Add a more serious mach_msg_server() routine
Message-ID: <20240327161841.95685-13-bugaevc@gmail.com>
-rw-r--r--tests/include/testlib.h16
-rw-r--r--tests/test-syscalls.c40
-rw-r--r--tests/testlib.c123
3 files changed, 142 insertions, 37 deletions
diff --git a/tests/include/testlib.h b/tests/include/testlib.h
index cdb2ce13..d2367124 100644
--- a/tests/include/testlib.h
+++ b/tests/include/testlib.h
@@ -70,6 +70,22 @@ thread_t test_thread_start(task_t task, void(*routine)(void*), void* arg);
mach_port_t host_priv(void);
mach_port_t device_priv(void);
+extern void mach_msg_destroy(mach_msg_header_t *msg);
+
+extern mach_msg_return_t mach_msg_server(
+ boolean_t (*demux) (mach_msg_header_t *request,
+ mach_msg_header_t *reply),
+ mach_msg_size_t max_size,
+ mach_port_t rcv_name,
+ mach_msg_option_t options);
+
+extern mach_msg_return_t mach_msg_server_once(
+ boolean_t (*demux) (mach_msg_header_t *request,
+ mach_msg_header_t *reply),
+ mach_msg_size_t max_size,
+ mach_port_t rcv_name,
+ mach_msg_option_t options);
+
int main(int argc, char *argv[], int envc, char *envp[]);
#endif /* TESTLIB_H */
diff --git a/tests/test-syscalls.c b/tests/test-syscalls.c
index be4df8c3..63c2690a 100644
--- a/tests/test-syscalls.c
+++ b/tests/test-syscalls.c
@@ -49,44 +49,10 @@ kern_return_t catch_exception_raise(mach_port_t exception_port,
last_exc.exception = exception;
last_exc.code = code;
last_exc.subcode = subcode;
+ thread_terminate(thread);
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
@@ -152,13 +118,13 @@ int main(int argc, char *argv[], int envc, char *envp[])
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_RET(mach_msg_server_once(exc_server, 4096, excp, MACH_MSG_OPTION_NONE), "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_RET(mach_msg_server_once(exc_server, 4096, excp, MACH_MSG_OPTION_NONE), "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()");
diff --git a/tests/testlib.c b/tests/testlib.c
index d2198830..baf1ce5c 100644
--- a/tests/testlib.c
+++ b/tests/testlib.c
@@ -26,6 +26,7 @@
#include <sys/reboot.h>
#include <mach.user.h>
+#include <mach_port.user.h>
#include <mach_host.user.h>
@@ -81,6 +82,128 @@ const char* e2s(int err)
}
}
+void mach_msg_destroy(mach_msg_header_t *msg)
+{
+ mach_port_t tmp;
+
+ tmp = mach_reply_port();
+
+ msg->msgh_local_port = msg->msgh_remote_port;
+ msg->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND,
+ MACH_MSGH_BITS_REMOTE(msg->msgh_bits))
+ | MACH_MSGH_BITS_OTHER(msg->msgh_bits);
+
+ mach_msg(msg, MACH_SEND_MSG, msg->msgh_size, 0, MACH_PORT_NULL,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+
+ mach_port_mod_refs(mach_task_self(), tmp, MACH_PORT_RIGHT_RECEIVE, -1);
+}
+
+mach_msg_return_t mach_msg_server(
+ boolean_t (*demux) (mach_msg_header_t *request,
+ mach_msg_header_t *reply),
+ mach_msg_size_t max_size,
+ mach_port_t rcv_name,
+ mach_msg_option_t options)
+{
+ mach_msg_return_t mr;
+ mig_reply_header_t *request;
+ mig_reply_header_t *reply;
+ mig_reply_header_t *tmp;
+ boolean_t handled;
+
+ request = __builtin_alloca(max_size);
+ reply = __builtin_alloca(max_size);
+
+GetRequest:
+ mr = mach_msg(&request->Head, MACH_RCV_MSG|options,
+ 0, max_size, rcv_name,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ if (mr)
+ return mr;
+
+Handle:
+ handled = demux(&request->Head, &reply->Head);
+ if (!handled)
+ reply->RetCode = MIG_BAD_ID;
+
+ if (reply->RetCode == MIG_NO_REPLY)
+ goto GetRequest;
+ else if (reply->RetCode != KERN_SUCCESS) {
+ request->Head.msgh_remote_port = MACH_PORT_NULL;
+ mach_msg_destroy(&request->Head);
+ }
+
+ if (!MACH_PORT_VALID(reply->Head.msgh_remote_port)) {
+ mach_msg_destroy(&reply->Head);
+ goto GetRequest;
+ }
+
+ tmp = request;
+ request = reply;
+ reply = tmp;
+
+ mr = mach_msg(&request->Head, MACH_SEND_MSG|MACH_RCV_MSG|options,
+ request->Head.msgh_size, max_size, rcv_name,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+
+ if (mr == MACH_MSG_SUCCESS)
+ goto Handle;
+ else if (mr == MACH_SEND_INVALID_DEST) {
+ mach_msg_destroy(&request->Head);
+ goto GetRequest;
+ }
+
+ return mr;
+}
+
+mach_msg_return_t mach_msg_server_once(
+ boolean_t (*demux) (mach_msg_header_t *request,
+ mach_msg_header_t *reply),
+ mach_msg_size_t max_size,
+ mach_port_t rcv_name,
+ mach_msg_option_t options)
+{
+ mach_msg_return_t mr;
+ mig_reply_header_t *request;
+ mig_reply_header_t *reply;
+ boolean_t handled;
+
+ request = __builtin_alloca(max_size);
+ reply = __builtin_alloca(max_size);
+
+ mr = mach_msg(&request->Head, MACH_RCV_MSG|options,
+ 0, max_size, rcv_name,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ if (mr)
+ return mr;
+
+ handled = demux(&request->Head, &reply->Head);
+ if (!handled)
+ reply->RetCode = MIG_BAD_ID;
+
+ if (reply->RetCode == MIG_NO_REPLY)
+ return MACH_MSG_SUCCESS;
+ else if (reply->RetCode != KERN_SUCCESS) {
+ request->Head.msgh_remote_port = MACH_PORT_NULL;
+ mach_msg_destroy(&request->Head);
+ }
+
+ if (!MACH_PORT_VALID(reply->Head.msgh_remote_port)) {
+ mach_msg_destroy(&reply->Head);
+ return MACH_MSG_SUCCESS;
+ }
+
+ mr = mach_msg(&reply->Head, MACH_SEND_MSG|options,
+ reply->Head.msgh_size, 0, MACH_PORT_NULL,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+
+ if (mr == MACH_SEND_INVALID_DEST)
+ mach_msg_destroy(&reply->Head);
+
+ return mr;
+}
+
/*
* Minimal _start() for test modules, we just take the arguments from the
* kernel, call main() and reboot. As in glibc, we expect the argument pointer