diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c index 1374b65122939e03f9b86944f1116596fa128b42..ca6babb048a6608612ca6514776bd0095f2a5d14 100644 --- a/src/backend/commands/variable.c +++ b/src/backend/commands/variable.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/variable.c,v 1.130 2009/06/11 14:48:56 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/variable.c,v 1.131 2009/09/03 22:08:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -717,21 +717,6 @@ assign_session_authorization(const char *value, bool doit, GucSource source) /* not a saved ID, so look it up */ HeapTuple roleTup; - if (InSecurityDefinerContext()) - { - /* - * Disallow SET SESSION AUTHORIZATION inside a security definer - * context. We need to do this because when we exit the context, - * GUC won't be notified, leaving things out of sync. Note that - * this test is positioned so that restoring a previously saved - * setting isn't prevented. - */ - ereport(GUC_complaint_elevel(source), - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot set session authorization within security-definer function"))); - return NULL; - } - if (!IsTransactionState()) { /* @@ -838,24 +823,6 @@ assign_role(const char *value, bool doit, GucSource source) } } - if (roleid == InvalidOid && InSecurityDefinerContext()) - { - /* - * Disallow SET ROLE inside a security definer context. We need to do - * this because when we exit the context, GUC won't be notified, - * leaving things out of sync. Note that this test is arranged so - * that restoring a previously saved setting isn't prevented. - * - * XXX it would be nice to allow this case in future, with the - * behavior being that the SET ROLE's effects end when the security - * definer context is exited. - */ - ereport(GUC_complaint_elevel(source), - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot set role within security-definer function"))); - return NULL; - } - if (roleid == InvalidOid && strcmp(actual_rolename, "none") != 0) { diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 03e2408737e849fdc5ba036b9407f569b85bc2fc..70dcefbc315616986d924cab8f447eb3c04cca19 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut <peter_e@gmx.net>. * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.514 2009/08/31 19:41:00 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.515 2009/09/03 22:08:05 tgl Exp $ * *-------------------------------------------------------------------- */ @@ -2321,7 +2321,7 @@ static struct config_string ConfigureNamesString[] = {"role", PGC_USERSET, UNGROUPED, gettext_noop("Sets the current role."), NULL, - GUC_IS_NAME | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE + GUC_IS_NAME | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_NOT_WHILE_SEC_DEF }, &role_string, "none", assign_role, show_role @@ -2332,7 +2332,7 @@ static struct config_string ConfigureNamesString[] = {"session_authorization", PGC_USERSET, UNGROUPED, gettext_noop("Sets the session user name."), NULL, - GUC_IS_NAME | GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE + GUC_IS_NAME | GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_NOT_WHILE_SEC_DEF }, &session_authorization_string, NULL, assign_session_authorization, show_session_authorization @@ -4661,6 +4661,32 @@ set_config_option(const char *name, const char *value, break; } + /* + * Disallow changing GUC_NOT_WHILE_SEC_DEF values if we are inside a + * security-definer function. We can reject this regardless of + * the context or source, mainly because sources that it might be + * reasonable to override for won't be seen while inside a function. + * + * Note: variables marked GUC_NOT_WHILE_SEC_DEF should probably be marked + * GUC_NO_RESET_ALL as well, because ResetAllOptions() doesn't check this. + * + * Note: this flag is currently used for "session_authorization" and + * "role". We need to prohibit this because when we exit the sec-def + * context, GUC won't be notified, leaving things out of sync. + * + * XXX it would be nice to allow these cases in future, with the behavior + * being that the SET's effects end when the security definer context is + * exited. + */ + if ((record->flags & GUC_NOT_WHILE_SEC_DEF) && InSecurityDefinerContext()) + { + ereport(elevel, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("cannot set parameter \"%s\" within security-definer function", + name))); + return false; + } + /* * Should we set reset/stacked values? (If so, the behavior is not * transactional.) This is done either when we get a default value from diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index 10eb70d01893c94bcb55cb27211df547f83277ff..6f4acdef70185aaaecf0a64541d6e534e2e5b229 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -7,7 +7,7 @@ * Copyright (c) 2000-2009, PostgreSQL Global Development Group * Written by Peter Eisentraut <peter_e@gmx.net>. * - * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.103 2009/08/29 19:26:52 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.104 2009/09/03 22:08:05 tgl Exp $ *-------------------------------------------------------------------- */ #ifndef GUC_H @@ -146,6 +146,8 @@ typedef enum #define GUC_UNIT_MIN 0x4000 /* value is in minutes */ #define GUC_UNIT_TIME 0x7000 /* mask for MS, S, MIN */ +#define GUC_NOT_WHILE_SEC_DEF 0x8000 /* can't change inside sec-def func */ + /* GUC vars that are actually declared in guc.c, rather than elsewhere */ extern bool log_duration; extern bool Debug_print_plan;