/// <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++; } }
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); } }
public void SetState(MemoryPermission permission, MemoryState state, MemoryAttribute attribute) { Permission = permission; State = state; Attribute &= MemoryAttribute.IpcAndDeviceMapped; Attribute |= attribute; }
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)); }
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 _)); } }
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); } }
/// <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); } } } }
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)); }
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); } }
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)); }
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)); }
/// <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); } }
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)); }
public KernelResult CreateTransferMemory64( ulong address, ulong size, MemoryPermission permission, out int handle) { return(CreateTransferMemory(address, size, permission, out handle)); }
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)); }
/// <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); } }
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); } }
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 _)); } }
public KSharedMemory( KPageList pageList, long ownerPid, MemoryPermission ownerPermission, MemoryPermission userPermission) { _pageList = pageList; _ownerPid = ownerPid; _ownerPermission = ownerPermission; _userPermission = userPermission; }
public KSharedMemory( KPageList PageList, long OwnerPid, MemoryPermission OwnerPermission, MemoryPermission UserPermission) { this.PageList = PageList; this.OwnerPid = OwnerPid; this.OwnerPermission = OwnerPermission; this.UserPermission = UserPermission; }
public KSharedMemory( Horizon system, KPageList pageList, long ownerPid, MemoryPermission ownerPermission, MemoryPermission userPermission) : base(system) { _pageList = pageList; _ownerPid = ownerPid; _ownerPermission = ownerPermission; _userPermission = userPermission; }
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) });
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) });
public KSharedMemory( KernelContext context, KPageList pageList, long ownerPid, MemoryPermission ownerPermission, MemoryPermission userPermission) : base(context) { _pageList = pageList; _ownerPid = ownerPid; _ownerPermission = ownerPermission; _userPermission = userPermission; }
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; }
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; }
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; }
/// <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(); } }
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)); }
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; }