From 38c75ecf8345bd338112ad2a3221dfc47929fb7e Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 26 Aug 2007 23:59:50 +0000 Subject: [PATCH] Restrict pgstattuple functions to superusers. (This might be too strict, but no permissions check at all is certainly no good.) Clean up usage of some deprecated APIs. --- contrib/pgstattuple/pgstatindex.c | 46 ++++++++++--------- contrib/pgstattuple/pgstattuple.c | 20 +++++--- contrib/pgstattuple/pgstattuple.sql.in | 66 +++++++++++++-------------- contrib/pgstattuple/uninstall_pgstattuple.sql | 6 +-- 4 files changed, 72 insertions(+), 66 deletions(-) diff --git a/contrib/pgstattuple/pgstatindex.c b/contrib/pgstattuple/pgstatindex.c index 0c2c9a1448..3018b6aedd 100644 --- a/contrib/pgstattuple/pgstatindex.c +++ b/contrib/pgstattuple/pgstatindex.c @@ -24,27 +24,21 @@ #include "postgres.h" -#include "fmgr.h" -#include "funcapi.h" #include "access/heapam.h" -#include "access/itup.h" #include "access/nbtree.h" -#include "access/transam.h" #include "catalog/namespace.h" -#include "catalog/pg_type.h" +#include "funcapi.h" +#include "miscadmin.h" #include "utils/builtins.h" -#include "utils/inval.h" -PG_FUNCTION_INFO_V1(pgstatindex); -PG_FUNCTION_INFO_V1(pg_relpages); extern Datum pgstatindex(PG_FUNCTION_ARGS); extern Datum pg_relpages(PG_FUNCTION_ARGS); -#define PGSTATINDEX_TYPE "public.pgstatindex_type" -#define PGSTATINDEX_NCOLUMNS 10 +PG_FUNCTION_INFO_V1(pgstatindex); +PG_FUNCTION_INFO_V1(pg_relpages); -#define IS_INDEX(r) ((r)->rd_rel->relkind == 'i') +#define IS_INDEX(r) ((r)->rd_rel->relkind == RELKIND_INDEX) #define IS_BTREE(r) ((r)->rd_rel->relam == BTREE_AM_OID) #define CHECK_PAGE_OFFSET_RANGE(pg, offnum) { \ @@ -97,15 +91,20 @@ pgstatindex(PG_FUNCTION_ARGS) uint32 blkno; BTIndexStat indexStat; + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("must be superuser to use pgstattuple functions")))); + relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); rel = relation_openrv(relrv, AccessShareLock); if (!IS_INDEX(rel) || !IS_BTREE(rel)) - elog(ERROR, "pgstatindex() can only be used on b-tree index"); + elog(ERROR, "relation \"%s\" is not a btree index", + RelationGetRelationName(rel)); - /*------------------- - * Read a metapage - *------------------- + /* + * Read metapage */ { Buffer buffer = ReadBuffer(rel, 0); @@ -194,11 +193,12 @@ pgstatindex(PG_FUNCTION_ARGS) { TupleDesc tupleDesc; int j; - char *values[PGSTATINDEX_NCOLUMNS]; - + char *values[10]; HeapTuple tuple; - tupleDesc = RelationNameGetTupleDesc(PGSTATINDEX_TYPE); + /* Build a tuple descriptor for our result type */ + if (get_call_result_type(fcinfo, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); j = 0; values[j] = palloc(32); @@ -229,7 +229,7 @@ pgstatindex(PG_FUNCTION_ARGS) tuple = BuildTupleFromCStrings(TupleDescGetAttInMetadata(tupleDesc), values); - result = TupleGetDatum(TupleDescGetSlot(tupleDesc), tuple); + result = HeapTupleGetDatum(tuple); } PG_RETURN_DATUM(result); @@ -238,7 +238,7 @@ pgstatindex(PG_FUNCTION_ARGS) /* -------------------------------------------------------- * pg_relpages() * - * Get a number of pages of the table/index. + * Get the number of pages of the table/index. * * Usage: SELECT pg_relpages('t1'); * SELECT pg_relpages('t1_pkey'); @@ -248,11 +248,15 @@ Datum pg_relpages(PG_FUNCTION_ARGS) { text *relname = PG_GETARG_TEXT_P(0); - Relation rel; RangeVar *relrv; int4 relpages; + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("must be superuser to use pgstattuple functions")))); + relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); rel = relation_openrv(relrv, AccessShareLock); diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c index 64e7f982fb..9072a37aa9 100644 --- a/contrib/pgstattuple/pgstattuple.c +++ b/contrib/pgstattuple/pgstattuple.c @@ -1,5 +1,5 @@ /* - * $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.27 2007/05/03 16:45:58 tgl Exp $ + * $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.28 2007/08/26 23:59:50 tgl Exp $ * * Copyright (c) 2001,2002 Tatsuo Ishii * @@ -24,14 +24,13 @@ #include "postgres.h" -#include "fmgr.h" -#include "funcapi.h" #include "access/gist_private.h" #include "access/hash.h" #include "access/heapam.h" #include "access/nbtree.h" -#include "access/transam.h" #include "catalog/namespace.h" +#include "funcapi.h" +#include "miscadmin.h" #include "utils/builtins.h" @@ -99,9 +98,6 @@ build_pgstattuple_type(pgstattuple_type * stat, FunctionCallInfo fcinfo) if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) elog(ERROR, "return type must be a row type"); - /* make sure we have a persistent copy of the tupdesc */ - tupdesc = CreateTupleDescCopy(tupdesc); - /* * Generate attribute metadata needed later to produce tuples from raw C * strings @@ -163,6 +159,11 @@ pgstattuple(PG_FUNCTION_ARGS) RangeVar *relrv; Relation rel; + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("must be superuser to use pgstattuple functions")))); + /* open relation */ relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); rel = relation_openrv(relrv, AccessShareLock); @@ -176,6 +177,11 @@ pgstattuplebyid(PG_FUNCTION_ARGS) Oid relid = PG_GETARG_OID(0); Relation rel; + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("must be superuser to use pgstattuple functions")))); + /* open relation */ rel = relation_open(relid, AccessShareLock); diff --git a/contrib/pgstattuple/pgstattuple.sql.in b/contrib/pgstattuple/pgstattuple.sql.in index 77a5e2d4b2..ec8f8b1bbe 100644 --- a/contrib/pgstattuple/pgstattuple.sql.in +++ b/contrib/pgstattuple/pgstattuple.sql.in @@ -1,48 +1,48 @@ -- Adjust this setting to control where the objects get created. SET search_path = public; -CREATE TYPE pgstattuple_type AS ( - table_len BIGINT, -- physical table length in bytes - tuple_count BIGINT, -- number of live tuples - tuple_len BIGINT, -- total tuples length in bytes - tuple_percent FLOAT, -- live tuples in % - dead_tuple_count BIGINT, -- number of dead tuples - dead_tuple_len BIGINT, -- total dead tuples length in bytes - dead_tuple_percent FLOAT, -- dead tuples in % - free_space BIGINT, -- free space in bytes - free_percent FLOAT -- free space in % -); - -CREATE OR REPLACE FUNCTION pgstattuple(text) -RETURNS pgstattuple_type +CREATE OR REPLACE FUNCTION pgstattuple(IN relname text, + OUT table_len BIGINT, -- physical table length in bytes + OUT tuple_count BIGINT, -- number of live tuples + OUT tuple_len BIGINT, -- total tuples length in bytes + OUT tuple_percent FLOAT, -- live tuples in % + OUT dead_tuple_count BIGINT, -- number of dead tuples + OUT dead_tuple_len BIGINT, -- total dead tuples length in bytes + OUT dead_tuple_percent FLOAT, -- dead tuples in % + OUT free_space BIGINT, -- free space in bytes + OUT free_percent FLOAT) -- free space in % AS 'MODULE_PATHNAME', 'pgstattuple' LANGUAGE C STRICT; -CREATE OR REPLACE FUNCTION pgstattuple(oid) -RETURNS pgstattuple_type +CREATE OR REPLACE FUNCTION pgstattuple(IN reloid oid, + OUT table_len BIGINT, -- physical table length in bytes + OUT tuple_count BIGINT, -- number of live tuples + OUT tuple_len BIGINT, -- total tuples length in bytes + OUT tuple_percent FLOAT, -- live tuples in % + OUT dead_tuple_count BIGINT, -- number of dead tuples + OUT dead_tuple_len BIGINT, -- total dead tuples length in bytes + OUT dead_tuple_percent FLOAT, -- dead tuples in % + OUT free_space BIGINT, -- free space in bytes + OUT free_percent FLOAT) -- free space in % AS 'MODULE_PATHNAME', 'pgstattuplebyid' LANGUAGE C STRICT; -- -- pgstatindex -- -CREATE TYPE pgstatindex_type AS ( - version int4, - tree_level int4, - index_size int4, - root_block_no int4, - internal_pages int4, - leaf_pages int4, - empty_pages int4, - deleted_pages int4, - avg_leaf_density float8, - leaf_fragmentation float8 -); - -CREATE OR REPLACE FUNCTION pgstatindex(text) -RETURNS pgstatindex_type +CREATE OR REPLACE FUNCTION pgstatindex(IN relname text, + OUT version int4, + OUT tree_level int4, + OUT index_size int4, + OUT root_block_no int4, + OUT internal_pages int4, + OUT leaf_pages int4, + OUT empty_pages int4, + OUT deleted_pages int4, + OUT avg_leaf_density float8, + OUT leaf_fragmentation float8) AS 'MODULE_PATHNAME', 'pgstatindex' -LANGUAGE 'C' STRICT; +LANGUAGE C STRICT; -- -- pg_relpages() @@ -50,4 +50,4 @@ LANGUAGE 'C' STRICT; CREATE OR REPLACE FUNCTION pg_relpages(text) RETURNS int AS 'MODULE_PATHNAME', 'pg_relpages' -LANGUAGE 'C' STRICT; +LANGUAGE C STRICT; diff --git a/contrib/pgstattuple/uninstall_pgstattuple.sql b/contrib/pgstattuple/uninstall_pgstattuple.sql index 16f3d9aa32..6d97590d4d 100644 --- a/contrib/pgstattuple/uninstall_pgstattuple.sql +++ b/contrib/pgstattuple/uninstall_pgstattuple.sql @@ -1,11 +1,7 @@ -- Adjust this setting to control where the objects get created. SET search_path = public; -DROP FUNCTION pgstattuple(oid); DROP FUNCTION pgstattuple(text); -DROP TYPE pgstattuple_type; - +DROP FUNCTION pgstattuple(oid); DROP FUNCTION pgstatindex(text); -DROP TYPE pgstatindex_type; - DROP FUNCTION pg_relpages(text); -- 2.11.0