File 0691-erts-Fix-bugs-doing-HAlloc-without-process-main-lock.patch of Package erlang

From eb5915d3f46ae9ba4b1fbf7c5e650ec1a0efa444 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson <sverker@erlang.org>
Date: Mon, 20 Jan 2020 20:04:36 +0100
Subject: [PATCH] erts: Fix bugs doing HAlloc without process main lock

after erts_thr_progress_block() has been called.

Dirty schedulers may still be running NIFs
that may seize the main lock to send a message for example
and thereby potentially corrupt the heap.
---
 erts/emulator/beam/beam_bif_load.c   | 4 +++-
 erts/emulator/beam/dist.c            | 2 +-
 erts/emulator/beam/erl_bif_trace.c   | 5 ++---
 erts/emulator/beam/erl_nif.c         | 2 +-
 erts/emulator/beam/erl_node_tables.c | 5 +++--
 erts/emulator/beam/erl_process.c     | 3 +--
 6 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index 19b6deecea..a7d16c6f2b 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -377,6 +377,7 @@ finish_loading_1(BIF_ALIST_1)
 	    /* tracing or hipe need thread blocking */
 	    erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
 	    erts_thr_progress_block();
+            erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
 	    is_blocking = 1;
 	    break;
 	}
@@ -464,7 +465,6 @@ staging_epilogue(Process* c_p, int commit, Eterm res, int is_blocking,
 	}
 	if (is_blocking) {
 	    erts_thr_progress_unblock();
-	    erts_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
 	}
 	erts_release_code_write_permission();
 	return res;
@@ -661,6 +661,7 @@ BIF_RETTYPE delete_module_1(BIF_ALIST_1)
 		/* tracing or hipe need to go single threaded */
 		erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
 		erts_thr_progress_block();
+                erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
 		is_blocking = 1;
 		if (modp->curr.num_breakpoints) {
 		    erts_clear_module_break(modp);
@@ -794,6 +795,7 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
 
             erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
             erts_thr_progress_block();
+            erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
             is_blocking = 1;
 	}
 
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index bbe2fc31f3..277ac378e9 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -4379,6 +4379,7 @@ erts_processes_monitoring_nodes(Process *c_p)
 
     erts_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN);
     erts_thr_progress_block();
+    erts_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
 
     erts_mtx_lock(&nodes_monitors_mtx);
 
@@ -4409,7 +4410,6 @@ erts_processes_monitoring_nodes(Process *c_p)
     erts_mtx_unlock(&nodes_monitors_mtx);
 
     erts_thr_progress_unblock();
-    erts_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
 
     return ctxt.res;
 }
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index b31d5b86cb..4162a6c591 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -1125,6 +1125,7 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key)
     if ( (key == am_call_time) || (key == am_all)) {
 	erts_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
 	erts_thr_progress_block();
+        erts_proc_lock(p, ERTS_PROC_LOCK_MAIN);
     }
     erts_mtx_lock(&erts_dirty_bp_ix_mtx);
 
@@ -1134,7 +1135,6 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key)
     erts_mtx_unlock(&erts_dirty_bp_ix_mtx);
     if ( (key == am_call_time) || (key == am_all)) {
 	erts_thr_progress_unblock();
-	erts_proc_lock(p, ERTS_PROC_LOCK_MAIN);
     }
 
     switch (r) {
@@ -2194,6 +2194,7 @@ system_monitor(Process *p, Eterm monitor_pid, Eterm list)
 	system_blocked = 1;
 	erts_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
 	erts_thr_progress_block();
+        erts_proc_lock(p, ERTS_PROC_LOCK_MAIN);
 
 	if (!erts_pid2proc(p, ERTS_PROC_LOCK_MAIN, monitor_pid, 0))
 	    goto error;
@@ -2233,7 +2234,6 @@ system_monitor(Process *p, Eterm monitor_pid, Eterm list)
 	erts_system_monitor_flags.busy_dist_port = !!busy_dist_port;
 
 	erts_thr_progress_unblock();
-	erts_proc_lock(p, ERTS_PROC_LOCK_MAIN);
 	BIF_RET(prev);
     }
 
@@ -2241,7 +2241,6 @@ system_monitor(Process *p, Eterm monitor_pid, Eterm list)
 
     if (system_blocked) {
 	erts_thr_progress_unblock();
-	erts_proc_lock(p, ERTS_PROC_LOCK_MAIN);
     }
 
     BIF_ERROR(p, BADARG);
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index ebef485b04..dccfd54110 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -4056,6 +4056,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
     /* Block system (is this the right place to do it?) */
     erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
     erts_thr_progress_block();
+    erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
 
     /* Find calling module */
     ASSERT(BIF_P->current != NULL);
@@ -4270,7 +4271,6 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
     }
 
     erts_thr_progress_unblock();
-    erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
     erts_release_code_write_permission();
     erts_free(ERTS_ALC_T_TMP, lib_name);
 
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index 8a80ecfa87..db3b9e3d58 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -1251,7 +1251,9 @@ erts_get_node_and_dist_references(struct process *proc)
 
     erts_proc_unlock(proc, ERTS_PROC_LOCK_MAIN);
     erts_thr_progress_block();
-    /* No need to lock any thing since we are alone... */
+    erts_proc_lock(proc, ERTS_PROC_LOCK_MAIN);
+    /* No need to lock any thing else since we are alone...
+       ... except dirty stuff... (?) */
 
     if (references_atoms_need_init) {
 	INIT_AM(heap);
@@ -1296,7 +1298,6 @@ erts_get_node_and_dist_references(struct process *proc)
     delete_reference_table();
 
     erts_thr_progress_unblock();
-    erts_proc_lock(proc, ERTS_PROC_LOCK_MAIN);
     return res;
 }
 
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 912dfa6b64..718fbfe95f 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -13165,8 +13165,7 @@ erts_dbg_check_halloc_lock(Process *p)
     esdp = erts_proc_sched_data(p);
     if (esdp && p == esdp->match_pseudo_process)
 	return 1;
-    if (erts_thr_progress_is_blocking())
-	return 1;
+    /* erts_thr_progress_is_blocking() is not enough as dirty NIFs may run */
     return 0;
 }
 #endif
-- 
2.16.4

openSUSE Build Service is sponsored by