REALTIMEKIT Realtime Policy and Watchdog Daemon
GIT:
git://git.0pointer.de/rtkit.git
GITWEB:
http://git.0pointer.de/?p=rtkit.git
NOTES:
RealtimeKit is a D-Bus system service that changes the
scheduling policy of user processes/threads to SCHED_RR
(i.e. realtime scheduling mode) on request. It is intended to
be used as a secure mechanism to allow real-time scheduling to
be used by normal user processes.
RealtimeKit enforces strict policies when handing out
real-time security to user threads:
* Only clients with RLIMIT_RTTIME set will get RT scheduling
* RT scheduling will only be handed out to processes with
SCHED_RESET_ON_FORK set to guarantee that the scheduling
settings cannot 'leak' to child processes, thus making sure
that 'RT fork bombs' cannot be used to bypass RLIMIT_RTTIME
and take the system down.
* Limits are enforced on all user controllable resources, only
a maximum number of users, processes, threads can request RT
scheduling at the same time.
* Only a limited number of threads may be made RT in a
specific time frame.
* Client authorization is verified with PolicyKit
RealtimeKit can also be used to hand outh high priority
scheduling (i.e. negative nice level) to user processes.
In addition to this a-priori policy enforcement, RealtimeKit
also provides a-posteriori policy enforcement, i.e. it
includes a canary-based watchdog that automatically demotes
all real-time threads to SCHED_OTHER should the system
overload despite the logic pointed out above. For more
information regarding canary-based RT watchdogs, see the
Acknowledgments section below.
In its duty to manage real-time scheduling *securely*
RealtimeKit runs as unpriviliged user, and uses capabalities,
resource limits and chroot() to minimize its security impact.
RealtimeKit probably has little use in embedded or server use
cases, use RLIMIT_RTPRIO tehre instead.
WHY:
If processes that have real-time scheduling privileges enter a
busy loop they can freeze the entire the system. To make sure
such run-away processes cannot do this RLIMIT_RTTIME has been
introduced. Being a per-process limit it is however easily
cirumvented by combining a fork bomb with a busy loop.
RealtimeKit hands out RT scheduling to specific threads that
ask for it -- but only to those and due to SCHED_RESET_ON_FORK
it can be sure that this won't 'leak'.
In contrast to RLIMIT_RTPRIO the RealtimeKit logic makes sure
that only a certain number of threads can be made realtime,
per user, per process and per time interval.
CLIENTS:
To be able to make use of realtime scheduling clients may
request so with a small D-Bus interface that is accessible on
the interface org.freedesktop.RealtimeKit1 as object
/org/freedesktop/RealtimeKit1 on the service
org.freedesktop.RealtimeKit1:
void MakeThreadRealtime(u64 thread_id, u32 priority);
void MakeThreadHighPriority(u64 thread_id, s32 priority);
The thread IDs need to be passed as kernel tids as returned by
gettid(), not a pthread_t! Only threads belonging to the
calling process can be made realtime/high priority. (Please
note that gettid() is not available in glibc, you need to
implement that manually using syscall(). Consult the reference
client implementation for details.)
A BSD-licensed reference implementation of the client is
available in rtkit.[ch] as part of the package. You may copy
this into your sources if you wish. However given how simple
the D-Bus interface is you might choose to implement your own
client implementation.
It is advisable to try acquiring realtime scheduling with
sched_setsheduler() first, so that systems where RLIMIT_RTPRIO
is set can be supported.
Here's an example using the reference implementation. Replace
this:
<snip>
struct sched_param p;
memset(&p, 0, sizeof(p));
p.sched_priority = 3;
sched_setscheduler(0, SCHED_RR|SCHED_RESET_ON_FORK, &p);
</snip>
by this:
<snip>
struct sched_param p;
memset(&p, 0, sizeof(p));
p.sched_priority = 3;
if (sched_setscheduler(0, SCHED_RR|SCHED_RESET_ON_FORK, &p) < 0
&& errno == EPERM)
rtkit_make_realtime(system_bus, 0, p.sched_priority);
</snip>
But of course add more appropriate error checking! Also,
falling back to plain SCHED_RR when SCHED_RESET_ON_FORK causes
EINVAL migt be advisable).
DAEMON:
The daemon is automatically started on first use via D-Bus
system bus activation.
Currently the daemon does not read on any configuration file,
however it can be configured with command line parameters. You
can edit
/usr/share/dbus-1/system-services/org.freedesktop.RealtimeKit1.service
to set those.
Run
/usr/libexec/rtkit-daemon --help
to get a quick overview on the supported parameters and their
defaults. Many of them should be obvious in their meaning. For
the remaining ones see below:
--max-realtime-priority= may be used to specify the maximum
realtime priority a client can acquire through
RealtimeKit. Please note that this value must be smaller than
the value passed to --our-realtime-priority=.
--our-realtime-priority= may be used to specify the realtime
priority of the daemon itself. Please note that this priority
is only used for a very short time while processing a client
request. Normally the daemon will not be running with a
realtime scheduling policy. The real-time priorities handed
out to the user must be lower than this value. (see above).
--min-nice-level= may be used to specify the minimum nice
level a client can acquire through RealtimeKit.
--our-nice-level= may be used to specify the nice level the
the daemon itself uses most of the time (except when
processing requests, see above). It is probably a good idea to
set this to a small positive value, to make sure that if the
system is overloaded already handing out further RT scheduling
will be delayed a bit.
--rttime-usec-max= may be used to control which RLIMIT_RTTIME
value clients need to have chosen at minumum before they may
acquire RT scheduling through RealtimeKit.
--users-max= specifies how many users may acquire RT
scheduling at the same time for one or multiple of their
processes.
--processes-per-user-max= specifies how many processes per
user may acquire RT scheduling at the same time.
--threads-per-user-max= specifies how many threads per user
may acquire RT scheduling at the same time. Of course this
value should be set higher than --process-per-user-max=.
--actions-burst-sec= may be used to influence the rate
limiting logic in RealtimeKit. The daemon will only pass
realtime scheduling privileges to a maximum number of threads
within this timeframe (see below).
--actions-per-burst-max= may be used to influence the rate
limiting logic in RealtimeKit. The daemon will only pass
realtime scheduling privileges to this number of threads
within the time frame configured via
--actions-burst-sec=. When this limit is reached clients need
to wait until that time passes before requesting RT scheduling
again.
--canary-cheep-msec= may be used to control how often the
canary thread shall cheep.
--canary-watchdog-msec= may be used to control how quickly the
watchdog thread expects to receive a cheep from the canary
thread. This value must be chosen larger than
--canary-cheep-msec=. If the former is set 10s and the latter
to 7s, then the canary thread can trigger and deliver the
cheep with a maximum latency of 3s.
ACKNOWLEDGMENTS:
The canary watchdog logic is inspired by previous work of
Vernon Mauery, Florian Schmidt, Kjetil Matheussen:
http://rt.wiki.kernel.org/index.php/RT_Watchdog
LICENSE:
GPLv3+ for the daemon
BSD for the client reference implementation
AUTHOR:
Lennart Poettering
REQUIREMENTS:
Linux kernel >= 2.6.31
D-Bus
PolicyKit >= 0.92
Mr. DellatioNx196 GaLers xh3LL Backd00r 1.0, Coded By Mr. DellatioNx196 - Bogor BlackHat