@@ -278,9 +278,9 @@ void IoContext::IncomingRequest::delivered(kj::SourceLocation location) {
278278 }
279279}
280280
281- kj::Date IoContext::IncomingRequest::now () {
281+ kj::Date IoContext::IncomingRequest::now (kj::Maybe<kj::Date> nextTimeout ) {
282282 metrics->clockRead ();
283- return ioChannelFactory->getTimer ().now ();
283+ return ioChannelFactory->getTimer ().now (kj::mv (nextTimeout) );
284284}
285285
286286IoContext::IncomingRequest::~IoContext_IncomingRequest () noexcept (false ) {
@@ -730,8 +730,7 @@ void IoContext::TimeoutManagerImpl::setTimeoutImpl(IoContext& context, Iterator
730730
731731 auto paf = kj::newPromiseAndFulfiller<void >();
732732
733- // Always schedule the timeout relative to what Date.now() currently returns, so that the delay
734- // appear exact. Otherwise, the delay could reveal non-determinism containing side channels.
733+ // Schedule relative to Date.now() so the delay appears exact to the application.
735734 auto when = context.now () + state.params .msDelay * kj::MILLISECONDS;
736735 // TODO(cleanup): The manual use of run() here (including carrying over the critical section) is
737736 // kind of ugly, but using awaitIo() doesn't work here because we need the ability to cancel
@@ -892,17 +891,9 @@ kj::Date IoContext::now(IncomingRequest& incomingRequest) {
892891 return kj::UNIX_EPOCH + roundedMs * kj::MILLISECONDS;
893892 }
894893
895- kj::Date adjustedTime = incomingRequest.now ();
896-
897- KJ_IF_SOME (maybeNextTimeout, timeoutManager->getNextTimeout ()) {
898- // Don't return a time beyond when the next setTimeout() callback is intended to run. This
899- // ensures that Date.now() inside the callback itself always returns exactly the time at which
900- // the callback was scheduled (hiding non-determinism which could contain side channels), and
901- // that the time returned by Date.now() never goes backwards.
902- return kj::min (adjustedTime, maybeNextTimeout);
903- } else {
904- return adjustedTime;
905- }
894+ // Let TimerChannel decide whether to clamp to the next timeout time. This is how Spectre
895+ // mitigations ensure Date.now() inside a callback returns exactly the scheduled time.
896+ return incomingRequest.now (timeoutManager->getNextTimeout ());
906897}
907898
908899kj::Date IoContext::now () {
0 commit comments