summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAdin Scannell <ascannell@google.com>2018-08-08 21:27:58 -0700
committerShentubot <shentubot@google.com>2018-08-08 21:29:19 -0700
commitdbbe9ec91541dba387f8044cbf73fd29f604f902 (patch)
tree55a2c580a849fe41d8d83bc8c0dc773f28d4cfdb
parent2a44362c0b99c6ab800e1b0d26e4f368a5e7f9f1 (diff)
Protect PCIDs with a mutex.
Because the Drop method may be called across vCPUs, it is necessary to protect the PCID database with a mutex to prevent concurrent modification. The PCID is assigned prior to entersyscall, so it's safe to block. PiperOrigin-RevId: 207992864 Change-Id: I8b36d55106981f51e30dcf03e12886330bb79d67
-rw-r--r--pkg/sentry/platform/ring0/pagetables/pcids_x86.go14
1 files changed, 14 insertions, 0 deletions
diff --git a/pkg/sentry/platform/ring0/pagetables/pcids_x86.go b/pkg/sentry/platform/ring0/pagetables/pcids_x86.go
index 227cf7aad..fa068e35e 100644
--- a/pkg/sentry/platform/ring0/pagetables/pcids_x86.go
+++ b/pkg/sentry/platform/ring0/pagetables/pcids_x86.go
@@ -16,6 +16,10 @@
package pagetables
+import (
+ "sync"
+)
+
// limitPCID is the number of valid PCIDs.
const limitPCID = 4096
@@ -24,6 +28,9 @@ const limitPCID = 4096
// This is not protected by locks and is thus suitable for use only with a
// single CPU at a time.
type PCIDs struct {
+ // mu protects below.
+ mu sync.Mutex
+
// cache are the assigned page tables.
cache map[*PageTables]uint16
@@ -56,7 +63,9 @@ func NewPCIDs(start, size uint16) *PCIDs {
// This may overwrite any previous assignment provided. If this in the case,
// true is returned to indicate that the PCID should be flushed.
func (p *PCIDs) Assign(pt *PageTables) (uint16, bool) {
+ p.mu.Lock()
if pcid, ok := p.cache[pt]; ok {
+ p.mu.Unlock()
return pcid, false // No flush.
}
@@ -68,6 +77,7 @@ func (p *PCIDs) Assign(pt *PageTables) (uint16, bool) {
// We need to flush because while this is in the available
// pool, it may have been used previously.
+ p.mu.Unlock()
return pcid, true
}
@@ -79,17 +89,21 @@ func (p *PCIDs) Assign(pt *PageTables) (uint16, bool) {
// A flush is definitely required in this case, these page
// tables may still be active. (They will just be assigned some
// other PCID if and when they hit the given CPU again.)
+ p.mu.Unlock()
return pcid, true
}
// No PCID.
+ p.mu.Unlock()
return 0, false
}
// Drop drops references to a set of page tables.
func (p *PCIDs) Drop(pt *PageTables) {
+ p.mu.Lock()
if pcid, ok := p.cache[pt]; ok {
delete(p.cache, pt)
p.avail = append(p.avail, pcid)
}
+ p.mu.Unlock()
}