Fix reference counting on kcov mappings.

Reported-by: syzbot+078580ce5dd6d607fcd8@syzkaller.appspotmail.com
Reported-by: syzbot+2096681f6891e7bf8aed@syzkaller.appspotmail.com
PiperOrigin-RevId: 337973519
This commit is contained in:
Dean Deng
2020-10-19 18:09:39 -07:00
committed by gVisor bot
parent 2a4ec9cf76
commit dcc1b71f1b
3 changed files with 15 additions and 12 deletions
+1 -1
View File
@@ -102,7 +102,7 @@ func (fd *kcovFD) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpts) erro
func (fd *kcovFD) Release(ctx context.Context) {
// kcov instances have reference counts in Linux, but this seems sufficient
// for our purposes.
fd.kcov.Clear()
fd.kcov.Clear(ctx)
}
// SetStat implements vfs.FileDescriptionImpl.SetStat.
+11 -8
View File
@@ -199,23 +199,25 @@ func (kcov *Kcov) DisableTrace(ctx context.Context) error {
}
kcov.mode = linux.KCOV_MODE_INIT
kcov.owningTask = nil
kcov.mappable = nil
if kcov.mappable != nil {
kcov.mappable.DecRef(ctx)
kcov.mappable = nil
}
return nil
}
// Clear resets the mode and clears the owning task and memory mapping for kcov.
// It is called when the fd corresponding to kcov is closed. Note that the mode
// needs to be set so that the next call to kcov.TaskWork() will exit early.
func (kcov *Kcov) Clear() {
func (kcov *Kcov) Clear(ctx context.Context) {
kcov.mu.Lock()
kcov.clearLocked()
kcov.mu.Unlock()
}
func (kcov *Kcov) clearLocked() {
kcov.mode = linux.KCOV_MODE_INIT
kcov.owningTask = nil
kcov.mappable = nil
if kcov.mappable != nil {
kcov.mappable.DecRef(ctx)
kcov.mappable = nil
}
kcov.mu.Unlock()
}
// OnTaskExit is called when the owning task exits. It is similar to
@@ -254,6 +256,7 @@ func (kcov *Kcov) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpts) erro
// will look different under /proc/[pid]/maps than they do on Linux.
kcov.mappable = mm.NewSpecialMappable(fmt.Sprintf("[kcov:%d]", t.ThreadID()), kcov.mfp, fr)
}
kcov.mappable.IncRef()
opts.Mappable = kcov.mappable
opts.MappingIdentity = kcov.mappable
return nil
+3 -3
View File
@@ -20,9 +20,9 @@ import (
"gvisor.dev/gvisor/pkg/safemem"
)
// countBlock provides a safemem.BlockSeq for k.count.
// countBlock provides a safemem.BlockSeq for kcov.count.
//
// Like k.count, the block returned is protected by k.mu.
func (k *Kcov) countBlock() safemem.BlockSeq {
return safemem.BlockSeqOf(safemem.BlockFromSafePointer(unsafe.Pointer(&k.count), int(unsafe.Sizeof(k.count))))
func (kcov *Kcov) countBlock() safemem.BlockSeq {
return safemem.BlockSeqOf(safemem.BlockFromSafePointer(unsafe.Pointer(&kcov.count), int(unsafe.Sizeof(kcov.count))))
}