From patchwork Sun Sep 19 04:56:43 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnaud Lacombe X-Patchwork-Id: 193112 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o8J4uk0t031115 for ; Sun, 19 Sep 2010 04:56:46 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751946Ab0ISE4q (ORCPT ); Sun, 19 Sep 2010 00:56:46 -0400 Received: from mail-ww0-f44.google.com ([74.125.82.44]:33326 "EHLO mail-ww0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751461Ab0ISE4p (ORCPT ); Sun, 19 Sep 2010 00:56:45 -0400 Received: by wwb39 with SMTP id 39so2331908wwb.1 for ; Sat, 18 Sep 2010 21:56:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:received:date:message-id :subject:from:to:cc:content-type; bh=kEXuv0jn1NhY9H6dzqPv/P+G6f9pNj6LmYkjzE+HiR4=; b=aOOOo8MGhvPV29Im6YyB8fHYKFdZkq3N1X6pIj6mBl4G76qGBsjyLX7/P8xMWPQwQc WkpgE/nF5or9xLoZan0NxMtQTMRkqOIqL6ap3saKiEnzGkAiVrRZ/4Wvb3I51bjzUAA4 3wo9IjgJRipbTzJU7aqyq/Zfy7DtHn8UPqlxg= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:cc:content-type; b=sX2afD7dT8Zz1M2d6b6kmUfuZmDNViUrP6WfSQPW6hr2IjNVhvlb10Tmka0FG2B/PX iS/zQDwOiudQHWhgTdCtQ24AhLzl7+IRK8RAsJP1AFULEVIh4RA7ERFSbrY/Xr7kWwow bMauaIFDreZLhfNTBw47kXS/RDj25sf4E9NQY= MIME-Version: 1.0 Received: by 10.227.152.131 with SMTP id g3mr395402wbw.108.1284872203874; Sat, 18 Sep 2010 21:56:43 -0700 (PDT) Received: by 10.216.229.99 with HTTP; Sat, 18 Sep 2010 21:56:43 -0700 (PDT) Date: Sun, 19 Sep 2010 00:56:43 -0400 Message-ID: Subject: Stale expression reference causing use-after-free From: Arnaud Lacombe To: Catalin Marinas , Michal Marek Cc: linux-kbuild@vger.kernel.org Sender: linux-kbuild-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kbuild@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Sun, 19 Sep 2010 04:56:46 +0000 (UTC) diff --git a/Kconfig.testcase b/Kconfig.testcase new file mode 100644 index 0000000..cb663e9 --- /dev/null +++ b/Kconfig.testcase @@ -0,0 +1 @@ +source "Kconfig.testcase.l1" diff --git a/Kconfig.testcase.l1 b/Kconfig.testcase.l1 new file mode 100644 index 0000000..79ec19e --- /dev/null +++ b/Kconfig.testcase.l1 @@ -0,0 +1,216 @@ +config DUMMY_BOOL_0 + bool + +config DUMMY_BOOL_1 + bool + +config DUMMY_BOOL_2 + bool + +config DUMMY_BOOL_3 + bool + default y + +config DUMMY_BOOL_4 + bool + default (DUMMY_COND_5 || DUMMY_COND_6) + +config DUMMY_STRING_0 + string + default "string0" if DUMMY_COND_7 + default "string1" if DUMMY_COND_8 + +config DUMMY_BOOL_5 # maybe unneeded + bool + default y + +config DUMMY_BOOL_6 + bool + default y + +config DUMMY_BOOL_7 + bool + default y + select DUMMY_SELECT_0 if DUMMY_COND_0 + select DUMMY_SELECT_1 + select DUMMY_SELECT_2 + select DUMMY_SELECT_3 + select DUMMY_SELECT_4 + +config DUMMY_BOOL_8 + bool + default y + depends on DUMMY_COND_9 || (DUMMY_COND_10 && DUMMY_COND_11) + +config DUMMY_BOOL_9 + bool + default y + select DUMMY_SELECT_5 + select DUMMY_SELECT_6 + select DUMMY_SELECT_7 if (!DUMMY_COND_1 || !DUMMY_COND_2) + select DUMMY_SELECT_8 + select DUMMY_SELECT_9 + +config DUMMY_BOOL_10 + bool + default y + select DUMMY_SELECT_10 + select DUMMY_SELECT_11 + select DUMMY_SELECT_12 + select DUMMY_SELECT_13 + select DUMMY_SELECT_14 + +config DUMMY_BOOL_11 + bool + default y + select DUMMY_SELECT_15 + select DUMMY_SELECT_16 + select DUMMY_SELECT_17 + select DUMMY_SELECT_18 + select DUMMY_SELECT_19 + +config DUMMY_BOOL_12 + bool + default y + select DUMMY_SELECT_20 if DUMMY_COND_3 + select DUMMY_SELECT_21 + select DUMMY_SELECT_22 + select DUMMY_SELECT_23 + select DUMMY_SELECT_24 + +config DUMMY_BOOL_13 + bool + default (DUMMY_COND_12 || DUMMY_COND_13 || DUMMY_COND_14) + select DUMMY_SELECT_25 + select DUMMY_SELECT_26 if DUMMY_COND_4 + select DUMMY_SELECT_27 + select DUMMY_SELECT_28 + select DUMMY_SELECT_29 + +config DUMMY_BOOL_14 + bool + default y + depends on DUMMY_COND_15 + select DUMMY_SELECT_30 + select DUMMY_SELECT_31 + select DUMMY_SELECT_32 + select DUMMY_SELECT_33 + select DUMMY_SELECT_34 if DUMMY_COND_16 + +config DUMMY_BOOL_16 + bool + default y + +config DUMMY_BOOL_17 + bool + default y + +config DUMMY_BOOL_18 + bool + default y + +config DUMMY_BOOL_19 + bool + default y + +config DUMMY_BOOL_20 + bool + default y + +config DUMMY_BOOL_21 + bool + default y + +config DUMMY_BOOL_22 + bool + default y + +config DUMMY_BOOL_23 + bool + default y + +config DUMMY_BOOL_24 + bool + default y + +config DUMMY_BOOL_30 + bool + default y + +config DUMMY_BOOL_25 + bool + default y + +config DUMMY_BOOL_26 + bool + default y + +config DUMMY_BOOL_27 + bool + default y + +config DUMMY_BOOL_28 + bool + default y + +config DUMMY_BOOL_29 + bool + default y + +config DUMMY_BOOL_30 + bool + default y + depends on DUMMY_COND_17 && DUMMY_COND_18 && DUMMY_COND_19 + +config DUMMY_STRING_1 + string + option env="ENV0" + +config DUMMY_STRING_2 + string + option env="ENV1" + +config DUMMY_STRING_3 + string + depends on !UML + option defconfig_list + default "string2" + default "string3" + default "string4" + default "_string5" + default "string6" + +menu "dummy menu 0" + +config DUMMY_BOOL_31 + bool "prompt0" + +config DUMMY_BOOL_32 + bool + +menuconfig DUMMY_BOOL_33 + bool "prompt1" + depends on DUMMY_COND_20 + +if DUMMY_BOOL_33 + +config DUMMY_BOOL_34 + bool "prompt2" + depends on DUMMY_BOOL_33 + +config DUMMY_BOOL_35 + bool "prompt3" + depends on DUMMY_COND_21 + +config DUMMY_BOOL_36 + bool "prompt4" + depends on DUMMY_COND_22 && DUMMY_COND_23 + +menuconfig DUMMY_BOOL_37 + bool "prompt5" + depends on DUMMY_COND_24 + +endif + +endmenu + diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c index 330e7c0..65f7ab3 100644 --- a/scripts/kconfig/expr.c +++ b/scripts/kconfig/expr.c @@ -71,6 +71,8 @@ struct expr *expr_copy(struct expr *org) if (!org) return NULL; + EXPR_CHECK(org); + e = malloc(sizeof(*org)); memcpy(e, org, sizeof(*org)); switch (org->type) { @@ -101,11 +103,13 @@ struct expr *expr_copy(struct expr *org) return e; } -void expr_free(struct expr *e) +void _expr_free(struct expr *e) { if (!e) return; + EXPR_CHECK(e); + switch (e->type) { case E_SYMBOL: break; @@ -124,6 +128,9 @@ void expr_free(struct expr *e) printf("how to free type %d?\n", e->type); break; } + + memset(e, 'A', sizeof(e)); + free(e); } diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h index 6ee2e4f..0adc104 100644 --- a/scripts/kconfig/expr.h +++ b/scripts/kconfig/expr.h @@ -48,6 +48,26 @@ struct expr { #define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2)) #define EXPR_NOT(dep) (2-(dep)) +#if 1 +#define expr_free(e) \ +({ \ + fprintf(stderr, "%s: %p:%d\n", __func__, e, __LINE__); \ + _expr_free(e); \ + e = NULL; \ +}) +#else +#define expr_free(e) _expr_free(e); +#endif + +#define EXPR_CHECK(e) \ +({ \ + if ((e) != NULL && ((e)->type < E_NONE || (e)->type > E_RANGE)) { \ + fprintf(stderr, "Invalid expr %p at %s:%d in %s(): %x\n", \ + e, __FILE__, __LINE__, __func__, (e)->type); \ + abort(); \ + } \ +}) + #define expr_list_for_each_sym(l, e, s) \ for (e = (l); e && (s = e->right.sym); e = e->left.expr) @@ -193,7 +213,7 @@ struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symb struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); struct expr *expr_copy(struct expr *org); -void expr_free(struct expr *e); +void _expr_free(struct expr *e); int expr_eq(struct expr *e1, struct expr *e2); void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); tristate expr_calc_value(struct expr *e); diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index 4fb5902..3563239 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -292,6 +292,7 @@ void menu_finalize(struct menu *parent) menu_finalize(menu); } else if (sym) { /* ignore inherited dependencies for dir_dep */ + EXPR_CHECK(parent->dir_dep); sym->dir_dep.expr = expr_transform(expr_copy(parent->dir_dep)); sym->dir_dep.expr = expr_eliminate_dups(sym->dir_dep.expr);