From 56f3fb3ba1aed1efbfb6b50e55159df8a0ad2f39 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 27 Aug 2007 00:13:51 +0000 Subject: [PATCH] Restrict pgrowlocks function 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/pgrowlocks/README.pgrowlocks | 14 +----- contrib/pgrowlocks/pgrowlocks.c | 50 +++++++-------------- contrib/pgrowlocks/pgrowlocks.sql.in | 21 ++++----- contrib/pgrowlocks/uninstall_pgrowlocks.sql | 2 - 4 files changed, 26 insertions(+), 61 deletions(-) diff --git a/contrib/pgrowlocks/README.pgrowlocks b/contrib/pgrowlocks/README.pgrowlocks index ebaea4ca5a..6964cc9c73 100644 --- a/contrib/pgrowlocks/README.pgrowlocks +++ b/contrib/pgrowlocks/README.pgrowlocks @@ -1,4 +1,4 @@ -$PostgreSQL: pgsql/contrib/pgrowlocks/README.pgrowlocks,v 1.1 2006/04/23 01:12:58 ishii Exp $ +$PostgreSQL: pgsql/contrib/pgrowlocks/README.pgrowlocks,v 1.2 2007/08/27 00:13:51 tgl Exp $ pgrowlocks README Tatsuo Ishii @@ -6,16 +6,14 @@ pgrowlocks README Tatsuo Ishii pgrowlocks shows row locking information for specified table. - pgrowlocks returns following data type: + pgrowlocks returns following columns: -CREATE TYPE pgrowlocks_type AS ( locked_row TID, -- row TID lock_type TEXT, -- lock type locker XID, -- locking XID multi bool, -- multi XID? xids xid[], -- multi XIDs pids INTEGER[] -- locker's process id -); Here is a sample execution of pgrowlocks: @@ -62,14 +60,6 @@ test=# SELECT * FROM pgrowlocks('t1'); 3. How to use pgrowlocks - The calling sequence for pgrowlocks is as follows: - - CREATE OR REPLACE FUNCTION pgrowlocks(text) RETURNS pgrowlocks_type - AS 'MODULE_PATHNAME', 'pgrowlocks' - LANGUAGE 'c' WITH (isstrict); - - The parameter is a name of table. pgrowlocks returns type pgrowlocks_type. - pgrowlocks grab AccessShareLock for the target table and read each row one by one to get the row locking information. You should notice that: diff --git a/contrib/pgrowlocks/pgrowlocks.c b/contrib/pgrowlocks/pgrowlocks.c index 002536b920..73dea0c4a5 100644 --- a/contrib/pgrowlocks/pgrowlocks.c +++ b/contrib/pgrowlocks/pgrowlocks.c @@ -1,5 +1,5 @@ /* - * $PostgreSQL: pgsql/contrib/pgrowlocks/pgrowlocks.c,v 1.5 2006/10/04 00:29:46 momjian Exp $ + * $PostgreSQL: pgsql/contrib/pgrowlocks/pgrowlocks.c,v 1.6 2007/08/27 00:13:51 tgl Exp $ * * Copyright (c) 2005-2006 Tatsuo Ishii * @@ -24,19 +24,15 @@ #include "postgres.h" -#include "funcapi.h" #include "access/heapam.h" -#include "access/transam.h" +#include "access/multixact.h" #include "access/xact.h" #include "catalog/namespace.h" -#include "catalog/pg_type.h" -#include "storage/proc.h" +#include "funcapi.h" +#include "miscadmin.h" +#include "storage/procarray.h" #include "utils/builtins.h" -#ifdef HEAP_XMAX_SHARED_LOCK -#include "access/multixact.h" -#include "storage/procarray.h" -#endif PG_MODULE_MAGIC; @@ -47,22 +43,11 @@ extern Datum pgrowlocks(PG_FUNCTION_ARGS); /* ---------- * pgrowlocks: * returns tids of rows being locked - * - * C FUNCTION definition - * pgrowlocks(text) returns set of pgrowlocks_type - * see pgrowlocks.sql for pgrowlocks_type * ---------- */ -#define DUMMY_TUPLE "public.pgrowlocks_type" #define NCHARS 32 -/* - * define this if makeRangeVarFromNameList() has two arguments. As far - * as I know, this only happens in 8.0.x. - */ -#undef MAKERANGEVARFROMNAMELIST_HAS_TWO_ARGS - typedef struct { Relation rel; @@ -82,6 +67,11 @@ pgrowlocks(PG_FUNCTION_ARGS) MyData *mydata; Relation rel; + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("must be superuser to use pgrowlocks")))); + if (SRF_IS_FIRSTCALL()) { text *relname; @@ -91,17 +81,17 @@ pgrowlocks(PG_FUNCTION_ARGS) funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); - tupdesc = RelationNameGetTupleDesc(DUMMY_TUPLE); + /* Build a tuple descriptor for our result type */ + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + attinmeta = TupleDescGetAttInMetadata(tupdesc); funcctx->attinmeta = attinmeta; relname = PG_GETARG_TEXT_P(0); -#ifdef MAKERANGEVARFROMNAMELIST_HAS_TWO_ARGS - relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname, "pgrowlocks")); -#else relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); -#endif rel = heap_openrv(relrv, AccessShareLock); + scan = heap_beginscan(rel, SnapshotNow, 0, NULL); mydata = palloc(sizeof(*mydata)); mydata->rel = rel; @@ -135,17 +125,12 @@ pgrowlocks(PG_FUNCTION_ARGS) i = 0; values[i++] = (char *) DirectFunctionCall1(tidout, PointerGetDatum(&tuple->t_self)); -#ifdef HEAP_XMAX_SHARED_LOCK if (tuple->t_data->t_infomask & HEAP_XMAX_SHARED_LOCK) values[i++] = pstrdup("Shared"); else values[i++] = pstrdup("Exclusive"); -#else - values[i++] = pstrdup("Exclusive"); -#endif values[i] = palloc(NCHARS * sizeof(char)); snprintf(values[i++], NCHARS, "%d", HeapTupleHeaderGetXmax(tuple->t_data)); -#ifdef HEAP_XMAX_SHARED_LOCK if (tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI) { TransactionId *xids; @@ -198,11 +183,6 @@ pgrowlocks(PG_FUNCTION_ARGS) values[i] = palloc(NCHARS * sizeof(char)); snprintf(values[i++], NCHARS, "{%d}", BackendXidGetPid(HeapTupleHeaderGetXmax(tuple->t_data))); } -#else - values[i++] = pstrdup("false"); - values[i++] = pstrdup("{}"); - values[i++] = pstrdup("{}"); -#endif LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK); diff --git a/contrib/pgrowlocks/pgrowlocks.sql.in b/contrib/pgrowlocks/pgrowlocks.sql.in index 0607c44349..0370831e66 100644 --- a/contrib/pgrowlocks/pgrowlocks.sql.in +++ b/contrib/pgrowlocks/pgrowlocks.sql.in @@ -1,16 +1,13 @@ -- Adjust this setting to control where the objects get created. SET search_path = public; -CREATE TYPE pgrowlocks_type AS ( - locked_row TID, -- row TID - lock_type TEXT, -- lock type - locker XID, -- locking XID - multi bool, -- multi XID? - xids xid[], -- multi XIDs - pids INTEGER[] -- locker's process id -); - -CREATE OR REPLACE FUNCTION pgrowlocks(text) -RETURNS setof pgrowlocks_type +CREATE OR REPLACE FUNCTION pgrowlocks(IN relname text, + OUT locked_row TID, -- row TID + OUT lock_type TEXT, -- lock type + OUT locker XID, -- locking XID + OUT multi bool, -- multi XID? + OUT xids xid[], -- multi XIDs + OUT pids INTEGER[]) -- locker's process id +RETURNS SETOF record AS 'MODULE_PATHNAME', 'pgrowlocks' -LANGUAGE 'C' STRICT; +LANGUAGE C STRICT; diff --git a/contrib/pgrowlocks/uninstall_pgrowlocks.sql b/contrib/pgrowlocks/uninstall_pgrowlocks.sql index 9e37d11975..b1a1f58b52 100644 --- a/contrib/pgrowlocks/uninstall_pgrowlocks.sql +++ b/contrib/pgrowlocks/uninstall_pgrowlocks.sql @@ -1,5 +1,3 @@ SET search_path = public; DROP FUNCTION pgrowlocks(text); - -DROP TYPE pgrowlocks_type;