Skip to content

Commit 38c75ec

Browse files
committed
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.
1 parent 0effa08 commit 38c75ec

File tree

4 files changed

+72
-66
lines changed

4 files changed

+72
-66
lines changed

contrib/pgstattuple/pgstatindex.c

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,21 @@
2424

2525
#include "postgres.h"
2626

27-
#include "fmgr.h"
28-
#include "funcapi.h"
2927
#include "access/heapam.h"
30-
#include "access/itup.h"
3128
#include "access/nbtree.h"
32-
#include "access/transam.h"
3329
#include "catalog/namespace.h"
34-
#include "catalog/pg_type.h"
30+
#include "funcapi.h"
31+
#include "miscadmin.h"
3532
#include "utils/builtins.h"
36-
#include "utils/inval.h"
3733

38-
PG_FUNCTION_INFO_V1(pgstatindex);
39-
PG_FUNCTION_INFO_V1(pg_relpages);
4034

4135
extern Datum pgstatindex(PG_FUNCTION_ARGS);
4236
extern Datum pg_relpages(PG_FUNCTION_ARGS);
4337

44-
#define PGSTATINDEX_TYPE "public.pgstatindex_type"
45-
#define PGSTATINDEX_NCOLUMNS 10
38+
PG_FUNCTION_INFO_V1(pgstatindex);
39+
PG_FUNCTION_INFO_V1(pg_relpages);
4640

47-
#define IS_INDEX(r) ((r)->rd_rel->relkind == 'i')
41+
#define IS_INDEX(r) ((r)->rd_rel->relkind == RELKIND_INDEX)
4842
#define IS_BTREE(r) ((r)->rd_rel->relam == BTREE_AM_OID)
4943

5044
#define CHECK_PAGE_OFFSET_RANGE(pg, offnum) { \
@@ -97,15 +91,20 @@ pgstatindex(PG_FUNCTION_ARGS)
9791
uint32 blkno;
9892
BTIndexStat indexStat;
9993

94+
if (!superuser())
95+
ereport(ERROR,
96+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
97+
(errmsg("must be superuser to use pgstattuple functions"))));
98+
10099
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
101100
rel = relation_openrv(relrv, AccessShareLock);
102101

103102
if (!IS_INDEX(rel) || !IS_BTREE(rel))
104-
elog(ERROR, "pgstatindex() can only be used on b-tree index");
103+
elog(ERROR, "relation \"%s\" is not a btree index",
104+
RelationGetRelationName(rel));
105105

106-
/*-------------------
107-
* Read a metapage
108-
*-------------------
106+
/*
107+
* Read metapage
109108
*/
110109
{
111110
Buffer buffer = ReadBuffer(rel, 0);
@@ -194,11 +193,12 @@ pgstatindex(PG_FUNCTION_ARGS)
194193
{
195194
TupleDesc tupleDesc;
196195
int j;
197-
char *values[PGSTATINDEX_NCOLUMNS];
198-
196+
char *values[10];
199197
HeapTuple tuple;
200198

201-
tupleDesc = RelationNameGetTupleDesc(PGSTATINDEX_TYPE);
199+
/* Build a tuple descriptor for our result type */
200+
if (get_call_result_type(fcinfo, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
201+
elog(ERROR, "return type must be a row type");
202202

203203
j = 0;
204204
values[j] = palloc(32);
@@ -229,7 +229,7 @@ pgstatindex(PG_FUNCTION_ARGS)
229229
tuple = BuildTupleFromCStrings(TupleDescGetAttInMetadata(tupleDesc),
230230
values);
231231

232-
result = TupleGetDatum(TupleDescGetSlot(tupleDesc), tuple);
232+
result = HeapTupleGetDatum(tuple);
233233
}
234234

235235
PG_RETURN_DATUM(result);
@@ -238,7 +238,7 @@ pgstatindex(PG_FUNCTION_ARGS)
238238
/* --------------------------------------------------------
239239
* pg_relpages()
240240
*
241-
* Get a number of pages of the table/index.
241+
* Get the number of pages of the table/index.
242242
*
243243
* Usage: SELECT pg_relpages('t1');
244244
* SELECT pg_relpages('t1_pkey');
@@ -248,11 +248,15 @@ Datum
248248
pg_relpages(PG_FUNCTION_ARGS)
249249
{
250250
text *relname = PG_GETARG_TEXT_P(0);
251-
252251
Relation rel;
253252
RangeVar *relrv;
254253
int4 relpages;
255254

255+
if (!superuser())
256+
ereport(ERROR,
257+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
258+
(errmsg("must be superuser to use pgstattuple functions"))));
259+
256260
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
257261
rel = relation_openrv(relrv, AccessShareLock);
258262

contrib/pgstattuple/pgstattuple.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.27 2007/05/03 16:45:58 tgl Exp $
2+
* $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.28 2007/08/26 23:59:50 tgl Exp $
33
*
44
* Copyright (c) 2001,2002 Tatsuo Ishii
55
*
@@ -24,14 +24,13 @@
2424

2525
#include "postgres.h"
2626

27-
#include "fmgr.h"
28-
#include "funcapi.h"
2927
#include "access/gist_private.h"
3028
#include "access/hash.h"
3129
#include "access/heapam.h"
3230
#include "access/nbtree.h"
33-
#include "access/transam.h"
3431
#include "catalog/namespace.h"
32+
#include "funcapi.h"
33+
#include "miscadmin.h"
3534
#include "utils/builtins.h"
3635

3736

@@ -99,9 +98,6 @@ build_pgstattuple_type(pgstattuple_type * stat, FunctionCallInfo fcinfo)
9998
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
10099
elog(ERROR, "return type must be a row type");
101100

102-
/* make sure we have a persistent copy of the tupdesc */
103-
tupdesc = CreateTupleDescCopy(tupdesc);
104-
105101
/*
106102
* Generate attribute metadata needed later to produce tuples from raw C
107103
* strings
@@ -163,6 +159,11 @@ pgstattuple(PG_FUNCTION_ARGS)
163159
RangeVar *relrv;
164160
Relation rel;
165161

162+
if (!superuser())
163+
ereport(ERROR,
164+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
165+
(errmsg("must be superuser to use pgstattuple functions"))));
166+
166167
/* open relation */
167168
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
168169
rel = relation_openrv(relrv, AccessShareLock);
@@ -176,6 +177,11 @@ pgstattuplebyid(PG_FUNCTION_ARGS)
176177
Oid relid = PG_GETARG_OID(0);
177178
Relation rel;
178179

180+
if (!superuser())
181+
ereport(ERROR,
182+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
183+
(errmsg("must be superuser to use pgstattuple functions"))));
184+
179185
/* open relation */
180186
rel = relation_open(relid, AccessShareLock);
181187

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,53 @@
11
-- Adjust this setting to control where the objects get created.
22
SET search_path = public;
33

4-
CREATE TYPE pgstattuple_type AS (
5-
table_len BIGINT, -- physical table length in bytes
6-
tuple_count BIGINT, -- number of live tuples
7-
tuple_len BIGINT, -- total tuples length in bytes
8-
tuple_percent FLOAT, -- live tuples in %
9-
dead_tuple_count BIGINT, -- number of dead tuples
10-
dead_tuple_len BIGINT, -- total dead tuples length in bytes
11-
dead_tuple_percent FLOAT, -- dead tuples in %
12-
free_space BIGINT, -- free space in bytes
13-
free_percent FLOAT -- free space in %
14-
);
15-
16-
CREATE OR REPLACE FUNCTION pgstattuple(text)
17-
RETURNS pgstattuple_type
4+
CREATE OR REPLACE FUNCTION pgstattuple(IN relname text,
5+
OUT table_len BIGINT, -- physical table length in bytes
6+
OUT tuple_count BIGINT, -- number of live tuples
7+
OUT tuple_len BIGINT, -- total tuples length in bytes
8+
OUT tuple_percent FLOAT, -- live tuples in %
9+
OUT dead_tuple_count BIGINT, -- number of dead tuples
10+
OUT dead_tuple_len BIGINT, -- total dead tuples length in bytes
11+
OUT dead_tuple_percent FLOAT, -- dead tuples in %
12+
OUT free_space BIGINT, -- free space in bytes
13+
OUT free_percent FLOAT) -- free space in %
1814
AS 'MODULE_PATHNAME', 'pgstattuple'
1915
LANGUAGE C STRICT;
2016

21-
CREATE OR REPLACE FUNCTION pgstattuple(oid)
22-
RETURNS pgstattuple_type
17+
CREATE OR REPLACE FUNCTION pgstattuple(IN reloid oid,
18+
OUT table_len BIGINT, -- physical table length in bytes
19+
OUT tuple_count BIGINT, -- number of live tuples
20+
OUT tuple_len BIGINT, -- total tuples length in bytes
21+
OUT tuple_percent FLOAT, -- live tuples in %
22+
OUT dead_tuple_count BIGINT, -- number of dead tuples
23+
OUT dead_tuple_len BIGINT, -- total dead tuples length in bytes
24+
OUT dead_tuple_percent FLOAT, -- dead tuples in %
25+
OUT free_space BIGINT, -- free space in bytes
26+
OUT free_percent FLOAT) -- free space in %
2327
AS 'MODULE_PATHNAME', 'pgstattuplebyid'
2428
LANGUAGE C STRICT;
2529

2630
--
2731
-- pgstatindex
2832
--
29-
CREATE TYPE pgstatindex_type AS (
30-
version int4,
31-
tree_level int4,
32-
index_size int4,
33-
root_block_no int4,
34-
internal_pages int4,
35-
leaf_pages int4,
36-
empty_pages int4,
37-
deleted_pages int4,
38-
avg_leaf_density float8,
39-
leaf_fragmentation float8
40-
);
41-
42-
CREATE OR REPLACE FUNCTION pgstatindex(text)
43-
RETURNS pgstatindex_type
33+
CREATE OR REPLACE FUNCTION pgstatindex(IN relname text,
34+
OUT version int4,
35+
OUT tree_level int4,
36+
OUT index_size int4,
37+
OUT root_block_no int4,
38+
OUT internal_pages int4,
39+
OUT leaf_pages int4,
40+
OUT empty_pages int4,
41+
OUT deleted_pages int4,
42+
OUT avg_leaf_density float8,
43+
OUT leaf_fragmentation float8)
4444
AS 'MODULE_PATHNAME', 'pgstatindex'
45-
LANGUAGE 'C' STRICT;
45+
LANGUAGE C STRICT;
4646

4747
--
4848
-- pg_relpages()
4949
--
5050
CREATE OR REPLACE FUNCTION pg_relpages(text)
5151
RETURNS int
5252
AS 'MODULE_PATHNAME', 'pg_relpages'
53-
LANGUAGE 'C' STRICT;
53+
LANGUAGE C STRICT;
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
-- Adjust this setting to control where the objects get created.
22
SET search_path = public;
33

4-
DROP FUNCTION pgstattuple(oid);
54
DROP FUNCTION pgstattuple(text);
6-
DROP TYPE pgstattuple_type;
7-
5+
DROP FUNCTION pgstattuple(oid);
86
DROP FUNCTION pgstatindex(text);
9-
DROP TYPE pgstatindex_type;
10-
117
DROP FUNCTION pg_relpages(text);

0 commit comments

Comments
 (0)