From b4006686d2752857b406c6c7e53a112efca826ff Mon Sep 17 00:00:00 2001 From: Jamie Liu Date: Mon, 1 Apr 2019 14:46:28 -0700 Subject: [PATCH] Don't expand COW-break on executable VMAs. PiperOrigin-RevId: 241403847 Change-Id: I4631ca05734142da6e80cdfa1a1d63ed68aa05cc --- pkg/sentry/mm/pma.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/pkg/sentry/mm/pma.go b/pkg/sentry/mm/pma.go index e090537cc..0cca743ef 100644 --- a/pkg/sentry/mm/pma.go +++ b/pkg/sentry/mm/pma.go @@ -318,7 +318,23 @@ func (mm *MemoryManager) getPMAsInternalLocked(ctx context.Context, vseg vmaIter panic(fmt.Sprintf("pma %v needs to be copied for writing, but is not readable: %v", pseg.Range(), oldpma)) } } - copyAR := pseg.Range().Intersect(maskAR) + // The majority of copy-on-write breaks on executable pages + // come from: + // + // - The ELF loader, which must zero out bytes on the last + // page of each segment after the end of the segment. + // + // - gdb's use of ptrace to insert breakpoints. + // + // Neither of these cases has enough spatial locality to + // benefit from copying nearby pages, so if the vma is + // executable, only copy the pages required. + var copyAR usermem.AddrRange + if vseg.ValuePtr().effectivePerms.Execute { + copyAR = pseg.Range().Intersect(ar) + } else { + copyAR = pseg.Range().Intersect(maskAR) + } // Get internal mappings from the pma to copy from. if err := pseg.getInternalMappingsLocked(); err != nil { return pstart, pseg.PrevGap(), err