⬢ DragonFlyBSD Kernel Audit
DF-5728 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/ddb/db_expr.c b/sys/ddb/db_expr.c
--- a/sys/ddb/db_expr.c
+++ b/sys/ddb/db_expr.c
@@ -43,6 +43,20 @@
 static boolean_t	db_term (db_expr_t *valuep);
 static boolean_t	db_unary (db_expr_t *valuep);
 
+/*
+ * Maximum parenthesis nesting depth accepted by the expression parser.
+ * Each '(' costs 272 bytes of kernel stack in the DDB context (measured
+ * on X86_64_GENERIC: db_term 32 + db_expression 16 + db_shift_expr 64 +
+ * db_add_expr 64 + db_mult_expr 64 + db_unary 32), and DDB runs on the
+ * interrupted context's 16 KB kernel stack, so unbounded nesting (the
+ * 120-char ddb line allows 120 levels = ~32 KB) overflows into the stack
+ * guard page (double fault / panic).  16 levels caps the parser's
+ * recursion at ~4.4 KB.  db_expr_depth is reset by db_flush_lex()
+ * so that db_error() longjmps out of the parser cannot leave it stale.
+ */
+#define	DB_MAX_EXPR_DEPTH	16
+int	db_expr_depth;
+
 static boolean_t
 db_term(db_expr_t *valuep)
 {
@@ -225,5 +239,12 @@
 int
 db_expression(db_expr_t *valuep)
 {
-	return (db_shift_expr(valuep));
+	int	rv;
+
+	if (db_expr_depth >= DB_MAX_EXPR_DEPTH)
+		db_error("Expression too deep\n");
+	db_expr_depth++;
+	rv = db_shift_expr(valuep);
+	db_expr_depth--;
+	return (rv);
 }
diff --git a/sys/ddb/db_lex.c b/sys/ddb/db_lex.c
--- a/sys/ddb/db_lex.c
+++ b/sys/ddb/db_lex.c
@@ -42,6 +42,8 @@
 static char	db_line[120];
 static char *	db_lp, *db_endlp;
 
+extern int	db_expr_depth;	/* db_expr.c; reset on abort paths */
+
 static int	db_lex (void);
 static void 	db_flush_line (void);
 static int 	db_read_char (void);
@@ -153,6 +155,7 @@
 	db_flush_line();
 	db_look_char = 0;
 	db_look_token = 0;
+	db_expr_depth = 0;
 }
 
 static int