CVE-2022-1031 (published 2022-03-22T20:15Z)

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

Severity: MEDIUM
CVSS v2 base score: 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 7.8, HIGH (CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/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: pancake
author_date: 2022-03-21 17:48:44+01:00
msg: Fix UAF in aaaa on arm/thumb switching ##crash

* Reported by @peacock-doris via huntr.dev
* Reproducer tests_65185
* This is a logic fix, but not the fully safe as changes in the code
  can result on UAF again, to properly protect r2 from crashing we
  need to break the ABI and add refcounting to RRegItem, which can't
  happen in 5.6.x because of abi-compat rules
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: fcn.c
change_type: ModificationType.MODIFY
diff: @@ -815,7 +815,7 @@ repeat:
 			// note, we have still increased size of basic block
 			// (and function)
 			if (anal->verbose) {
-				eprintf("Enter branch delay at 0x%08"PFMT64x ". bb->sz=%"PFMT64u"\n", at - oplen, bb->size);
+				eprintf ("Enter branch delay at 0x%08"PFMT64x ". bb->sz=%"PFMT64u"\n", at - oplen, bb->size);
 			}
 			delay.idx = idx - oplen;
 			delay.cnt = op->delay;
@@ -882,6 +882,12 @@ repeat:
 			// swapped parameters wtf
 			r_anal_xrefs_set (anal, op->addr, op->ptr, R_ANAL_REF_TYPE_DATA);
 		}
+		if (anal->opt.vars && !varset) {
+			// XXX uses op.src/dst and fails because regprofile invalidates the regitems
+			// lets just call this BEFORE retpoline() to avoid such issue
+			r_anal_extract_vars (anal, fcn, op);
+		}
+		// this call may cause regprofile changes which cause ranalop.regitem references to be invalid
 		analyze_retpoline (anal, op);
 		switch (op->type & R_ANAL_OP_TYPE_MASK) {
 		case R_ANAL_OP_TYPE_CMOV:
@@ -973,7 +979,7 @@ repeat:
 				fcn->bp_off = fcn->stack - op->src[0]->delta;
 			}
 			if (op->dst && op->dst->reg && op->dst->reg->name && op->ptr > 0 && op->ptr != UT64_MAX) {
-				free(last_reg_mov_lea_name);
+				free (last_reg_mov_lea_name);
 				if ((last_reg_mov_lea_name = strdup(op->dst->reg->name))) {
 					last_reg_mov_lea_val = op->ptr;
 					last_is_reg_mov_lea = true;
@@ -1404,10 +1410,13 @@ analopfinish:
 				}
 			}
 		}
+#if 0
 		if (anal->opt.vars && !varset) {
 			// XXX uses op.src/dst and fails because regprofile invalidates the regitems
+			// we must ranalop in here to avoid uaf
 			r_anal_extract_vars (anal, fcn, op);
 		}
+#endif
 		if (op->type != R_ANAL_OP_TYPE_MOV && op->type != R_ANAL_OP_TYPE_CMOV && op->type != R_ANAL_OP_TYPE_LEA) {
 			last_is_reg_mov_lea = false;
 		}

programming_language: C
filename: var.c
change_type: ModificationType.MODIFY
diff: @@ -1048,7 +1048,7 @@ static void extract_arg(RAnal *anal, RAnalFunction *fcn, RAnalOp *op, const char
 		free (vartype);
 	} else {
 		st64 frame_off = -(ptr + fcn->bp_off);
-		if (maxstackframe != 0 && (frame_off > maxstackframe || frame_off < -maxstackframe)) {
+		if (maxstackframe > 0 && (frame_off > maxstackframe || frame_off < -maxstackframe)) {
 			goto beach;
 		}
 		RAnalVar *var = get_stack_var (fcn, frame_off);

programming_language: C