From a68739048ab72be15f9a31d0c0c57d847394f19d Mon Sep 17 00:00:00 2001 From: Shubham Shinde Date: Tue, 4 Jun 2024 15:39:26 +0530 Subject: [PATCH] (PA-6386) Patch/Upgrade Ruby for CVE-2024-27282 - Patches the ruby 'Use-After-Free' issue for regexp for 7.x (ruby 2.7.8). - Upstream fix commit: ruby/ruby@90b194b - Bump projects using ruby 3.2.3 to ruby 3.2.4 since 3.2.4 has addressed the CVE. - Adjust windows patches for ruby 3.2.4 --- configs/components/ruby-2.7.8.rb | 1 + .../{ruby-3.2.3.rb => ruby-3.2.4.rb} | 6 ++-- configs/projects/agent-runtime-main.rb | 2 +- configs/projects/pdk-runtime.rb | 2 +- .../projects/pe-bolt-server-runtime-main.rb | 2 +- configs/projects/pe-installer-runtime-main.rb | 2 +- .../ruby_27/regexp_use_after_free.patch | 13 +++++++ .../revert-ruby-double-load-symlink.patch | 35 +++++++++---------- ...d_up_rebuilding_loaded_feature_index.patch | 6 ++-- 9 files changed, 41 insertions(+), 28 deletions(-) rename configs/components/{ruby-3.2.3.rb => ruby-3.2.4.rb} (98%) create mode 100644 resources/patches/ruby_27/regexp_use_after_free.patch diff --git a/configs/components/ruby-2.7.8.rb b/configs/components/ruby-2.7.8.rb index 9af699e1e..cf1df8999 100644 --- a/configs/components/ruby-2.7.8.rb +++ b/configs/components/ruby-2.7.8.rb @@ -38,6 +38,7 @@ base = 'resources/patches/ruby_27' # Patch for https://bugs.ruby-lang.org/issues/14972 pkg.apply_patch "#{base}/net_http_eof_14972_r2.5.patch" + pkg.apply_patch "#{base}/regexp_use_after_free.patch" pkg.apply_patch "#{base}/uri-redos-cve-2023-36617.patch" diff --git a/configs/components/ruby-3.2.3.rb b/configs/components/ruby-3.2.4.rb similarity index 98% rename from configs/components/ruby-3.2.3.rb rename to configs/components/ruby-3.2.4.rb index b7e4a69df..b5e808a1b 100644 --- a/configs/components/ruby-3.2.3.rb +++ b/configs/components/ruby-3.2.4.rb @@ -1,7 +1,7 @@ # The file name of the ruby component must match the ruby_version -component 'ruby-3.2.3' do |pkg, settings, platform| - pkg.version '3.2.3' - pkg.sha256sum 'af7f1757d9ddb630345988139211f1fd570ff5ba830def1cc7c468ae9b65c9ba' +component 'ruby-3.2.4' do |pkg, settings, platform| + pkg.version '3.2.4' + pkg.sha256sum 'c72b3c5c30482dca18b0f868c9075f3f47d8168eaf626d4e682ce5b59c858692' # rbconfig-update is used to munge rbconfigs after the fact. pkg.add_source("file://resources/files/ruby/rbconfig-update.rb") diff --git a/configs/projects/agent-runtime-main.rb b/configs/projects/agent-runtime-main.rb index 26f20c4ca..bf08e684e 100644 --- a/configs/projects/agent-runtime-main.rb +++ b/configs/projects/agent-runtime-main.rb @@ -1,7 +1,7 @@ project 'agent-runtime-main' do |proj| # Set preferred component versions if they differ from defaults: - proj.setting :ruby_version, '3.2.3' + proj.setting :ruby_version, '3.2.4' proj.setting :rubygem_deep_merge_version, '1.2.2' proj.setting :rubygem_highline_version, '3.0.1' proj.setting :rubygem_hocon_version, '1.4.0' diff --git a/configs/projects/pdk-runtime.rb b/configs/projects/pdk-runtime.rb index cd6ea3edc..d5ff4b6ec 100644 --- a/configs/projects/pdk-runtime.rb +++ b/configs/projects/pdk-runtime.rb @@ -48,7 +48,7 @@ proj.setting(:includedir, File.join(proj.prefix, 'include')) proj.setting(:bindir, File.join(proj.prefix, 'bin')) - proj.setting(:ruby_version, '3.2.3') + proj.setting(:ruby_version, '3.2.4') proj.setting(:ruby_major_version, 3) proj.setting(:ruby_api, '3.2.0') diff --git a/configs/projects/pe-bolt-server-runtime-main.rb b/configs/projects/pe-bolt-server-runtime-main.rb index 2bd5c4a94..5495b89ee 100644 --- a/configs/projects/pe-bolt-server-runtime-main.rb +++ b/configs/projects/pe-bolt-server-runtime-main.rb @@ -6,7 +6,7 @@ # Once we are no longer using ruby 2.5 we can update. proj.setting(:no_doc, true) - proj.setting(:ruby_version, '3.2.3') + proj.setting(:ruby_version, '3.2.4') proj.setting(:openssl_version, '3.0') # We enable legacy algorithms for winrm transport. Currently the winrm transport diff --git a/configs/projects/pe-installer-runtime-main.rb b/configs/projects/pe-installer-runtime-main.rb index c5bfd22a0..6fdfc66cf 100644 --- a/configs/projects/pe-installer-runtime-main.rb +++ b/configs/projects/pe-installer-runtime-main.rb @@ -1,5 +1,5 @@ project 'pe-installer-runtime-main' do |proj| - proj.setting(:ruby_version, '3.2.3') + proj.setting(:ruby_version, '3.2.4') proj.setting(:openssl_version, '3.0') # NLTM uses MD4 unconditionally in its protocol, so legacy algos must be # enabled in OpenSSL >= 3.0 for Bolt's WinRM transport to work. diff --git a/resources/patches/ruby_27/regexp_use_after_free.patch b/resources/patches/ruby_27/regexp_use_after_free.patch new file mode 100644 index 000000000..8b58d9cd7 --- /dev/null +++ b/resources/patches/ruby_27/regexp_use_after_free.patch @@ -0,0 +1,13 @@ +diff --git a/regexec.c b/regexec.c +index 73694ab14a..140691ad42 100644 +--- a/regexec.c ++++ b/regexec.c +@@ -3449,8 +3449,8 @@ match_at(regex_t* reg, const UChar* str, const UChar* end, + CASE(OP_MEMORY_END_PUSH_REC) MOP_IN(OP_MEMORY_END_PUSH_REC); + GET_MEMNUM_INC(mem, p); + STACK_GET_MEM_START(mem, stkp); /* should be before push mem-end. */ +- STACK_PUSH_MEM_END(mem, s); + mem_start_stk[mem] = GET_STACK_INDEX(stkp); ++ STACK_PUSH_MEM_END(mem, s); + MOP_OUT; + JUMP; diff --git a/resources/patches/ruby_32/revert-ruby-double-load-symlink.patch b/resources/patches/ruby_32/revert-ruby-double-load-symlink.patch index 07afc2c53..7520f80ed 100644 --- a/resources/patches/ruby_32/revert-ruby-double-load-symlink.patch +++ b/resources/patches/ruby_32/revert-ruby-double-load-symlink.patch @@ -28,13 +28,13 @@ Date: Wed Feb 22 11:53:00 2023 -0800 which is very unlikely on Windows, so revert it. diff --git a/load.c b/load.c -index 282bebdb62..636a124d03 100644 +index 818665dde8..9a2ae8a8dc 100644 --- a/load.c +++ b/load.c @@ -157,12 +157,6 @@ get_loaded_features(rb_vm_t *vm) return vm->loaded_features; } - + -static VALUE -get_loaded_features_realpaths(rb_vm_t *vm) -{ @@ -47,17 +47,16 @@ index 282bebdb62..636a124d03 100644 @@ -360,8 +354,6 @@ get_loaded_features_index(rb_vm_t *vm) modified loaded_features. Rebuild the index. */ st_foreach(vm->loaded_features_index, loaded_features_index_clear_i, 0); - + - VALUE realpaths = vm->loaded_features_realpaths; - rb_hash_clear(realpaths); features = vm->loaded_features; for (i = 0; i < RARRAY_LEN(features); i++) { VALUE entry, as_str; -@@ -373,15 +365,6 @@ get_loaded_features_index(rb_vm_t *vm) - features_index_add(vm, as_str, INT2FIX(i)); +@@ -374,14 +366,6 @@ get_loaded_features_index(rb_vm_t *vm) } reset_loaded_features_snapshot(vm); -- + - features = rb_ary_dup(vm->loaded_features_snapshot); - long j = RARRAY_LEN(features); - for (i = 0; i < j; i++) { @@ -69,7 +68,7 @@ index 282bebdb62..636a124d03 100644 } return vm->loaded_features_index; } -@@ -1158,8 +1141,6 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa +@@ -1161,8 +1145,6 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa char *volatile ftptr = 0; VALUE path; volatile VALUE saved_path; @@ -77,11 +76,11 @@ index 282bebdb62..636a124d03 100644 - VALUE realpaths = get_loaded_features_realpaths(th->vm); volatile bool reset_ext_config = false; struct rb_ext_config prev_ext_config; - -@@ -1192,10 +1173,6 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa + +@@ -1192,10 +1174,6 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa + else if (found == 's' && run_static_ext_init(th->vm, RSTRING_PTR(path))) { result = TAG_RETURN; } - #endif - else if (RTEST(rb_hash_aref(realpaths, - realpath = rb_realpath_internal(Qnil, path, 1)))) { - result = 0; @@ -89,8 +88,8 @@ index 282bebdb62..636a124d03 100644 else { switch (found) { case 'r': -@@ -1249,10 +1226,6 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa - +@@ -1249,10 +1227,6 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa + if (result == TAG_RETURN) { rb_provide_feature(th2->vm, path); - VALUE real = realpath; @@ -99,14 +98,14 @@ index 282bebdb62..636a124d03 100644 - } } ec->errinfo = saved.errinfo; - -@@ -1470,8 +1443,6 @@ Init_load(void) + +@@ -1485,8 +1485,6 @@ Init_load(void) vm->loaded_features = rb_ary_new(); vm->loaded_features_snapshot = rb_ary_hidden_new(0); vm->loaded_features_index = st_init_numtable(); - vm->loaded_features_realpaths = rb_hash_new(); - rb_obj_hide(vm->loaded_features_realpaths); - + rb_define_global_function("load", rb_f_load, -1); rb_define_global_function("require", rb_f_require, 1); diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb @@ -167,14 +166,14 @@ index 4c2ef9834e..4fa4ec2b54 100644 rb_gc_mark_movable(vm->orig_progname); RUBY_MARK_MOVABLE_UNLESS_NULL(vm->coverages); diff --git a/vm_core.h b/vm_core.h -index 4f6e07d818..6b9cfca2cd 100644 +index 1842519edd..eb2265c97d 100644 --- a/vm_core.h +++ b/vm_core.h -@@ -679,7 +679,6 @@ typedef struct rb_vm_struct { +@@ -675,7 +675,6 @@ typedef struct rb_vm_struct { VALUE expanded_load_path; VALUE loaded_features; VALUE loaded_features_snapshot; - VALUE loaded_features_realpaths; struct st_table *loaded_features_index; struct st_table *loading_table; - #if EXTSTATIC + // For running the init function of statically linked diff --git a/resources/patches/ruby_32/revert_speed_up_rebuilding_loaded_feature_index.patch b/resources/patches/ruby_32/revert_speed_up_rebuilding_loaded_feature_index.patch index 7ccc483ee..d8fbc7de9 100644 --- a/resources/patches/ruby_32/revert_speed_up_rebuilding_loaded_feature_index.patch +++ b/resources/patches/ruby_32/revert_speed_up_rebuilding_loaded_feature_index.patch @@ -132,14 +132,14 @@ index de43d022c0..d009a5f64a 100644 rb_gc_mark_movable(vm->orig_progname); RUBY_MARK_MOVABLE_UNLESS_NULL(vm->coverages); diff --git a/vm_core.h b/vm_core.h -index b6adeadd87..d86fdbaecd 100644 +index a8c1e6b917..1842519edd 100644 --- a/vm_core.h +++ b/vm_core.h -@@ -680,7 +680,6 @@ typedef struct rb_vm_struct { +@@ -676,7 +676,6 @@ typedef struct rb_vm_struct { VALUE loaded_features; VALUE loaded_features_snapshot; VALUE loaded_features_realpaths; - VALUE loaded_features_realpath_map; struct st_table *loaded_features_index; struct st_table *loading_table; - #if EXTSTATIC + // For running the init function of statically linked