hw: sanitize kernel's signal datastructures

* Move all Kernel::Signal_* structures to kernel/signal.*
* Remove return value of kill_signal_context, which wasn't evaluated
* Remove Kernel::Signal_context::can_kill
* Remove Kernel::Signal_context::can_submit
* Remove Kernel::Signal_receiver::can_add_handler
* Turn nullptr into cxx nullptr instead of just zero
* Turn boolean values into true/false instead of one/zero
* Always add to signal FIFO also if submit counter
  cannot get increased enough

Fix genodelabs/genode#5416
This commit is contained in:
Stefan Kalkowski
2025-01-10 21:17:19 +01:00
committed by Christian Helmuth
parent 2728853005
commit 0d648eae62
10 changed files with 41 additions and 115 deletions

View File

@ -382,13 +382,10 @@ namespace Kernel {
* Halt processing of a signal context synchronously * Halt processing of a signal context synchronously
* *
* \param context capability ID of the targeted signal context * \param context capability ID of the targeted signal context
*
* \retval 0 suceeded
* \retval -1 failed
*/ */
inline int kill_signal_context(capid_t const context) inline void kill_signal_context(capid_t const context)
{ {
return (int)call(call_id_kill_signal_context(), context); call(call_id_kill_signal_context(), context);
} }
/** /**

View File

@ -54,7 +54,7 @@ SRC_CC += kernel/ipc_node.cc
SRC_CC += kernel/irq.cc SRC_CC += kernel/irq.cc
SRC_CC += kernel/main.cc SRC_CC += kernel/main.cc
SRC_CC += kernel/object.cc SRC_CC += kernel/object.cc
SRC_CC += kernel/signal_receiver.cc SRC_CC += kernel/signal.cc
SRC_CC += kernel/thread.cc SRC_CC += kernel/thread.cc
SRC_CC += kernel/timer.cc SRC_CC += kernel/timer.cc
SRC_CC += capability.cc SRC_CC += capability.cc

View File

@ -20,7 +20,7 @@
#include <util/avl_tree.h> #include <util/avl_tree.h>
/* core includes */ /* core includes */
#include <kernel/signal_receiver.h> #include <kernel/signal.h>
namespace Board { namespace Board {
@ -161,9 +161,7 @@ class Kernel::User_irq : public Kernel::Irq
*/ */
void occurred() override void occurred() override
{ {
if (_context.can_submit(1)) { _context.submit(1);
_context.submit(1);
}
disable(); disable();
} }

View File

@ -1,18 +1,19 @@
/* /*
* \brief Kernel backend for asynchronous inter-process communication * \brief Kernel backend for asynchronous inter-process communication
* \author Martin Stein * \author Martin Stein
* \author Stefan Kalkowski
* \date 2012-11-30 * \date 2012-11-30
*/ */
/* /*
* Copyright (C) 2012-2019 Genode Labs GmbH * Copyright (C) 2012-2025 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3. * under the terms of the GNU Affero General Public License version 3.
*/ */
/* core includes */ /* core includes */
#include <kernel/signal_receiver.h> #include <kernel/signal.h>
#include <kernel/thread.h> #include <kernel/thread.h>
using namespace Kernel; using namespace Kernel;
@ -26,7 +27,7 @@ void Signal_handler::cancel_waiting()
{ {
if (_receiver) { if (_receiver) {
_receiver->_handler_cancelled(*this); _receiver->_handler_cancelled(*this);
_receiver = 0; _receiver = nullptr;
} }
} }
@ -71,28 +72,20 @@ void Signal_context::_deliverable()
void Signal_context::_delivered() void Signal_context::_delivered()
{ {
_submits = 0; _submits = 0;
_ack = 0; _ack = false;
} }
void Signal_context::_killer_cancelled() { _killer = 0; } void Signal_context::_killer_cancelled() { _killer = nullptr; }
bool Signal_context::can_submit(unsigned const n) const
{
if (_killed || _submits >= (unsigned)~0 - n)
return false;
return true;
}
void Signal_context::submit(unsigned const n) void Signal_context::submit(unsigned const n)
{ {
if (_killed || _submits >= (unsigned)~0 - n) if (_killed)
return; return;
_submits += n; if (_submits < ((unsigned)~0 - n))
_submits += n;
if (_ack) if (_ack)
_deliverable(); _deliverable();
@ -105,32 +98,19 @@ void Signal_context::ack()
return; return;
if (!_killed) { if (!_killed) {
_ack = 1; _ack = true;
_deliverable(); _deliverable();
return; return;
} }
if (_killer) { if (_killer) {
_killer->_context = 0; _killer->_context = nullptr;
_killer->_thread.signal_context_kill_done(); _killer->_thread.signal_context_kill_done();
_killer = 0; _killer = nullptr;
} }
} }
bool Signal_context::can_kill() const
{
/* check if in a kill operation or already killed */
if (_killed) {
if (_ack)
return true;
return false;
}
return true;
}
void Signal_context::kill(Signal_context_killer &k) void Signal_context::kill(Signal_context_killer &k)
{ {
/* check if in a kill operation or already killed */ /* check if in a kill operation or already killed */
@ -139,13 +119,13 @@ void Signal_context::kill(Signal_context_killer &k)
/* kill directly if there is no unacknowledged delivery */ /* kill directly if there is no unacknowledged delivery */
if (_ack) { if (_ack) {
_killed = 1; _killed = true;
return; return;
} }
/* wait for delivery acknowledgement */ /* wait for delivery acknowledgement */
_killer = &k; _killer = &k;
_killed = 1; _killed = true;
_killer->_context = this; _killer->_context = this;
_killer->_thread.signal_context_kill_pending(); _killer->_thread.signal_context_kill_pending();
} }
@ -231,24 +211,17 @@ void Signal_receiver::_add_context(Signal_context &c) {
_contexts.enqueue(c._contexts_fe); } _contexts.enqueue(c._contexts_fe); }
bool Signal_receiver::can_add_handler(Signal_handler const &h) const
bool Signal_receiver::add_handler(Signal_handler &h)
{ {
if (h._receiver) if (h._receiver)
return false; return false;
return true;
}
void Signal_receiver::add_handler(Signal_handler &h)
{
if (h._receiver)
return;
_handlers.enqueue(h._handlers_fe); _handlers.enqueue(h._handlers_fe);
h._receiver = this; h._receiver = this;
h._thread.signal_wait_for_signal(); h._thread.signal_wait_for_signal();
_listen(); _listen();
return true;
} }

View File

@ -1,18 +1,19 @@
/* /*
* \brief Kernel backend for asynchronous inter-process communication * \brief Kernel backend for asynchronous inter-process communication
* \author Martin Stein * \author Martin Stein
* \author Stefan Kalkowski
* \date 2012-11-30 * \date 2012-11-30
*/ */
/* /*
* Copyright (C) 2012-2017 Genode Labs GmbH * Copyright (C) 2012-2025 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3. * under the terms of the GNU Affero General Public License version 3.
*/ */
#ifndef _CORE__KERNEL__SIGNAL_RECEIVER_H_ #ifndef _CORE__KERNEL__SIGNAL_H_
#define _CORE__KERNEL__SIGNAL_RECEIVER_H_ #define _CORE__KERNEL__SIGNAL_H_
/* Genode includes */ /* Genode includes */
#include <base/signal.h> #include <base/signal.h>
@ -165,11 +166,7 @@ class Kernel::Signal_context
* Submit the signal * Submit the signal
* *
* \param n number of submits * \param n number of submits
*
* \retval 0 succeeded
* \retval -1 failed
*/ */
bool can_submit(unsigned const n) const;
void submit(unsigned const n); void submit(unsigned const n);
/** /**
@ -180,12 +177,8 @@ class Kernel::Signal_context
/** /**
* Destruct context or prepare to do it as soon as delivery is done * Destruct context or prepare to do it as soon as delivery is done
* *
* \param killer object that shall receive progress reports * \param k object that shall receive progress reports
*
* \retval 0 succeeded
* \retval -1 failed
*/ */
bool can_kill() const;
void kill(Signal_context_killer &k); void kill(Signal_context_killer &k);
/** /**
@ -270,8 +263,7 @@ class Kernel::Signal_receiver
* \retval 0 succeeded * \retval 0 succeeded
* \retval -1 failed * \retval -1 failed
*/ */
bool can_add_handler(Signal_handler const &h) const; bool add_handler(Signal_handler &h);
void add_handler(Signal_handler &h);
/** /**
* Syscall to create a signal receiver * Syscall to create a signal receiver

View File

@ -522,11 +522,8 @@ void Thread::timeout_triggered()
{ {
Signal_context * const c = Signal_context * const c =
pd().cap_tree().find<Signal_context>(_timeout_sigid); pd().cap_tree().find<Signal_context>(_timeout_sigid);
if (!c || !c->can_submit(1)) { if (c) c->submit(1);
Genode::raw(*this, ": failed to submit timeout signal"); else Genode::warning(*this, ": failed to submit timeout signal");
return;
}
c->submit(1);
} }
@ -602,12 +599,11 @@ void Thread::_call_await_signal()
return; return;
} }
/* register handler at the receiver */ /* register handler at the receiver */
if (!r->can_add_handler(_signal_handler)) { if (!r->add_handler(_signal_handler)) {
Genode::raw("failed to register handler at signal receiver"); Genode::raw("failed to register handler at signal receiver");
user_arg_0(-1); user_arg_0(-1);
return; return;
} }
r->add_handler(_signal_handler);
user_arg_0(0); user_arg_0(0);
} }
@ -624,11 +620,10 @@ void Thread::_call_pending_signal()
} }
/* register handler at the receiver */ /* register handler at the receiver */
if (!r->can_add_handler(_signal_handler)) { if (!r->add_handler(_signal_handler)) {
user_arg_0(-1); user_arg_0(-1);
return; return;
} }
r->add_handler(_signal_handler);
if (_state == AWAITS_SIGNAL) { if (_state == AWAITS_SIGNAL) {
_cancel_blocking(); _cancel_blocking();
@ -663,20 +658,7 @@ void Thread::_call_submit_signal()
{ {
/* lookup signal context */ /* lookup signal context */
Signal_context * const c = pd().cap_tree().find<Signal_context>((Kernel::capid_t)user_arg_1()); Signal_context * const c = pd().cap_tree().find<Signal_context>((Kernel::capid_t)user_arg_1());
if(!c) { if(c) c->submit((unsigned)user_arg_2());
/* cannot submit unknown signal context */
user_arg_0(-1);
return;
}
/* trigger signal context */
if (!c->can_submit((unsigned)user_arg_2())) {
Genode::raw("failed to submit signal context");
user_arg_0(-1);
return;
}
c->submit((unsigned)user_arg_2());
user_arg_0(0);
} }
@ -684,13 +666,8 @@ void Thread::_call_ack_signal()
{ {
/* lookup signal context */ /* lookup signal context */
Signal_context * const c = pd().cap_tree().find<Signal_context>((Kernel::capid_t)user_arg_1()); Signal_context * const c = pd().cap_tree().find<Signal_context>((Kernel::capid_t)user_arg_1());
if (!c) { if (c) c->ack();
Genode::raw(*this, ": cannot ack unknown signal context"); else Genode::warning(*this, ": cannot ack unknown signal context");
return;
}
/* acknowledge */
c->ack();
} }
@ -698,19 +675,8 @@ void Thread::_call_kill_signal_context()
{ {
/* lookup signal context */ /* lookup signal context */
Signal_context * const c = pd().cap_tree().find<Signal_context>((Kernel::capid_t)user_arg_1()); Signal_context * const c = pd().cap_tree().find<Signal_context>((Kernel::capid_t)user_arg_1());
if (!c) { if (c) c->kill(_signal_context_killer);
Genode::raw(*this, ": cannot kill unknown signal context"); else Genode::warning(*this, ": cannot kill unknown signal context");
user_arg_0(-1);
return;
}
/* kill signal context */
if (!c->can_kill()) {
Genode::raw("failed to kill signal context");
user_arg_0(-1);
return;
}
c->kill(_signal_context_killer);
} }

View File

@ -20,7 +20,7 @@
/* base-hw core includes */ /* base-hw core includes */
#include <kernel/cpu_context.h> #include <kernel/cpu_context.h>
#include <kernel/inter_processor_work.h> #include <kernel/inter_processor_work.h>
#include <kernel/signal_receiver.h> #include <kernel/signal.h>
#include <kernel/ipc_node.h> #include <kernel/ipc_node.h>
#include <object.h> #include <object.h>
#include <kernel/interface.h> #include <kernel/interface.h>

View File

@ -18,7 +18,7 @@
/* core includes */ /* core includes */
#include <kernel/cpu_context.h> #include <kernel/cpu_context.h>
#include <kernel/pd.h> #include <kernel/pd.h>
#include <kernel/signal_receiver.h> #include <kernel/signal.h>
#include <board.h> #include <board.h>

View File

@ -22,7 +22,7 @@
#include <pager/capability.h> #include <pager/capability.h>
/* core includes */ /* core includes */
#include <kernel/signal_receiver.h> #include <kernel/signal.h>
#include <hw/mapping.h> #include <hw/mapping.h>
#include <mapping.h> #include <mapping.h>
#include <object.h> #include <object.h>

View File

@ -19,7 +19,7 @@
/* core includes */ /* core includes */
#include <object.h> #include <object.h>
#include <kernel/signal_receiver.h> #include <kernel/signal.h>
#include <assertion.h> #include <assertion.h>
namespace Core { namespace Core {