CVE-2022-0849 (published 2022-03-05T10:15Z)

Use After Free in r_reg_get_name_idx in GitHub repository radareorg/radare2 prior to 5.6.6.

Severity: MEDIUM
CVSS v2 base score: 4.3 (AV:N/AC:M/Au:N/C:N/I:N/A:P)
CVSS v3 base score: 5.5, MEDIUM (CVSS:3.1/AV:L/AC:L/PR:N/UI:R/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: 2022-03-04 10:48:13+01:00
msg: aaef on arm/thumb switches causes uaf ##crash

* Reported by peacock-doris via huntr.dev
* Reproducer: poc_uaf_r_reg_get
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: kvx-dis.c
change_type: ModificationType.MODIFY
diff: @@ -94,9 +94,11 @@ static inline int kvx_is_tca_opcode(ut32 x) {
 	return (major > 1) && (major < 8);
 }
 
+#if UNUSED0
 static inline int kvx_is_nop_opcode(ut32 x) {
 	return ((x)<<1) == 0xFFFFFFFE;
 }
+#endif
 
 static inline int kvx_opc_match(const opc_t *opc, insn_t *insn) {
 	int i;

programming_language: C
filename: canal.c
change_type: ModificationType.MODIFY
diff: @@ -1,4 +1,4 @@
-/* radare - LGPL - Copyright 2009-2021 - pancake, nibble */
+/* radare - LGPL - Copyright 2009-2022 - pancake, nibble */
 
 #include <r_types.h>
 #include <r_list.h>
@@ -4727,7 +4727,7 @@ static bool myvalid(RIO *io, ut64 addr) {
 typedef struct {
 	RAnalOp *op;
 	RAnalFunction *fcn;
-	const char *spname;
+	char *spname;
 	ut64 initial_sp;
 } EsilBreakCtx;
 
@@ -5099,7 +5099,7 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
 	bool gp_fixed = r_config_get_i (core->config, "anal.gpfixed");
 	RAnalEsil *ESIL = core->anal->esil;
 	ut64 refptr = 0LL;
-	const char *pcname;
+	char *pcname = NULL;
 	RAnalOp op = R_EMPTY;
 	ut8 *buf = NULL;
 	bool end_address_set = false;
@@ -5188,11 +5188,12 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
 		r_core_cmd0 (core, "aeim");
 		ESIL = core->anal->esil;
 	}
-	const char *spname = r_reg_get_name (core->anal->reg, R_REG_NAME_SP);
-	if (!spname) {
+	const char *kspname = r_reg_get_name (core->anal->reg, R_REG_NAME_SP);
+	if (R_STR_ISEMPTY (kspname)) {
 		eprintf ("Error: No =SP defined in the reg profile.\n");
 		return;
 	}
+	char *spname = strdup (kspname);
 	EsilBreakCtx ctx = {
 		&op,
 		fcn,
@@ -5210,11 +5211,12 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
 	}
 	//eprintf ("Analyzing ESIL refs from 0x%"PFMT64x" - 0x%"PFMT64x"\n", addr, end);
 	// TODO: backup/restore register state before/after analysis
-	pcname = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
-	if (!pcname || !*pcname) {
+	const char *kpcname = r_reg_get_name (core->anal->reg, R_REG_NAME_PC);
+	if (!kpcname || !*kpcname) {
 		eprintf ("Cannot find program counter register in the current profile.\n");
 		return;
 	}
+	pcname = strdup (kpcname);
 	esil_anal_stop = false;
 	r_cons_break_push (cccb, core);
 
@@ -5299,11 +5301,9 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
 		r_anal_op_fini (&op);
 		r_asm_set_pc (core->rasm, cur);
 		i_old = i;
-#if 1
 		if (i > iend) {
 			goto repeat;
 		}
-#endif
 		if (!r_anal_op (core->anal, &op, cur, buf + i, iend - i, R_ANAL_OP_MASK_ESIL | R_ANAL_OP_MASK_VAL | R_ANAL_OP_MASK_HINT)) {
 			i += minopsize - 1; //   XXX dupe in op.size below
 		}
@@ -5544,6 +5544,8 @@ repeat:
 			break;
 		}
 	} while (get_next_i (&ictx, &i));
+	free (pcname);
+	free (spname);
 	r_list_free (ictx.bbl);
 	r_list_free (ictx.path);
 	r_list_free (ictx.switch_path);

programming_language: C