Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wVTZr-001zLm-35 for pgsql-bugs@arkaria.postgresql.org; Fri, 05 Jun 2026 12:23:08 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wVTZq-00CGni-1K for pgsql-bugs@arkaria.postgresql.org; Fri, 05 Jun 2026 12:23:06 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wVJAN-009Xqt-0y for pgsql-bugs@lists.postgresql.org; Fri, 05 Jun 2026 01:16:07 +0000 Received: from mahout.postgresql.org ([2001:4800:3e1:1::227]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1wVJAL-000000019u2-1pNq for pgsql-bugs@lists.postgresql.org; Fri, 05 Jun 2026 01:16:06 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=postgresql.org; s=20171124; h=Message-ID:Date:Reply-To:Cc:From:To:Subject: Content-Transfer-Encoding:MIME-Version:Content-Type:Sender:Content-ID: Content-Description:In-Reply-To:References; bh=J2WOYiEUcc2qS+Sw8i95RrbHlg4L0o1S+DXO4Kqg9zg=; b=VaCHgmiXbz+UFvTZck85OXfWZx fX3SjbZjsMDWljgTa3//a0TKAG/KB2XDM7s06D7KDOMzsThkETvk//s30lHEXFcnzT38oQjK9uFwq Ps8TI2rl7iEiUcY6QktvSFBlwxmXq+wtg6zrMT6ghj2jLBeY3036I5L6fK+E06etKGtT5hZ8ZFMln ChkZgaqjnc2sKT3f4VlSXNyZlwl+DhldH5E+RxO4ofh/jFC220uLvvsZonkEgDLH0idcqHpORHwfo tkQVsDxZeESmf3dWrvsFmSUAHqywMAi+Mj6J5+JgFh0dRE5qzDmfMZTKRSomzEjxIqt03vs4T5XFt 94DlgmkA==; Received: from wrigleys.postgresql.org ([2a02:16a8:dc51::60]) by mahout.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wVJAL-003XAm-0U for pgsql-bugs@lists.postgresql.org; Fri, 05 Jun 2026 01:16:05 +0000 Received: from localhost ([127.0.0.1] helo=wrigleys.postgresql.org) by wrigleys.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wVJAJ-008ECc-1W for pgsql-bugs@lists.postgresql.org; Fri, 05 Jun 2026 01:16:03 +0000 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: BUG #19511: contrib/dblink: NULL dereference in dblink_get_notify() when called without a prior connection To: pgsql-bugs@lists.postgresql.org From: PG Bug reporting form Cc: amjadshahzad2000@gmail.com Reply-To: amjadshahzad2000@gmail.com, pgsql-bugs@lists.postgresql.org Date: Fri, 05 Jun 2026 01:15:40 +0000 Message-ID: <19511-f9f251767b658232@postgresql.org> X-Auto-Response-Suppress: All Auto-Submitted: auto-generated List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk The following bug has been logged on the website: Bug reference: 19511 Logged by: Amjad Shahzad Email address: amjadshahzad2000@gmail.com PostgreSQL version: 18.4 Operating system: Ubuntu 24.04 x86_64 Description: =20 I found a NULL pointer dereference in contrib/dblink/dblink.c in the dblink_get_notify() function. Any user with EXECUTE on the function can crash their backend process with a single call. Confirmed against master commit 0392fb900eb. WHAT IS THE ISSUE =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D dblink_get_notify() retrieves async notifications from a remote connection. When called with no arguments it uses the default (unnamed) connection. If no default connection has been established first, pconn->conn is NULL. The code assigns this NULL to conn and then passes it directly to PQconsumeInput() and PQnotifies(): /* line 1893 (master) */ else conn =3D pconn->conn; /* NULL =E2=80=94 no connection establis= hed */ InitMaterializedSRF(fcinfo, 0); PQconsumeInput(conn); /* passes NULL to libpq */ while ((notify =3D PQnotifies(conn)) !=3D NULL) /* NULL dereference */ PQnotifies(NULL) dereferences a null pointer internally, causing a backend SIGSEGV. Every other function in dblink.c that uses the default connection already has an explicit NULL guard: if (!conn) dblink_conn_not_avail(conname); dblink_get_notify() is the only function that skips this guard. WHAT CAN BE COMPROMISED =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D Any user with EXECUTE on dblink_get_notify(), granted to PUBLIC by default can crash their backend process on demand. No password, no connection, no special privileges required. In a shared server environment this can be used as a denial-of-service against a specific session. Combined with connection pooling or persistent connections it could repeatedly crash backend processes. PREREQUISITES =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 1. Any connected database user 2. EXECUTE on dblink_get_notify (granted to PUBLIC by default) 3. contrib/dblink installed (CREATE EXTENSION dblink) No dblink connection needed. No password needed. STEPS TO REPRODUCE =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D -- STEP 1: Install dblink CREATE EXTENSION dblink; -- STEP 2: As any user, call without connecting first SELECT * FROM dblink_get_notify(); -- Result before fix: -- server closed the connection unexpectedly -- SIGSEGV in server log -- Result after fix: -- ERROR: connection not available THE FIX =3D=3D=3D=3D=3D=3D=3D Add the same NULL guard that every other dblink function already has: /* BEFORE */ else conn =3D pconn->conn; /* AFTER */ else { conn =3D pconn->conn; if (!conn) dblink_conn_not_avail(NULL); } 4 lines added. Patch attached. BEHAVIOUR AFTER THE FIX =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D -- No prior connection: SELECT * FROM dblink_get_notify(); -- ERROR: connection not available (clean error, no crash) -- With valid connection: SELECT * FROM dblink_get_notify('myconn'); -- (0 rows) (works exactly as before) REGRESSION TEST RESULTS =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D $ meson test --suite dblink 1/2 dblink - postgresql:dblink/regress OK (all SQL tests pass) 2/2 dblink - postgresql:dblink/001_auth_scram OK 12 subtests passed Ok: 2 Fail: 0 $ meson test --suite regress 1/1 regress - postgresql:regress/regress OK 245 subtests passed Ok: 1 Fail: 0 Tested on: PostgreSQL master 0392fb900eb, Ubuntu 24.04, x86_64.