@@ -69,7 +69,6 @@ typedef struct MtmGucEntry
6969{
7070 char key [GUC_KEY_MAXLEN ];
7171 dlist_node list_node ;
72- char * value ;
7372} MtmGucEntry ;
7473
7574typedef struct {
@@ -83,8 +82,6 @@ bool MtmMonotonicSequences;
8382char * MtmRemoteFunctionsList ;
8483bool MtmIgnoreTablesWithoutPk ;
8584
86- fmgr_hook_type prev_fmgr_hook = NULL ;
87-
8885static char MtmTempSchema [NAMEDATALEN ];
8986static bool TempDropRegistered ;
9087
@@ -127,7 +124,7 @@ static void MtmProcessUtilitySender(PlannedStmt *pstmt,
127124 QueryEnvironment * queryEnv , DestReceiver * dest ,
128125 char * completionTag );
129126
130- static void MtmGucUpdate (const char * key , char * value );
127+ static void MtmGucUpdate (const char * key );
131128static void MtmInitializeRemoteFunctionsMap (void );
132129static char * MtmGucSerialize (void );
133130static void MtmMakeRelationLocal (Oid relid , bool locked );
@@ -325,31 +322,24 @@ MtmGucInit(void)
325322 oldcontext = MemoryContextSwitchTo (TopMemoryContext );
326323 current_role = GetConfigOptionByName ("session_authorization" , NULL , false);
327324 // XXX if (current_role && *current_role && strcmp(MtmDatabaseUser, current_role) != 0)
328- MtmGucUpdate ("session_authorization" , current_role );
325+ MtmGucUpdate ("session_authorization" );
329326 MemoryContextSwitchTo (oldcontext );
330327}
331328
332329static void
333330MtmGucDiscard ()
334331{
335- dlist_iter iter ;
336-
337332 if (dlist_is_empty (& MtmGucList ))
338333 return ;
339334
340- dlist_foreach (iter , & MtmGucList )
341- {
342- MtmGucEntry * cur_entry = dlist_container (MtmGucEntry , list_node , iter .cur );
343- pfree (cur_entry -> value );
344- }
345335 dlist_init (& MtmGucList );
346336
347337 hash_destroy (MtmGucHash );
348338 MtmGucHash = NULL ;
349339}
350340
351341static inline void
352- MtmGucUpdate (const char * key , char * value )
342+ MtmGucUpdate (const char * key )
353343{
354344 MtmGucEntry * hentry ;
355345 bool found ;
@@ -359,11 +349,8 @@ MtmGucUpdate(const char *key, char *value)
359349
360350 hentry = (MtmGucEntry * )hash_search (MtmGucHash , key , HASH_ENTER , & found );
361351 if (found )
362- {
363- pfree (hentry -> value );
364352 dlist_delete (& hentry -> list_node );
365- }
366- hentry -> value = value ;
353+
367354 dlist_push_tail (& MtmGucList , & hentry -> list_node );
368355}
369356
@@ -379,7 +366,6 @@ MtmGucRemove(const char *key)
379366 hentry = (MtmGucEntry * )hash_search (MtmGucHash , key , HASH_FIND , & found );
380367 if (found )
381368 {
382- pfree (hentry -> value );
383369 dlist_delete (& hentry -> list_node );
384370 hash_search (MtmGucHash , key , HASH_REMOVE , NULL );
385371 }
@@ -398,7 +384,7 @@ MtmGucSet(VariableSetStmt *stmt, const char *queryStr)
398384 switch (stmt -> kind )
399385 {
400386 case VAR_SET_VALUE :
401- MtmGucUpdate (stmt -> name , ExtractSetVariableArgs ( stmt ) );
387+ MtmGucUpdate (stmt -> name );
402388 break ;
403389
404390 case VAR_SET_DEFAULT :
@@ -488,6 +474,10 @@ MtmGucSerialize(void)
488474 StringInfo serialized_gucs = makeStringInfo ();
489475 dlist_iter iter ;
490476 const char * search_path ;
477+ bool found ;
478+ Oid ceUserId = GetUserId ();
479+ Oid csUserId = GetSessionUserId ();
480+ bool useRole = is_member_of_role (csUserId , ceUserId );
491481
492482 if (!MtmGucHash )
493483 MtmGucInit ();
@@ -496,10 +486,34 @@ MtmGucSerialize(void)
496486 appendStringInfoString (serialized_gucs , "RESET session_authorization; " );
497487 appendStringInfo (serialized_gucs , "select mtm.set_temp_schema('%s'); " , MtmTempSchema );
498488
489+ hash_search (MtmGucHash , "session_authorization" , HASH_FIND , & found );
490+ if (found )
491+ {
492+ MemoryContext oldcontext ;
493+
494+ oldcontext = MemoryContextSwitchTo (TopMemoryContext );
495+ hash_search (MtmGucHash , "role" , HASH_FIND , & found );
496+ if ((found ) && (ceUserId == csUserId ))
497+ /*
498+ * We need to do this because SET LOCAL return only WARNING if is used
499+ * out of transaction block. DDL will be passed to another nodes and
500+ * will set "role" variable at current node.
501+ */
502+ MtmGucRemove ("role" );
503+ else if ((!found ) && (ceUserId != csUserId ) && useRole )
504+ /*
505+ * We need to do this because SECURITY DEFINER changed current user
506+ * value quietly.
507+ */
508+ MtmGucUpdate ("role" );
509+ MemoryContextSwitchTo (oldcontext );
510+ }
511+
499512 dlist_foreach (iter , & MtmGucList )
500513 {
501514 MtmGucEntry * cur_entry = dlist_container (MtmGucEntry , list_node , iter .cur );
502515 struct config_generic * gconf ;
516+ const char * gucValue ;
503517
504518 if (strcmp (cur_entry -> key , "search_path" ) == 0 )
505519 continue ;
@@ -508,19 +522,27 @@ MtmGucSerialize(void)
508522 appendStringInfoString (serialized_gucs , cur_entry -> key );
509523 appendStringInfoString (serialized_gucs , " TO " );
510524
525+ /* Current effective user can have more privileges than session user
526+ * (increase in rights by SECURITY DEFINER, for example). In this case
527+ * we need to set session authorization role in the current user value.
528+ */
529+ if (strcmp (cur_entry -> key , "session_authorization" ) == 0 )
530+ gucValue = GetUserNameFromId (useRole ? csUserId : ceUserId , false);
531+ else
532+ gucValue = GetConfigOption (cur_entry -> key , false, true);
533+
511534 gconf = fing_guc_conf (cur_entry -> key );
512535 if (gconf && (gconf -> vartype == PGC_STRING ||
513536 gconf -> vartype == PGC_ENUM ||
514537 (gconf -> flags & (GUC_UNIT_MEMORY | GUC_UNIT_TIME ))))
515538 {
516539 appendStringInfoString (serialized_gucs , "'" );
517- appendStringInfoString (serialized_gucs , cur_entry -> value );
540+ appendStringInfoString (serialized_gucs , gucValue );
518541 appendStringInfoString (serialized_gucs , "'" );
519542 }
520543 else
521- {
522- appendStringInfoString (serialized_gucs , cur_entry -> value );
523- }
544+ appendStringInfoString (serialized_gucs , gucValue );
545+
524546 appendStringInfoString (serialized_gucs , "; " );
525547 }
526548
@@ -1499,37 +1521,3 @@ MtmToggleDML(void)
14991521{
15001522 MtmTx .contains_dml = true;
15011523}
1502-
1503- /*
1504- * Multimaster need to adjust its preferences with authorization parameters,
1505- * provided by SECURITY DEFINER.
1506- */
1507- void
1508- multimaster_fmgr_hook (FmgrHookEventType event ,
1509- FmgrInfo * flinfo , Datum * private )
1510- {
1511- Oid roleid ;
1512- int sec_context ;
1513- char * current_role ;
1514- MemoryContext oldcontext ;
1515-
1516- if (prev_fmgr_hook )
1517- (* prev_fmgr_hook ) (event , flinfo , private );
1518-
1519- switch (event )
1520- {
1521- case FHET_START :
1522- case FHET_END :
1523- case FHET_ABORT :
1524- oldcontext = MemoryContextSwitchTo (TopMemoryContext );
1525- GetUserIdAndSecContext (& roleid , & sec_context );
1526- current_role = GetUserNameFromId (roleid , false);
1527- MtmGucUpdate ("session_authorization" , current_role );
1528- MemoryContextSwitchTo (oldcontext );
1529- break ;
1530-
1531- default :
1532- elog (ERROR , "unexpected event type: %d" , (int ) event );
1533- break ;
1534- }
1535- }
0 commit comments