diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index b214218..ad04252 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -19238,6 +19238,10 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
present on the operating system are never removed by this function.)
+
+ By default, use of this function is restricted to superusers, but access
+ can be given to other users via GRANT>.
+
@@ -19318,7 +19322,9 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
database cluster directory and the log_directory> can be
accessed. Use a relative path for files in the cluster directory,
and a path matching the log_directory> configuration setting
- for log files. Use of these functions is restricted to superusers.
+ for log files. Use of these functions is restricted to superusers
+ by default but access may be granted to others using
+ GRANT.
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 4dfedf8..2e31462 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1080,8 +1080,20 @@ REVOKE EXECUTE ON FUNCTION pg_xlog_replay_pause() FROM public;
REVOKE EXECUTE ON FUNCTION pg_xlog_replay_resume() FROM public;
REVOKE EXECUTE ON FUNCTION pg_rotate_logfile() FROM public;
REVOKE EXECUTE ON FUNCTION pg_reload_conf() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_import_system_collations(boolean, regnamespace) FROM public;
REVOKE EXECUTE ON FUNCTION pg_stat_reset() FROM public;
REVOKE EXECUTE ON FUNCTION pg_stat_reset_shared(text) FROM public;
REVOKE EXECUTE ON FUNCTION pg_stat_reset_single_table_counters(oid) FROM public;
REVOKE EXECUTE ON FUNCTION pg_stat_reset_single_function_counters(oid) FROM public;
+
+REVOKE EXECUTE ON FUNCTION pg_read_binary_file(text) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_read_binary_file(text, bigint, bigint) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_read_binary_file(text, bigint, bigint, boolean) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_read_file(text) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_read_file(text, bigint, bigint) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_read_file(text, bigint, bigint, boolean) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_stat_file(text) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_stat_file(text, boolean) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_ls_dir(text) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_ls_dir(text, boolean, boolean) FROM public;
diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c
index 8d4d5b7..a15ac16 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -218,7 +218,12 @@ normalize_locale_name(char *new, const char *old)
return changed;
}
-
+/*
+ * Import operating system collations.
+ *
+ * Permission checking for this function is managed through the normal
+ * GRANT system.
+ */
Datum
pg_import_system_collations(PG_FUNCTION_ARGS)
{
@@ -237,11 +242,6 @@ pg_import_system_collations(PG_FUNCTION_ARGS)
*lce;
#endif
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- (errmsg("must be superuser to import system collations"))));
-
#if defined(HAVE_LOCALE_T) && !defined(WIN32)
locale_a_handle = OpenPipeStream("locale -a", "r");
if (locale_a_handle == NULL)
diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c
index 1a127d9..4f1021e 100644
--- a/src/backend/utils/adt/genfile.c
+++ b/src/backend/utils/adt/genfile.c
@@ -183,6 +183,9 @@ read_text_file(const char *filename, int64 seek_offset, int64 bytes_to_read,
/*
* Read a section of a file, returning it as text
+ *
+ * Permission checking for this function is managed through the normal
+ * GRANT system.
*/
Datum
pg_read_file(PG_FUNCTION_ARGS)
@@ -194,11 +197,6 @@ pg_read_file(PG_FUNCTION_ARGS)
char *filename;
text *result;
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- (errmsg("must be superuser to read files"))));
-
/* handle optional arguments */
if (PG_NARGS() >= 3)
{
@@ -224,6 +222,9 @@ pg_read_file(PG_FUNCTION_ARGS)
/*
* Read a section of a file, returning it as bytea
+ *
+ * Permission checking for this function is managed through the normal
+ * GRANT system.
*/
Datum
pg_read_binary_file(PG_FUNCTION_ARGS)
@@ -235,11 +236,6 @@ pg_read_binary_file(PG_FUNCTION_ARGS)
char *filename;
bytea *result;
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- (errmsg("must be superuser to read files"))));
-
/* handle optional arguments */
if (PG_NARGS() >= 3)
{
@@ -299,6 +295,9 @@ pg_read_binary_file_all(PG_FUNCTION_ARGS)
/*
* stat a file
+ *
+ * Permission checking for this function is managed through the normal
+ * GRANT system.
*/
Datum
pg_stat_file(PG_FUNCTION_ARGS)
@@ -312,11 +311,6 @@ pg_stat_file(PG_FUNCTION_ARGS)
TupleDesc tupdesc;
bool missing_ok = false;
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- (errmsg("must be superuser to get file information"))));
-
/* check the optional argument */
if (PG_NARGS() == 2)
missing_ok = PG_GETARG_BOOL(1);
@@ -389,6 +383,9 @@ pg_stat_file_1arg(PG_FUNCTION_ARGS)
/*
* List a directory (returns the filenames only)
+ *
+ * Permission checking for this function is managed through the normal
+ * GRANT system.
*/
Datum
pg_ls_dir(PG_FUNCTION_ARGS)
@@ -398,11 +395,6 @@ pg_ls_dir(PG_FUNCTION_ARGS)
directory_fctx *fctx;
MemoryContext oldcontext;
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- (errmsg("must be superuser to get directory listings"))));
-
if (SRF_IS_FIRSTCALL())
{
bool missing_ok = false;
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
index f66b443..7da6826 100644
--- a/src/test/regress/expected/privileges.out
+++ b/src/test/regress/expected/privileges.out
@@ -582,6 +582,56 @@ SELECT testfunc1(5); -- ok
DROP FUNCTION testfunc1(int); -- fail
ERROR: must be owner of function testfunc1
+-- try to use built-in functions that are superuser-only by default
+-- these should all fail with permissions errors
+SELECT pg_start_backup('regress', false, false);
+ERROR: permission denied for function pg_start_backup
+SELECT pg_stop_backup();
+ERROR: permission denied for function pg_stop_backup
+SELECT pg_stop_backup(false);
+ERROR: permission denied for function pg_stop_backup
+SELECT pg_create_restore_point('regress');
+ERROR: permission denied for function pg_create_restore_point
+SELECT pg_switch_xlog();
+ERROR: permission denied for function pg_switch_xlog
+SELECT pg_xlog_replay_pause();
+ERROR: permission denied for function pg_xlog_replay_pause
+SELECT pg_xlog_replay_resume();
+ERROR: permission denied for function pg_xlog_replay_resume
+SELECT pg_rotate_logfile();
+ERROR: permission denied for function pg_rotate_logfile
+SELECT pg_reload_conf();
+ERROR: permission denied for function pg_reload_conf
+SELECT pg_import_system_collations(false, 'public'::regnamespace);
+ERROR: permission denied for function pg_import_system_collations
+SELECT pg_stat_reset();
+ERROR: permission denied for function pg_stat_reset
+SELECT pg_stat_reset_shared('regress');
+ERROR: permission denied for function pg_stat_reset_shared
+SELECT pg_stat_reset_single_table_counters(0);
+ERROR: permission denied for function pg_stat_reset_single_table_counters
+SELECT pg_stat_reset_single_function_counters(0);
+ERROR: permission denied for function pg_stat_reset_single_function_counters
+SELECT pg_read_binary_file('regress');
+ERROR: permission denied for function pg_read_binary_file
+SELECT pg_read_binary_file('regress', 0, 0);
+ERROR: permission denied for function pg_read_binary_file
+SELECT pg_read_binary_file('regress', 0, 0, false);
+ERROR: permission denied for function pg_read_binary_file
+SELECT pg_read_file('regress');
+ERROR: permission denied for function pg_read_file
+SELECT pg_read_file('regress', 0, 0);
+ERROR: permission denied for function pg_read_file
+SELECT pg_read_file('regress', 0, 0, false);
+ERROR: permission denied for function pg_read_file
+SELECT pg_stat_file('regress');
+ERROR: permission denied for function pg_stat_file
+SELECT pg_stat_file('regress', false);
+ERROR: permission denied for function pg_stat_file
+SELECT pg_ls_dir('regress');
+ERROR: permission denied for function pg_ls_dir
+SELECT pg_ls_dir('regress', false, false);
+ERROR: permission denied for function pg_ls_dir
\c -
DROP FUNCTION testfunc1(int); -- ok
-- restore to sanity
diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql
index 00dc7bd..a3011b9 100644
--- a/src/test/regress/sql/privileges.sql
+++ b/src/test/regress/sql/privileges.sql
@@ -392,6 +392,33 @@ SELECT testfunc1(5); -- ok
DROP FUNCTION testfunc1(int); -- fail
+-- try to use built-in functions that are superuser-only by default
+-- these should all fail with permissions errors
+SELECT pg_start_backup('regress', false, false);
+SELECT pg_stop_backup();
+SELECT pg_stop_backup(false);
+SELECT pg_create_restore_point('regress');
+SELECT pg_switch_xlog();
+SELECT pg_xlog_replay_pause();
+SELECT pg_xlog_replay_resume();
+SELECT pg_rotate_logfile();
+SELECT pg_reload_conf();
+SELECT pg_import_system_collations(false, 'public'::regnamespace);
+SELECT pg_stat_reset();
+SELECT pg_stat_reset_shared('regress');
+SELECT pg_stat_reset_single_table_counters(0);
+SELECT pg_stat_reset_single_function_counters(0);
+SELECT pg_read_binary_file('regress');
+SELECT pg_read_binary_file('regress', 0, 0);
+SELECT pg_read_binary_file('regress', 0, 0, false);
+SELECT pg_read_file('regress');
+SELECT pg_read_file('regress', 0, 0);
+SELECT pg_read_file('regress', 0, 0, false);
+SELECT pg_stat_file('regress');
+SELECT pg_stat_file('regress', false);
+SELECT pg_ls_dir('regress');
+SELECT pg_ls_dir('regress', false, false);
+
\c -
DROP FUNCTION testfunc1(int); -- ok