nova: remove nova_die from receive window calc.

Issue #5443
This commit is contained in:
Alexander Boettcher 2025-02-04 15:12:53 +01:00 committed by Christian Helmuth
parent 76a4253132
commit d71ddeb983
2 changed files with 32 additions and 9 deletions

View File

@ -135,6 +135,12 @@ struct Genode::Receive_window
unsigned num_received_caps() const { return _rcv_pt_sel_max; } unsigned num_received_caps() const { return _rcv_pt_sel_max; }
enum Receive_cleanup_result {
SELECTORS_KEPT = 0,
REINIT_REQUIRED = 1,
OUT_OF_BOUNDS = 2
};
/** /**
* Return true if receive window must be re-initialized * Return true if receive window must be re-initialized
* *
@ -152,10 +158,12 @@ struct Genode::Receive_window
* because object is freed * because object is freed
* afterwards. * afterwards.
* *
* \result 'true' - receive window must be re-initialized * \result Receive_cleanup_result:
* 'false' - portal selectors has been kept * REINIT_REQUIRED - receive window must be re-initialized
* SELECTORS_KEPT - portal selectors has been kept
* OUT_OF_BOUNDS - invalid internal state which would lead to out of bounds access
*/ */
bool rcv_cleanup(bool keep, unsigned short const new_max = MAX_CAP_ARGS); Receive_cleanup_result rcv_cleanup(bool keep, uint16_t new_max = MAX_CAP_ARGS);
/** /**
* Initialize receive window for portal capability * Initialize receive window for portal capability

View File

@ -116,7 +116,8 @@ bool Receive_window::rcv_invalid() const
} }
bool Receive_window::rcv_cleanup(bool keep, unsigned short const new_max) Receive_window::Receive_cleanup_result Receive_window::rcv_cleanup(bool const keep,
uint16_t const new_max)
{ {
/* mark used mapped capabilities as used to prevent freeing */ /* mark used mapped capabilities as used to prevent freeing */
bool reinit = false; bool reinit = false;
@ -127,7 +128,7 @@ bool Receive_window::rcv_cleanup(bool keep, unsigned short const new_max)
/* should never happen */ /* should never happen */
if (_rcv_pt_sel[i].sel < _rcv_pt_base || if (_rcv_pt_sel[i].sel < _rcv_pt_base ||
(_rcv_pt_sel[i].sel >= _rcv_pt_base + MAX_CAP_ARGS)) (_rcv_pt_sel[i].sel >= _rcv_pt_base + MAX_CAP_ARGS))
nova_die(); return Receive_cleanup_result::OUT_OF_BOUNDS;
_rcv_pt_cap_free [_rcv_pt_sel[i].sel - _rcv_pt_base] = USED_CAP; _rcv_pt_cap_free [_rcv_pt_sel[i].sel - _rcv_pt_base] = USED_CAP;
@ -154,7 +155,7 @@ bool Receive_window::rcv_cleanup(bool keep, unsigned short const new_max)
cap_map().remove(_rcv_pt_base + i, 0, false); cap_map().remove(_rcv_pt_base + i, 0, false);
} }
return false; return Receive_cleanup_result::SELECTORS_KEPT;
} }
/* decrease ref count if valid selector */ /* decrease ref count if valid selector */
@ -164,7 +165,7 @@ bool Receive_window::rcv_cleanup(bool keep, unsigned short const new_max)
cap_map().remove(_rcv_pt_base + i, 0, _rcv_pt_cap_free[i] != FREE_SEL); cap_map().remove(_rcv_pt_base + i, 0, _rcv_pt_cap_free[i] != FREE_SEL);
} }
return true; return Receive_cleanup_result::REINIT_REQUIRED;
} }
@ -186,8 +187,22 @@ bool Receive_window::prepare_rcv_window(Nova::Utcb &utcb, addr_t rcv_window)
} }
/* allocate receive window if necessary, otherwise use old one */ /* allocate receive window if necessary, otherwise use old one */
if (rcv_invalid() || rcv_cleanup(true, 1U << _rcv_wnd_log2)) bool reinit_required = rcv_invalid();
{
if (!reinit_required) {
auto const rcv_result = rcv_cleanup(true, 1U << _rcv_wnd_log2);
if (rcv_result == Receive_cleanup_result::OUT_OF_BOUNDS) {
_rcv_pt_base = INVALID_INDEX;
/* no mappings can be received */
utcb.crd_rcv = Nova::Obj_crd();
return false;
}
reinit_required = rcv_result == Receive_cleanup_result::REINIT_REQUIRED;
}
if (reinit_required) {
_rcv_pt_base = cap_map().insert(_rcv_wnd_log2); _rcv_pt_base = cap_map().insert(_rcv_wnd_log2);
if (_rcv_pt_base == INVALID_INDEX) { if (_rcv_pt_base == INVALID_INDEX) {