Ejemplo n.º 1
0
        /// <inheritdoc/>
        public void TrackingReprotect(ulong va, ulong size, MemoryPermission protection)
        {
            AssertValidAddressAndSize(va, size);

            // Protection is inverted on software pages, since the default value is 0.
            protection = (~protection) & MemoryPermission.ReadAndWrite;

            long tag = protection switch
            {
                MemoryPermission.None => 0L,
                MemoryPermission.Write => 2L << PointerTagBit,
                    _ => 3L << PointerTagBit
            };

            int   pages      = GetPagesCount(va, (uint)size, out va);
            ulong pageStart  = va >> PageBits;
            long  invTagMask = ~(0xffffL << 48);

            for (int page = 0; page < pages; page++)
            {
                ref long pageRef = ref _pageTable.GetRef <long>(pageStart * PteSize);

                long pte;

                do
                {
                    pte = Volatile.Read(ref pageRef);
                }while (pte != 0 && Interlocked.CompareExchange(ref pageRef, (pte & invTagMask) | tag, pte) != pte);

                pageStart++;
            }
        }
Ejemplo n.º 2
0
        public static void Reprotect(IntPtr address, ulong size, MemoryPermission permission, bool throwOnFail)
        {
            bool result;

            if (OperatingSystem.IsWindows())
            {
                IntPtr sizeNint = new IntPtr((long)size);

                result = MemoryManagementWindows.Reprotect(address, sizeNint, permission);
            }
            else if (OperatingSystem.IsLinux() ||
                     OperatingSystem.IsMacOS())
            {
                result = MemoryManagementUnix.Reprotect(address, size, permission);
            }
            else
            {
                throw new PlatformNotSupportedException();
            }

            if (!result && throwOnFail)
            {
                throw new MemoryProtectionException(permission);
            }
        }
Ejemplo n.º 3
0
 public void SetState(MemoryPermission permission, MemoryState state, MemoryAttribute attribute)
 {
     Permission = permission;
     State      = state;
     Attribute &= MemoryAttribute.IpcAndDeviceMapped;
     Attribute |= attribute;
 }
Ejemplo n.º 4
0
        public long ReserveTransferMemory(long Position, long Size, MemoryPermission Permission)
        {
            lock (Blocks)
            {
                if (CheckRange(
                        Position,
                        Size,
                        MemoryState.TransferMemoryAllowed | MemoryState.IsPoolAllocated,
                        MemoryState.TransferMemoryAllowed | MemoryState.IsPoolAllocated,
                        MemoryPermission.Mask,
                        MemoryPermission.ReadAndWrite,
                        MemoryAttribute.Mask,
                        MemoryAttribute.None,
                        MemoryAttribute.IpcAndDeviceMapped,
                        out MemoryState State,
                        out _,
                        out MemoryAttribute Attribute))
                {
                    long PagesCount = Size / PageSize;

                    Attribute |= MemoryAttribute.Borrowed;

                    InsertBlock(Position, PagesCount, State, Permission, Attribute);

                    return(0);
                }
            }

            return(MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm));
        }
Ejemplo n.º 5
0
        public static bool Reprotect(IntPtr address, IntPtr size, MemoryPermission permission)
        {
            if (UseWin10Placeholders)
            {
                ulong uaddress = (ulong)address;
                ulong usize    = (ulong)size;
                while (usize > 0)
                {
                    ulong nextGranular = (uaddress & ~EmulatedSharedMemoryWindows.MappingMask) + EmulatedSharedMemoryWindows.MappingGranularity;
                    ulong mapSize      = Math.Min(usize, nextGranular - uaddress);

                    if (!VirtualProtect((IntPtr)uaddress, (IntPtr)mapSize, GetProtection(permission), out _))
                    {
                        return(false);
                    }

                    uaddress = nextGranular;
                    usize   -= mapSize;
                }

                return(true);
            }
            else
            {
                return(VirtualProtect(address, size, GetProtection(permission), out _));
            }
        }
Ejemplo n.º 6
0
        public static void Reprotect(IntPtr address, ulong size, MemoryPermission permission, bool throwOnFail)
        {
            bool result;

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                IntPtr sizeNint = new IntPtr((long)size);

                result = MemoryManagementWindows.Reprotect(address, sizeNint, permission);
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ||
                     RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                result = MemoryManagementUnix.Reprotect(address, size, permission);
            }
            else
            {
                throw new PlatformNotSupportedException();
            }

            if (!result && throwOnFail)
            {
                throw new MemoryProtectionException(permission);
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Removes protection from the list of protections.
        /// </summary>
        /// <param name="address">Address of the protected region</param>
        /// <param name="size">Size of the protected region in bytes</param>
        private void RemoveProtection(ulong address, ulong size)
        {
            ulong endAddress = address + size;
            var   overlaps   = Array.Empty <IntervalTreeNode <ulong, MemoryPermission> >();
            int   count;

            lock (_protections)
            {
                count = _protections.Get(address, endAddress, ref overlaps);

                for (int index = 0; index < count; index++)
                {
                    var protection = overlaps[index];

                    ulong            protAddress    = protection.Start;
                    ulong            protEndAddress = protection.End;
                    MemoryPermission protPermission = protection.Value;

                    _protections.Remove(protection);

                    if (address > protAddress)
                    {
                        _protections.Add(protAddress, address, protPermission);
                    }

                    if (endAddress < protEndAddress)
                    {
                        _protections.Add(endAddress, protEndAddress, protPermission);
                    }
                }
            }
        }
Ejemplo n.º 8
0
        public KernelResult MapIntoProcess(
            KMemoryManager MemoryManager,
            ulong Address,
            ulong Size,
            KProcess Process,
            MemoryPermission Permission)
        {
            ulong PagesCountRounded = BitUtils.DivRoundUp(Size, KMemoryManager.PageSize);

            if (PageList.GetPagesCount() != PagesCountRounded)
            {
                return(KernelResult.InvalidSize);
            }

            MemoryPermission ExpectedPermission = Process.Pid == OwnerPid
                ? OwnerPermission
                : UserPermission;

            if (Permission != ExpectedPermission)
            {
                return(KernelResult.InvalidPermission);
            }

            return(MemoryManager.MapPages(Address, PageList, MemoryState.SharedMemory, Permission));
        }
Ejemplo n.º 9
0
        public static void Reprotect(IntPtr address, ulong size, MemoryPermission permission, bool forView, bool force4KBMap, bool throwOnFail)
        {
            bool result;

            if (OperatingSystem.IsWindows())
            {
                if (forView && force4KBMap)
                {
                    result = MemoryManagementWindows.Reprotect4KB(address, (IntPtr)size, permission, forView);
                }
                else
                {
                    result = MemoryManagementWindows.Reprotect(address, (IntPtr)size, permission, forView);
                }
            }
            else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
            {
                result = MemoryManagementUnix.Reprotect(address, size, permission);
            }
            else
            {
                throw new PlatformNotSupportedException();
            }

            if (!result && throwOnFail)
            {
                throw new MemoryProtectionException(permission);
            }
        }
Ejemplo n.º 10
0
        public KernelResult MapIntoProcess(
            KMemoryManager memoryManager,
            ulong address,
            ulong size,
            KProcess process,
            MemoryPermission permission)
        {
            ulong pagesCountRounded = BitUtils.DivRoundUp(size, KMemoryManager.PageSize);

            if (_pageList.GetPagesCount() != pagesCountRounded)
            {
                return(KernelResult.InvalidSize);
            }

            MemoryPermission expectedPermission = process.Pid == _ownerPid
                ? _ownerPermission
                : _userPermission;

            if (permission != expectedPermission)
            {
                return(KernelResult.InvalidPermission);
            }

            return(memoryManager.MapPages(address, _pageList, MemoryState.SharedMemory, permission));
        }
Ejemplo n.º 11
0
        private KernelResult CreateTransferMemory(ulong address, ulong size, MemoryPermission permission, out int handle)
        {
            handle = 0;

            if (!PageAligned(address))
            {
                return(KernelResult.InvalidAddress);
            }

            if (!PageAligned(size) || size == 0)
            {
                return(KernelResult.InvalidSize);
            }

            if (address + size <= address)
            {
                return(KernelResult.InvalidMemState);
            }

            if (permission > MemoryPermission.ReadAndWrite || permission == MemoryPermission.Write)
            {
                return(KernelResult.InvalidPermission);
            }

            KernelResult result = _process.MemoryManager.ReserveTransferMemory(address, size, permission);

            if (result != KernelResult.Success)
            {
                return(result);
            }

            KTransferMemory transferMemory = new KTransferMemory(address, size);

            return(_process.HandleTable.GenerateHandle(transferMemory, out handle));
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Adds a protection to the list of protections.
        /// </summary>
        /// <param name="address">Address of the protected region</param>
        /// <param name="size">Size of the protected region in bytes</param>
        /// <param name="permission">Memory permissions of the region</param>
        private void AddProtection(ulong address, ulong size, MemoryPermission permission)
        {
            ulong endAddress = address + size;
            var   overlaps   = Array.Empty <IntervalTreeNode <ulong, MemoryPermission> >();
            int   count;

            lock (_protections)
            {
                count = _protections.Get(address, endAddress, ref overlaps);

                if (count == 1 &&
                    overlaps[0].Start <= address &&
                    overlaps[0].End >= endAddress &&
                    overlaps[0].Value == permission)
                {
                    return;
                }

                ulong startAddress = address;

                for (int index = 0; index < count; index++)
                {
                    var protection = overlaps[index];

                    ulong            protAddress    = protection.Start;
                    ulong            protEndAddress = protection.End;
                    MemoryPermission protPermission = protection.Value;

                    _protections.Remove(protection);

                    if (protection.Value == permission)
                    {
                        if (startAddress > protAddress)
                        {
                            startAddress = protAddress;
                        }

                        if (endAddress < protEndAddress)
                        {
                            endAddress = protEndAddress;
                        }
                    }
                    else
                    {
                        if (startAddress > protAddress)
                        {
                            _protections.Add(protAddress, startAddress, protPermission);
                        }

                        if (endAddress < protEndAddress)
                        {
                            _protections.Add(endAddress, protEndAddress, protPermission);
                        }
                    }
                }

                _protections.Add(startAddress, endAddress, permission);
            }
        }
Ejemplo n.º 13
0
 public KernelResult CreateTransferMemory64(
     [R(1)] ulong address,
     [R(2)] ulong size,
     [R(3)] MemoryPermission permission,
     [R(1)] out int handle)
 {
     return(CreateTransferMemory(address, size, permission, out handle));
 }
Ejemplo n.º 14
0
 public KernelResult CreateTransferMemory64(
     ulong address,
     ulong size,
     MemoryPermission permission,
     out int handle)
 {
     return(CreateTransferMemory(address, size, permission, out handle));
 }
Ejemplo n.º 15
0
 public KernelResult CreateTransferMemory32(
     [R(1)] uint address,
     [R(2)] uint size,
     [R(3)] MemoryPermission permission,
     [R(1)] out int handle)
 {
     return(_syscall.CreateTransferMemory(address, size, permission, out handle));
 }
Ejemplo n.º 16
0
        /// <summary>
        /// Signal that this region has been mapped or unmapped.
        /// </summary>
        /// <param name="mapped">True if the region has been mapped, false if unmapped</param>
        public void SignalMappingChanged(bool mapped)
        {
            _lastPermission = MemoryPermission.Invalid;

            foreach (RegionHandle handle in Handles)
            {
                handle.SignalMappingChanged(mapped);
            }
        }
Ejemplo n.º 17
0
 public override void Signal(ulong address, ulong size, bool write)
 {
     Protection = MemoryPermission.ReadAndWrite;
     Tracking.ProtectPhysicalRegion(this, MemoryPermission.ReadAndWrite); // Remove our protection immedately.
     foreach (var parent in VirtualParents)
     {
         parent.Signal(address, size, write);
     }
 }
Ejemplo n.º 18
0
 public static bool Reprotect(IntPtr address, IntPtr size, MemoryPermission permission, bool forView)
 {
     if (forView)
     {
         return(_placeholders.ReprotectView(address, size, permission));
     }
     else
     {
         return(WindowsApi.VirtualProtect(address, size, WindowsApi.GetProtection(permission), out _));
     }
 }
Ejemplo n.º 19
0
 public KSharedMemory(
     KPageList pageList,
     long ownerPid,
     MemoryPermission ownerPermission,
     MemoryPermission userPermission)
 {
     _pageList        = pageList;
     _ownerPid        = ownerPid;
     _ownerPermission = ownerPermission;
     _userPermission  = userPermission;
 }
Ejemplo n.º 20
0
 public KSharedMemory(
     KPageList PageList,
     long OwnerPid,
     MemoryPermission OwnerPermission,
     MemoryPermission UserPermission)
 {
     this.PageList        = PageList;
     this.OwnerPid        = OwnerPid;
     this.OwnerPermission = OwnerPermission;
     this.UserPermission  = UserPermission;
 }
Ejemplo n.º 21
0
 public KSharedMemory(
     Horizon system,
     KPageList pageList,
     long ownerPid,
     MemoryPermission ownerPermission,
     MemoryPermission userPermission) : base(system)
 {
     _pageList        = pageList;
     _ownerPid        = ownerPid;
     _ownerPermission = ownerPermission;
     _userPermission  = userPermission;
 }
Ejemplo n.º 22
0
 private static MmapProts GetProtection(MemoryPermission permission)
 {
     return(permission switch
     {
         MemoryPermission.None => MmapProts.PROT_NONE,
         MemoryPermission.Read => MmapProts.PROT_READ,
         MemoryPermission.ReadAndWrite => MmapProts.PROT_READ | MmapProts.PROT_WRITE,
         MemoryPermission.ReadAndExecute => MmapProts.PROT_READ | MmapProts.PROT_EXEC,
         MemoryPermission.ReadWriteExecute => MmapProts.PROT_READ | MmapProts.PROT_WRITE | MmapProts.PROT_EXEC,
         MemoryPermission.Execute => MmapProts.PROT_EXEC,
         _ => throw new MemoryProtectionException(permission)
     });
Ejemplo n.º 23
0
 private static MemoryProtection GetProtection(MemoryPermission permission)
 {
     return(permission switch
     {
         MemoryPermission.None => MemoryProtection.NoAccess,
         MemoryPermission.Read => MemoryProtection.ReadOnly,
         MemoryPermission.ReadAndWrite => MemoryProtection.ReadWrite,
         MemoryPermission.ReadAndExecute => MemoryProtection.ExecuteRead,
         MemoryPermission.ReadWriteExecute => MemoryProtection.ExecuteReadWrite,
         MemoryPermission.Execute => MemoryProtection.Execute,
         _ => throw new MemoryProtectionException(permission)
     });
Ejemplo n.º 24
0
 public KSharedMemory(
     KernelContext context,
     KPageList pageList,
     long ownerPid,
     MemoryPermission ownerPermission,
     MemoryPermission userPermission) : base(context)
 {
     _pageList        = pageList;
     _ownerPid        = ownerPid;
     _ownerPermission = ownerPermission;
     _userPermission  = userPermission;
 }
Ejemplo n.º 25
0
        private void SvcCreateTransferMemory(CpuThreadState threadState)
        {
            ulong address = threadState.X1;
            ulong size    = threadState.X2;

            if (!PageAligned(address))
            {
                Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{address:x16} is not page aligned!");

                threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);

                return;
            }

            if (!PageAligned(size) || size == 0)
            {
                Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{size:x16} is not page aligned or is zero!");

                threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);

                return;
            }

            if (address + size <= address)
            {
                Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{address:x16} / size 0x{size:x16}!");

                threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);

                return;
            }

            MemoryPermission permission = (MemoryPermission)threadState.X3;

            if (permission > MemoryPermission.ReadAndWrite || permission == MemoryPermission.Write)
            {
                Logger.PrintWarning(LogClass.KernelSvc, $"Invalid permission {permission}!");

                threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidPermission);

                return;
            }

            _process.MemoryManager.ReserveTransferMemory(address, size, permission);

            KTransferMemory transferMemory = new KTransferMemory(address, size);

            KernelResult result = _process.HandleTable.GenerateHandle(transferMemory, out int handle);

            threadState.X0 = (uint)result;
            threadState.X1 = (ulong)handle;
        }
Ejemplo n.º 26
0
        private void SvcCreateTransferMemory(CpuThreadState ThreadState)
        {
            long Position = (long)ThreadState.X1;
            long Size     = (long)ThreadState.X2;

            if (!PageAligned(Position))
            {
                Logger.PrintWarning(LogClass.KernelSvc, $"Address 0x{Position:x16} is not page aligned!");

                ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);

                return;
            }

            if (!PageAligned(Size) || Size == 0)
            {
                Logger.PrintWarning(LogClass.KernelSvc, $"Size 0x{Size:x16} is not page aligned or is zero!");

                ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidAddress);

                return;
            }

            if ((ulong)(Position + Size) <= (ulong)Position)
            {
                Logger.PrintWarning(LogClass.KernelSvc, $"Invalid region address 0x{Position:x16} / size 0x{Size:x16}!");

                ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm);

                return;
            }

            MemoryPermission Permission = (MemoryPermission)ThreadState.X3;

            if (Permission > MemoryPermission.ReadAndWrite || Permission == MemoryPermission.Write)
            {
                Logger.PrintWarning(LogClass.KernelSvc, $"Invalid permission {Permission}!");

                ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidPermission);

                return;
            }

            Process.MemoryManager.ReserveTransferMemory(Position, Size, Permission);

            KTransferMemory TransferMemory = new KTransferMemory(Position, Size);

            KernelResult Result = Process.HandleTable.GenerateHandle(TransferMemory, out int Handle);

            ThreadState.X0 = (uint)Result;
            ThreadState.X1 = (ulong)Handle;
        }
Ejemplo n.º 27
0
 public KMemoryBlock(
     long BasePosition,
     long PagesCount,
     MemoryState State,
     MemoryPermission Permission,
     MemoryAttribute Attribute)
 {
     this.BasePosition = BasePosition;
     this.PagesCount   = PagesCount;
     this.State        = State;
     this.Attribute    = Attribute;
     this.Permission   = Permission;
 }
Ejemplo n.º 28
0
        /// <summary>
        /// Reprotects a region of memory that has been mapped.
        /// </summary>
        /// <param name="address">Address of the region to reprotect</param>
        /// <param name="size">Size of the region to reprotect in bytes</param>
        /// <param name="permission">New permissions</param>
        /// <returns>True if the reprotection was successful, false otherwise</returns>
        public bool ReprotectView(IntPtr address, IntPtr size, MemoryPermission permission)
        {
            _partialUnmapLock.AcquireReaderLock(Timeout.Infinite);

            try
            {
                return(ReprotectViewInternal(address, size, permission, false));
            }
            finally
            {
                _partialUnmapLock.ReleaseReaderLock();
            }
        }
Ejemplo n.º 29
0
        public KernelResult SetProcessMemoryPermission32(
            [R(0)] int handle,
            [R(1)] uint sizeLow,
            [R(2)] uint srcLow,
            [R(3)] uint srcHigh,
            [R(4)] uint sizeHigh,
            [R(5)] MemoryPermission permission)
        {
            ulong src  = srcLow | ((ulong)srcHigh << 32);
            ulong size = sizeLow | ((ulong)sizeHigh << 32);

            return(_syscall.SetProcessMemoryPermission(handle, src, size, permission));
        }
Ejemplo n.º 30
0
 public KMemoryBlock(
     ulong BaseAddress,
     ulong PagesCount,
     MemoryState State,
     MemoryPermission Permission,
     MemoryAttribute Attribute)
 {
     this.BaseAddress = BaseAddress;
     this.PagesCount  = PagesCount;
     this.State       = State;
     this.Attribute   = Attribute;
     this.Permission  = Permission;
 }