diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/transam/xact.c | 20 | ||||
-rw-r--r-- | src/backend/catalog/index.c | 14 | ||||
-rw-r--r-- | src/backend/commands/schemacmds.c | 9 | ||||
-rw-r--r-- | src/backend/commands/vacuum.c | 15 | ||||
-rw-r--r-- | src/backend/commands/variable.c | 16 | ||||
-rw-r--r-- | src/backend/utils/adt/ri_triggers.c | 125 | ||||
-rw-r--r-- | src/backend/utils/fmgr/fmgr.c | 11 | ||||
-rw-r--r-- | src/backend/utils/init/miscinit.c | 69 | ||||
-rw-r--r-- | src/include/miscadmin.h | 7 |
9 files changed, 197 insertions, 89 deletions
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 1c5ffb1192d..24a50e5eb8f 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.135.2.4 2007/04/26 23:25:48 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.135.2.5 2008/01/03 21:25:58 tgl Exp $ * * NOTES * Transaction aborts can now occur two ways: @@ -215,6 +215,8 @@ static TransactionStateData CurrentTransactionStateData = { TransactionState CurrentTransactionState = &CurrentTransactionStateData; +static Oid prevUser; /* CurrentUserId at transaction start */ + /* * User-tweakable parameters */ @@ -960,6 +962,7 @@ static void CommitTransaction(void) { TransactionState s = CurrentTransactionState; + bool prevSecDefCxt; /* * check the current transaction state @@ -983,6 +986,10 @@ CommitTransaction(void) */ s->state = TRANS_COMMIT; + GetUserIdAndContext(&prevUser, &prevSecDefCxt); + /* SecurityDefinerContext should never be set outside a transaction */ + Assert(!prevSecDefCxt); + /* * Do pre-commit processing (most of this stuff requires database * access, and in fact could still cause an error...) @@ -1118,9 +1125,16 @@ AbortTransaction(void) AtAbort_Memory(); /* - * Reset user id which might have been changed transiently + * 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 + * 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(prevUser, false); /* * do abort processing diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index debc3945eec..506fd43dcae 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.202.2.1 2005/06/25 16:54:30 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.202.2.2 2008/01/03 21:25:58 tgl Exp $ * * * INTERFACE ROUTINES @@ -1439,6 +1439,8 @@ index_build(Relation heapRelation, IndexInfo *indexInfo) { RegProcedure procedure; + Oid save_userid; + bool save_secdefcxt; /* * sanity checks @@ -1450,12 +1452,22 @@ index_build(Relation heapRelation, Assert(RegProcedureIsValid(procedure)); /* + * Switch to the table owner's userid, so that any index functions are + * run as that user. + */ + GetUserIdAndContext(&save_userid, &save_secdefcxt); + SetUserIdAndContext(heapRelation->rd_rel->relowner, true); + + /* * Call the access method's build procedure */ OidFunctionCall3(procedure, PointerGetDatum(heapRelation), PointerGetDatum(indexRelation), PointerGetDatum(indexInfo)); + + /* Restore userid */ + SetUserIdAndContext(save_userid, save_secdefcxt); } diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index 09165d47bd3..ba62a54223f 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.6 2002/09/04 20:31:15 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.6.2.1 2008/01/03 21:25:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -43,9 +43,10 @@ CreateSchemaCommand(CreateSchemaStmt *stmt) const char *owner_name; Oid owner_userid; Oid saved_userid; + bool saved_secdefcxt; AclResult aclresult; - saved_userid = GetUserId(); + GetUserIdAndContext(&saved_userid, &saved_secdefcxt); /* * Figure out user identities. @@ -68,7 +69,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt) * (This will revert to session user on error or at the end of * this routine.) */ - SetUserId(owner_userid); + SetUserIdAndContext(owner_userid, true); } else /* not superuser */ @@ -143,7 +144,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt) PopSpecialNamespace(namespaceId); /* Reset current user */ - SetUserId(saved_userid); + SetUserIdAndContext(saved_userid, saved_secdefcxt); } diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 31a4be47853..9befea59e0a 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -13,7 +13,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.244.2.2 2007/03/14 18:49:32 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.244.2.3 2008/01/03 21:25:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -720,6 +720,8 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) LockRelId onerelid; Oid toast_relid; bool result; + Oid save_userid; + bool save_secdefcxt; /* Begin a transaction for vacuuming this relation */ StartTransactionCommand(true); @@ -821,6 +823,14 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) toast_relid = onerel->rd_rel->reltoastrelid; /* + * Switch to the table owner's userid, so that any index functions are + * run as that user. (This is unnecessary, but harmless, for lazy + * VACUUM.) + */ + GetUserIdAndContext(&save_userid, &save_secdefcxt); + SetUserIdAndContext(onerel->rd_rel->relowner, true); + + /* * Do the actual work --- either FULL or "lazy" vacuum */ if (vacstmt->full) @@ -830,6 +840,9 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) result = true; /* did the vacuum */ + /* Restore userid */ + SetUserIdAndContext(save_userid, save_secdefcxt); + /* all done with this class, but hold lock until commit */ relation_close(onerel, NoLock); diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c index 87f8953ee26..1a351b62876 100644 --- a/src/backend/commands/variable.c +++ b/src/backend/commands/variable.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.71.2.4 2006/02/12 22:33:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.71.2.5 2008/01/03 21:25:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -561,6 +561,20 @@ assign_session_authorization(const char *value, bool doit, bool interactive) /* not a saved ID, so look it up */ HeapTuple userTup; + 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. + */ + if (interactive) + elog(ERROR, "cannot set session authorization within security-definer function"); + return NULL; + } + if (! IsTransactionState()) { /* diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index 6f85e6fc4a5..acb17219da8 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -17,7 +17,7 @@ * * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.43.2.5 2004/10/13 22:22:22 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.43.2.6 2008/01/03 21:25:58 tgl Exp $ * * ---------- */ @@ -178,9 +178,10 @@ RI_FKey_check(PG_FUNCTION_ARGS) bool isnull; int i; int match_type; - Oid save_uid; + Oid save_userid; + bool save_secdefcxt; - save_uid = GetUserId(); + GetUserIdAndContext(&save_userid, &save_secdefcxt); ReferentialIntegritySnapshotOverride = true; @@ -297,12 +298,12 @@ RI_FKey_check(PG_FUNCTION_ARGS) /* * Execute the plan */ - SetUserId(RelationGetForm(pk_rel)->relowner); + SetUserIdAndContext(RelationGetForm(pk_rel)->relowner, true); if (SPI_execp(qplan, check_values, check_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in RI_FKey_check()"); - SetUserId(save_uid); + SetUserIdAndContext(save_userid, save_secdefcxt); if (SPI_processed == 0) elog(ERROR, "%s referential integrity violation - " @@ -486,12 +487,12 @@ RI_FKey_check(PG_FUNCTION_ARGS) * Now check that foreign key exists in PK table */ - SetUserId(RelationGetForm(pk_rel)->relowner); + SetUserIdAndContext(RelationGetForm(pk_rel)->relowner, true); if (SPI_execp(qplan, check_values, check_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in RI_FKey_check()"); - SetUserId(save_uid); + SetUserIdAndContext(save_userid, save_secdefcxt); if (SPI_processed == 0) elog(ERROR, "%s referential integrity violation - " @@ -558,10 +559,11 @@ ri_Check_Pk_Match(Relation pk_rel, HeapTuple old_row, Oid tgoid, int match_type, Datum check_values[RI_MAX_NUMKEYS]; char check_nulls[RI_MAX_NUMKEYS + 1]; int i; - Oid save_uid; + Oid save_userid; + bool save_secdefcxt; bool result; - save_uid = GetUserId(); + GetUserIdAndContext(&save_userid, &save_secdefcxt); ri_BuildQueryKeyPkCheck(&qkey, tgoid, RI_PLAN_CHECK_LOOKUPPK, pk_rel, @@ -681,12 +683,12 @@ ri_Check_Pk_Match(Relation pk_rel, HeapTuple old_row, Oid tgoid, int match_type, * Now check that foreign key exists in PK table */ - SetUserId(RelationGetForm(pk_rel)->relowner); + SetUserIdAndContext(RelationGetForm(pk_rel)->relowner, true); if (SPI_execp(qplan, check_values, check_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in ri_Check_Pk_Match()"); - SetUserId(save_uid); + SetUserIdAndContext(save_userid, save_secdefcxt); result = (SPI_processed != 0); @@ -721,9 +723,10 @@ RI_FKey_noaction_del(PG_FUNCTION_ARGS) bool isnull; int i; int match_type; - Oid save_uid; + Oid save_userid; + bool save_secdefcxt; - save_uid = GetUserId(); + GetUserIdAndContext(&save_userid, &save_secdefcxt); ReferentialIntegritySnapshotOverride = true; @@ -886,12 +889,12 @@ RI_FKey_noaction_del(PG_FUNCTION_ARGS) /* * Now check for existing references */ - SetUserId(RelationGetForm(pk_rel)->relowner); + SetUserIdAndContext(RelationGetForm(pk_rel)->relowner, true); if (SPI_execp(qplan, del_values, del_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in RI_FKey_noaction_del()"); - SetUserId(save_uid); + SetUserIdAndContext(save_userid, save_secdefcxt); if (SPI_processed > 0) elog(ERROR, "%s referential integrity violation - " @@ -948,9 +951,10 @@ RI_FKey_noaction_upd(PG_FUNCTION_ARGS) bool isnull; int i; int match_type; - Oid save_uid; + Oid save_userid; + bool save_secdefcxt; - save_uid = GetUserId(); + GetUserIdAndContext(&save_userid, &save_secdefcxt); ReferentialIntegritySnapshotOverride = true; @@ -1124,12 +1128,12 @@ RI_FKey_noaction_upd(PG_FUNCTION_ARGS) /* * Now check for existing references */ - SetUserId(RelationGetForm(pk_rel)->relowner); + SetUserIdAndContext(RelationGetForm(pk_rel)->relowner, true); if (SPI_execp(qplan, upd_values, upd_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in RI_FKey_noaction_upd()"); - SetUserId(save_uid); + SetUserIdAndContext(save_userid, save_secdefcxt); if (SPI_processed > 0) elog(ERROR, "%s referential integrity violation - " @@ -1182,7 +1186,8 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS) char del_nulls[RI_MAX_NUMKEYS + 1]; bool isnull; int i; - Oid save_uid; + Oid save_userid; + bool save_secdefcxt; Oid fk_owner; ReferentialIntegritySnapshotOverride = true; @@ -1333,13 +1338,13 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS) /* * Now delete constraint */ - save_uid = GetUserId(); - SetUserId(fk_owner); + GetUserIdAndContext(&save_userid, &save_secdefcxt); + SetUserIdAndContext(fk_owner, true); if (SPI_execp(qplan, del_values, del_nulls, 0) != SPI_OK_DELETE) elog(ERROR, "SPI_execp() failed in RI_FKey_cascade_del()"); - SetUserId(save_uid); + SetUserIdAndContext(save_userid, save_secdefcxt); if (SPI_finish() != SPI_OK_FINISH) elog(WARNING, "SPI_finish() failed in RI_FKey_cascade_del()"); @@ -1387,7 +1392,8 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS) bool isnull; int i; int j; - Oid save_uid; + Oid save_userid; + bool save_secdefcxt; Oid fk_owner; ReferentialIntegritySnapshotOverride = true; @@ -1569,13 +1575,13 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS) /* * Now update the existing references */ - save_uid = GetUserId(); - SetUserId(fk_owner); + GetUserIdAndContext(&save_userid, &save_secdefcxt); + SetUserIdAndContext(fk_owner, true); if (SPI_execp(qplan, upd_values, upd_nulls, 0) != SPI_OK_UPDATE) elog(ERROR, "SPI_execp() failed in RI_FKey_cascade_upd()"); - SetUserId(save_uid); + SetUserIdAndContext(save_userid, save_secdefcxt); if (SPI_finish() != SPI_OK_FINISH) elog(WARNING, "SPI_finish() failed in RI_FKey_cascade_upd()"); @@ -1628,7 +1634,8 @@ RI_FKey_restrict_del(PG_FUNCTION_ARGS) char del_nulls[RI_MAX_NUMKEYS + 1]; bool isnull; int i; - Oid save_uid; + Oid save_userid; + bool save_secdefcxt; Oid fk_owner; ReferentialIntegritySnapshotOverride = true; @@ -1781,13 +1788,13 @@ RI_FKey_restrict_del(PG_FUNCTION_ARGS) /* * Now check for existing references */ - save_uid = GetUserId(); - SetUserId(fk_owner); + GetUserIdAndContext(&save_userid, &save_secdefcxt); + SetUserIdAndContext(fk_owner, true); if (SPI_execp(qplan, del_values, del_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in RI_FKey_restrict_del()"); - SetUserId(save_uid); + SetUserIdAndContext(save_userid, save_secdefcxt); if (SPI_processed > 0) elog(ERROR, "%s referential integrity violation - " @@ -1848,7 +1855,8 @@ RI_FKey_restrict_upd(PG_FUNCTION_ARGS) char upd_nulls[RI_MAX_NUMKEYS + 1]; bool isnull; int i; - Oid save_uid; + Oid save_userid; + bool save_secdefcxt; Oid fk_owner; ReferentialIntegritySnapshotOverride = true; @@ -2012,15 +2020,13 @@ RI_FKey_restrict_upd(PG_FUNCTION_ARGS) /* * Now check for existing references */ - save_uid = GetUserId(); - SetUserId(fk_owner); - - SetUserId(RelationGetForm(pk_rel)->relowner); + GetUserIdAndContext(&save_userid, &save_secdefcxt); + SetUserIdAndContext(RelationGetForm(pk_rel)->relowner, true); if (SPI_execp(qplan, upd_values, upd_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in RI_FKey_restrict_upd()"); - SetUserId(save_uid); + SetUserIdAndContext(save_userid, save_secdefcxt); if (SPI_processed > 0) elog(ERROR, "%s referential integrity violation - " @@ -2073,7 +2079,8 @@ RI_FKey_setnull_del(PG_FUNCTION_ARGS) char upd_nulls[RI_MAX_NUMKEYS + 1]; bool isnull; int i; - Oid save_uid; + Oid save_userid; + bool save_secdefcxt; Oid fk_owner; ReferentialIntegritySnapshotOverride = true; @@ -2234,13 +2241,13 @@ RI_FKey_setnull_del(PG_FUNCTION_ARGS) /* * Now update the existing references */ - save_uid = GetUserId(); - SetUserId(fk_owner); + GetUserIdAndContext(&save_userid, &save_secdefcxt); + SetUserIdAndContext(fk_owner, true); if (SPI_execp(qplan, upd_values, upd_nulls, 0) != SPI_OK_UPDATE) elog(ERROR, "SPI_execp() failed in RI_FKey_setnull_del()"); - SetUserId(save_uid); + SetUserIdAndContext(save_userid, save_secdefcxt); if (SPI_finish() != SPI_OK_FINISH) elog(WARNING, "SPI_finish() failed in RI_FKey_setnull_del()"); @@ -2289,7 +2296,8 @@ RI_FKey_setnull_upd(PG_FUNCTION_ARGS) int i; int match_type; bool use_cached_query; - Oid save_uid; + Oid save_userid; + bool save_secdefcxt; Oid fk_owner; ReferentialIntegritySnapshotOverride = true; @@ -2495,13 +2503,13 @@ RI_FKey_setnull_upd(PG_FUNCTION_ARGS) /* * Now update the existing references */ - save_uid = GetUserId(); - SetUserId(fk_owner); + GetUserIdAndContext(&save_userid, &save_secdefcxt); + SetUserIdAndContext(fk_owner, true); if (SPI_execp(qplan, upd_values, upd_nulls, 0) != SPI_OK_UPDATE) elog(ERROR, "SPI_execp() failed in RI_FKey_setnull_upd()"); - SetUserId(save_uid); + SetUserIdAndContext(save_userid, save_secdefcxt); if (SPI_finish() != SPI_OK_FINISH) elog(WARNING, "SPI_finish() failed in RI_FKey_setnull_upd()"); @@ -2547,7 +2555,8 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS) char upd_nulls[RI_MAX_NUMKEYS + 1]; bool isnull; int i; - Oid save_uid; + Oid save_userid; + bool save_secdefcxt; Oid fk_owner; ReferentialIntegritySnapshotOverride = true; @@ -2739,13 +2748,13 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS) /* * Now update the existing references */ - save_uid = GetUserId(); - SetUserId(fk_owner); + GetUserIdAndContext(&save_userid, &save_secdefcxt); + SetUserIdAndContext(fk_owner, true); if (SPI_execp(qplan, upd_values, upd_nulls, 0) != SPI_OK_UPDATE) elog(ERROR, "SPI_execp() failed in RI_FKey_setdefault_del()"); - SetUserId(save_uid); + SetUserIdAndContext(save_userid, save_secdefcxt); if (SPI_finish() != SPI_OK_FINISH) elog(WARNING, "SPI_finish() failed in RI_FKey_setdefault_del()"); @@ -2803,7 +2812,8 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS) bool isnull; int i; int match_type; - Oid save_uid; + Oid save_userid; + bool save_secdefcxt; Oid fk_owner; ReferentialIntegritySnapshotOverride = true; @@ -3018,13 +3028,13 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS) /* * Now update the existing references */ - save_uid = GetUserId(); - SetUserId(fk_owner); + GetUserIdAndContext(&save_userid, &save_secdefcxt); + SetUserIdAndContext(fk_owner, true); if (SPI_execp(qplan, upd_values, upd_nulls, 0) != SPI_OK_UPDATE) elog(ERROR, "SPI_execp() failed in RI_FKey_setdefault_upd()"); - SetUserId(save_uid); + SetUserIdAndContext(save_userid, save_secdefcxt); if (SPI_finish() != SPI_OK_FINISH) elog(WARNING, "SPI_finish() failed in RI_FKey_setdefault_upd()"); @@ -3171,7 +3181,8 @@ ri_PlanCheck(char *querystr, int nargs, Oid *argtypes, { void *qplan; Relation query_rel; - Oid save_uid; + Oid save_userid; + bool save_secdefcxt; /* * The query is always run against the FK table except @@ -3185,14 +3196,14 @@ ri_PlanCheck(char *querystr, int nargs, Oid *argtypes, query_rel = fk_rel; /* Switch to proper UID to perform check as */ - save_uid = GetUserId(); - SetUserId(RelationGetForm(query_rel)->relowner); + GetUserIdAndContext(&save_userid, &save_secdefcxt); + SetUserIdAndContext(RelationGetForm(query_rel)->relowner, true); /* Create the plan */ qplan = SPI_prepare(querystr, nargs, argtypes); /* Restore UID */ - SetUserId(save_uid); + SetUserIdAndContext(save_userid, save_secdefcxt); /* Save the plan if requested */ if (cache_plan) diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c index 470d4a11dd6..5cebe0595b5 100644 --- a/src/backend/utils/fmgr/fmgr.c +++ b/src/backend/utils/fmgr/fmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.63 2002/10/04 17:19:55 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.63.2.1 2008/01/03 21:25:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -651,6 +651,7 @@ fmgr_security_definer(PG_FUNCTION_ARGS) FmgrInfo *save_flinfo; struct fmgr_security_definer_cache *fcache; Oid save_userid; + bool save_secdefcxt; HeapTuple tuple; if (!fcinfo->flinfo->fn_extra) @@ -673,16 +674,18 @@ fmgr_security_definer(PG_FUNCTION_ARGS) else fcache = fcinfo->flinfo->fn_extra; + GetUserIdAndContext(&save_userid, &save_secdefcxt); + SetUserIdAndContext(fcache->userid, true); + save_flinfo = fcinfo->flinfo; fcinfo->flinfo = &fcache->flinfo; - save_userid = GetUserId(); - SetUserId(fcache->userid); result = FunctionCallInvoke(fcinfo); - SetUserId(save_userid); fcinfo->flinfo = save_flinfo; + SetUserIdAndContext(save_userid, save_secdefcxt); + return result; } diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index f41706862fa..e772d6a8ec5 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.96 2002/09/04 20:31:31 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.96.2.1 2008/01/03 21:25:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -483,6 +483,9 @@ GetCharSetByHost(char *TableName, int host, const char *DataDir) * are implemented. Conceptually there is a stack, whose bottom * is the session user. You are yourself responsible to save and * restore the current user id if you need to change it. + * + * SecurityDefinerContext is TRUE if we are within a SECURITY DEFINER function + * or another context that temporarily changes CurrentUserId. * ---------------------------------------------------------------- */ static Oid AuthenticatedUserId = InvalidOid; @@ -491,8 +494,13 @@ static Oid CurrentUserId = InvalidOid; static bool AuthenticatedUserIsSuperuser = false; +static bool SecurityDefinerContext = false; + + /* - * This function is relevant for all privilege checks. + * GetUserId - get the current effective user ID. + * + * Note: there's no SetUserId() anymore; use SetUserIdAndContext(). */ Oid GetUserId(void) @@ -502,14 +510,6 @@ GetUserId(void) } -void -SetUserId(Oid newid) -{ - AssertArg(OidIsValid(newid)); - CurrentUserId = newid; -} - - /* * This value is only relevant for informational purposes. */ @@ -521,17 +521,57 @@ GetSessionUserId(void) } -void +static void SetSessionUserId(Oid newid) { + AssertState(!SecurityDefinerContext); AssertArg(OidIsValid(newid)); SessionUserId = newid; - /* Current user defaults to session user. */ - if (!OidIsValid(CurrentUserId)) - CurrentUserId = newid; + CurrentUserId = newid; } +/* + * GetUserIdAndContext/SetUserIdAndContext - get/set the current user ID + * and the SecurityDefinerContext flag. + * + * Unlike GetUserId, GetUserIdAndContext does *not* Assert that the current + * value of CurrentUserId is valid; nor does SetUserIdAndContext require + * the new value to be valid. In fact, these routines had better not + * ever throw any kind of error. This is because they are used by + * StartTransaction and AbortTransaction to save/restore the settings, + * and during the first transaction within a backend, the value to be saved + * and perhaps restored is indeed invalid. We have to be able to get + * through AbortTransaction without asserting in case InitPostgres fails. + */ +void +GetUserIdAndContext(Oid *userid, bool *sec_def_context) +{ + *userid = CurrentUserId; + *sec_def_context = SecurityDefinerContext; +} + +void +SetUserIdAndContext(Oid userid, bool sec_def_context) +{ + CurrentUserId = userid; + SecurityDefinerContext = sec_def_context; +} + + +/* + * InSecurityDefinerContext - are we inside a SECURITY DEFINER context? + */ +bool +InSecurityDefinerContext(void) +{ + return SecurityDefinerContext; +} + + +/* + * Initialize user identity during normal backend startup + */ void InitializeSessionUserId(const char *username) { @@ -616,7 +656,6 @@ SetSessionAuthorization(Oid userid) elog(ERROR, "permission denied"); SetSessionUserId(userid); - SetUserId(userid); } diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 1dbd737db3b..7f7894b597a 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -12,7 +12,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: miscadmin.h,v 1.111 2002/10/03 17:07:53 momjian Exp $ + * $Id: miscadmin.h,v 1.111.2.1 2008/01/03 21:25:58 tgl Exp $ * * NOTES * some of the information in this file should be moved to @@ -203,9 +203,10 @@ extern void SetDatabasePath(const char *path); extern char *GetUserNameFromId(Oid userid); extern Oid GetUserId(void); -extern void SetUserId(Oid userid); extern Oid GetSessionUserId(void); -extern void SetSessionUserId(Oid userid); +extern void GetUserIdAndContext(Oid *userid, bool *sec_def_context); +extern void SetUserIdAndContext(Oid userid, bool sec_def_context); +extern bool InSecurityDefinerContext(void); extern void InitializeSessionUserId(const char *username); extern void InitializeSessionUserIdStandalone(void); extern void SetSessionAuthorization(Oid userid); |