summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/kernel/task_block.go
diff options
context:
space:
mode:
authorJamie Liu <jamieliu@google.com>2020-11-13 14:46:03 -0800
committergVisor bot <gvisor-bot@google.com>2020-11-13 14:47:47 -0800
commita1cb52447f3e9414211b9e0558f1231ae3e59329 (patch)
treeb1618b3e2507f0ec6d2461c1a0ba92d140d4e0a4 /pkg/sentry/kernel/task_block.go
parent89517eca414a311598aa6e64a229c7acc5e3a22f (diff)
Check for misuse of kernel.Task as context.Context.
Checks in Task.block() and Task.Value() are conditional on race detection being enabled, since these functions are relatively hot. Checks in Task.SleepStart() and Task.UninterruptibleSleepStart() are enabled unconditionally, since these functions are not thought to lie on any critical paths, and misuse of these functions is required for b/168241471 to manifest. PiperOrigin-RevId: 342342175
Diffstat (limited to 'pkg/sentry/kernel/task_block.go')
-rw-r--r--pkg/sentry/kernel/task_block.go16
1 files changed, 14 insertions, 2 deletions
diff --git a/pkg/sentry/kernel/task_block.go b/pkg/sentry/kernel/task_block.go
index 4a4a69ee2..147a3d286 100644
--- a/pkg/sentry/kernel/task_block.go
+++ b/pkg/sentry/kernel/task_block.go
@@ -20,6 +20,7 @@ import (
"time"
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
+ "gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/syserror"
)
@@ -32,6 +33,8 @@ import (
//
// - An error which is nil if an event is received from C, ETIMEDOUT if the timeout
// expired, and syserror.ErrInterrupted if t is interrupted.
+//
+// Preconditions: The caller must be running on the task goroutine.
func (t *Task) BlockWithTimeout(C chan struct{}, haveTimeout bool, timeout time.Duration) (time.Duration, error) {
if !haveTimeout {
return timeout, t.block(C, nil)
@@ -112,7 +115,14 @@ func (t *Task) Block(C <-chan struct{}) error {
// block blocks a task on one of many events.
// N.B. defer is too expensive to be used here.
+//
+// Preconditions: The caller must be running on the task goroutine.
func (t *Task) block(C <-chan struct{}, timerChan <-chan struct{}) error {
+ // This function is very hot; skip this check outside of +race builds.
+ if sync.RaceEnabled {
+ t.assertTaskGoroutine()
+ }
+
// Fast path if the request is already done.
select {
case <-C:
@@ -156,14 +166,15 @@ func (t *Task) block(C <-chan struct{}, timerChan <-chan struct{}) error {
}
}
-// SleepStart implements amutex.Sleeper.SleepStart.
+// SleepStart implements context.ChannelSleeper.SleepStart.
func (t *Task) SleepStart() <-chan struct{} {
+ t.assertTaskGoroutine()
t.Deactivate()
t.accountTaskGoroutineEnter(TaskGoroutineBlockedInterruptible)
return t.interruptChan
}
-// SleepFinish implements amutex.Sleeper.SleepFinish.
+// SleepFinish implements context.ChannelSleeper.SleepFinish.
func (t *Task) SleepFinish(success bool) {
if !success {
// The interrupted notification is consumed only at the top-level
@@ -183,6 +194,7 @@ func (t *Task) Interrupted() bool {
// UninterruptibleSleepStart implements context.Context.UninterruptibleSleepStart.
func (t *Task) UninterruptibleSleepStart(deactivate bool) {
+ t.assertTaskGoroutine()
if deactivate {
t.Deactivate()
}