diff options
author | Adin Scannell <ascannell@google.com> | 2018-08-08 21:27:58 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-08-08 21:29:19 -0700 |
commit | dbbe9ec91541dba387f8044cbf73fd29f604f902 (patch) | |
tree | 55a2c580a849fe41d8d83bc8c0dc773f28d4cfdb | |
parent | 2a44362c0b99c6ab800e1b0d26e4f368a5e7f9f1 (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.go | 14 |
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() } |