Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kXLne-0006Ks-Kf for pgsql-hackers@arkaria.postgresql.org; Tue, 27 Oct 2020 10:01:55 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1kXLnd-0005mp-K7 for pgsql-hackers@arkaria.postgresql.org; Tue, 27 Oct 2020 10:01:53 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kXLP7-0004pQ-H3 for pgsql-hackers@lists.postgresql.org; Tue, 27 Oct 2020 09:36:33 +0000 Received: from mail.postgrespro.ru ([93.174.131.139]) by makus.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1kXLP4-0007Km-HN for pgsql-hackers@postgresql.org; Tue, 27 Oct 2020 09:36:32 +0000 Received: from ars-thinkpad (nat03-43-2.netorn.net [188.35.130.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mail.postgrespro.ru (Postfix) with ESMTPSA id 96E1621C1C39; Tue, 27 Oct 2020 12:36:28 +0300 (MSK) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=postgrespro.ru; s=mail; t=1603791388; bh=hbRJus65a0eIpN6u4+JUI9z5pNKwLyFFuJz2hNHRVdQ=; h=From:To:Subject:CC:Date; b=g5/8ty67OXE89yJLVYwH7/NLaiCCmy49hN3JcU8JeBD8HsoBGE8sRGawBtNVYCjpW hXkhRpNVmFG7CffwFE05436s5nXrfZ2lb8QVGuv/21FmH3kgWiIekoX4tXAC1S/zsO rcO/OguonM4ch07O9pnJgUNk61s56ZRP7XH2lq/k= User-agent: mu4e 1.2.0; emacs 26.0.50 From: Arseny Sher To: pgsql-hackers Subject: Use-after-free in 12- EventTriggerAlterTableEnd CC: Alvaro Herrera Date: Tue, 27 Oct 2020 12:36:24 +0300 Message-ID: <877drcyprb.fsf@ars-thinkpad> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --=-=-= Content-Type: text/plain Hi, Valgrind on our internal buildfarm complained about use-after-free during currentEventTriggerState->commandList manipulations, e.g. lappend in EventTriggerCollectSimpleCommand. I've discovered that the source of problem is EventTriggerAlterTableEnd not bothering to switch into its own context before appending to the list. ced138e8cba fixed this in master and 13 but wasn't backpatched further, so I see the problem in 12-. The particular reproducing scenario is somewhat involved; it combines pg_pathman [1] extension and SQL interface to it created in our fork of Postgres. Namely, we allow to create partitions in CREATE TABLE PARTITIONED by statement (similar to what [2] proposes). Each partition is created via separate SPI call which in turn ends up making AlterTableStmt as ProcessUtility PROCESS_UTILITY_SUBCOMMAND; so EventTriggerAlterTableStart/End is done, but additional EventTriggerQueryState is not allocated and commands are collected in toplevel EventTriggerQueryState. Of course SPI frees its memory between the calls which makes valgrind scream. Admittedly our case is tricky and I'm not sure it is possible to make up something like that in the pure core code, but I do believe other extension writers might run into this, so I propose to backpatch (the attached) 3 lines healing to all supported branches. Technically, all you (an extension author) have to do to encounter this is 1) Have toplevel EvenTriggerQueryState, i.e. catch utility statement. 2) Inside it, run AlterTable as PROCESS_UTILITY_SUBCOMMAND in some short-living context. [1] https://github.com/postgrespro/pg_pathman [2] https://www.postgresql.org/message-id/flat/CALT9ZEFBv05OhLMKO1Lbo_Zg9a0v%2BU9q9twe%3Dt-dixfR45RmVQ%40mail.gmail.com#f86f0fcfa62d5108fb81556a43f42457 --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=use_after_free_EventTriggerAlterTableEnd.diff diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index f7ee9838f7..d1972e2d7f 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -1807,9 +1807,15 @@ EventTriggerAlterTableEnd(void) /* If no subcommands, don't collect */ if (list_length(currentEventTriggerState->currentCommand->d.alterTable.subcmds) != 0) { + MemoryContext oldcxt; + + oldcxt = MemoryContextSwitchTo(currentEventTriggerState->cxt); + currentEventTriggerState->commandList = lappend(currentEventTriggerState->commandList, currentEventTriggerState->currentCommand); + + MemoryContextSwitchTo(oldcxt); } else pfree(currentEventTriggerState->currentCommand); --=-=-= Content-Type: text/plain -- Arseny Sher Postgres Professional: http://www.postgrespro.com The Russian Postgres Company --=-=-=--