/// <summary>set r/w/x protection on a portion of memory. rounded to encompassing pages</summary> /// <exception cref="InvalidOperationException">failed to protect memory</exception> public void Protect(ulong start, ulong length, Protection prot) { EnsureActive(); if (length == 0) { return; } // Note: asking for prot.none on memory that was not previously committed, commits it var computedStart = WaterboxUtils.AlignDown(start); var computedEnd = WaterboxUtils.AlignUp(start + length); var computedLength = computedEnd - computedStart; // potentially commit more memory var minNewCommittedSize = computedEnd - Start; if (minNewCommittedSize > CommittedSize) { CommittedSize = minNewCommittedSize; // Since Commit() was called, we have to do a full ProtectAll -- remember that when refactoring _pal.Commit(CommittedSize); } int pstart = GetPage(start); int pend = GetPage(start + length - 1); for (int i = pstart; i <= pend; i++) { _pageData[i] = prot; } // TODO: restore the previous behavior where we would only reprotect a partial range ProtectAll(); }
/// <exception cref="InvalidOperationException">failed to protect memory</exception> public override void Protect(ulong start, ulong length, Protection prot) { if (length == 0) { return; } int pstart = GetPage(start); int pend = GetPage(start + length - 1); var p = GetKernelMemoryProtectionValue(prot); for (int i = pstart; i <= pend; i++) { _pageData[i] = prot; // also store the value for later use } if (Active) // it's legal to Protect() if we're not active; the information is just saved for the next activation { var computedStart = WaterboxUtils.AlignDown(start); var computedEnd = WaterboxUtils.AlignUp(start + length); var computedLength = computedEnd - computedStart; Kernel32.MemoryProtection old; if (!Kernel32.VirtualProtect(Z.UU(computedStart), Z.UU(computedLength), p, out old)) { throw new InvalidOperationException($"{nameof(Kernel32.VirtualProtect)}() returned FALSE!"); } } }
/// <exception cref="InvalidOperationException">failed to protect memory</exception> public override void Protect(ulong start, ulong length, Protection prot) { if (length == 0) { return; } var pstart = GetPage(start); var pend = GetPage(start + length - 1); for (var i = pstart; i <= pend; i++) { _pageData[i] = prot; // also store the value for later use } if (!Active) { return; // it's legal to call this method if we're not active; the information is just saved for the next activation } var computedStart = WaterboxUtils.AlignDown(start); var protEnum = prot.ToMemoryProtection(); var exitCode = mprotect( Z.US(computedStart), Z.UU(WaterboxUtils.AlignUp(start + length) - computedStart), protEnum ); if (exitCode != 0) { throw new InvalidOperationException($"{nameof(mprotect)}() returned {exitCode}!"); } }
/// <summary>set r/w/x protection on a portion of memory. rounded to encompassing pages</summary /// <exception cref="InvalidOperationException">failed to protect memory</exception> public void Protect(ulong start, ulong length, Protection prot) { EnsureActive(); if (length == 0) { return; } if (_sealed) { _pal.GetWriteStatus(_dirtydata, _pageData); } // Note: asking for prot.none on memory that was not previously committed, commits it var computedStart = WaterboxUtils.AlignDown(start); var computedEnd = WaterboxUtils.AlignUp(start + length); var computedLength = computedEnd - computedStart; // potentially commit more memory var minNewCommittedSize = computedEnd - Start; if (minNewCommittedSize > CommittedSize) { CommittedSize = minNewCommittedSize; // Since Commit() was called, we have to do a full ProtectAll -- remember that when refactoring _pal.Commit(CommittedSize); } int pstart = GetPage(start); int pend = GetPage(start + length - 1); for (int i = pstart; i <= pend; i++) { _pageData[i] = prot; // inform the low level code what addresses might fault on it if (prot == Protection.RW || prot == Protection.RW_Stack) { _dirtydata[i] |= WriteDetectionStatus.CanChange; } else { _dirtydata[i] &= ~WriteDetectionStatus.CanChange; } } // TODO: restore the previous behavior where we would only reprotect a partial range ProtectAll(); if (_sealed) { _pal.SetWriteStatus(_dirtydata); } }
/// <summary>set r/w/x protection on a portion of memory. rounded to encompassing pages</summary> /// <exception cref="InvalidOperationException">failed to protect memory</exception> public void Protect(ulong start, ulong length, Protection prot) { if (length == 0) { return; } // Note: asking for prot.none on memory that was not previously committed, commits it var computedStart = WaterboxUtils.AlignDown(start); var computedEnd = WaterboxUtils.AlignUp(start + length); var computedLength = computedEnd - computedStart; _pal.Protect(computedStart, computedLength, prot); }
/// <summary>set r/w/x protection on a portion of memory. rounded to encompassing pages</summary> /// <exception cref="InvalidOperationException">failed to protect memory</exception> /// <exception cref="ObjectDisposedException">disposed</exception> public void Protect(ulong start, ulong length, Protection prot) { if (_pal == null) { throw new ObjectDisposedException(nameof(MemoryBlock)); } if (length == 0) { return; } // Note: asking for prot.none on memory that was not previously committed, commits it var computedStart = WaterboxUtils.AlignDown(start); var computedEnd = WaterboxUtils.AlignUp(start + length); var computedLength = computedEnd - computedStart; _pal.Protect(computedStart, computedLength, prot); }
/// <summary>set r/w/x protection on a portion of memory. rounded to encompassing pages</summary /// <exception cref="InvalidOperationException">failed to protect memory</exception> public void Protect(ulong start, ulong length, Protection prot) { if (length == 0) { return; } // Note: asking for prot.none on memory that was not previously committed, commits it var computedStart = WaterboxUtils.AlignDown(start); var computedEnd = WaterboxUtils.AlignUp(start + length); var computedLength = computedEnd - computedStart; int pstart = GetPage(start); int pend = GetPage(start + length - 1); for (int i = pstart; i <= pend; i++) { _pageData[i] = prot; // also store the value for later use } // potentially commit more memory var minNewCommittedSize = computedEnd - Start; if (minNewCommittedSize > CommittedSize) { CommittedSize = minNewCommittedSize; } if (Active) // it's legal to Protect() if we're not active; the information is just saved for the next activation { if (CommittedSize > LastActiveCommittedSize) { _pal.Commit(CommittedSize); LastActiveCommittedSize = CommittedSize; ProtectAll(); } else { _pal.Protect(computedStart, computedLength, prot); } } }