summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDean Deng <deandeng@google.com>2020-10-19 18:07:38 -0700
committergVisor bot <gvisor-bot@google.com>2020-10-19 18:09:39 -0700
commitdcc1b71f1ba47646808f61cc86e560179c233af2 (patch)
tree3e5c56a972f7d8ea96ead15b7b8404f0a6b2a1b8
parent2a4ec9cf765608de6c11b9a68ea3a0dfea533967 (diff)
Fix reference counting on kcov mappings.
Reported-by: syzbot+078580ce5dd6d607fcd8@syzkaller.appspotmail.com Reported-by: syzbot+2096681f6891e7bf8aed@syzkaller.appspotmail.com PiperOrigin-RevId: 337973519
-rw-r--r--pkg/sentry/fsimpl/sys/kcov.go2
-rw-r--r--pkg/sentry/kernel/kcov.go19
-rw-r--r--pkg/sentry/kernel/kcov_unsafe.go6
3 files changed, 15 insertions, 12 deletions
diff --git a/pkg/sentry/fsimpl/sys/kcov.go b/pkg/sentry/fsimpl/sys/kcov.go
index 94366d429..31a361029 100644
--- a/pkg/sentry/fsimpl/sys/kcov.go
+++ b/pkg/sentry/fsimpl/sys/kcov.go
@@ -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.
diff --git a/pkg/sentry/kernel/kcov.go b/pkg/sentry/kernel/kcov.go
index 060c056df..4fcdfc541 100644
--- a/pkg/sentry/kernel/kcov.go
+++ b/pkg/sentry/kernel/kcov.go
@@ -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
diff --git a/pkg/sentry/kernel/kcov_unsafe.go b/pkg/sentry/kernel/kcov_unsafe.go
index 6f64022eb..6f8a0266b 100644
--- a/pkg/sentry/kernel/kcov_unsafe.go
+++ b/pkg/sentry/kernel/kcov_unsafe.go
@@ -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))))
}