Cannot execute CPU instructions composed at runtime

38 views
Skip to first unread message

Frederick Virchanza Gotham

unread,
Jan 30, 2024, 8:43:11 AM1/30/24
to v8-dev

I have access to a remote web server running Linux, and I want to run NodeJs on it. When I try to run NodeJs though, it crashes because it cannot set a page as executable. Specifically the failure occurs in 'platform-posix.cc' inside the function 'SetPermissions'. mprotect returns -1 with errno set to EACCES. I cannot use 'paxctl' to change this.

Because I couldn't set a page as executable, I thought I might at compile time write a very long function and fill it with 'nop' instructions, and then at runtime try to set this executable page as writeable, but this too is forbidden.

So I have one more idea. Let's say I write a C source file "monkey.c" as follows:

    void MyCode(void)
    {
        __asm__ volatile("nop");
        __asm__ volatile("nop");
        __asm__ volatile("nop");
        __asm__ volatile("nop");
       ....
    }

Let's say I put 8 kilobytes worth of nop's inside this function. Next I compile it to a shared library as follows:

    gcc -o libmonkey.so -shared -fPIC monkey.c

So now I have a shared library file named "libmonkey.so" which contains an exported function called 'MyCode' that contains 8 thousand nop's.

Then, in the v8 library, let's say we have an array of CPU instructions, something like:

    char unsigned instructions[8192u] = { 0xac, 0xb4,  . . . .  };

So in the v8 library, we open up "libmonkey.so" and we write to it:

    FILE *f = fopen("libmonkey.so", "rb+");
    fseek(f, offset_of_MyCode, SEEK_SET);
    fwrite(instructions, 1u, 8192u, f);
    fclose(f);

Then in the v8 library, we use 'dlopen' to load this shared library, and we use 'dlsym' to find "MyCode", and then we execute it:

    void *h = dlopen("libmonkey.so", RTLD_NOW);
    void (*func)(void) = (void(*)(void))dlsym(h, "MyCode");
    func();
    dlclose(h);

This is a bit Frankenstein-ish but it will work. IDoes anybody want to help me fork the v8 repo and get this working? I've done this kind of stuff before.

Jakob Kummerow

unread,
Jan 30, 2024, 10:31:00 AM1/30/24
to v8-...@googlegroups.com
Running V8 in jitless mode might be an easier path forward.

(But good luck with the `dlopen` adventure if you decide to go down that route!)


--
--
v8-dev mailing list
v8-...@googlegroups.com
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to v8-dev+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/v8-dev/a881826d-745f-456d-9e9e-9d5394c0e12en%40googlegroups.com.

Frederick Virchanza Gotham

unread,
Jan 30, 2024, 10:34:03 AM1/30/24
to v8-dev
On Tuesday, January 30, 2024 at 3:31:00 PM UTC Jakob Kummerow wrote:
 
Running V8 in jitless mode might be an easier path forward.


Please tell me how.  Do I rebuild v8 with different options (e.g. "./configure --no-jit")? Or do I use my current build and give it different options at runtime? Note that I'm building NodeJs which appears to be statically linked with v8.


(But good luck with the `dlopen` adventure if you decide to go down that route!)


Just now I've created a small project to demonstrate my program working, it's just two source files and a build script:

    https://github.com/healytpk/just_in_time/
 

Jakob Kummerow

unread,
Jan 30, 2024, 10:36:48 AM1/30/24
to v8-...@googlegroups.com
V8 has a --jitless flag. (I haven't tested whether Node passes it through to V8.)


--
Reply all
Reply to author
Forward
0 new messages