diff --git a/repos/base-sel4/patches/noise.patch b/repos/base-sel4/patches/noise.patch new file mode 100644 index 0000000000..cdbb1f4d6b --- /dev/null +++ b/repos/base-sel4/patches/noise.patch @@ -0,0 +1,11 @@ +--- src/kernel/sel4/src/api/syscall.c ++++ src/kernel/sel4/src/api/syscall.c +@@ -325,7 +325,7 @@ handleReply(void) + } + + case cap_null_cap: +- userError("Attempted reply operation when no reply cap present."); ++// userError("Attempted reply operation when no reply cap present."); + return; + + default: diff --git a/repos/base-sel4/ports/sel4.hash b/repos/base-sel4/ports/sel4.hash index 27c605babf..8a8d4ef757 100644 --- a/repos/base-sel4/ports/sel4.hash +++ b/repos/base-sel4/ports/sel4.hash @@ -1 +1 @@ -c8947bc79b1c29d570be6ad917c8310bc79d39e1 +fa69a91f3d2a79383ec72c8a52ac78ddc68becd5 diff --git a/repos/base-sel4/src/lib/base/ipc.cc b/repos/base-sel4/src/lib/base/ipc.cc index b475cae4be..c6665b07ba 100644 --- a/repos/base-sel4/src/lib/base/ipc.cc +++ b/repos/base-sel4/src/lib/base/ipc.cc @@ -110,13 +110,6 @@ static seL4_MessageInfo_t new_seL4_message(Msgbuf_base const &msg) for (size_t i = msg.used_caps(); i < Msgbuf_base::MAX_CAPS_PER_MSG; i++) seL4_SetMR(MR_IDX_CAPS + i, Rpc_obj_key::INVALID); - /* - * Allocate and define receive selector - */ - - if (!rcv_sel()) - rcv_sel() = Capability_space::alloc_rcv_sel(); - /* * Supply data payload */ @@ -140,16 +133,64 @@ static seL4_MessageInfo_t new_seL4_message(Msgbuf_base const &msg) static void decode_seL4_message(seL4_MessageInfo_t const &msg_info, Msgbuf_base &dst_msg) { - /* - * Extract Genode capabilities from seL4 IPC message + /** + * Read all required data from seL4 IPC message + * + * You must not use any Genode primitives which may corrupt the IPCBuffer + * during this step, e.g. Lock or RPC for output !!! */ - dst_msg.reset(); - size_t const num_caps = seL4_GetMR(MR_IDX_NUM_CAPS); - size_t curr_sel4_cap_idx = 0; + size_t const num_caps = min(seL4_GetMR(MR_IDX_NUM_CAPS), Msgbuf_base::MAX_CAPS_PER_MSG); + uint32_t const caps_extra = seL4_MessageInfo_get_extraCaps(msg_info); + uint32_t const caps_unwrapped = seL4_MessageInfo_get_capsUnwrapped(msg_info); + uint32_t const num_msg_words = seL4_MessageInfo_get_length(msg_info); + + Rpc_obj_key rpc_obj_keys[Msgbuf_base::MAX_CAPS_PER_MSG]; + unsigned long arg_badges[Msgbuf_base::MAX_CAPS_PER_MSG]; for (size_t i = 0; i < num_caps; i++) { + rpc_obj_keys[i] = Rpc_obj_key(seL4_GetMR(MR_IDX_CAPS + i)); + if (!rpc_obj_keys[i].valid()) + /* + * If rpc_obj_key is invalid, avoid calling + * seL4_CapData_Badge_get_Badge. It may trigger a assertion if + * the lowest bit is set by the garbage badge value we got. + */ + arg_badges[i] = Rpc_obj_key::INVALID; + else + arg_badges[i] = seL4_CapData_Badge_get_Badge(seL4_GetBadge(i)); + } - Rpc_obj_key const rpc_obj_key(seL4_GetMR(MR_IDX_CAPS + i)); + /** + * Extract message data payload + */ + + /* detect malformed message with too small header */ + if (num_msg_words >= MR_IDX_DATA) { + + /* copy data payload */ + size_t const max_words = dst_msg.capacity()/sizeof(umword_t); + size_t const num_data_words = min(num_msg_words - MR_IDX_DATA, max_words); + + umword_t *dst = (umword_t *)dst_msg.data(); + for (size_t i = 0; i < num_data_words; i++) + *dst++ = seL4_GetMR(MR_IDX_DATA + i); + + dst_msg.data_size(num_data_words*sizeof(umword_t)); + } + + /** + * Now we got all data from the IPCBuffer, we may use Native_capability + */ + + /** + * Construct Genode capabilities from read seL4 IPC message stored in + * rpc_opj_keys and arg_badges. + */ + + size_t curr_sel4_cap_idx = 0; + for (size_t i = 0; i < num_caps; i++) { + + Rpc_obj_key const rpc_obj_key = rpc_obj_keys[i]; /* * Detect passing of invalid capabilities as arguments @@ -166,7 +207,7 @@ static void decode_seL4_message(seL4_MessageInfo_t const &msg_info, * denote a valid capability that is not an RPC-object capability. * Hence it is meaningless as a key. */ - if (!rpc_obj_key.valid() && seL4_MessageInfo_get_extraCaps(msg_info) == 0) { + if (!rpc_obj_key.valid() && caps_extra == 0) { dst_msg.insert(Native_capability()); continue; } @@ -175,9 +216,7 @@ static void decode_seL4_message(seL4_MessageInfo_t const &msg_info, * RPC object key as contained in the message data is valid. */ - unsigned const unwrapped = - seL4_MessageInfo_get_capsUnwrapped(msg_info) & - (1 << curr_sel4_cap_idx); + bool const unwrapped = caps_unwrapped & (1U << curr_sel4_cap_idx); /* distinguish unwrapped from delegated cap */ if (unwrapped) { @@ -189,8 +228,8 @@ static void decode_seL4_message(seL4_MessageInfo_t const &msg_info, * So it is already present within the capability space. */ - unsigned long const arg_badge = - seL4_CapData_Badge_get_Badge(seL4_GetBadge(curr_sel4_cap_idx)); + ASSERT(curr_sel4_cap_idx < Msgbuf_base::MAX_CAPS_PER_MSG); + unsigned long const arg_badge = arg_badges[curr_sel4_cap_idx]; if (arg_badge != rpc_obj_key.value()) { warning("argument badge (", arg_badge, ") != RPC object key (", @@ -219,7 +258,7 @@ static void decode_seL4_message(seL4_MessageInfo_t const &msg_info, * badge mechanism is not in effect. */ - bool const delegated = seL4_MessageInfo_get_extraCaps(msg_info); + bool const delegated = caps_extra; ASSERT(delegated); @@ -256,26 +295,6 @@ static void decode_seL4_message(seL4_MessageInfo_t const &msg_info, } curr_sel4_cap_idx++; } - - /* - * Extract message data payload - */ - - size_t const num_msg_words = seL4_MessageInfo_get_length(msg_info); - - /* detect malformed message with too small header */ - if (num_msg_words < MR_IDX_DATA) - return; - - /* copy data payload */ - size_t const max_words = dst_msg.capacity()/sizeof(umword_t); - size_t const num_data_words = min(num_msg_words - MR_IDX_DATA, max_words); - - umword_t *dst = (umword_t *)dst_msg.data(); - for (size_t i = 0; i < num_data_words; i++) - *dst++ = seL4_GetMR(MR_IDX_DATA + i); - - dst_msg.data_size(num_data_words*sizeof(umword_t)); } @@ -292,19 +311,26 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst, kernel_debugger_panic("IPC destination is invalid"); } + /* allocate and define receive selector */ if (!rcv_sel()) rcv_sel() = Capability_space::alloc_rcv_sel(); - seL4_MessageInfo_t const request_msg_info = new_seL4_message(snd_msg); + rcv_msg.reset(); unsigned const dst_sel = Capability_space::ipc_cap_data(dst).sel.value(); - seL4_MessageInfo_t const reply_msg_info = - seL4_Call(dst_sel, request_msg_info); + /** + * Do not use Genode primitives after this point until the return which may + * alter the content of the IPCBuffer, e.g. Lock or RPC. + */ + + seL4_MessageInfo_t const request = new_seL4_message(snd_msg); + seL4_MessageInfo_t const reply_msg_info = seL4_Call(dst_sel, request); + Rpc_exception_code const exc_code(seL4_GetMR(MR_IDX_EXC_CODE)); decode_seL4_message(reply_msg_info, rcv_msg); - return Rpc_exception_code(seL4_GetMR(MR_IDX_EXC_CODE)); + return exc_code; } @@ -315,6 +341,15 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst, void Genode::ipc_reply(Native_capability caller, Rpc_exception_code exc, Msgbuf_base &snd_msg) { + /* allocate and define receive selector */ + if (!rcv_sel()) + rcv_sel() = Capability_space::alloc_rcv_sel(); + + /** + * Do not use Genode primitives after this point until the return which may + * alter the content of the IPCBuffer, e.g. Lock or RPC. + */ + /* called when entrypoint thread leaves entry loop and exits */ seL4_MessageInfo_t const reply_msg_info = new_seL4_message(snd_msg); seL4_SetMR(MR_IDX_EXC_CODE, exc.value); @@ -328,30 +363,28 @@ Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &last_caller, Msgbuf_base &reply_msg, Msgbuf_base &request_msg) { + /* allocate and define receive selector */ if (!rcv_sel()) rcv_sel() = Capability_space::alloc_rcv_sel(); + seL4_CPtr const dest = Thread::myself()->native_thread().ep_sel; seL4_Word badge = 0; - if (exc.value == Rpc_exception_code::INVALID_OBJECT) { + if (exc.value == Rpc_exception_code::INVALID_OBJECT) + reply_msg.reset(); - seL4_MessageInfo_t const request_msg_info = - seL4_Recv(Thread::myself()->native_thread().ep_sel, &badge); + request_msg.reset(); - decode_seL4_message(request_msg_info, request_msg); + /** + * Do not use Genode primitives after this point until the return which may + * alter the content of the IPCBuffer, e.g. Lock or RPC. + */ - } else { + seL4_MessageInfo_t const reply_msg_info = new_seL4_message(reply_msg); + seL4_SetMR(MR_IDX_EXC_CODE, exc.value); + seL4_MessageInfo_t const req = seL4_ReplyRecv(dest, reply_msg_info, &badge); - seL4_MessageInfo_t const reply_msg_info = new_seL4_message(reply_msg); - - seL4_SetMR(MR_IDX_EXC_CODE, exc.value); - - seL4_MessageInfo_t const request_msg_info = - seL4_ReplyRecv(Thread::myself()->native_thread().ep_sel, - reply_msg_info, &badge); - - decode_seL4_message(request_msg_info, request_msg); - } + decode_seL4_message(req, request_msg); return Rpc_request(Native_capability(), badge); }