From b7578b5ce2b873bb6afe2fd64ab80674ea4e2237 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 31 Mar 2009 22:55:41 +0000 Subject: [PATCH] Fix contrib/pgstattuple and contrib/pageinspect to prevent attempts to read temporary tables of other sessions; that is unsafe because of the way our buffer management works. Per report from Stuart Bishop. This is redundant with the bufmgr.c checks in HEAD, but not at all redundant in the back branches. --- contrib/pgstattuple/pgstatindex.c | 62 ++++++++++++++++++++++++++----- contrib/pgstattuple/pgstattuple.c | 12 +++++- 2 files changed, 63 insertions(+), 11 deletions(-) diff --git a/contrib/pgstattuple/pgstatindex.c b/contrib/pgstattuple/pgstatindex.c index fe2062f9bd0..c0ac1ae5bfb 100644 --- a/contrib/pgstattuple/pgstatindex.c +++ b/contrib/pgstattuple/pgstatindex.c @@ -247,6 +247,16 @@ pgstatindex(PG_FUNCTION_ARGS) if (!IS_INDEX(rel) || !IS_BTREE(rel)) elog(ERROR, "pgstatindex() can be used only on b-tree index."); + /* + * Reject attempts to read non-local temporary relations; we would + * be likely to get wrong data since we have no visibility into the + * owning session's local buffers. + */ + if (isOtherTempNamespace(RelationGetNamespace(rel))) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot access temporary tables of other sessions"))); + /*------------------- * Read a metapage *------------------- @@ -405,16 +415,26 @@ bt_page_stats(PG_FUNCTION_ARGS) relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); rel = relation_openrv(relrv, AccessShareLock); - CHECK_RELATION_BLOCK_RANGE(rel, blkno); - - buffer = ReadBuffer(rel, blkno); - if (!IS_INDEX(rel) || !IS_BTREE(rel)) elog(ERROR, "bt_page_stats() can be used only on b-tree index."); + /* + * Reject attempts to read non-local temporary relations; we would + * be likely to get wrong data since we have no visibility into the + * owning session's local buffers. + */ + if (isOtherTempNamespace(RelationGetNamespace(rel))) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot access temporary tables of other sessions"))); + if (blkno == 0) elog(ERROR, "Block 0 is a meta page."); + CHECK_RELATION_BLOCK_RANGE(rel, blkno); + + buffer = ReadBuffer(rel, blkno); + { HeapTuple tuple; TupleDesc tupleDesc; @@ -513,9 +533,6 @@ bt_page_items(PG_FUNCTION_ARGS) (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be superuser to use pgstattuple functions")))); - if (blkno == 0) - elog(ERROR, "Block 0 is a meta page."); - if (SRF_IS_FIRSTCALL()) { fctx = SRF_FIRSTCALL_INIT(); @@ -529,13 +546,26 @@ bt_page_items(PG_FUNCTION_ARGS) relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); uargs->rel = relation_openrv(relrv, AccessShareLock); + if (!IS_INDEX(uargs->rel) || !IS_BTREE(uargs->rel)) + elog(ERROR, "bt_page_items() can be used only on b-tree index."); + + /* + * Reject attempts to read non-local temporary relations; we would + * be likely to get wrong data since we have no visibility into the + * owning session's local buffers. + */ + if (isOtherTempNamespace(RelationGetNamespace(uargs->rel))) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot access temporary tables of other sessions"))); + + if (blkno == 0) + elog(ERROR, "Block 0 is a meta page."); + CHECK_RELATION_BLOCK_RANGE(uargs->rel, blkno); uargs->buffer = ReadBuffer(uargs->rel, blkno); - if (!IS_INDEX(uargs->rel) || !IS_BTREE(uargs->rel)) - elog(ERROR, "bt_page_items() can be used only on b-tree index."); - uargs->page = BufferGetPage(uargs->buffer); opaque = (BTPageOpaque) PageGetSpecialPointer(uargs->page); @@ -651,6 +681,16 @@ bt_metap(PG_FUNCTION_ARGS) if (!IS_INDEX(rel) || !IS_BTREE(rel)) elog(ERROR, "bt_metap() can be used only on b-tree index."); + /* + * Reject attempts to read non-local temporary relations; we would + * be likely to get wrong data since we have no visibility into the + * owning session's local buffers. + */ + if (isOtherTempNamespace(RelationGetNamespace(rel))) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot access temporary tables of other sessions"))); + buffer = ReadBuffer(rel, 0); { @@ -720,6 +760,8 @@ pg_relpages(PG_FUNCTION_ARGS) relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); rel = relation_openrv(relrv, AccessShareLock); + /* note: this will work OK on non-local temp tables */ + relpages = RelationGetNumberOfBlocks(rel); relation_close(rel, AccessShareLock); diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c index 2bc2067bbc7..4d001cc2a46 100644 --- a/contrib/pgstattuple/pgstattuple.c +++ b/contrib/pgstattuple/pgstattuple.c @@ -1,5 +1,5 @@ /* - * $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.25.2.1 2007/08/28 23:11:12 tgl Exp $ + * $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.25.2.2 2009/03/31 22:55:41 tgl Exp $ * * Copyright (c) 2001,2002 Tatsuo Ishii * @@ -201,6 +201,16 @@ pgstat_relation(Relation rel, FunctionCallInfo fcinfo) { const char *err; + /* + * Reject attempts to read non-local temporary relations; we would + * be likely to get wrong data since we have no visibility into the + * owning session's local buffers. + */ + if (isOtherTempNamespace(RelationGetNamespace(rel))) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot access temporary tables of other sessions"))); + switch (rel->rd_rel->relkind) { case RELKIND_RELATION: -- 2.39.5