github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/pkg/sentry/mm/shm.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package mm 16 17 import ( 18 "github.com/MerlinKodo/gvisor/pkg/context" 19 "github.com/MerlinKodo/gvisor/pkg/errors/linuxerr" 20 "github.com/MerlinKodo/gvisor/pkg/hostarch" 21 "github.com/MerlinKodo/gvisor/pkg/sentry/kernel/shm" 22 "github.com/MerlinKodo/gvisor/pkg/sentry/memmap" 23 ) 24 25 // DetachShm unmaps a sysv shared memory segment. 26 func (mm *MemoryManager) DetachShm(ctx context.Context, addr hostarch.Addr) error { 27 if addr != addr.RoundDown() { 28 // "... shmaddr is not aligned on a page boundary." - man shmdt(2) 29 return linuxerr.EINVAL 30 } 31 32 var detached *shm.Shm 33 var vgap vmaGapIterator 34 35 var droppedIDs []memmap.MappingIdentity 36 // This must run after mm.mappingMu.Unlock(). 37 defer func() { 38 for _, id := range droppedIDs { 39 id.DecRef(ctx) 40 } 41 }() 42 43 mm.mappingMu.Lock() 44 defer mm.mappingMu.Unlock() 45 46 // Find and remove the first vma containing an address >= addr that maps a 47 // segment originally attached at addr. 48 vseg := mm.vmas.LowerBoundSegment(addr) 49 for vseg.Ok() { 50 vma := vseg.ValuePtr() 51 if shm, ok := vma.mappable.(*shm.Shm); ok && vseg.Start() >= addr && uint64(vseg.Start()-addr) == vma.off { 52 detached = shm 53 vgap, droppedIDs = mm.unmapLocked(ctx, vseg.Range(), droppedIDs) 54 vseg = vgap.NextSegment() 55 break 56 } else { 57 vseg = vseg.NextSegment() 58 } 59 } 60 61 if detached == nil { 62 // There is no shared memory segment attached at addr. 63 return linuxerr.EINVAL 64 } 65 66 // Remove all vmas that could have been created by the same attach. 67 end := addr + hostarch.Addr(detached.EffectiveSize()) 68 for vseg.Ok() && vseg.End() <= end { 69 vma := vseg.ValuePtr() 70 if vma.mappable == detached && uint64(vseg.Start()-addr) == vma.off { 71 vgap, droppedIDs = mm.unmapLocked(ctx, vseg.Range(), droppedIDs) 72 vseg = vgap.NextSegment() 73 } else { 74 vseg = vseg.NextSegment() 75 } 76 } 77 78 return nil 79 }