allow_set_role.2.patch
application/octet-stream
Filename: allow_set_role.2.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/utils/fmgr/fmgr.c | 15 | 1 |
| src/backend/utils/init/miscinit.c | 1 | 1 |
| src/backend/utils/misc/guc.c | 8 | 7 |
| src/include/utils/guc.h | 3 | 1 |
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 9a1da59..28ab39f 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -981,8 +981,22 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
if (fcache->proconfig)
AtEOXact_GUC(true, save_nestlevel);
+
if (OidIsValid(fcache->userid))
- SetUserIdAndSecContext(save_userid, save_sec_context);
+ {
+ Oid current_userid;
+ int current_sec_context;
+ /*
+ * If the called function stack used SET ROLE to change CurrentUserId
+ * then do not revert the setting back to the saved user.
+ */
+ GetUserIdAndSecContext(¤t_userid, ¤t_sec_context);
+
+ if(fcache->userid == current_userid)
+ SetUserIdAndSecContext(save_userid, save_sec_context);
+ else
+ SetUserIdAndSecContext(current_userid, save_sec_context);
+ }
return result;
}
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 359edee..a565836 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -313,7 +313,7 @@ GetOuterUserId(void)
static void
SetOuterUserId(Oid userid)
{
- AssertState(SecurityRestrictionContext == 0);
+ AssertState(!InSecurityRestrictedOperation());
AssertArg(OidIsValid(userid));
OuterUserId = userid;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index b530720..4a54df3 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -2381,7 +2381,8 @@ 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_NOT_WHILE_SEC_REST
+ 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_REST | GUC_NOT_WHILE_USER_CHANGE
},
&session_authorization_string,
NULL, assign_session_authorization, show_session_authorization
@@ -4747,20 +4748,20 @@ set_config_option(const char *name, const char *value,
* we prohibit changing these in a security-restricted operation because
* otherwise RESET could be used to regain the session user's privileges.
*/
- if (record->flags & GUC_NOT_WHILE_SEC_REST)
+ if (record->flags & GUC_NOT_WHILE_USER_CHANGE)
{
if (InLocalUserIdChange())
{
- /*
- * Phrasing of this error message is historical, but it's the
- * most common case.
- */
ereport(elevel,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("cannot set parameter \"%s\" within security-definer function",
+ errmsg("cannot set parameter \"%s\" while user-id changed temporarily",
name)));
return false;
}
+ }
+
+ if (record->flags & GUC_NOT_WHILE_SEC_REST)
+ {
if (InSecurityRestrictedOperation())
{
ereport(elevel,
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 9c95b60..469c787 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -149,7 +149,9 @@ 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_REST 0x8000 /* can't set if security restricted */
+#define GUC_NOT_WHILE_SEC_REST 0x08000 /* can't set if security restricted */
+#define GUC_NOT_WHILE_USER_CHANGE 0x10000 /* can't set if current-user-id temporarily changed */
+
/* GUC vars that are actually declared in guc.c, rather than elsewhere */
extern bool log_duration;