mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 08:25:38 +00:00
core: prevent transfer of static PD session quota
This patch makes sure that the initial PD session limit (as defined by the client-provided session quota) is preserved over the entire lifetime of the PD session. That means, it cannot be transferred to other PD sessions. Otherwise, it may be impossive to hand back all the static session quota to the PD-session client at session-destruction time because parts of the initial quota would no longer belong to the session. Note that the initial limit can still be used for allocations within the PD session as those allocations are automatically reverted at session-destruction time.
This commit is contained in:
parent
238df4dd58
commit
f278024e44
@ -30,7 +30,25 @@ class Genode::Account
|
||||
|
||||
Session::Label const &_label;
|
||||
|
||||
UNIT const _initial_used = _quota_guard.used();
|
||||
UNIT const _initial_used = _quota_guard.used();
|
||||
|
||||
/*
|
||||
* The initial limit corresponds to the static session quota donated
|
||||
* by the client at the session-creation time. During the lifetime
|
||||
* of the session, the account's limit must never become lower than
|
||||
* the initial limit (e.g., via transfer_quota) to allow the initial
|
||||
* limit to be transferred back to the client at session-destruction
|
||||
* time.
|
||||
*/
|
||||
UNIT const _initial_limit;
|
||||
|
||||
/**
|
||||
* Return maximum amount of transferrable quota
|
||||
*/
|
||||
UNIT const _transferrable_quota() const
|
||||
{
|
||||
return UNIT { _quota_guard.limit().value - _initial_limit.value };
|
||||
}
|
||||
|
||||
Lock mutable _lock;
|
||||
|
||||
@ -71,13 +89,18 @@ class Genode::Account
|
||||
*/
|
||||
Account(Quota_guard<UNIT> "a_guard, Session_label const &label,
|
||||
Account &ref_account)
|
||||
: _quota_guard(quota_guard), _label(label) { ref_account._adopt(*this); }
|
||||
:
|
||||
_quota_guard(quota_guard), _label(label),
|
||||
_initial_limit(_quota_guard.limit())
|
||||
{
|
||||
ref_account._adopt(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used for creating the initial account
|
||||
*/
|
||||
Account(Quota_guard<UNIT> "a_guard, Session_label const &label)
|
||||
: _quota_guard(quota_guard), _label(label) { }
|
||||
: _quota_guard(quota_guard), _label(label), _initial_limit(UNIT{0}) { }
|
||||
|
||||
~Account()
|
||||
{
|
||||
@ -91,7 +114,10 @@ class Genode::Account
|
||||
}
|
||||
|
||||
/* transfer remaining quota to our reference account */
|
||||
_ref_account->_quota_guard.upgrade(_quota_guard.limit());
|
||||
UNIT const downgrade = _transferrable_quota();
|
||||
_ref_account->_quota_guard.upgrade(downgrade);
|
||||
if (!_quota_guard.try_downgrade(downgrade))
|
||||
error(_label, ": final quota downgrade unexpectedly failed");
|
||||
|
||||
/* assign all sub accounts to our reference account */
|
||||
_ref_account_members.for_each([&] (Account &orphan) {
|
||||
@ -113,6 +139,12 @@ class Genode::Account
|
||||
if (_ref_account != &other && other._ref_account != this)
|
||||
throw Unrelated_account();
|
||||
|
||||
/* make sure to stay within the initial limit */
|
||||
if (amount.value > _transferrable_quota().value) {
|
||||
error(_label, ": attempt to transfer initial quota");
|
||||
throw Limit_exceeded();
|
||||
}
|
||||
|
||||
/* downgrade from this account */
|
||||
if (!_quota_guard.try_downgrade(amount))
|
||||
throw Limit_exceeded();
|
||||
|
Loading…
x
Reference in New Issue
Block a user