ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:105737] [Ruby master Bug#18260] YJIT uses insecure mmap protections
@ 2021-10-21 15:58 jeremyevans0 (Jeremy Evans)
  2021-10-21 20:34 ` [ruby-core:105741] " maximecb (Maxime Chevalier-Boisvert)
  2021-12-01 21:07 ` [ruby-core:106367] " jeremyevans0 (Jeremy Evans)
  0 siblings, 2 replies; 3+ messages in thread
From: jeremyevans0 (Jeremy Evans) @ 2021-10-21 15:58 UTC (permalink / raw)
  To: ruby-core

Issue #18260 has been reported by jeremyevans0 (Jeremy Evans).

----------------------------------------
Bug #18260: YJIT uses insecure mmap protections
https://bugs.ruby-lang.org/issues/18260

* Author: jeremyevans0 (Jeremy Evans)
* Status: Open
* Priority: Normal
* Assignee: maximecb (Maxime Chevalier-Boisvert)
* Backport: 2.6: DONTNEED, 2.7: DONTNEED, 3.0: DONTNEED
----------------------------------------
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`).



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [ruby-core:105741] [Ruby master Bug#18260] YJIT uses insecure mmap protections
  2021-10-21 15:58 [ruby-core:105737] [Ruby master Bug#18260] YJIT uses insecure mmap protections jeremyevans0 (Jeremy Evans)
@ 2021-10-21 20:34 ` maximecb (Maxime Chevalier-Boisvert)
  2021-12-01 21:07 ` [ruby-core:106367] " jeremyevans0 (Jeremy Evans)
  1 sibling, 0 replies; 3+ messages in thread
From: maximecb (Maxime Chevalier-Boisvert) @ 2021-10-21 20:34 UTC (permalink / raw)
  To: ruby-core

Issue #18260 has been updated by maximecb (Maxime Chevalier-Boisvert).


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.

----------------------------------------
Bug #18260: YJIT uses insecure mmap protections
https://bugs.ruby-lang.org/issues/18260#change-94242

* Author: jeremyevans0 (Jeremy Evans)
* Status: Open
* Priority: Normal
* Assignee: maximecb (Maxime Chevalier-Boisvert)
* Backport: 2.6: DONTNEED, 2.7: DONTNEED, 3.0: DONTNEED
----------------------------------------
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`).



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [ruby-core:106367] [Ruby master Bug#18260] YJIT uses insecure mmap protections
  2021-10-21 15:58 [ruby-core:105737] [Ruby master Bug#18260] YJIT uses insecure mmap protections jeremyevans0 (Jeremy Evans)
  2021-10-21 20:34 ` [ruby-core:105741] " maximecb (Maxime Chevalier-Boisvert)
@ 2021-12-01 21:07 ` jeremyevans0 (Jeremy Evans)
  1 sibling, 0 replies; 3+ messages in thread
From: jeremyevans0 (Jeremy Evans) @ 2021-12-01 21:07 UTC (permalink / raw)
  To: ruby-core

Issue #18260 has been updated by jeremyevans0 (Jeremy Evans).

Status changed from Open to Closed

Fixed by commit:157095b3a44d8b0130a532a0b7be3f5ac197111c

----------------------------------------
Bug #18260: YJIT uses insecure mmap protections
https://bugs.ruby-lang.org/issues/18260#change-95002

* Author: jeremyevans0 (Jeremy Evans)
* Status: Closed
* Priority: Normal
* Assignee: maximecb (Maxime Chevalier-Boisvert)
* Backport: 2.6: DONTNEED, 2.7: DONTNEED, 3.0: DONTNEED
----------------------------------------
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`).



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-12-01 21:08 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-21 15:58 [ruby-core:105737] [Ruby master Bug#18260] YJIT uses insecure mmap protections jeremyevans0 (Jeremy Evans)
2021-10-21 20:34 ` [ruby-core:105741] " maximecb (Maxime Chevalier-Boisvert)
2021-12-01 21:07 ` [ruby-core:106367] " jeremyevans0 (Jeremy Evans)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).