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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers