1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- -->
<HTML>
<HEAD>
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">
<TITLE></TITLE>
<META NAME="GENERATOR" CONTENT="LibreOffice 3.5 (Linux)">
<META NAME="AUTHOR" CONTENT="Martin Corino">
<META NAME="CREATED" CONTENT="20120802;12245200">
<META NAME="CHANGEDBY" CONTENT="Martin Corino">
<META NAME="CHANGED" CONTENT="20120816;12280900">
<STYLE TYPE="text/css">
<!--
@page { margin: 0.79in }
P { margin-bottom: 0.08in }
H1 { margin-bottom: 0.08in }
H1.western { font-family: "Liberation Sans", sans-serif; font-size: 16pt }
H1.cjk { font-family: "Droid Sans Fallback"; font-size: 16pt }
H1.ctl { font-family: "Arial"; font-size: 16pt }
H2 { margin-bottom: 0.08in }
H2.western { font-family: "Liberation Sans", sans-serif; font-size: 14pt; font-style: italic }
H2.cjk { font-family: "Droid Sans Fallback"; font-size: 14pt; font-style: italic }
H2.ctl { font-size: 14pt; font-style: italic }
H3 { margin-bottom: 0.08in }
H3.western { font-family: "Liberation Sans", sans-serif; font-size: 13pt }
H3.cjk { font-family: "Droid Sans Fallback" }
PRE { margin-left: 0.49in; border-top: none; border-bottom: none; border-left: 1.05pt solid #808080; border-right: none; padding-top: 0in; padding-bottom: 0in; padding-left: 0.02in; padding-right: 0in }
PRE.cjk { font-family: "Droid Sans Fallback", monospace }
-->
</STYLE>
</HEAD>
<BODY LANG="en-US" DIR="LTR">
<DIV TYPE=HEADER>
<P STYLE="margin-bottom: 0in">Author: M.J.N. Corino Copyright <FONT FACE="Liberation Serif, serif">©</FONT><FONT FACE="Liberation Serif, serif">
2012, Remedy IT</FONT></P>
<P STYLE="margin-bottom: 0.2in"><FONT FACE="Liberation Serif, serif">Date:
November 06, 2012 The Netherlands</FONT></P>
</DIV>
<H1 CLASS="western">Monotonic timer support for ACE conditions and events</H1>
<H2 CLASS="western">Introduction</H2>
<P>This document describes how to use the changes to the ACE API
which provide support to use monotonic timers for condition and event
variables to solve the problem of system timeshift vulnerability of
the ACE Condition and Event variable timeout functionality.</P>
<H3 CLASS="western">Background</H3>
<P>ACE Condition and Event variables implement an API to wait for the
condition or event to be signalled with a maximum wait timeout value.
This timeout value must be specified as <B>absolute time</B><SPAN STYLE="font-weight: normal">
(this API spec has been derived from the POSIX threading API,
pthread, the most widely available, standardized, threading API
available) or, in the case of events, optionally as relative time
(converted to absolute time by ACE on certain platforms).</SPAN></P>
<P><SPAN STYLE="font-weight: normal">Currently ACE expects the
timeout value to be based on the system time clock through the ACE
API support for that clock (</SPAN><I><SPAN STYLE="font-weight: normal">ACE_OS::gettimeofday
()</SPAN></I><SPAN STYLE="font-weight: normal">) which is also the
default for the POSIX API (originally POSIX did not support anything
else).</SPAN></P>
<P STYLE="font-weight: normal">This dependency on the system time
clock however makes ACE Condition and Event variables vulnerable to
system clock time shifts since a change in the system clock time setting
after an absolute time value has been determined (based on the
unchanged system clock) will influence the outstanding wait
operations based on these time values.</P>
<P STYLE="font-weight: normal">The ACE implementation for the Windows
platform does not use the POSIX interface but is still potentially
vulnerable because the ACE implementation itself performs a
conversion from absolute to relative time before executing wait
operation on a Condition variable (as this is what the Win32 API
expects). Since this conversion is based on the system time clock
here also a vulnerability exists.</P>
<P STYLE="font-weight: normal">To resolve this vulnerability the
notion of MONOTONIC timer sources should be integrated into the ACE
Condition and Event support. MONOTONIC timers are timer sources which are
independent of the system time clock and will always return time
values which are correct relative to previously returned time values
(at least within the lifetime of a single running process).</P>
<P STYLE="font-weight: normal">The customer encountered this problem
while making use of the ACE_Message_Queue classes in the
implementation of their application. The enqueu/dequeue functionality
of the message queues makes heavy use of the ACE Condition variable
timed wait support. The customer also used ACE_Event derived classes
which suffer from the same vulnerability.</P>
<H3 CLASS="western">Requirements</H3>
<P STYLE="font-weight: normal">Prerequisites for the solution are:</P>
<UL>
<LI><P STYLE="font-weight: normal">maintain backward compatibility
(as for all changes made to the ACE API) and cross platform
stability (if not full support on all platforms);</P>
<LI><P STYLE="font-weight: normal">create an implementation that
allows for integration in the customers application with minimal
code changes;</P>
<LI><P STYLE="font-weight: normal">create an implementation allowing
for staged completion in the full ACE API, i.e. only change those
parts of ACE now that are essential to the solution of the customer
problem and postpone any non-essential changes without losing
library consistency and stability.</P>
</UL>
<H2 CLASS="western"><B>Solution</B></H2>
<P STYLE="font-weight: normal">The implemented solution involves
adding support for the ACE Time_Policy traits in the ACE Condition
and Event APIs and those classes directly related to the ACE Condition
and Event timed wait functionality that are used by the customer (like
ACE_Event, ACE_Message_Queue and ACE_Task). Also some classes tightly linked to
those classes have been updated.</P>
<P STYLE="font-weight: normal">The newly added monotonic time policy,
ACE_Monotonic_Time_Policy, provides support for monotonic time values
(on Windows and any POSIX platform providing the necessary support
like recent versions of Linux).</P>
<P STYLE="font-weight: normal">New (virtual) functionality in
ACE_Time_Value combined with a derived template class
(ACE_Time_Value_T<>) provide time policy awareness in time
values.</P>
<P STYLE="font-weight: normal">Using the combination of these changes
it is now possible to set up message queues that support monotonic
time values for timed wait methods in a portable way as will be shown
in the following section.</P>
<H3 CLASS="western"><BR><BR>
</H3>
<H3 CLASS="western" STYLE="page-break-before: always"><B>User Code
Changes</B></H3>
<P STYLE="font-weight: normal">The following are examples of user
code changes required to update an application to support monotonic
timed message queues.</P>
<P STYLE="font-weight: normal">Message_Queue and Task class templates
have been provided with an additional template argument to specify
the Time_Policy to use for condition variables. To use monotonic time
values the new ACE_Monotonic_Time_Policy should be used.
</P>
<P STYLE="font-weight: normal">So, where an existing application
declared a Message_Queue as:</P>
<PRE CLASS="western" STYLE="font-weight: normal">ACE_Message_Queue<ACE_MT_SYNCH> msg_queue_;</PRE><P STYLE="font-weight: normal">
<BR><BR>
</P>
<P STYLE="font-weight: normal">this would need to change to:</P>
<PRE CLASS="western" STYLE="font-weight: normal">ACE_Message_Queue<ACE_MT_SYNCH, ACE_Monotonic_Time_Policy> msg_queue_;</PRE><P STYLE="font-weight: normal">
<BR><BR>
</P>
<P STYLE="font-weight: normal">The changes for task are similar:</P>
<PRE CLASS="western" STYLE="font-weight: normal">class MyTask : public ACE_Task<ACE_MT_SYNCH>
{
…
};</PRE><P STYLE="font-weight: normal">
should change to:</P>
<PRE CLASS="western" STYLE="font-weight: normal">class MyTask : public ACE_Task<ACE_MT_SYNCH, ACE_Monotonic_Time_Policy>
{
…
};</PRE><P STYLE="font-weight: normal">
<BR><BR>
</P>
<P STYLE="font-weight: normal">To specify timeout values to these
message queues on the enqueue/dequeue operations you would have to
use time values that are Time_Policy aware. To that end a templated
derivative of ACE_Time_Value has been implemented allowing one to
declare a time value as:</P>
<PRE CLASS="western" STYLE="font-weight: normal">ACE_Time_Value_T<ACE_Monotonic_Time_Policy> timeout_;</PRE><P STYLE="font-weight: normal">
<BR><BR>
</P>
<P STYLE="font-weight: normal">The updated Message_Queue and Task
classes provide a convenience method to initialize such a time value
with the time policy based time of day as follows:</P>
<PRE CLASS="western" STYLE="font-weight: normal">ACE_Time_Value_T<ACE_Monotonic_Time_Policy>
timeout_ (msg_queue_.gettimeofday ());
<B>// or</B>
ACE_Time_Value_T<ACE_Monotonic_Time_Policy> timeout_;
timeout_ = msg_queue_.gettimeofday ();</PRE><P STYLE="font-weight: normal">
<BR><BR>
</P>
<P STYLE="font-weight: normal">The return type of this method is a
time policy specific time value as follows:</P>
<PRE CLASS="western" STYLE="font-weight: normal">tempate <ACE_SYNCH_DECL, class TIME_POLICY>
class ACE_Message_Queue : public ACE_Message_Queue_Base
{
…
ACE_Time_Value_T<TIME_POLICY> gettimeofday () const;
…
};</PRE><P STYLE="font-weight: normal">
<BR><BR>
</P>
<P STYLE="font-weight: normal">To define a wait timeout of 5 sec and
execute an enqueu operation the following would apply:</P>
<PRE CLASS="western" STYLE="font-weight: normal">...
ACE_Time_Value_T<ACE_Monotonic_Time_Policy> timeout_;
timeout_ = msg_queue_.gettimeofday ();
timeout_ += ACE_Time_Value (5,0);
msg_queue_.enqueue (msg_block, &timeout_);
…</PRE><P STYLE="font-weight: normal">
<BR><BR>
</P>
<P STYLE="font-weight: normal">Similar changes apply to the refactored ACE_Event classes. In
addition to the added support for time policies also a new base class is introduced to allow
for generic use of an Event variable after instantiation of a specific time policy based type.</P>
<PRE CLASS="western" STYLE="font-weight: normal">
…
// declare an Event variable
ACE_Event_Base &evt;
…
// initialize Event variable
ACE_Manual_Event_T<ACE_Monotonic_Time_Policy> mono_evt;
evt = mono_evt;
…
// wait 5 sec for event to be signalled
ACE_Time_Value_T<ACE_Monotonic_Time_Policy> timeout_;
timeout_ = timeout_.now ();
timeout_ += ACE_Time_Value (5,0);
evt.wait (&timeout_);
…
// OR (using relative timeout)
…
ACE_Time_Value_T<ACE_Monotonic_Time_Policy> timeout_ (5,0);
evt.wait (&timeout_, 0);
</PRE><P STYLE="font-weight: normal">
<BR><BR>
</P>
<P><B>NOTE:</B><SPAN STYLE="font-weight: normal"> To function
properly the ACE_Time_Value pointer passed to the timed wait methods
</SPAN><B>MUST</B><SPAN STYLE="font-weight: normal"> be the address
of an ACE_Time_Value_T<TIME_POLICY> instance which matches the
TIME_POLICY of the message queue or task. This is because the lower
layers now rely on the new time policy aware virtual methods of the
ACE_Time_Value classes to perform time calculations (to_relative_time
(), to_absolute_time (), now ()).<BR>Unfortunately due to backward
compatibility issues it was not possible to change the signatures of
the timed wait methods to type safe versions accepting only correct
time value instances.</SPAN></P>
<P><B>NOTE2:</B><SPAN STYLE="font-weight: normal"> Please be aware of
the differences in behaviour of the time calculation operations.</SPAN></P>
<UL>
<LI><P><I><SPAN STYLE="font-weight: normal">unary</SPAN></I><SPAN STYLE="font-style: normal"><SPAN STYLE="font-weight: normal">
calculations (-=, += ,*=, –, ++) maintain time policy awareness,
i.e. these operations always return a time policy aware time value
(ACE_Time_Value_T<> instance; which may a reference to the
time value itself);</SPAN></SPAN></P>
<LI><P><I><SPAN STYLE="font-weight: normal">binary</SPAN></I><SPAN STYLE="font-style: normal"><SPAN STYLE="font-weight: normal">
calculations (+, -, *) always return a default ACE_Time_Value
instance and thus loose time policy awareness. The basic numeric
time values contained in these instances should only be used for
comparative purposes or to update the value of a time policy based
instance like:</SPAN></SPAN></P>
</UL>
<PRE CLASS="western" STYLE="font-style: normal; font-weight: normal">ACE_Time_Value_T<ACE_Monotonic_Time_Policy> t1, t2;
… // t1 and t2 get assigned values
// calculate difference between t1 and t2
ACE_Time_Value tdiff = t2 – t1;
…
// at some point calculate new absolute time based on tdiff
ACE_Time_Value_T<ACE_Monotonic_Time_Policy> tv;
// now () returns an ACE_Time_Value representing current time according
// to the active time policy of tv
tv = tv.now () + tdiff;</PRE><P STYLE="font-style: normal; font-weight: normal">
<BR><BR>
</P>
<P STYLE="font-style: normal; font-weight: normal">More examples code
can be found in the following regression tests</P>
<UL>
<LI><P STYLE="font-style: normal; font-weight: normal">$ACE_ROOT/tests/Bug_4055_Regression</P>
<LI><P STYLE="font-style: normal; font-weight: normal">$ACE_ROOT/tests/Monotonic_Task_Test</P>
<LI><P STYLE="font-style: normal; font-weight: normal">$ACE_ROOT/tests/Monotonic_Message_Queue_Test</P>
<LI><P STYLE="font-style: normal; font-weight: normal">$ACE_ROOT/tests/Monotonic_Manual_Event_Test</P>
</UL>
<DIV TYPE=FOOTER>
<P STYLE="margin-top: 0.2in; margin-bottom: 0in"><BR>
</P>
</DIV>
</BODY>
</HTML>
|