Skip to content

PCRE2 JIT Use-After-Free during graceful reload #1027

@patryk4815

Description

@patryk4815

Feature Overview

A use-after-free vulnerability occurs in nginx when pcre_jit on; is enabled and a graceful reload (nginx -s reload) is performed. The crash happens due to concurrent access to PCRE2 JIT executable memory regions during the reload process.

Environment

  • nginx version: 1.28.0
  • PCRE2 version: 10.46
  • OS: Linux (glibc 2.40-66)
  • Build: Compiled with AddressSanitizer

Configuration

pcre_jit on;

Steps to Reproduce

  1. It is hard to reproduce it. It happens "randomly"
  2. Start nginx with pcre_jit on; in configuration + add few regexes
  3. Execute nginx -s reload while workers are running
  4. Observe SEGV/SIGILL crashes in worker processes (and occasionally in the master process; the master also crashes randomly)

ASAN report

AddressSanitizer:DEADLYSIGNAL
=================================================================
==207937==ERROR: AddressSanitizer: SEGV on unknown address 0x7f8ab7e177d0 (pc 0x7f8ab91dd8ab bp 0x7ffdb7fe2bf0 sp 0x7ffdb7fe2bd0 T0)
==207937==The signal is caused by a WRITE memory access.
    #0 0x7f8ab91dd8ab in sljit_free_exec (/pcre2-10.46/lib/libpcre2-8.so.0+0x298ab) (BuildId: 68ec9a4129abc46adc12406062a815b3a6b5ce11)
    #1 0x7f8ab9215f3b in _pcre2_jit_free_8 (/pcre2-10.46/lib/libpcre2-8.so.0+0x61f3b) (BuildId: 68ec9a4129abc46adc12406062a815b3a6b5ce11)
    #2 0x7f8ab91c1101 in pcre2_code_free_8 (/pcre2-10.46/lib/libpcre2-8.so.0+0xd101) (BuildId: 68ec9a4129abc46adc12406062a815b3a6b5ce11)
    #3 0x5568fbb274d6 in ngx_regex_cleanup (/nginx-1.28.0/bin/nginx+0x1ab4d6) (BuildId: 88e08219618dea7389271ee16a11fec8de0df8a0)
    #4 0x5568fba450f8 in ngx_destroy_pool (/nginx-1.28.0/bin/nginx+0xc90f8) (BuildId: 88e08219618dea7389271ee16a11fec8de0df8a0)
    #5 0x5568fbab8a70 in ngx_worker_process_exit (/nginx-1.28.0/bin/nginx+0x13ca70) (BuildId: 88e08219618dea7389271ee16a11fec8de0df8a0)
    #6 0x5568fbaba787 in ngx_worker_process_cycle (/nginx-1.28.0/bin/nginx+0x13e787) (BuildId: 88e08219618dea7389271ee16a11fec8de0df8a0)
    #7 0x5568fbab61ed in ngx_spawn_process (/nginx-1.28.0/bin/nginx+0x13a1ed) (BuildId: 88e08219618dea7389271ee16a11fec8de0df8a0)
    #8 0x5568fbab8ff3 in ngx_start_worker_processes (/nginx-1.28.0/bin/nginx+0x13cff3) (BuildId: 88e08219618dea7389271ee16a11fec8de0df8a0)
    #9 0x5568fbabbc1b in ngx_master_process_cycle (/nginx-1.28.0/bin/nginx+0x13fc1b) (BuildId: 88e08219618dea7389271ee16a11fec8de0df8a0)
    #10 0x5568fba41124 in main (/nginx-1.28.0/bin/nginx+0xc5124) (BuildId: 88e08219618dea7389271ee16a11fec8de0df8a0)
    #11 0x7f8ab862a4d7 in __libc_start_call_main (/glibc-2.40-66/lib/libc.so.6+0x2a4d7) (BuildId: cddea92d6cba8333be952b5a02fd47d61054c5ab)
    #12 0x7f8ab862a59a in __libc_start_main_alias_1 (/glibc-2.40-66/lib/libc.so.6+0x2a59a) (BuildId: cddea92d6cba8333be952b5a02fd47d61054c5ab)
    #13 0x5568fba3cfe4 in _start (/nginx-1.28.0/bin/nginx+0xc0fe4) (BuildId: 88e08219618dea7389271ee16a11fec8de0df8a0)

AddressSanitizer:DEADLYSIGNAL
=================================================================
==207813==ERROR: AddressSanitizer: SEGV on unknown address 0x7f8ab7e17430 (pc 0x7f8ab91dda0d bp 0x7ffdb7fe2710 sp 0x7ffdb7fe26e0 T0)
==207813==The signal is caused by a WRITE memory access.
    #0 0x7f8ab91dda0d in sljit_malloc_exec (/pcre2-10.46/lib/libpcre2-8.so.0+0x29a0d) (BuildId: 68ec9a4129abc46adc12406062a815b3a6b5ce11)
    #1 0x7f8ab91ddf5e in sljit_generate_code.constprop.0 (/pcre2-10.46/lib/libpcre2-8.so.0+0x29f5e) (BuildId: 68ec9a4129abc46adc12406062a815b3a6b5ce11)
    #2 0x7f8ab9214c80 in jit_compile (/pcre2-10.46/lib/libpcre2-8.so.0+0x60c80) (BuildId: 68ec9a4129abc46adc12406062a815b3a6b5ce11)
    #3 0x7f8ab9215b8c in pcre2_jit_compile_8 (/pcre2-10.46/lib/libpcre2-8.so.0+0x61b8c) (BuildId: 68ec9a4129abc46adc12406062a815b3a6b5ce11)
    #4 0x5568fbb2704c in ngx_regex_module_init (/nginx-1.28.0/bin/nginx+0x1ab04c) (BuildId: 88e08219618dea7389271ee16a11fec8de0df8a0)
    #5 0x5568fba7ebee in ngx_init_modules (/nginx-1.28.0/bin/nginx+0x102bee) (BuildId: 88e08219618dea7389271ee16a11fec8de0df8a0)
    #6 0x5568fba76493 in ngx_init_cycle (/nginx-1.28.0/bin/nginx+0xfa493) (BuildId: 88e08219618dea7389271ee16a11fec8de0df8a0)
    #7 0x5568fbabc9a0 in ngx_master_process_cycle (/nginx-1.28.0/bin/nginx+0x1409a0) (BuildId: 88e08219618dea7389271ee16a11fec8de0df8a0)
    #8 0x5568fba41124 in main (/nginx-1.28.0/bin/nginx+0xc5124) (BuildId: 88e08219618dea7389271ee16a11fec8de0df8a0)
    #9 0x7f8ab862a4d7 in __libc_start_call_main (/glibc-2.40-66/lib/libc.so.6+0x2a4d7) (BuildId: cddea92d6cba8333be952b5a02fd47d61054c5ab)
    #10 0x7f8ab862a59a in __libc_start_main_alias_1 (/glibc-2.40-66/lib/libc.so.6+0x2a59a) (BuildId: cddea92d6cba8333be952b5a02fd47d61054c5ab)
    #11 0x5568fba3cfe4 in _start (/nginx-1.28.0/bin/nginx+0xc0fe4) (BuildId: 88e08219618dea7389271ee16a11fec8de0df8a0)

2025/12/11 22:08:46 [alert] 241285#241285: worker process 241412 exited on signal 4 (core dumped)

Timeline of the bug:

  1. Master process (reload):

    • Creates new cycle
    • ngx_regex_module_init()pcre2_jit_compile()
    • Allocates JIT executable memory at 0x7f8ab7e17xxx
  2. Old worker process (graceful shutdown):

    • ngx_worker_process_exit()ngx_regex_cleanup()
    • pcre2_code_free()sljit_free_exec()
    • Attempts to free the same JIT memory region
  3. Master process forks new workers

    • Workers inherit memory mappings (COW)

Alternatives Considered

No response

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions