Beispiel #1
0
        /// <summary>
        /// take a hash of the current full contents of the block, including unreadable areas
        /// but not uncommitted areas
        /// </summary>
        /// <exception cref="InvalidOperationException">
        /// <see cref="MemoryBlock.Active"/> is <see langword="false"/> or failed to make memory read-only
        /// </exception>
        public byte[] FullHash()
        {
            if (!Active)
            {
                throw new InvalidOperationException("Not active");
            }
            // temporarily switch the committed parts to `R` so we can read them
            if (CommittedSize > 0)
            {
                _pal.Protect(Start, CommittedSize, Protection.R);
            }
            var ret = WaterboxUtils.Hash(GetStream(Start, CommittedSize, false));

            ProtectAll();
            return(ret);
        }
Beispiel #2
0
        /// <summary>restore all recorded protections</summary>
        private void ProtectAll()
        {
            if (CommittedSize == 0)
            {
                return;
            }
            int ps        = 0;
            int pageLimit = (int)(CommittedSize >> WaterboxUtils.PageShift);

            for (int i = 0; i < pageLimit; i++)
            {
                if (i == pageLimit - 1 || _pageData[i] != _pageData[i + 1] || _dirtydata[i] != _dirtydata[i + 1])
                {
                    ulong zstart = GetStartAddr(ps);
                    ulong zend   = GetStartAddr(i + 1);
                    var   prot   = _pageData[i];
                    // adjust frontend notion of prot to the PAL layer's expectation
                    if (prot == Protection.RW_Stack)
                    {
                        if (!_sealed)
                        {
                            // don't activate this protection yet
                            prot = Protection.RW;
                        }
                        else
                        {
                            var didChange = (_dirtydata[i] & WriteDetectionStatus.DidChange) != 0;
                            if (didChange)
                            {
                                // don't needlessly retrigger
                                prot = Protection.RW;
                            }
                        }
                    }
                    else if (prot == Protection.RW_Invisible)
                    {
                        // this never matters to the backend
                        prot = Protection.RW;
                    }
                    else if (_sealed && prot == Protection.RW)
                    {
                        var didChange = (_dirtydata[i] & WriteDetectionStatus.DidChange) != 0;
                        if (!didChange)
                        {
                            // set to trigger if we have not before
                            prot = Protection.R;
                        }
                    }

                    _pal.Protect(zstart, zend - zstart, prot);
                    ps = i + 1;
                }
            }
        }
        /// <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);
        }
Beispiel #4
0
        /// <summary>restore all recorded protections</summary>
        private void ProtectAll()
        {
            if (CommittedSize == 0)
            {
                return;
            }
            int ps        = 0;
            int pageLimit = (int)(CommittedSize >> WaterboxUtils.PageShift);

            for (int i = 0; i < pageLimit; i++)
            {
                if (i == pageLimit - 1 || _pageData[i] != _pageData[i + 1])
                {
                    ulong zstart = GetStartAddr(ps);
                    ulong zend   = GetStartAddr(i + 1);
                    var   prot   = _pageData[i];
                    _pal.Protect(zstart, zend - zstart, prot);
                    ps = i + 1;
                }
            }
        }