diff --git a/meta-oe/recipes-dbs/postgresql/files/CVE-2024-0985.patch b/meta-oe/recipes-dbs/postgresql/files/CVE-2024-0985.patch
new file mode 100644
index 000000000..24245406c
--- /dev/null
+++ b/meta-oe/recipes-dbs/postgresql/files/CVE-2024-0985.patch
@@ -0,0 +1,98 @@
+From f2fdea198b3d0ab30b9e8478a762488ecebabd88 Mon Sep 17 00:00:00 2001
+From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
+Date: Mon, 5 Feb 2024 11:01:23 +0200
+Subject: [PATCH] Run REFRESH MATERIALIZED VIEW CONCURRENTLY in right security
+ context
+
+The internal commands in REFRESH MATERIALIZED VIEW CONCURRENTLY are
+correctly executed in SECURITY_RESTRICTED_OPERATION mode, except for
+creating the temporary "diff" table, because you cannot create
+temporary tables in SRO mode. But creating the temporary "diff" table
+is a pretty complex CTAS command that selects from another temporary
+table created earlier in the command. If you can cajole that CTAS
+command to execute code defined by the table owner, the table owner
+can run code with the privileges of the user running the REFRESH
+command.
+
+The proof-of-concept reported to the security team relied on CREATE
+RULE to convert the internally-built temp table to a view. That's not
+possible since commit b23cd185fd, and I was not able to find a
+different way to turn the SELECT on the temp table into code
+execution, so as far as I know this is only exploitable in v15 and
+below. That's a fiddly assumption though, so apply this patch to
+master and all stable versions.
+
+Thanks to Pedro Gallegos for the report.
+
+Security: CVE-2023-5869
+Reviewed-by: Noah Misch
+
+CVE: CVE-2024-0985
+
+Upstream-Status: Backport [https://git.postgresql.org/gitweb/?p=postgresql.git;a=patch;h=f2fdea198b3d0ab30b9e8478a762488ecebabd88]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ src/backend/commands/matview.c | 33 ++++++++++++++++++++++++++-------
+ 1 file changed, 26 insertions(+), 7 deletions(-)
+
+diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
+index 3fc50e8..0aa0a74 100644
+--- a/src/backend/commands/matview.c
++++ b/src/backend/commands/matview.c
+@@ -655,13 +655,35 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
+						   SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1))));
+	}
+
++	/*
++	 * Create the temporary "diff" table.
++	 *
++	 * Temporarily switch out of the SECURITY_RESTRICTED_OPERATION context,
++	 * because you cannot create temp tables in SRO context.  For extra
++	 * paranoia, add the composite type column only after switching back to
++	 * SRO context.
++	 */
+	SetUserIdAndSecContext(relowner,
+						   save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
++	resetStringInfo(&querybuf);
++	appendStringInfo(&querybuf,
++					 "CREATE TEMP TABLE %s (tid pg_catalog.tid)",
++					 diffname);
++	if (SPI_exec(querybuf.data, 0) != SPI_OK_UTILITY)
++		elog(ERROR, "SPI_exec failed: %s", querybuf.data);
++	SetUserIdAndSecContext(relowner,
++						   save_sec_context | SECURITY_RESTRICTED_OPERATION);
++	resetStringInfo(&querybuf);
++	appendStringInfo(&querybuf,
++					 "ALTER TABLE %s ADD COLUMN newdata %s",
++					 diffname, tempname);
++	if (SPI_exec(querybuf.data, 0) != SPI_OK_UTILITY)
++		elog(ERROR, "SPI_exec failed: %s", querybuf.data);
+
+-	/* Start building the query for creating the diff table. */
++	/* Start building the query for populating the diff table. */
+	resetStringInfo(&querybuf);
+	appendStringInfo(&querybuf,
+-					 "CREATE TEMP TABLE %s AS "
++					 "INSERT INTO %s "
+					 "SELECT mv.ctid AS tid, newdata.*::%s AS newdata "
+					 "FROM %s mv FULL JOIN %s newdata ON (",
+					 diffname, tempname, matviewname, tempname);
+@@ -790,13 +812,10 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
+						   "WHERE newdata.* IS NULL OR mv.* IS NULL "
+						   "ORDER BY tid");
+
+-	/* Create the temporary "diff" table. */
+-	if (SPI_exec(querybuf.data, 0) != SPI_OK_UTILITY)
++	/* Populate the temporary "diff" table. */
++	if (SPI_exec(querybuf.data, 0) != SPI_OK_INSERT)
+		elog(ERROR, "SPI_exec failed: %s", querybuf.data);
+
+-	SetUserIdAndSecContext(relowner,
+-						   save_sec_context | SECURITY_RESTRICTED_OPERATION);
+-
+	/*
+	 * We have no further use for data from the "full-data" temp table, but we
+	 * must keep it around because its type is referenced from the diff table.
+--
+2.40.0
diff --git a/meta-oe/recipes-dbs/postgresql/postgresql_14.9.bb b/meta-oe/recipes-dbs/postgresql/postgresql_14.9.bb
index a879de20c..d9911fd4a 100644
--- a/meta-oe/recipes-dbs/postgresql/postgresql_14.9.bb
+++ b/meta-oe/recipes-dbs/postgresql/postgresql_14.9.bb
@@ -12,6 +12,7 @@ SRC_URI += "\
    file://CVE-2023-5868.patch \
    file://CVE-2023-5869.patch \
    file://CVE-2023-5870.patch \
+   file://CVE-2024-0985.patch \
 "
 
 SRC_URI[sha256sum] = "b1fe3ba9b1a7f3a9637dd1656dfdad2889016073fd4d35f13b50143cbbb6a8ef"
