Project

General

Profile

Actions

Bug #18260

closed

YJIT uses insecure mmap protections

Added by jeremyevans0 (Jeremy Evans) about 2 months ago. Updated 4 days ago.

Status:
Closed
Priority:
Normal
Target version:
-
[ruby-core:105737]

Description

YJIT uses mmap with PROT_READ | PROT_WRITE | PROT_EXEC protections, which reduces security because it makes code injection attacks much easier, as the attacker only needs to be able to write their shellcode to the mapped memory region and then directly jump to the shellcode just written.

The security principle being violated here is referred to as W^X (W xor X). Basically, memory can be either writable or executable, but never both at the same.

OpenBSD has disallowed mmap with PROT_WRITE | PROT_EXEC by default since 2016. NetBSD/Linux with PaX MPROTECT disallows this as well, as does SELinux unless you enable allow_execmem.

Fixing this generally involves initially mapping pages with PROT_READ | PROT_WRITE, and after writing executable code, using mprotect to switch to PROT_READ | PROT_EXEC. This is the approach that Firefox takes for their Javascript engine starting in Firefox 46. This makes code injection attacks more difficult as an attacker either cannot write the shellcode (if mapped PROT_READ | PROT_EXEC), or cannot jump directly to the shellcode after writing (if mapped PROT_READ | PROT_WRITE).

Updated by maximecb (Maxime Chevalier-Boisvert) about 2 months ago

We can look into this. The downside is that YJIT does a lot of code patching, so this would presumably involve two system calls every time YJIT needs to generate code. Hopefully the performance impact will be relatively minimal.

Updated by jeremyevans0 (Jeremy Evans) 4 days ago

  • Status changed from Open to Closed
Actions

Also available in: Atom PDF