Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make MAX_CONTEXT_SIZE dynamically sized to future-proof it #2666

Closed
derekbruening opened this issue Oct 20, 2017 · 24 comments · Fixed by #4703
Closed

Make MAX_CONTEXT_SIZE dynamically sized to future-proof it #2666

derekbruening opened this issue Oct 20, 2017 · 24 comments · Fixed by #4703

Comments

@derekbruening
Copy link
Contributor

On Skylake this assert fires:

Internal Error: DynamoRIO debug check failure: D:\dynamorio_package\core\win32\ntdll.c:5359 res >= 0 && len <= MAX_CONTEXT_SIZE

Xref #1937 for the corresponding Linux signal context issue.
We need to make MAX_CONTEXT_SIZE be dynamically sized.

@newgre
Copy link
Contributor

newgre commented Oct 24, 2017

For the record: the extended context size for both, Skylake and Kaby Lake, is 0x4F7.
Would you be ok with an update to MAX_CONTEXT_SIZE until dynamic context size has been implemented?

@newgre
Copy link
Contributor

newgre commented Oct 24, 2017

err, above size was the result without CONTEXT_XSTATE. The correct value should be 0x6EF and 0x4E3 for a 32-bit process.

@derekbruening
Copy link
Contributor Author

Would you be ok with an update to MAX_CONTEXT_SIZE until dynamic context size has been implemented?

Yes that's a reasonable short-term fix. The current value in the code today for 64-bit MAX_CONTEXT_SIZE is 0x6ef and for 32-bit 0x4e3 -- are you reporting a subset of the context above?
Your values above wouldn't have triggered the assert.

@newgre
Copy link
Contributor

newgre commented Oct 24, 2017

in 7 RC1 I see 0x680 and 0x480, respectively, defined in os_private.h?

@derekbruening
Copy link
Contributor Author

Would you be ok with an update to MAX_CONTEXT_SIZE until dynamic context size has been implemented?

The only concern here is that stack buffers of this size are used in a number of places in the code and DR has a limited stack size. If the MAX_CONTEXT_SIZE gets too much larger they will need to be changed to use the heap.

@derekbruening
Copy link
Contributor Author

in 7 RC1 I see 0x680 and 0x480, respectively, defined in os_private.h?

Ah ok, I'm looking at the latest, and it was updated in 5eebc95. So perhaps the short-term fix has already been done?

@newgre
Copy link
Contributor

newgre commented Oct 24, 2017

Oh neat, yes those values are the same that I deduced. Are there nightly builds?

@newgre
Copy link
Contributor

newgre commented Oct 24, 2017

@newgre
Copy link
Contributor

newgre commented Oct 24, 2017

no windows builds?

@derekbruening
Copy link
Contributor Author

Unfortunately the old Cr nightly builds no longer exist (we should update that wiki page) and noone has set them up with Appveyor yet (#1967)

@newgre
Copy link
Contributor

newgre commented Oct 24, 2017

I can confirm that the context size related bug is fixed in trunk.

@derekbruening derekbruening changed the title ASSERT MAX_CONTEXT_SIZE too small for Skylake CONTEXT Make MAX_CONTEXT_SIZE dynamically sized to future-proof it Oct 27, 2017
@securitykernel
Copy link

Got here via #3923. I tried launching drrun and drmemory via windbg from cygwin, from within windbg, loading symbols to find out the value of len in ntdll.c:5221, but all attempts fail, I get access violations, breakpoints fail to trigger, symbols fail to load, etc.

If you can provide a source code snippet that I can compile with VS 2013 to call RtlGetExtendedContextLength() on my system, than I'd be happy to compile and run it.

@lieser
Copy link
Contributor

lieser commented Jan 15, 2020

On the system that @securitykernel tried the context size seems to be 0xd2f.

image

@lieser
Copy link
Contributor

lieser commented Feb 19, 2020

@derekbruening Is there any plan to increase the MAX_CONTEXT_SIZE further? Nothing urgent as we currently use a local build there we changed the size, but would be nice to get back to an official build in the long run.

@derekbruening
Copy link
Contributor Author

Happy to take a pull request for either a short-term size increase or long-term switch to dynamic sizing.

derekbruening pushed a commit that referenced this issue Feb 22, 2020
Long-term we need to dynamically size the context and move it to the heap, but for now we increase the hardcoded size to avoid failures.

Issue: #2666
derekbruening pushed a commit that referenced this issue Feb 25, 2020
fb55bf6 over-provisioned the 32-bit context size.  Here we set it to the precise current maximum.

Issue: #2666
@ntfshard
Copy link

This trouble is still reproducible, is it possible to workaround somehow on my side?

@derekbruening
Copy link
Contributor Author

This trouble is still reproducible, is it possible to workaround somehow on my side?

You can see all the discussion above about local builds and changing the constant (and longer-term refactoring). It would be awesome if someone with these affected machine environments who can thus test it were able to send a pull request for at least a short-term fix.

@lieser
Copy link
Contributor

lieser commented Nov 13, 2020

For reference, here are the notes I took then I debugged it on our affected machine to get the needed value. Note that it has been some time since I did it, so no guarantee about correctness/completes about them:

All done with WinDbg and a cronbuild from https://github.com/DynamoRIO/dynamorio/releases:

As the automatic loading of symbols described at https://github.com/DynamoRIO/dynamorio/wiki/Debugging#debugging-on-windows did nor work for use, we had to load the symbols manually (adapt paths below):

.sympath+ C:\<path>\DynamoRIO-Windows\lib64\debug;C:\<path>\DynamoRIO-Windows\lib64
.reload dynamorio.dll=15000000

To get to the nt_initialize_context function (e.g. to get the value on a system that does trigger the assert), execute the following afterwards:

.childdbg 1
g
$$ should now be at the running process, e.g. notepad
bp dynamorio!nt_initialize_context
g

Afterwards, make a few manual single steps, until the len variable gets populated with the value your machine has.

@ntfshard
Copy link

@lieser Thank you for your guidance. Sorry for delay. It seems I got the value, but not sure that I do it in the right way, could you please check:
image
W/o a call value was undefined. 0n3375 is a dec? I'm quite new with windbg (

@lieser
Copy link
Contributor

lieser commented Nov 21, 2020

Also not an expert on WinDbg, but as far as I can tell you did everything right. But does this error still happen to you with the latest cronbuild?
We already updated MAX_CONTEXT_64_SIZE to 0xd2f (decimal 3375) in a PR. As this is the same value as you found out for your machine, I would expect the latest cronbuild to work for you.

@ntfshard
Copy link

Ok, I see, thank you. The difficult is that drmemory crontab releases are appear quite rare: latest - 12 Sep, previous - 4 Jul and 4 Apr

@ntfshard
Copy link

Hello
Thank you for fixing crontab releases. I ran 2.3.18633 and it works fine.

@derekbruening
Copy link
Contributor Author

I think this was accidentally closed: the hardcoded constant was raised, fixing it short-term, but this issue covers a long-term dynamic-sizing fix. Re-opening.

@derekbruening derekbruening reopened this Jan 31, 2021
@derekbruening derekbruening self-assigned this Jan 31, 2021
@derekbruening
Copy link
Contributor Author

Looks like thread_set_self_mcontext is one place where a heap buffer cannot be freed (at least locally). I think all the others can easily heap-allocate.

derekbruening added a commit that referenced this issue Feb 1, 2021
Changes all stack buffers using hardcoded sizes for CONTEXT to instead
use heap-allocated buffers sized to match the kernel's actual CONTEXT
size for the given flags.

Adds a mechanism to query the CONTEXT64 size from 32-bit DR using
switch_modes_and_call().

The one place where we can't easily use heap is
thread_set_self_mcontext() because it doesn't return and we thus do
not have a simple way to free the buffer.  There, we use a large
4096-byte stack buffer, and we check the size needed: if it's larger
than that, we use a lost heap allocation and issue a debug build
warning which should alert someone.  If we end up needing more space
there in the future we may want to store a pointer in the dcontext and
have a special check to free it or something.

Fixes #2666
derekbruening added a commit that referenced this issue Feb 1, 2021
Changes all stack buffers using hardcoded sizes for CONTEXT to instead
use heap-allocated buffers sized to match the kernel's actual CONTEXT
size for the given flags.

Adds a mechanism to query the CONTEXT64 size from 32-bit DR using
switch_modes_and_call().

The one place where we can't easily use heap is
thread_set_self_mcontext() because it doesn't return and we thus do
not have a simple way to free the buffer.  There, we use a large
4096-byte stack buffer, and we check the size needed: if it's larger
than that, we use a lost heap allocation and issue a debug build
warning which should alert someone.  If we end up needing more space
there in the future we may want to store a pointer in the dcontext and
have a special check to free it or something.

Fixes #2666
derekbruening added a commit that referenced this issue Feb 6, 2021
Fixes a bug in PR #4703 where for post-CreateUserProcess handling it
frees the heap buffer for a CONTEXT before the code is finished using
it.

Also updates the CONTEXT heap buffers from PR #4703 to use
thread-private heap where possible, to avoid locks.

Issue: #2666
derekbruening added a commit that referenced this issue Feb 6, 2021
Fixes a bug in PR #4703 where for post-CreateUserProcess handling it
frees the heap buffer for a CONTEXT before the code is finished using
it.

Also updates the CONTEXT heap buffers from PR #4703 to use
thread-private heap where possible, to avoid locks.

Issue: #2666
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants