diff --git a/kernel/fiasco/src/kern/arm/thread-arm.cpp b/kernel/fiasco/src/kern/arm/thread-arm.cpp index 4127551e..13041c49 100644 --- a/kernel/fiasco/src/kern/arm/thread-arm.cpp +++ b/kernel/fiasco/src/kern/arm/thread-arm.cpp @@ -505,7 +505,17 @@ Thread::copy_utcb_to_ts(L4_msg_tag const &tag, Thread *snd, Thread *rcv, } else { - Mem::memcpy_mwords (ts, snd_utcb->values, s > 19 ? 19 : s); + /* + * copy R0..R12,SP,LR,PC,PSR (UTCB Mwords 3..15,16,17,19,20) + * don't allow to overwrite pf_address, error_code, tpidruro, km_lr + * (these might have changed in the kernel without the Genode exception + * handler knowing about it, so it could try to restore outdated values) + */ + Mem::memcpy_mwords (&ts->r[0], &snd_utcb->values[3], s > 15 ? 13 : s); + if (EXPECT_TRUE(s > 16)) + ts->usp = snd_utcb->values[16]; + if (EXPECT_TRUE(s > 17)) + ts->ulr = snd_utcb->values[17]; if (EXPECT_TRUE(s > 19)) ts->pc = snd_utcb->values[19]; if (EXPECT_TRUE(s > 20)) diff --git a/kernel/fiasco/src/kern/ia32/32/thread-ia32-32.cpp b/kernel/fiasco/src/kern/ia32/32/thread-ia32-32.cpp index 60112269..4fe71213 100644 --- a/kernel/fiasco/src/kern/ia32/32/thread-ia32-32.cpp +++ b/kernel/fiasco/src/kern/ia32/32/thread-ia32-32.cpp @@ -79,6 +79,7 @@ Thread::copy_utcb_to_ts(L4_msg_tag const &tag, Thread *snd, Thread *rcv, Trap_state *ts = (Trap_state*)rcv->_utcb_handler; Mword s = tag.words(); Unsigned32 cs = ts->cs(); + Unsigned32 eflags_tf = ts->flags() & EFLAGS_TF; Utcb *snd_utcb = snd->utcb().access(); // XXX: check that gs and fs point to valid user_entry only, for gdt and @@ -110,6 +111,13 @@ Thread::copy_utcb_to_ts(L4_msg_tag const &tag, Thread *snd, Thread *rcv, // don't allow to overwrite the code selector! ts->cs(cs); + /* + * don't allow to overwrite the single-step flag + * (it might have changed in the kernel without the Genode exception handler + * knowing about it, so it could try to restore an outdated value) + */ + ts->flags((ts->flags() & ~EFLAGS_TF) | eflags_tf); + bool ret = transfer_msg_items(tag, snd, snd_utcb, rcv, rcv->utcb().access(), rights);