diff options
author | Sergey Bugaev <bugaevc@gmail.com> | 2024-03-27 19:18:36 +0300 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2024-03-27 19:56:53 +0100 |
commit | 2fb1f4ccbb369c06ef80dc0fe5798b239383fa4c (patch) | |
tree | b03ad80da0e1297994feb48e3fa3131eb3f0e5a6 | |
parent | b5a1c677cae00261962ccfc31f33bc826539fc23 (diff) | |
download | gnumach-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.h | 16 | ||||
-rw-r--r-- | tests/test-syscalls.c | 40 | ||||
-rw-r--r-- | tests/testlib.c | 123 |
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 |