CVE-2022-28073 (published 2023-08-22T19:16Z)

A use after free in r_reg_set_value function in radare2 5.4.2 and 5.4.0.

CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-416
cwe_name: Use After Free
description: The product reuses or references memory after it has been freed. At some point afterward, the memory may be allocated again and saved in another pointer, while the original pointer references a location somewhere within the new allocation. Any operations using the original pointer are no longer valid because the memory "belongs" to the code that operates on the new pointer.
extended_description: 
             
             
             
			 
             
             
         
         

Fix information:
repo_url: https://github.com/radareorg/radare2
commit_details: repo_url: https://github.com/radareorg/radare2
author: Sergi Àlvarez i Capilla
author_date: 2021-10-30 00:51:53+02:00
msg: Fix uaf crash in aaft (tests_64927) ##crash

Reported by giantbranch of NSFOCUS TIANJI Lab
repository: repo_url: https://github.com/radareorg/radare2
repo_name: radareorg/radare2
description: UNIX-like reverse engineering framework and command-line toolset
repo_language: C
owner: radareorg
file_changes: filename: anal_tp.c
change_type: ModificationType.MODIFY
diff: @@ -510,16 +510,16 @@ R_API void r_core_anal_type_match(RCore *core, RAnalFunction *fcn) {
 		return;
 	}
 	char *pc = strdup (_pc);
-	RRegItem *r = r_reg_get (core->dbg->reg, pc, -1);
-	if (!r) {
-		free (buf);
-		return;
-	}
 	r_cons_break_push (NULL, NULL);
 	r_list_sort (fcn->bbs, bb_cmpaddr); // TODO: The algorithm can be more accurate if blocks are followed by their jmp/fail, not just by address
 	r_list_foreach (fcn->bbs, it, bb) {
 		ut64 addr = bb->addr;
 		int i = 0;
+		RRegItem *r = r_reg_get (core->dbg->reg, pc, -1);
+		if (!r) {
+			free (buf);
+			return;
+		}
 		r_reg_set_value (core->dbg->reg, r, addr);
 		while (1) {
 			if (r_cons_is_breaked ()) {
@@ -549,6 +549,11 @@ R_API void r_core_anal_type_match(RCore *core, RAnalFunction *fcn) {
 			}
 			sdb_num_set (anal->esil->trace->db, sdb_fmt ("0x%"PFMT64x".count", addr), loop_count + 1, 0);
 			if (r_anal_op_nonlinear (aop.type)) {   // skip the instr
+				RRegItem *r = r_reg_get (core->dbg->reg, pc, -1);
+				if (!r) {
+					free (buf);
+					return;
+				}
 				r_reg_set_value (core->dbg->reg, r, addr + ret);
 			} else {
 				r_core_esil_step (core, UT64_MAX, NULL, NULL, false);

programming_language: C
filename: cmd_anal.c
change_type: ModificationType.MODIFY
diff: @@ -4766,7 +4766,7 @@ void cmd_anal_reg(RCore *core, const char *str) {
 	int size = 0, i, type = R_REG_TYPE_GPR;
 	int bits = (core->anal->bits & R_SYS_BITS_64)? 64: 32;
 	int use_colors = r_config_get_i (core->config, "scr.color");
-	RRegItem *r;
+	RRegItem *r = NULL;
 	const char *use_color;
 	const char *name;
 	char *arg;
@@ -5098,6 +5098,7 @@ void cmd_anal_reg(RCore *core, const char *str) {
 		arg = strchr (str + 1, '=');
 		if (arg) {
 			*arg = 0;
+			ut64 n = r_num_math (core->num, arg + 1);
 			char *ostr = r_str_trim_dup (str + 1);
 			char *regname = r_str_trim_nc (ostr);
 			r = r_reg_get (core->dbg->reg, regname, -1);
@@ -5113,8 +5114,7 @@ void cmd_anal_reg(RCore *core, const char *str) {
 			if (r) {
 				//eprintf ("%s 0x%08"PFMT64x" -> ", str,
 				//	r_reg_get_value (core->dbg->reg, r));
-				r_reg_set_value (core->dbg->reg, r,
-						r_num_math (core->num, arg + 1));
+				r_reg_set_value (core->dbg->reg, r, n); 
 				r_debug_reg_sync (core->dbg, R_REG_TYPE_ALL, true);
 				//eprintf ("0x%08"PFMT64x"\n",
 				//	r_reg_get_value (core->dbg->reg, r));

programming_language: Go
filename: rvalue.c
change_type: ModificationType.MODIFY
diff: @@ -141,9 +141,10 @@ R_API ut64 r_reg_get_value_by_role(RReg *reg, RRegisterId role) {
 }
 
 R_API bool r_reg_set_value(RReg *reg, RRegItem *item, ut64 value) {
+	r_return_val_if_fail (reg && item, false);
+
 	ut8 bytes[12];
 	ut8 *src = bytes;
-	r_return_val_if_fail (reg && item, false);
 
 	if (r_reg_is_readonly (reg, item)) {
 		return true;

programming_language: C