Skip to content

Commit 973b2f2

Browse files
nixprimegvisor-bot
authored andcommitted
Check for fatal signals and reset watchdog during MM.mapASLocked().
PiperOrigin-RevId: 777697337
1 parent 0a99125 commit 973b2f2

File tree

7 files changed

+50
-18
lines changed

7 files changed

+50
-18
lines changed

pkg/context/context.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ type Blocker interface {
4343
// Interrupted notes whether this context is Interrupted.
4444
Interrupted() bool
4545

46+
// Killed returns true if this context is interrupted by a fatal signal.
47+
Killed() bool
48+
4649
// BlockOn blocks until one of the previously registered events occurs,
4750
// or some external interrupt (cancellation).
4851
//
@@ -94,6 +97,11 @@ func (nt *NoTask) Interrupted() bool {
9497
return nt.cancel != nil && len(nt.cancel) > 0
9598
}
9699

100+
// Killed implements Blocker.Killed.
101+
func (nt *NoTask) Killed() bool {
102+
return false
103+
}
104+
97105
// Block implements Blocker.Block.
98106
func (nt *NoTask) Block(C <-chan struct{}) error {
99107
if nt.cancel == nil {

pkg/sentry/kernel/task_block.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ func (t *Task) Interrupted() bool {
234234
}
235235
// Indicate that t's task goroutine is still responsive (i.e. reset the
236236
// watchdog timer).
237-
t.accountTaskGoroutineRunning()
237+
t.touchGostateTime()
238238
return false
239239
}
240240

pkg/sentry/kernel/task_exit.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,17 @@ func (t *Task) killLocked() {
100100
t.interrupt()
101101
}
102102

103+
// Killed implements context.Blocker.Killed.
104+
func (t *Task) Killed() bool {
105+
if t.killed() {
106+
return true
107+
}
108+
// Indicate that t's task goroutine is still responsive (i.e. reset the
109+
// watchdog timer).
110+
t.touchGostateTime()
111+
return false
112+
}
113+
103114
// killed returns true if t has a SIGKILL pending. killed is analogous to
104115
// Linux's fatal_signal_pending().
105116
//

pkg/sentry/kernel/task_sched.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,14 +116,6 @@ func (t *Task) accountTaskGoroutineLeave(state TaskGoroutineState) {
116116
t.gostateSeq.EndWrite()
117117
}
118118

119-
// Preconditions: The caller must be running on the task goroutine.
120-
func (t *Task) accountTaskGoroutineRunning() {
121-
if oldState := t.TaskGoroutineState(); oldState != TaskGoroutineRunningSys {
122-
panic(fmt.Sprintf("Task goroutine in state %v (expected %v)", oldState, TaskGoroutineRunningSys))
123-
}
124-
t.touchGostateTime()
125-
}
126-
127119
// Preconditions: The caller must be running on the task goroutine.
128120
func (t *Task) touchGostateTime() {
129121
t.gostateTime.Store(t.k.cpuClock.Load())

pkg/sentry/mm/address_space.go

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"fmt"
1919

2020
"gvisor.dev/gvisor/pkg/context"
21+
"gvisor.dev/gvisor/pkg/errors/linuxerr"
2122
"gvisor.dev/gvisor/pkg/hostarch"
2223
"gvisor.dev/gvisor/pkg/sentry/memmap"
2324
"gvisor.dev/gvisor/pkg/sentry/pgalloc"
@@ -172,7 +173,7 @@ func (mm *MemoryManager) Deactivate() {
172173
// - ar.Length() != 0.
173174
// - ar must be page-aligned.
174175
// - pseg == mm.pmas.LowerBoundSegment(ar.Start).
175-
func (mm *MemoryManager) mapASLocked(pseg pmaIterator, ar hostarch.AddrRange, platformEffect memmap.MMapPlatformEffect) error {
176+
func (mm *MemoryManager) mapASLocked(ctx context.Context, pseg pmaIterator, ar hostarch.AddrRange, platformEffect memmap.MMapPlatformEffect) error {
176177
// By default, map entire pmas at a time, under the assumption that there
177178
// is no cost to mapping more of a pma than necessary.
178179
mapAR := hostarch.AddrRange{0, ^hostarch.Addr(hostarch.PageSize - 1)}
@@ -217,8 +218,28 @@ func (mm *MemoryManager) mapASLocked(pseg pmaIterator, ar hostarch.AddrRange, pl
217218
perms.Write = false
218219
}
219220
if perms.Any() { // MapFile precondition
220-
if err := mm.as.MapFile(pmaMapAR.Start, pma.file, pseg.fileRangeOf(pmaMapAR), perms, platformEffect == memmap.PlatformEffectCommit); err != nil {
221-
return err
221+
// If the length of the mapping exceeds singleMapThreshold, call
222+
// AddressSpace.MapFile() on singleMapThreshold-aligned chunks so
223+
// we can check ctx.Killed() reasonably frequently.
224+
const singleMapThreshold = 1 << 30
225+
if pmaMapAR.Length() <= singleMapThreshold {
226+
if err := mm.as.MapFile(pmaMapAR.Start, pma.file, pseg.fileRangeOf(pmaMapAR), perms, platformEffect == memmap.PlatformEffectCommit); err != nil {
227+
return err
228+
}
229+
if ctx.Killed() {
230+
return linuxerr.EINTR
231+
}
232+
} else {
233+
for windowStart := pmaMapAR.Start &^ (singleMapThreshold - 1); windowStart < pmaMapAR.End; windowStart += singleMapThreshold {
234+
windowAR := hostarch.AddrRange{windowStart, windowStart + singleMapThreshold}
235+
thisMapAR := pmaMapAR.Intersect(windowAR)
236+
if err := mm.as.MapFile(thisMapAR.Start, pma.file, pseg.fileRangeOf(thisMapAR), perms, platformEffect == memmap.PlatformEffectCommit); err != nil {
237+
return err
238+
}
239+
if ctx.Killed() {
240+
return linuxerr.EINTR
241+
}
242+
}
222243
}
223244
}
224245
pseg = pseg.NextSegment()

pkg/sentry/mm/io.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ func (mm *MemoryManager) handleASIOFault(ctx context.Context, addr hostarch.Addr
514514
// anymore.
515515
mm.activeMu.DowngradeLock()
516516

517-
err = mm.mapASLocked(pseg, ar, memmap.PlatformEffectDefault)
517+
err = mm.mapASLocked(ctx, pseg, ar, memmap.PlatformEffectDefault)
518518
mm.activeMu.RUnlock()
519519
return translateIOError(ctx, err)
520520
}

pkg/sentry/mm/syscalls.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ func (mm *MemoryManager) HandleUserFault(ctx context.Context, addr hostarch.Addr
6666
mm.activeMu.DowngradeLock()
6767

6868
// Map the faulted page into the active AddressSpace.
69-
err = mm.mapASLocked(pseg, ar, memmap.PlatformEffectDefault)
69+
err = mm.mapASLocked(ctx, pseg, ar, memmap.PlatformEffectDefault)
7070
mm.activeMu.RUnlock()
7171
return err
7272
}
@@ -201,7 +201,7 @@ func (mm *MemoryManager) populateVMA(ctx context.Context, vseg vmaIterator, ar h
201201
// Downgrade to a read-lock on activeMu since we don't need to mutate pmas
202202
// anymore.
203203
mm.activeMu.DowngradeLock()
204-
err = mm.mapASLocked(pseg, ar, platformEffect)
204+
err = mm.mapASLocked(ctx, pseg, ar, platformEffect)
205205
mm.activeMu.RUnlock()
206206
return err
207207
}
@@ -250,7 +250,7 @@ func (mm *MemoryManager) populateVMAAndUnlock(ctx context.Context, vseg vmaItera
250250

251251
// As above, errors are silently ignored.
252252
mm.activeMu.DowngradeLock()
253-
mm.mapASLocked(pseg, ar, platformEffect)
253+
mm.mapASLocked(ctx, pseg, ar, platformEffect)
254254
mm.activeMu.RUnlock()
255255
}
256256

@@ -930,7 +930,7 @@ func (mm *MemoryManager) MLock(ctx context.Context, addr hostarch.Addr, length u
930930
mm.mappingMu.RUnlock()
931931
if mm.as != nil {
932932
mm.activeMu.DowngradeLock()
933-
err := mm.mapASLocked(mm.pmas.LowerBoundSegment(ar.Start), ar, memmap.PlatformEffectCommit)
933+
err := mm.mapASLocked(ctx, mm.pmas.LowerBoundSegment(ar.Start), ar, memmap.PlatformEffectCommit)
934934
mm.activeMu.RUnlock()
935935
if err != nil {
936936
return err
@@ -1014,7 +1014,7 @@ func (mm *MemoryManager) MLockAll(ctx context.Context, opts MLockAllOpts) error
10141014
mm.mappingMu.RUnlock()
10151015
if mm.as != nil {
10161016
mm.activeMu.DowngradeLock()
1017-
mm.mapASLocked(mm.pmas.FirstSegment(), mm.applicationAddrRange(), memmap.PlatformEffectCommit)
1017+
mm.mapASLocked(ctx, mm.pmas.FirstSegment(), mm.applicationAddrRange(), memmap.PlatformEffectCommit)
10181018
mm.activeMu.RUnlock()
10191019
} else {
10201020
mm.activeMu.Unlock()

0 commit comments

Comments
 (0)