summaryrefslogtreecommitdiff
path: root/src/backend/access/transam/xact.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/transam/xact.c')
-rw-r--r--src/backend/access/transam/xact.c70
1 files changed, 25 insertions, 45 deletions
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index f5a73caddba..d2ec35a7bae 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.195.4.3 2007/05/30 21:02:02 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.195.4.4 2008/01/03 21:25:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -117,7 +117,8 @@ typedef struct TransactionStateData
* context */
ResourceOwner curTransactionOwner; /* my query resources */
List *childXids; /* subcommitted child XIDs */
- AclId currentUser; /* subxact start current_user */
+ AclId 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;
@@ -149,7 +150,8 @@ static TransactionStateData TopTransactionStateData = {
NULL, /* cur transaction context */
NULL, /* cur transaction resource owner */
NIL, /* subcommitted child Xids */
- 0, /* entry-time current userid */
+ 0, /* previous CurrentUserId setting */
+ false, /* previous SecurityDefinerContext setting */
false, /* entry-time xact r/o state */
NULL /* link to parent state block */
};
@@ -1390,18 +1392,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
@@ -1652,17 +1650,16 @@ AbortTransaction(void)
AtAbort_ResourceOwner();
/*
- * Reset user id which might have been changed transiently. We cannot
- * use s->currentUser, but must get the session userid from
- * 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
+ * setting here because that can only be changed via GUC, and GUC will
+ * take care of rolling it back if need be.)
*/
- SetUserId(GetSessionUserId());
+ SetUserIdAndContext(s->prevUser, s->prevSecDefCxt);
/*
* do abort processing
@@ -3395,6 +3392,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...
*/
@@ -3447,22 +3450,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.
@@ -3516,13 +3503,6 @@ PushTransaction(void)
{
TransactionState p = CurrentTransactionState;
TransactionState s;
- AclId 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.
@@ -3553,7 +3533,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;