nova: avoid dying thread in platform.run

Avoids timely interference by dying thread.

Fixes #3670
This commit is contained in:
Alexander Boettcher 2020-02-26 16:34:47 +01:00 committed by Norman Feske
parent d452094f43
commit 97bbad5aea
2 changed files with 45 additions and 46 deletions

View File

@ -6,7 +6,7 @@
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
* Copyright (C) 2015-2020 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
@ -266,8 +266,31 @@ void test_revoke(Genode::Env &env)
}
}
static void portal_entry()
{
Genode::Thread &myself = *Genode::Thread::myself();
Nova::Utcb &utcb = *reinterpret_cast<Nova::Utcb *>(myself.utcb());
Nova::Crd const snd_crd(utcb.msg()[0]);
enum {
HOTSPOT = 0, USER_PD = false, HOST_PGT = false, SOLELY_MAP = false,
NO_DMA = false, EVILLY_DONT_WRITE_COMBINE = false
};
utcb.set_msg_word(0);
bool ok = utcb.append_item(snd_crd, HOTSPOT, USER_PD, HOST_PGT,
SOLELY_MAP, NO_DMA, EVILLY_DONT_WRITE_COMBINE);
(void)ok;
Nova::reply(myself.stack_top());
}
void test_pat(Genode::Env &env)
{
Genode::Thread &myself = *Genode::Thread::myself();
Nova::Utcb &utcb = *reinterpret_cast<Nova::Utcb *>(myself.utcb());
/* read out the tsc frequenzy once */
Attached_rom_dataspace const platform_info (env, "platform_info");
Xml_node const hardware = platform_info.xml().sub_node("hardware");
@ -283,10 +306,6 @@ void test_pat(Genode::Env &env)
static Rpc_entrypoint ep(&env.pd(), STACK_SIZE, "rpc_ep_pat");
Test::Component component;
Test::Capability session_cap = ep.manage(&component);
Test::Client client(session_cap);
Genode::Rm_connection rm(env);
Genode::Region_map_client rm_free_area(rm.create(1 << (DS_ORDER + PAGE_4K)));
addr_t remap_addr = env.rm().attach(rm_free_area.dataspace());
@ -296,36 +315,32 @@ void test_pat(Genode::Env &env)
touch_read(reinterpret_cast<unsigned char *>(map_addr));
/*
* Manipulate entrypoint
* Establish memory mapping with evilly wrong mapping attributes
*/
Nova::Rights all(true, true, true);
Genode::addr_t utcb_ep_addr_t = client.leak_utcb_address();
Nova::Utcb *utcb_ep = reinterpret_cast<Nova::Utcb *>(utcb_ep_addr_t);
/* overwrite receive window of entrypoint */
utcb_ep->crd_rcv = Nova::Mem_crd(remap_addr >> PAGE_4K, DS_ORDER, all);
Nova_native_pd_client native_pd { env.pd().native_pd() };
Thread * thread = reinterpret_cast<Genode::Thread *>(&ep);
Native_capability const thread_cap
= Capability_space::import(thread->native_thread().ec_sel);
/*
* Set-up current (client) thread to delegate write-combined memory
*/
Nova::Mem_crd snd_crd(map_addr >> PAGE_4K, DS_ORDER, all);
Untyped_capability const pt =
native_pd.alloc_rpc_cap(thread_cap, (addr_t)portal_entry, 0 /* MTD */);
Nova::Utcb *utcb = reinterpret_cast<Nova::Utcb *>(Thread::myself()->utcb());
enum {
HOTSPOT = 0, USER_PD = false, HOST_PGT = false, SOLELY_MAP = false,
NO_DMA = false, EVILLY_DONT_WRITE_COMBINE = false
};
Nova::Rights const all(true, true, true);
Nova::Mem_crd const rcv_crd(remap_addr >> PAGE_4K, DS_ORDER, all);
Nova::Mem_crd const snd_crd(map_addr >> PAGE_4K, DS_ORDER, all);
Nova::Crd const old_crd = utcb.crd_rcv;
Nova::Crd old = utcb->crd_rcv;
utcb.crd_rcv = rcv_crd;
utcb.set_msg_word(1);
utcb.msg()[0] = snd_crd.value();
utcb->set_msg_word(0);
bool ok = utcb->append_item(snd_crd, HOTSPOT, USER_PD, HOST_PGT,
SOLELY_MAP, NO_DMA, EVILLY_DONT_WRITE_COMBINE);
(void)ok;
uint8_t const res = Nova::call(pt.local_name());
utcb.crd_rcv = old_crd;
uint8_t res = Nova::call(session_cap.local_name());
(void)res;
utcb->crd_rcv = old;
if (res != Nova::NOVA_OK) {
Genode::error("establishing memory failed ", res);
failed++;
}
/* sanity check - touch re-mapped area */
for (addr_t i = remap_addr; i < remap_addr + (1 << (DS_ORDER + PAGE_4K)); i += (1 << PAGE_4K))
@ -358,11 +373,6 @@ void test_pat(Genode::Env &env)
}
Nova::revoke(Nova::Mem_crd(remap_addr >> PAGE_4K, DS_ORDER, all));
/*
* note: server entrypoint died because of unexpected receive window
* state - that is expected
*/
}
void test_server_oom(Genode::Env &env)

View File

@ -47,10 +47,7 @@ struct Test::Session : Genode::Session
void_cap);
GENODE_RPC(Rpc_cap_cap, Genode::Native_capability, cap_cap,
Genode::addr_t);
GENODE_RPC(Rpc_leak_utcb_address, Genode::addr_t, leak_utcb_address);
GENODE_RPC_INTERFACE(Rpc_cap_void, Rpc_void_cap, Rpc_cap_cap,
Rpc_leak_utcb_address);
GENODE_RPC_INTERFACE(Rpc_cap_void, Rpc_void_cap, Rpc_cap_cap);
};
struct Test::Client : Genode::Rpc_client<Session>
@ -65,9 +62,6 @@ struct Test::Client : Genode::Rpc_client<Session>
Genode::Native_capability cap_cap(Genode::addr_t cap) {
return call<Rpc_cap_cap>(cap); }
Genode::addr_t leak_utcb_address() {
return call<Rpc_leak_utcb_address>(); }
};
struct Test::Component : Genode::Rpc_object<Test::Session, Test::Component>
@ -78,8 +72,6 @@ struct Test::Component : Genode::Rpc_object<Test::Session, Test::Component>
Genode::Native_capability void_cap();
/* Test to transfer a specific object capability during reply */
Genode::Native_capability cap_cap(Genode::addr_t);
/* Leak utcb address of entrypoint to manipulate utcb receive window */
Genode::addr_t leak_utcb_address();
};
namespace Test { typedef Genode::Capability<Test::Session> Capability; }
@ -114,8 +106,5 @@ inline Genode::Native_capability Test::Component::void_cap() {
return send_cap;
}
inline Genode::addr_t Test::Component::leak_utcb_address() {
return reinterpret_cast<Genode::addr_t>(Genode::Thread::myself()->utcb()); }
inline Genode::Native_capability Test::Component::cap_cap(Genode::addr_t cap) {
return Genode::Capability_space::import(cap); }