On Tue, 2012-10-09 at 20:45 -0400, Peter Eisentraut wrote: > About that plugins directory ($libdir/plugins) ... I don't think we > ever > really got that to work sensibly. I don't remember the original > design > discussion, but I have seen a number of explanations offered over the > years. It's not clear who decides what to put in there (plugin > author, > packager, DBA?), how to put it there (move it, copy it, symlink it? -- > no support in pgxs), and based on what criteria. > > It would seem to be much more in the spirit of things to simply list > the > allowed plugins in a GUC variable, like > > some_clever_name_here = $libdir/this, $libdir/that
Here is a patch, with some_clever_name = user_loadable_libraries. There are obviously some conflict/transition issues with using user_loadable_libraries vs the plugins directory. I have tried to explain the mechanisms in the documentation, but there are other choices possible in some situations.
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index b7df8ce..e276dd6 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -5547,16 +5547,25 @@ <title>Other Defaults</title> </para> <para> - Because this is not a superuser-only option, the libraries - that can be loaded are restricted to those appearing in the - <filename>plugins</> subdirectory of the installation's - standard library directory. (It is the database administrator's + Because this is not a superuser-only option, the libraries that can be + loaded are restricted. Either they have to be listed + in <xref linkend="guc-user-loadable-libraries"> or they have to be + stored in the <filename>plugins</> subdirectory of the installation's + standard library directory. It is the database administrator's responsibility to ensure that only <quote>safe</> libraries - are installed there.) Entries in <varname>local_preload_libraries</> - can specify this directory explicitly, for example - <literal>$libdir/plugins/mylib</literal>, or just specify - the library name — <literal>mylib</literal> would have - the same effect as <literal>$libdir/plugins/mylib</literal>. + are enabled in these ways. + </para> + + <para> + Entries in <varname>local_preload_libraries</> + can specify the <filename>plugins</filename> directory explicitly, for example + <literal>$libdir/plugins/mylib</literal>. If they don't, but the + <filename>plugins</filename> directory exists, then a library name + without a slash, such as <literal>mylib</literal> will be expanded + to <literal>$libdir/plugins/mylib</literal>. If + the <literal>plugins</literal> directory does not exist, then all + listed names would need to be listed + in <literal>user_loadable_libraries</literal>. </para> <para> @@ -5584,6 +5593,27 @@ <title>Other Defaults</title> </listitem> </varlistentry> + <varlistentry id="guc-user-loadable-libraries" xreflabel="user_loadable_libraries"> + <term><varname>user_loadable_libraries</varname> (<type>string</type>)</term> + <indexterm> + <primary><varname>user_loadable_libraries</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + This parameter specifies a list of shared libraries that unprivileged + users can load using either the <command>LOAD</command> command or by + listing them in <xref linkend="guc-local-preload-libraries">. The + library names listed here and the libraries names invoked by one the + mentioned methods must match verbatim in order for the loading to be + allowed. + </para> + + <para> + Using this parameter is an alternative to placing those libraries into + the <filename>plugins</filename> directory. + </para> + </listitem> + </varlistentry> </variablelist> </sect2> </sect1> diff --git a/doc/src/sgml/ref/load.sgml b/doc/src/sgml/ref/load.sgml index f44f313..fc77bd5 100644 --- a/doc/src/sgml/ref/load.sgml +++ b/doc/src/sgml/ref/load.sgml @@ -51,11 +51,12 @@ <title>Description</title> <para> Non-superusers can only apply <command>LOAD</> to library files + listed in <xref linkend='guc-user-loadable-libraries'> or located in <filename>$libdir/plugins/</> — the specified <replaceable class="PARAMETER">filename</replaceable> must begin - with exactly that string. (It is the database administrator's + with exactly that string. It is the database administrator's responsibility to ensure that only <quote>safe</> libraries - are installed there.) + are enabled in these ways. </para> </refsect1> diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c index 562a7c9..eab1d2b 100644 --- a/src/backend/utils/fmgr/dfmgr.c +++ b/src/backend/utils/fmgr/dfmgr.c @@ -23,6 +23,8 @@ #endif #include "lib/stringinfo.h" #include "miscadmin.h" +#include "nodes/pg_list.h" +#include "utils/builtins.h" #include "utils/dynamic_loader.h" #include "utils/hsearch.h" @@ -70,6 +72,7 @@ #endif char *Dynamic_library_path; +char *user_loadable_libraries_string; static void *internal_load_library(const char *libname); static void incompatible_module_error(const char *libname, @@ -538,12 +541,44 @@ static void incompatible_module_error(const char *libname, static void check_restricted_library_name(const char *name) { - if (strncmp(name, "$libdir/plugins/", 16) != 0 || - first_dir_separator(name + 16) != NULL) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("access to library \"%s\" is not allowed", - name))); + char *rawstring; + List *elemlist; + ListCell *l; + + rawstring = pstrdup(user_loadable_libraries_string); + + if (!SplitIdentifierString(rawstring, ',', &elemlist)) + { + pfree(rawstring); + list_free(elemlist); + ereport(LOG, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("invalid list syntax in parameter \"%s\"", + "user_loadable_libraries"))); + return; + } + + foreach(l, elemlist) + { + char *tok = (char *) lfirst(l); + + if (strcmp(tok, name) == 0) + { + list_free(elemlist); + return; + } + } + + list_free(elemlist); + + if (strncmp(name, "$libdir/plugins/", 16) == 0 && + first_dir_separator(name + 16) == NULL) + return; + + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("access to library \"%s\" is not allowed", + name))); } /* diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 24ca97d..c30f414 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -1241,6 +1241,9 @@ List *elemlist; int elevel; ListCell *l; + char path[MAXPGPATH]; + struct stat statbuf; + bool use_plugins_dir = false; if (libraries == NULL || libraries[0] == '\0') return; /* nothing to do */ @@ -1273,6 +1276,10 @@ #endif elevel = LOG; + snprintf(path, sizeof(path), "%s/plugins", pkglib_path); + if (stat(path, &statbuf) == 0) + use_plugins_dir = true; + foreach(l, elemlist) { char *tok = (char *) lfirst(l); @@ -1281,7 +1288,7 @@ filename = pstrdup(tok); canonicalize_path(filename); /* If restricting, insert $libdir/plugins if not mentioned already */ - if (restricted && first_dir_separator(filename) == NULL) + if (restricted && first_dir_separator(filename) == NULL && use_plugins_dir) { char *expanded; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index ac5e4f3..dadfb29 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -2739,6 +2739,17 @@ static char *config_enum_get_options(struct config_enum * record, }, { + {"user_loadable_libraries", PGC_SIGHUP, CLIENT_CONN_OTHER, + gettext_noop("Lists shared libraries that non-superusers can load using local_preload_libraries or LOAD."), + NULL, + GUC_LIST_INPUT | GUC_LIST_QUOTE + }, + &user_loadable_libraries_string, + "", + NULL, NULL, NULL + }, + + { {"search_path", PGC_USERSET, CLIENT_CONN_STATEMENT, gettext_noop("Sets the schema search order for names that are not schema-qualified."), NULL, diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index eeb9b82..486652d 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -525,6 +525,7 @@ #dynamic_library_path = '$libdir' #local_preload_libraries = '' +#user_loadable_libraries = '' #------------------------------------------------------------------------------ diff --git a/src/include/fmgr.h b/src/include/fmgr.h index fe4a41b..9d9ae9b 100644 --- a/src/include/fmgr.h +++ b/src/include/fmgr.h @@ -629,6 +629,7 @@ extern bool get_call_expr_arg_stable(fmNodePtr expr, int argnum); * Routines in dfmgr.c */ extern char *Dynamic_library_path; +extern char *user_loadable_libraries_string; extern PGFunction load_external_function(char *filename, char *funcname, bool signalNotFound, void **filehandle);
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers