diff options
author | Jamie Liu <jamieliu@google.com> | 2019-03-25 12:41:36 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2019-03-25 12:42:43 -0700 |
commit | f3723f805989d0c5956fbb6aa88b1cd9ac20753c (patch) | |
tree | f8992ae20287a20ab4325a0fa8f5da213283470f /pkg/sentry/mm/io.go | |
parent | ddc05e3053e387be9c81aa98c621b6fc92b01000 (diff) |
Call memmap.Mappable.Translate with more conservative usermem.AccessType.
MM.insertPMAsLocked() passes vma.maxPerms to memmap.Mappable.Translate
(although it unsets AccessType.Write if the vma is private). This
somewhat simplifies handling of pmas, since it means only COW-break
needs to replace existing pmas. However, it also means that a MAP_SHARED
mapping of a file opened O_RDWR dirties the file, regardless of the
mapping's permissions and whether or not the mapping is ever actually
written to with I/O that ignores permissions (e.g.
ptrace(PTRACE_POKEDATA)).
To fix this:
- Change the pma-getting path to request only the permissions that are
required for the calling access.
- Change memmap.Mappable.Translate to take requested permissions, and
return allowed permissions. This preserves the existing behavior in the
common cases where the memmap.Mappable isn't
fsutil.CachingInodeOperations and doesn't care if the translated
platform.File pages are written to.
- Change the MM.getPMAsLocked path to support permission upgrading of
pmas outside of copy-on-write.
PiperOrigin-RevId: 240196979
Change-Id: Ie0147c62c1fbc409467a6fa16269a413f3d7d571
Diffstat (limited to 'pkg/sentry/mm/io.go')
-rw-r--r-- | pkg/sentry/mm/io.go | 20 |
1 files changed, 5 insertions, 15 deletions
diff --git a/pkg/sentry/mm/io.go b/pkg/sentry/mm/io.go index e0cebef84..81787a6fd 100644 --- a/pkg/sentry/mm/io.go +++ b/pkg/sentry/mm/io.go @@ -466,9 +466,7 @@ func (mm *MemoryManager) handleASIOFault(ctx context.Context, addr usermem.Addr, // Ensure that we have usable pmas. mm.activeMu.Lock() - pseg, pend, err := mm.getPMAsLocked(ctx, vseg, ar, pmaOpts{ - breakCOW: at.Write, - }) + pseg, pend, err := mm.getPMAsLocked(ctx, vseg, ar, at) mm.mappingMu.RUnlock() if pendaddr := pend.Start(); pendaddr < ar.End { if pendaddr <= ar.Start { @@ -498,14 +496,10 @@ func (mm *MemoryManager) handleASIOFault(ctx context.Context, addr usermem.Addr, // // Preconditions: 0 < ar.Length() <= math.MaxInt64. func (mm *MemoryManager) withInternalMappings(ctx context.Context, ar usermem.AddrRange, at usermem.AccessType, ignorePermissions bool, f func(safemem.BlockSeq) (uint64, error)) (int64, error) { - po := pmaOpts{ - breakCOW: at.Write, - } - // If pmas are already available, we can do IO without touching mm.vmas or // mm.mappingMu. mm.activeMu.RLock() - if pseg := mm.existingPMAsLocked(ar, at, ignorePermissions, po, true /* needInternalMappings */); pseg.Ok() { + if pseg := mm.existingPMAsLocked(ar, at, ignorePermissions, true /* needInternalMappings */); pseg.Ok() { n, err := f(mm.internalMappingsLocked(pseg, ar)) mm.activeMu.RUnlock() // Do not convert errors returned by f to EFAULT. @@ -526,7 +520,7 @@ func (mm *MemoryManager) withInternalMappings(ctx context.Context, ar usermem.Ad // Ensure that we have usable pmas. mm.activeMu.Lock() - pseg, pend, perr := mm.getPMAsLocked(ctx, vseg, ar, po) + pseg, pend, perr := mm.getPMAsLocked(ctx, vseg, ar, at) mm.mappingMu.RUnlock() if pendaddr := pend.Start(); pendaddr < ar.End { if pendaddr <= ar.Start { @@ -578,14 +572,10 @@ func (mm *MemoryManager) withVecInternalMappings(ctx context.Context, ars userme return mm.withInternalMappings(ctx, ars.Head(), at, ignorePermissions, f) } - po := pmaOpts{ - breakCOW: at.Write, - } - // If pmas are already available, we can do IO without touching mm.vmas or // mm.mappingMu. mm.activeMu.RLock() - if mm.existingVecPMAsLocked(ars, at, ignorePermissions, po, true /* needInternalMappings */) { + if mm.existingVecPMAsLocked(ars, at, ignorePermissions, true /* needInternalMappings */) { n, err := f(mm.vecInternalMappingsLocked(ars)) mm.activeMu.RUnlock() // Do not convert errors returned by f to EFAULT. @@ -603,7 +593,7 @@ func (mm *MemoryManager) withVecInternalMappings(ctx context.Context, ars userme // Ensure that we have usable pmas. mm.activeMu.Lock() - pars, perr := mm.getVecPMAsLocked(ctx, vars, po) + pars, perr := mm.getVecPMAsLocked(ctx, vars, at) mm.mappingMu.RUnlock() if pars.NumBytes() == 0 { mm.activeMu.Unlock() |