Re: [Tinycc-devel] setjmp/longjmp with in-memory compilation on Windows with CFG

2024-01-17 Thread Brad Robinson via Tinycc-devel



I still haven't been able to figure out why this isn't working.

I worked around it using a custom implementation of setjmp/longjmp from 
here.


https://github.com/GlinkieGamesInc/longjmp_win64

But, it'd be much nicer if the built-in function worked correctly.  If 
anyone has any idea why this isn't working, I'd love to hear it.


On 2024-01-17 20:02, Brad Robinson via Tinycc-devel wrote:


A little more information on this from here [5]:

You also have the option of dynamically controlling the set of icall 
target addresses that are considered valid by CFG using the 
SetProcessValidCallTargets [1] from the Memory Management API. The 
same API can be used to specify whether pages are invalid or valid 
targets for CFG. The VirtualProtect [2] and VirtualAlloc [3] functions 
will by default treat a specified region of executable and committed 
pages as valid indirect call targets. It is possible to override this 
behavior, such as when implementing a Just-in-Time compiler, by 
specifying PAGE_TARGETS_INVALID when calling VirtualAlloc or 
PAGE_TARGETS_NO_UPDATE when calling VirtualProtect as detailed under 
Memory Protection Constants [4].


On 2024-01-17 19:25, Brad Robinson via Tinycc-devel wrote:


Hi All,

I'm trying to use setjmp/longjmp in code that needs to be compiled to 
in-memory.


On Windows 11 (and presumably Windows 10) when you have Control Flow 
Guard enabled, it crashes on calling longjmp.


If compiled to .exe it works fine.  When Control Flow Guard is 
disabled (Control Panel ... -> ... Exploit Protection) is works fine.


I've read up a little on this and it seems like it's an exception 
being thrown in kernel, by a call to check the call target from the 
CRT.  I've also read that the call target should be allowed if the 
target address' page has been marked executable - so I think this 
should work, but it's definitely not.


Sample program test.c below that fails in the longjmp call when 
running `tcc -run test.c`


Any ideas?

Brad

#include 
#include 
jmp_buf jmpbuf;
void my_function()
{
longjmp(jmpbuf, 1);
}
int main()
{
if (setjmp(jmpbuf) == 0)
{
printf("A\n");
my_function();
printf("B\n");
}
printf("C\n");
return 0;
}

___
Tinycc-devel mailing list
Tinycc-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel


___
Tinycc-devel mailing list
Tinycc-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel




Links:
--
[1] 
https://learn.microsoft.com/en-us/windows/desktop/api/memoryapi/nf-memoryapi-setprocessvalidcalltargets
[2] 
https://learn.microsoft.com/en-us/windows/desktop/api/memoryapi/nf-memoryapi-virtualprotect
[3] 
https://learn.microsoft.com/en-us/windows/desktop/api/memoryapi/nf-memoryapi-virtualalloc
[4] 
https://learn.microsoft.com/en-us/windows/desktop/Memory/memory-protection-constants
[5] 
https://learn.microsoft.com/en-us/windows/win32/secbp/control-flow-guard___
Tinycc-devel mailing list
Tinycc-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel


Re: [Tinycc-devel] setjmp/longjmp with in-memory compilation on Windows with CFG

2024-01-17 Thread Brad Robinson via Tinycc-devel



A little more information on this from here [5]:

You also have the option of dynamically controlling the set of icall 
target addresses that are considered valid by CFG using the 
SetProcessValidCallTargets [1] from the Memory Management API. The same 
API can be used to specify whether pages are invalid or valid targets 
for CFG. The VirtualProtect [2] and VirtualAlloc [3] functions will by 
default treat a specified region of executable and committed pages as 
valid indirect call targets. It is possible to override this behavior, 
such as when implementing a Just-in-Time compiler, by specifying 
PAGE_TARGETS_INVALID when calling VirtualAlloc or 
PAGE_TARGETS_NO_UPDATE when calling VirtualProtect as detailed under 
Memory Protection Constants [4].


On 2024-01-17 19:25, Brad Robinson via Tinycc-devel wrote:


Hi All,

I'm trying to use setjmp/longjmp in code that needs to be compiled to 
in-memory.


On Windows 11 (and presumably Windows 10) when you have Control Flow 
Guard enabled, it crashes on calling longjmp.


If compiled to .exe it works fine.  When Control Flow Guard is disabled 
(Control Panel ... -> ... Exploit Protection) is works fine.


I've read up a little on this and it seems like it's an exception being 
thrown in kernel, by a call to check the call target from the CRT.  
I've also read that the call target should be allowed if the target 
address' page has been marked executable - so I think this should work, 
but it's definitely not.


Sample program test.c below that fails in the longjmp call when running 
`tcc -run test.c`


Any ideas?

Brad

#include 
#include 
jmp_buf jmpbuf;
void my_function()
{
longjmp(jmpbuf, 1);
}
int main()
{
if (setjmp(jmpbuf) == 0)
{
printf("A\n");
my_function();
printf("B\n");
}
printf("C\n");
return 0;
}

___
Tinycc-devel mailing list
Tinycc-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel




Links:
--
[1] 
https://learn.microsoft.com/en-us/windows/desktop/api/memoryapi/nf-memoryapi-setprocessvalidcalltargets
[2] 
https://learn.microsoft.com/en-us/windows/desktop/api/memoryapi/nf-memoryapi-virtualprotect
[3] 
https://learn.microsoft.com/en-us/windows/desktop/api/memoryapi/nf-memoryapi-virtualalloc
[4] 
https://learn.microsoft.com/en-us/windows/desktop/Memory/memory-protection-constants
[5] 
https://learn.microsoft.com/en-us/windows/win32/secbp/control-flow-guard___
Tinycc-devel mailing list
Tinycc-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel