summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/kernel/task_run.go
diff options
context:
space:
mode:
authorDean Deng <deandeng@google.com>2020-07-23 16:22:41 -0700
committergVisor bot <gvisor-bot@google.com>2020-07-23 16:25:34 -0700
commit8fed97794edcbaa7069dbd39604030e4fbb6891c (patch)
tree2bfacd76be57fd91a279f256c35c73ba640db164 /pkg/sentry/kernel/task_run.go
parent3a2fac0ab9e24382c8e19e6cf8170ba01e78930c (diff)
Add task work mechanism.
Like task_work in Linux, this allows us to register callbacks to be executed before returning to userspace. This is needed for kcov support, which requires coverage information to be up-to-date whenever we are in user mode. We will provide coverage data through the kcov interface to enable coverage-directed fuzzing in syzkaller. One difference from Linux is that task work cannot queue work before the transition to userspace that it precedes; queued work will be picked up before the next transition. PiperOrigin-RevId: 322889984
Diffstat (limited to 'pkg/sentry/kernel/task_run.go')
-rw-r--r--pkg/sentry/kernel/task_run.go17
1 files changed, 16 insertions, 1 deletions
diff --git a/pkg/sentry/kernel/task_run.go b/pkg/sentry/kernel/task_run.go
index d654dd997..7d4f44caf 100644
--- a/pkg/sentry/kernel/task_run.go
+++ b/pkg/sentry/kernel/task_run.go
@@ -167,7 +167,22 @@ func (app *runApp) execute(t *Task) taskRunState {
return (*runInterrupt)(nil)
}
- // We're about to switch to the application again. If there's still a
+ // Execute any task work callbacks before returning to user space.
+ if atomic.LoadInt32(&t.taskWorkCount) > 0 {
+ t.taskWorkMu.Lock()
+ queue := t.taskWork
+ t.taskWork = nil
+ atomic.StoreInt32(&t.taskWorkCount, 0)
+ t.taskWorkMu.Unlock()
+
+ // Do not hold taskWorkMu while executing task work, which may register
+ // more work.
+ for _, work := range queue {
+ work.TaskWork(t)
+ }
+ }
+
+ // We're about to switch to the application again. If there's still an
// unhandled SyscallRestartErrno that wasn't translated to an EINTR,
// restart the syscall that was interrupted. If there's a saved signal
// mask, restore it. (Note that restoring the saved signal mask may unblock