diff options
Diffstat (limited to 'src/backend/access/transam/xact.c')
-rw-r--r-- | src/backend/access/transam/xact.c | 68 |
1 files changed, 25 insertions, 43 deletions
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 6fdbdda068c..ebef10cb0ef 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.215.2.3 2007/05/30 21:01:53 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.215.2.4 2008/01/03 21:24:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -120,7 +120,8 @@ typedef struct TransactionStateData MemoryContext curTransactionContext; /* my xact-lifetime context */ ResourceOwner curTransactionOwner; /* my query resources */ List *childXids; /* subcommitted child XIDs */ - Oid currentUser; /* subxact start current_user */ + Oid prevUser; /* previous CurrentUserId setting */ + bool prevSecDefCxt; /* previous SecurityDefinerContext setting */ bool prevXactReadOnly; /* entry-time xact r/o state */ struct TransactionStateData *parent; /* back link to parent */ } TransactionStateData; @@ -152,7 +153,8 @@ static TransactionStateData TopTransactionStateData = { NULL, /* cur transaction context */ NULL, /* cur transaction resource owner */ NIL, /* subcommitted child Xids */ - 0, /* entry-time current userid */ + InvalidOid, /* previous CurrentUserId setting */ + false, /* previous SecurityDefinerContext setting */ false, /* entry-time xact r/o state */ NULL /* link to parent state block */ }; @@ -1373,18 +1375,14 @@ StartTransaction(void) /* * initialize current transaction state fields + * + * note: prevXactReadOnly is not used at the outermost level */ s->nestingLevel = 1; s->childXids = NIL; - - /* - * You might expect to see "s->currentUser = GetUserId();" here, but you - * won't because it doesn't work during startup; the userid isn't set yet - * during a backend's first transaction start. We only use the - * currentUser field in sub-transaction state structs. - * - * prevXactReadOnly is also valid only in sub-transactions. - */ + GetUserIdAndContext(&s->prevUser, &s->prevSecDefCxt); + /* SecurityDefinerContext should never be set outside a transaction */ + Assert(!s->prevSecDefCxt); /* * initialize other subsystems for new transaction @@ -1866,17 +1864,16 @@ AbortTransaction(void) AtAbort_ResourceOwner(); /* - * Reset user id which might have been changed transiently. We cannot use - * s->currentUser, since it may not be set yet; instead rely on internal - * state of miscinit.c. + * Reset user ID which might have been changed transiently. We need this + * to clean up in case control escaped out of a SECURITY DEFINER function + * or other local change of CurrentUserId; therefore, the prior value + * of SecurityDefinerContext also needs to be restored. * - * (Note: it is not necessary to restore session authorization here - * because that can only be changed via GUC, and GUC will take care of - * rolling it back if need be. However, an error within a SECURITY - * DEFINER function could send control here with the wrong current - * userid.) + * (Note: it is not necessary to restore session authorization or role + * settings here because those can only be changed via GUC, and GUC will + * take care of rolling them back if need be.) */ - AtAbort_UserId(); + SetUserIdAndContext(s->prevUser, s->prevSecDefCxt); /* * do abort processing @@ -3717,6 +3714,12 @@ AbortSubTransaction(void) AtSubAbort_ResourceOwner(); /* + * Reset user ID which might have been changed transiently. (See notes + * in AbortTransaction.) + */ + SetUserIdAndContext(s->prevUser, s->prevSecDefCxt); + + /* * We can skip all this stuff if the subxact failed before creating a * ResourceOwner... */ @@ -3769,20 +3772,6 @@ AbortSubTransaction(void) } /* - * Reset user id which might have been changed transiently. Here we want - * to restore to the userid that was current at subxact entry. (As in - * AbortTransaction, we need not worry about the session userid.) - * - * Must do this after AtEOXact_GUC to handle the case where we entered the - * subxact inside a SECURITY DEFINER function (hence current and session - * userids were different) and then session auth was changed inside the - * subxact. GUC will reset both current and session userids to the - * entry-time session userid. This is right in every other scenario so it - * seems simplest to let GUC do that and fix it here. - */ - SetUserId(s->currentUser); - - /* * Restore the upper transaction's read-only state, too. This should be * redundant with GUC's cleanup but we may as well do it for consistency * with the commit case. @@ -3836,13 +3825,6 @@ PushTransaction(void) { TransactionState p = CurrentTransactionState; TransactionState s; - Oid currentUser; - - /* - * At present, GetUserId cannot fail, but let's not assume that. Get the - * ID before entering the critical code sequence. - */ - currentUser = GetUserId(); /* * We keep subtransaction state nodes in TopTransactionContext. @@ -3875,7 +3857,7 @@ PushTransaction(void) s->savepointLevel = p->savepointLevel; s->state = TRANS_DEFAULT; s->blockState = TBLOCK_SUBBEGIN; - s->currentUser = currentUser; + GetUserIdAndContext(&s->prevUser, &s->prevSecDefCxt); s->prevXactReadOnly = XactReadOnly; CurrentTransactionState = s; |