[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 1/2] Add user-visible functions jit_protect and jit_unprotect.
From: |
marc . nieper+gnu |
Subject: |
[PATCH 1/2] Add user-visible functions jit_protect and jit_unprotect. |
Date: |
Mon, 31 Oct 2022 13:15:31 +0100 |
From: Marc Nieper-Wißkirchen <marc@nieper-wisskirchen.de>
* check/Makefile.am: Add test for jit_protect and jit_unprotect.
* check/protect.c: New test.
* doc/body.texi: Add documentation for jit_protect and
jit_unprotect.
* include/lightning.h.in: Add prototypes for jit_protect and
jit_unprotect.
* include/lightning/jit_private.h: Add a field to store the size
of the protected memory.
* lib/lightning.c: Remember the size of the protected memory and
implement the two new functions.
---
ChangeLog | 14 ++++++++
check/Makefile.am | 8 +++--
check/protect.c | 59 +++++++++++++++++++++++++++++++++
doc/body.texi | 22 ++++++++++++
include/lightning.h.in | 4 +++
include/lightning/jit_private.h | 2 ++
lib/lightning.c | 32 ++++++++++++++++--
7 files changed, 136 insertions(+), 5 deletions(-)
create mode 100644 check/protect.c
diff --git a/ChangeLog b/ChangeLog
index 40ade7a..0848e6c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2022-10-30 Marc Nieper-Wißkirchen <marc@nieper-wisskirchen.de>
+
+ Add user-visible functions jit_protect and jit_unprotect.
+ * check/Makefile.am: Add test for jit_protect and jit_unprotect.
+ * check/protect.c: New test.
+ * doc/body.texi: Add documentation for jit_protect and
+ jit_unprotect.
+ * include/lightning.h.in: Add prototypes for jit_protect and
+ jit_unprotect.
+ * include/lightning/jit_private.h: Add a field to store the size
+ of the protected memory.
+ * lib/lightning.c: Remember the size of the protected memory and
+ implement the two new functions.
+
2022-10-12 Paulo Andrade <pcpa@gnu.org>
* include/lightning/jit_loongarch.h, lib/jit_loongarch-cpu.c,
diff --git a/check/Makefile.am b/check/Makefile.am
index f58dc8b..f1839ef 100644
--- a/check/Makefile.am
+++ b/check/Makefile.am
@@ -17,7 +17,7 @@
AM_CFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include -D_GNU_SOURCE
check_PROGRAMS = lightning ccall self setcode nodata ctramp carg cva_list \
- catomic
+ catomic protect
lightning_LDADD = $(top_builddir)/lib/liblightning.la -lm $(SHLIB)
lightning_SOURCES = lightning.c
@@ -46,6 +46,9 @@ cva_list_SOURCES = cva_list.c
catomic_LDADD = $(top_builddir)/lib/liblightning.la -lm -lpthread $(SHLIB)
catomic_SOURCES = catomic.c
+protect_LDADD = $(top_builddir)/lib/liblightning.la -lm $(SHLIB)
+protect_SOURCES = protect.c
+
$(top_builddir)/lib/liblightning.la:
cd $(top_builddir)/lib; $(MAKE) $(AM_MAKEFLAGS) liblightning.la
@@ -324,7 +327,8 @@ $(nodata_TESTS): check.nodata.sh
TESTS += $(nodata_TESTS)
endif
-TESTS += ccall self setcode nodata ctramp carg cva_list catomic
+TESTS += ccall self setcode nodata ctramp carg cva_list catomic \
+ protect
CLEANFILES = $(TESTS)
#TESTS_ENVIRONMENT=$(srcdir)/run-test;
diff --git a/check/protect.c b/check/protect.c
new file mode 100644
index 0000000..256242b
--- /dev/null
+++ b/check/protect.c
@@ -0,0 +1,59 @@
+/*
+ * Simple test of (un)protecting a code buffer.
+ */
+
+#include <lightning.h>
+#include <stdio.h>
+#include <assert.h>
+
+#define MARKER 10
+
+int
+main(int argc, char *argv[])
+{
+ jit_state_t *_jit;
+ jit_node_t *load, *label, *ok;
+ unsigned char *ptr;
+ void (*function)(void);
+ int mmap_prot, mmap_flags;
+
+ init_jit(argv[0]);
+ _jit = jit_new_state();
+
+ jit_prolog();
+
+ load = jit_movi(JIT_R0, 0);
+ jit_ldr_c(JIT_R0, JIT_R0);
+ ok = jit_forward();
+ jit_patch_at(jit_beqi(JIT_R0, MARKER), ok);
+ jit_prepare();
+ jit_pushargi(1);
+ jit_finishi(exit);
+ jit_link(ok);
+ jit_prepare();
+ jit_pushargi((jit_word_t)"%s\n");
+ jit_ellipsis();
+ jit_pushargi((jit_word_t)"ok");
+ jit_finishi(printf);
+
+ jit_epilog();
+ label = jit_indirect();
+ jit_prolog(); /* Reserves enough space for a byte. */
+ jit_patch_at(load, label);
+
+ function = jit_emit();
+ if (function == NULL)
+ abort();
+
+ jit_unprotect ();
+ ptr = jit_address (label);
+ *ptr = MARKER;
+ jit_protect ();
+
+ jit_clear_state();
+
+ (*function)();
+
+ jit_destroy_state();
+ finish_jit();
+}
diff --git a/doc/body.texi b/doc/body.texi
index 1d8d277..58f84ee 100644
--- a/doc/body.texi
+++ b/doc/body.texi
@@ -1680,6 +1680,28 @@ Get the current memory allocation function. Also, unlike
the GNU GMP
counterpart, it is an error to pass @code{NULL} pointers as arguments.
@end deftypefun
+@section Protection
+Unless an alternate code buffer is used (see below), @code{jit_emit}
+set the access protections that the code buffer's memory can be read and
+executed, but not modified. One can use the following functions after
+@code{jit_emit} but before @code{jit_clear} to temporarily lift the
+protection:
+
+@deftypefun void jit_unprotect ()
+Changes the access protection that the code buffer's memory can be read and
+modified. Before the emitted code can be invoked, @code{jit_protect}
+has to be called to reset the change.
+
+This procedure has no effect when an alternate code buffer (see below) is used.
+@end deftypefun
+
+@deftypefun void jit_protect ()
+Changes the access protection that the code buffer's memory can be read and
+executed.
+
+This procedure has no effect when an alternate code buffer (see below) is used.
+@end deftypefun
+
@section Alternate code buffer
To instruct @lightning{} to use an alternate code buffer it is required
to call @code{jit_realize} before @code{jit_emit}, and then query states
diff --git a/include/lightning.h.in b/include/lightning.h.in
index 67c6af1..2ed593b 100644
--- a/include/lightning.h.in
+++ b/include/lightning.h.in
@@ -1016,6 +1016,10 @@ extern void _jit_frame(jit_state_t*, jit_int32_t);
extern void _jit_tramp(jit_state_t*, jit_int32_t);
#define jit_emit() _jit_emit(_jit)
extern jit_pointer_t _jit_emit(jit_state_t*);
+#define jit_unprotect() _jit_unprotect(_jit)
+extern void _jit_unprotect(jit_state_t*);
+#define jit_protect() _jit_protect(_jit)
+extern void _jit_protect(jit_state_t*);
#define jit_print() _jit_print(_jit)
extern void _jit_print(jit_state_t*);
diff --git a/include/lightning/jit_private.h b/include/lightning/jit_private.h
index 6d93ad8..a0c59af 100644
--- a/include/lightning/jit_private.h
+++ b/include/lightning/jit_private.h
@@ -658,6 +658,8 @@ struct jit_state {
struct {
jit_uint8_t *ptr;
jit_word_t length;
+ /* PROTECTED bytes starting at PTR are mprotect'd. */
+ jit_word_t protected;
} code;
struct {
jit_uint8_t *ptr;
diff --git a/lib/lightning.c b/lib/lightning.c
index 00f2a07..b308844 100644
--- a/lib/lightning.c
+++ b/lib/lightning.c
@@ -2398,12 +2398,12 @@ _jit_emit(jit_state_t *_jit)
assert(result == 0);
}
if (!_jit->user_code) {
- length = _jit->pc.uc - _jit->code.ptr;
+ _jit->code.protected = _jit->pc.uc - _jit->code.ptr;
# if __riscv && __WORDSIZE == 64
/* FIXME should start adding consts at a page boundary */
- length -= _jitc->consts.hash.count * sizeof(jit_word_t);
+ _jit->code.protected -= _jitc->consts.hash.count * sizeof(jit_word_t);
# endif
- result = mprotect(_jit->code.ptr, length, PROT_READ | PROT_EXEC);
+ result = mprotect(_jit->code.ptr, _jit->code.protected, PROT_READ |
PROT_EXEC);
assert(result == 0);
}
#endif /* HAVE_MMAP */
@@ -2413,6 +2413,32 @@ fail:
return (NULL);
}
+void
+_jit_protect(jit_state_t *_jit)
+{
+#if !HAVE_MMAP
+ assert (_jit->user_code);
+#else
+ int result;
+ if (_jit->user_code) return;
+ result = mprotect (_jit->code.ptr, _jit->code.protected, PROT_READ |
PROT_EXEC);
+ assert (result == 0);
+#endif
+}
+
+void
+_jit_unprotect(jit_state_t *_jit)
+{
+#if !HAVE_MMAP
+ assert (_jit->user_code);
+#else
+ int result;
+ if (_jit->user_code) return;
+ result = mprotect (_jit->code.ptr, _jit->code.protected, PROT_READ |
PROT_WRITE);
+ assert (result == 0);
+#endif
+}
+
void
_jit_frame(jit_state_t *_jit, jit_int32_t frame)
{
--
2.34.1
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH 1/2] Add user-visible functions jit_protect and jit_unprotect.,
marc . nieper+gnu <=