Hi all,

In light of CVE-2018-1058, user's applications need to be careful about
the use of schema-unqualified queries.  A lookup at the upstream code is
showing four areas which are missing such handling:
- psql has one problem in get_create_object_cmd which misses twice to
qualify array_remove().
- isolationtester is missing one for a call to pg_backend_pid()
- information_schema.sql has one problem as well: the function
_pg_interval_type does not qualify upper().  Please note that there is
no need to care about view's bodies because those use OID references, so
only the function body need to be taken care of.
- worker_spi scans pg_namespace and uses count() without schema
qualification.

Attached is a patch which fixes all four of them, and which should be
back-patched.  For information_schema.sql, users can always replace the
body of the function by redefining them (using SET search_path in CREATE
FUNCTION would work as well however this is more costly than a simple
qualification).

Thoughts?
--
Michael
From 44fafa6076a2108043e67ac76777c1c20664ea78 Mon Sep 17 00:00:00 2001
From: Michael Paquier <mich...@paquier.xyz>
Date: Fri, 9 Mar 2018 16:43:06 +0900
Subject: [PATCH] Fix missing schema qualifications in code

Per CVE-2018-1058, not using proper schema qualifications can allow an
attacker who has an account on the server to execute arbitrary code as a
superuser even if he has no such rights.  After monitoring the whole
code of Postgres, I have bumped into four places that need to be
addressed:
- isolationtester is missing one qualification when calling
pg_backend_pid.
- psql is missing two qualifications for array_remove
- information_schema.sql has one problem within function
_pg_interval_type
- worker_spi scans pg_namespace and uses count() without
qualifications.
---
 src/backend/catalog/information_schema.sql | 2 +-
 src/bin/psql/command.c                     | 2 +-
 src/test/isolation/isolationtester.c       | 2 +-
 src/test/modules/worker_spi/worker_spi.c   | 4 +++-
 4 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/backend/catalog/information_schema.sql b/src/backend/catalog/information_schema.sql
index f4e69f4a26..4f2af408ac 100644
--- a/src/backend/catalog/information_schema.sql
+++ b/src/backend/catalog/information_schema.sql
@@ -186,7 +186,7 @@ CREATE FUNCTION _pg_interval_type(typid oid, mod int4) RETURNS text
     AS
 $$SELECT
   CASE WHEN $1 IN (1186) /* interval */
-           THEN upper(substring(format_type($1, $2) from 'interval[()0-9]* #"%#"' for '#'))
+           THEN pg_catalog.upper(substring(pg_catalog.format_type($1, $2) from 'interval[()0-9]* #"%#"' for '#'))
        ELSE null
   END$$;
 
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 3560318749..f345572c8c 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -4483,7 +4483,7 @@ get_create_object_cmd(EditableObjectType obj_type, Oid oid,
 				printfPQExpBuffer(query,
 								  "SELECT nspname, relname, relkind, "
 								  "pg_catalog.pg_get_viewdef(c.oid, true), "
-								  "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
+								  "pg_catalog.array_remove(pg_catalog.array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
 								  "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
 								  "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption "
 								  "FROM pg_catalog.pg_class c "
diff --git a/src/test/isolation/isolationtester.c b/src/test/isolation/isolationtester.c
index 4ecad038bd..64d666f5cd 100644
--- a/src/test/isolation/isolationtester.c
+++ b/src/test/isolation/isolationtester.c
@@ -184,7 +184,7 @@ main(int argc, char **argv)
 		PQclear(res);
 
 		/* Get the backend pid for lock wait checking. */
-		res = PQexec(conns[i], "SELECT pg_backend_pid()");
+		res = PQexec(conns[i], "SELECT pg_catalog.pg_backend_pid()");
 		if (PQresultStatus(res) == PGRES_TUPLES_OK)
 		{
 			if (PQntuples(res) == 1 && PQnfields(res) == 1)
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index 3b98b1682b..547bdb26c4 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -115,7 +115,9 @@ initialize_worker_spi(worktable *table)
 
 	/* XXX could we use CREATE SCHEMA IF NOT EXISTS? */
 	initStringInfo(&buf);
-	appendStringInfo(&buf, "select count(*) from pg_namespace where nspname = '%s'",
+	appendStringInfo(&buf,
+					 "select pg_catalog.count(*) "
+					 "from pg_catalog.pg_namespace where nspname = '%s'",
 					 table->schema);
 
 	ret = SPI_execute(buf.data, true, 0);
-- 
2.16.2

Attachment: signature.asc
Description: PGP signature

Reply via email to