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