diff options
author | Peter Zhu <[email protected]> | 2024-06-20 13:25:30 -0400 |
---|---|---|
committer | Peter Zhu <[email protected]> | 2024-06-21 11:49:01 -0400 |
commit | 90763e04ba2200f96a485d2ef3bb56817ae1b2db (patch) | |
tree | a5b9327ee455e0ab5ff25487f348aff3e39f98a6 | |
parent | bd583ca645ea348a2894f4227fcb1af650ee8dec (diff) |
Load external GC using command line argument
This commit changes the external GC to be loaded with the `--gc-library`
command line argument instead of the RUBY_GC_LIBRARY_PATH environment
variable because @nobu pointed out that loading binaries using environment
variables can pose a security risk.
-rw-r--r-- | gc.c | 42 | ||||
-rw-r--r-- | main.c | 5 | ||||
-rw-r--r-- | ruby.c | 10 | ||||
-rw-r--r-- | vm_core.h | 11 |
4 files changed, 38 insertions, 30 deletions
@@ -1862,31 +1862,44 @@ static void *rb_gc_impl_objspace_alloc(void); #if USE_SHARED_GC # include "dln.h" -# define RUBY_GC_LIBRARY_PATH "RUBY_GC_LIBRARY_PATH" +typedef struct gc_function_map { + void *(*objspace_alloc)(void); +} rb_gc_function_map_t; -static void -ruby_external_gc_init(void) +static rb_gc_function_map_t rb_gc_functions; + +# define RUBY_GC_LIBRARY_ARG "--gc-library=" + +void +ruby_load_external_gc_from_argv(int argc, char **argv) { - char *gc_so_path = getenv(RUBY_GC_LIBRARY_PATH); + char *gc_so_path = NULL; + + for (int i = 0; i < argc; i++) { + if (strncmp(argv[i], RUBY_GC_LIBRARY_ARG, sizeof(RUBY_GC_LIBRARY_ARG) - 1) == 0) { + gc_so_path = argv[i] + sizeof(RUBY_GC_LIBRARY_ARG) - 1; + } + } + void *handle = NULL; if (gc_so_path && dln_supported_p()) { char error[1024]; handle = dln_open(gc_so_path, error, sizeof(error)); if (!handle) { fprintf(stderr, "%s", error); - rb_bug("ruby_external_gc_init: Shared library %s cannot be opened", gc_so_path); + rb_bug("ruby_load_external_gc_from_argv: Shared library %s cannot be opened", gc_so_path); } } # define load_external_gc_func(name) do { \ if (handle) { \ - rb_gc_functions->name = dln_symbol(handle, "rb_gc_impl_" #name); \ - if (!rb_gc_functions->name) { \ - rb_bug("ruby_external_gc_init: " #name " func not exported by library %s", gc_so_path); \ + rb_gc_functions.name = dln_symbol(handle, "rb_gc_impl_" #name); \ + if (!rb_gc_functions.name) { \ + rb_bug("ruby_load_external_gc_from_argv: " #name " func not exported by library %s", gc_so_path); \ } \ } \ else { \ - rb_gc_functions->name = rb_gc_impl_##name; \ + rb_gc_functions.name = rb_gc_impl_##name; \ } \ } while (0) @@ -1895,15 +1908,12 @@ ruby_external_gc_init(void) # undef load_external_gc_func } -# define rb_gc_impl_objspace_alloc rb_gc_functions->objspace_alloc +# define rb_gc_impl_objspace_alloc rb_gc_functions.objspace_alloc #endif rb_objspace_t * rb_objspace_alloc(void) { -#if USE_SHARED_GC - ruby_external_gc_init(); -#endif return (rb_objspace_t *)rb_gc_impl_objspace_alloc(); } @@ -13638,12 +13648,6 @@ rb_gcdebug_remove_stress_to_class(int argc, VALUE *argv, VALUE self) void Init_GC(void) { -#if USE_SHARED_GC - if (getenv(RUBY_GC_LIBRARY_PATH) != NULL && !dln_supported_p()) { - rb_warn(RUBY_GC_LIBRARY_PATH " is ignored because this executable file can't load extension libraries"); - } -#endif - #undef rb_intern malloc_offset = gc_compute_malloc_offset(); @@ -32,10 +32,15 @@ # undef RUBY_DEBUG_ENV #endif +void ruby_load_external_gc_from_argv(int argc, char **argv); + static int rb_main(int argc, char **argv) { RUBY_INIT_STACK; +#if USE_SHARED_GC + ruby_load_external_gc_from_argv(argc, argv); +#endif ruby_init(); return ruby_run_node(ruby_options(argc, argv)); } @@ -1436,6 +1436,16 @@ proc_long_options(ruby_cmdline_options_t *opt, const char *s, long argc, char ** set_source_encoding_once(opt, s, 0); } #endif +#if defined(USE_SHARED_GC) && USE_SHARED_GC + else if (is_option_with_arg("gc-library", Qfalse, Qfalse)) { + // no-op + // Handled by ruby_load_external_gc_from_argv + + if (!dln_supported_p()) { + rb_warn("--gc-library is ignored because this executable file can't load extension libraries"); + } + } +#endif else if (strcmp("version", s) == 0) { if (envopt) goto noenvopt_long; opt->dump |= DUMP_BIT(version); @@ -106,14 +106,6 @@ extern int ruby_assert_critical_section_entered; #include "ruby/thread_native.h" -#if USE_SHARED_GC -typedef struct gc_function_map { - void *(*objspace_alloc)(void); -} rb_gc_function_map_t; - -#define rb_gc_functions (&GET_VM()->gc_functions_map) -#endif - /* * implementation selector of get_insn_info algorithm * 0: linear search @@ -761,9 +753,6 @@ typedef struct rb_vm_struct { int coverage_mode; struct rb_objspace *objspace; -#if USE_SHARED_GC - rb_gc_function_map_t gc_functions_map; -#endif rb_at_exit_list *at_exit; |