Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitcfd7fb7

Browse files
committed
Fix permission-checking bug reported by Tim Burgess 10-Feb-03 (this time
for sure...). Rather than relying on the query context of a rangetableentry to identify what permissions it wants checked, store a full AclModemask in each RTE, and check exactly those bits. This allows an RTEspecifying, say, INSERT privilege on a view to be copied into a derivedUPDATE query without changing meaning. Per recent discussion thread.initdb forced due to change of stored rule representation.
1 parent01d320d commitcfd7fb7

File tree

18 files changed

+183
-183
lines changed

18 files changed

+183
-183
lines changed

‎src/backend/commands/view.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.80 2004/01/10 23:28:44 neilc Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.81 2004/01/14 23:01:54 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -297,8 +297,8 @@ UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse)
297297
makeAlias("*NEW*",NIL),
298298
false, false);
299299
/* Must override addRangeTableEntry's default access-check flags */
300-
rt_entry1->checkForRead=false;
301-
rt_entry2->checkForRead=false;
300+
rt_entry1->requiredPerms=0;
301+
rt_entry2->requiredPerms=0;
302302

303303
new_rt=lcons(rt_entry1,lcons(rt_entry2,viewParse->rtable));
304304

‎src/backend/executor/execMain.c

Lines changed: 59 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
*
2828
* IDENTIFICATION
29-
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.226 2004/01/10 23:28:44 neilc Exp $
29+
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.227 2004/01/14 23:01:54 tgl Exp $
3030
*
3131
*-------------------------------------------------------------------------
3232
*/
@@ -86,8 +86,8 @@ static void ExecUpdate(TupleTableSlot *slot, ItemPointer tupleid,
8686
EState*estate);
8787
staticTupleTableSlot*EvalPlanQualNext(EState*estate);
8888
staticvoidEndEvalPlanQual(EState*estate);
89-
staticvoidExecCheckRTEPerms(RangeTblEntry*rte,CmdTypeoperation);
90-
staticvoidExecCheckXactReadOnly(Query*parsetree,CmdTypeoperation);
89+
staticvoidExecCheckRTEPerms(RangeTblEntry*rte);
90+
staticvoidExecCheckXactReadOnly(Query*parsetree);
9191
staticvoidEvalPlanQualStart(evalPlanQual*epq,EState*estate,
9292
evalPlanQual*priorepq);
9393
staticvoidEvalPlanQualStop(evalPlanQual*epq);
@@ -136,8 +136,8 @@ ExecutorStart(QueryDesc *queryDesc, bool useCurrentSnapshot, bool explainOnly)
136136
* If the transaction is read-only, we need to check if any writes are
137137
* planned to non-temporary tables.
138138
*/
139-
if (!explainOnly)
140-
ExecCheckXactReadOnly(queryDesc->parsetree,queryDesc->operation);
139+
if (XactReadOnly&&!explainOnly)
140+
ExecCheckXactReadOnly(queryDesc->parsetree);
141141

142142
/*
143143
* Build EState, switch into per-query memory context for startup.
@@ -351,15 +351,15 @@ ExecutorRewind(QueryDesc *queryDesc)
351351
*Check access permissions for all relations listed in a range table.
352352
*/
353353
void
354-
ExecCheckRTPerms(List*rangeTable,CmdTypeoperation)
354+
ExecCheckRTPerms(List*rangeTable)
355355
{
356356
List*lp;
357357

358358
foreach(lp,rangeTable)
359359
{
360360
RangeTblEntry*rte=lfirst(lp);
361361

362-
ExecCheckRTEPerms(rte,operation);
362+
ExecCheckRTEPerms(rte);
363363
}
364364
}
365365

@@ -368,18 +368,18 @@ ExecCheckRTPerms(List *rangeTable, CmdType operation)
368368
*Check access permissions for a single RTE.
369369
*/
370370
staticvoid
371-
ExecCheckRTEPerms(RangeTblEntry*rte,CmdTypeoperation)
371+
ExecCheckRTEPerms(RangeTblEntry*rte)
372372
{
373+
AclModerequiredPerms;
373374
OidrelOid;
374375
AclIduserid;
375-
AclResultaclcheck_result;
376376

377377
/*
378378
* If it's a subquery, recursively examine its rangetable.
379379
*/
380380
if (rte->rtekind==RTE_SUBQUERY)
381381
{
382-
ExecCheckRTPerms(rte->subquery->rtable,operation);
382+
ExecCheckRTPerms(rte->subquery->rtable);
383383
return;
384384
}
385385

@@ -391,6 +391,13 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
391391
if (rte->rtekind!=RTE_RELATION)
392392
return;
393393

394+
/*
395+
* No work if requiredPerms is empty.
396+
*/
397+
requiredPerms=rte->requiredPerms;
398+
if (requiredPerms==0)
399+
return;
400+
394401
relOid=rte->relid;
395402

396403
/*
@@ -404,77 +411,68 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
404411
*/
405412
userid=rte->checkAsUser ?rte->checkAsUser :GetUserId();
406413

407-
#defineCHECK(MODE)pg_class_aclcheck(relOid, userid, MODE)
414+
/*
415+
* For each bit in requiredPerms, apply the required check. (We can't
416+
* do this in one aclcheck call because aclcheck treats multiple bits
417+
* as OR semantics, when we want AND.)
418+
*
419+
* We use a well-known cute trick for isolating the rightmost one-bit
420+
* in a nonzero word. See nodes/bitmapset.c for commentary.
421+
*/
422+
#defineRIGHTMOST_ONE(x) ((int32) (x) & -((int32) (x)))
408423

409-
if (rte->checkForRead)
424+
while (requiredPerms!=0)
410425
{
411-
aclcheck_result=CHECK(ACL_SELECT);
412-
if (aclcheck_result!=ACLCHECK_OK)
413-
aclcheck_error(aclcheck_result,ACL_KIND_CLASS,
414-
get_rel_name(relOid));
415-
}
426+
AclModethisPerm;
427+
AclResultaclcheck_result;
416428

417-
if (rte->checkForWrite)
418-
{
419-
/*
420-
* Note: write access in a SELECT context means SELECT FOR UPDATE.
421-
* Right now we don't distinguish that from true update as far as
422-
* permissions checks are concerned.
423-
*/
424-
switch (operation)
425-
{
426-
caseCMD_INSERT:
427-
aclcheck_result=CHECK(ACL_INSERT);
428-
break;
429-
caseCMD_SELECT:
430-
caseCMD_UPDATE:
431-
aclcheck_result=CHECK(ACL_UPDATE);
432-
break;
433-
caseCMD_DELETE:
434-
aclcheck_result=CHECK(ACL_DELETE);
435-
break;
436-
default:
437-
elog(ERROR,"unrecognized operation code: %d",
438-
(int)operation);
439-
aclcheck_result=ACLCHECK_OK;/* keep compiler quiet */
440-
break;
441-
}
429+
thisPerm=RIGHTMOST_ONE(requiredPerms);
430+
requiredPerms &= ~thisPerm;
431+
432+
aclcheck_result=pg_class_aclcheck(relOid,userid,thisPerm);
442433
if (aclcheck_result!=ACLCHECK_OK)
443434
aclcheck_error(aclcheck_result,ACL_KIND_CLASS,
444435
get_rel_name(relOid));
445436
}
446437
}
447438

439+
/*
440+
* Check that the query does not imply any writes to non-temp tables.
441+
*/
448442
staticvoid
449-
ExecCheckXactReadOnly(Query*parsetree,CmdTypeoperation)
443+
ExecCheckXactReadOnly(Query*parsetree)
450444
{
451-
if (!XactReadOnly)
452-
return;
445+
List*lp;
453446

454-
/* CREATE TABLE AS or SELECT INTO */
455-
if (operation==CMD_SELECT&&parsetree->into!=NULL)
447+
/*
448+
* CREATE TABLE AS or SELECT INTO?
449+
*
450+
* XXX should we allow this if the destination is temp?
451+
*/
452+
if (parsetree->into!=NULL)
456453
gotofail;
457454

458-
if(operation==CMD_DELETE||operation==CMD_INSERT
459-
||operation==CMD_UPDATE)
455+
/* Failifwrite permissions are requested on any non-temp table */
456+
foreach(lp,parsetree->rtable)
460457
{
461-
List*lp;
458+
RangeTblEntry*rte=lfirst(lp);
462459

463-
foreach(lp,parsetree->rtable)
460+
if (rte->rtekind==RTE_SUBQUERY)
464461
{
465-
RangeTblEntry*rte=lfirst(lp);
462+
ExecCheckXactReadOnly(rte->subquery);
463+
continue;
464+
}
466465

467-
if (rte->rtekind!=RTE_RELATION)
468-
continue;
466+
if (rte->rtekind!=RTE_RELATION)
467+
continue;
469468

470-
if (!rte->checkForWrite)
471-
continue;
469+
if ((rte->requiredPerms& (~ACL_SELECT))==0)
470+
continue;
472471

473-
if (isTempNamespace(get_rel_namespace(rte->relid)))
474-
continue;
472+
if (isTempNamespace(get_rel_namespace(rte->relid)))
473+
continue;
475474

476-
gotofail;
477-
}
475+
gotofail;
478476
}
479477

480478
return;
@@ -511,7 +509,7 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
511509
* rangetable here --- subplan RTEs will be checked during
512510
* ExecInitSubPlan().
513511
*/
514-
ExecCheckRTPerms(parseTree->rtable,operation);
512+
ExecCheckRTPerms(parseTree->rtable);
515513

516514
/*
517515
* get information from query descriptor

‎src/backend/executor/nodeSubplan.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.59 2003/11/29 19:51:48 pgsql Exp $
10+
* $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.60 2004/01/14 23:01:54 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -670,10 +670,9 @@ ExecInitSubPlan(SubPlanState *node, EState *estate)
670670
MemoryContextoldcontext;
671671

672672
/*
673-
* Do access checking on the rangetable entries in the subquery. Here,
674-
* we assume the subquery is a SELECT.
673+
* Do access checking on the rangetable entries in the subquery.
675674
*/
676-
ExecCheckRTPerms(subplan->rtable,CMD_SELECT);
675+
ExecCheckRTPerms(subplan->rtable);
677676

678677
/*
679678
* initialize my state

‎src/backend/nodes/copyfuncs.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.276 2004/01/10 23:28:44 neilc Exp $
18+
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.277 2004/01/14 23:01:54 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -1258,8 +1258,7 @@ _copyRangeTblEntry(RangeTblEntry *from)
12581258
COPY_NODE_FIELD(eref);
12591259
COPY_SCALAR_FIELD(inh);
12601260
COPY_SCALAR_FIELD(inFromCl);
1261-
COPY_SCALAR_FIELD(checkForRead);
1262-
COPY_SCALAR_FIELD(checkForWrite);
1261+
COPY_SCALAR_FIELD(requiredPerms);
12631262
COPY_SCALAR_FIELD(checkAsUser);
12641263

12651264
returnnewnode;

‎src/backend/nodes/equalfuncs.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* Portions Copyright (c) 1994, Regents of the University of California
1919
*
2020
* IDENTIFICATION
21-
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.214 2004/01/10 23:28:45 neilc Exp $
21+
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.215 2004/01/14 23:01:55 tgl Exp $
2222
*
2323
*-------------------------------------------------------------------------
2424
*/
@@ -1574,8 +1574,7 @@ _equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
15741574
COMPARE_NODE_FIELD(eref);
15751575
COMPARE_SCALAR_FIELD(inh);
15761576
COMPARE_SCALAR_FIELD(inFromCl);
1577-
COMPARE_SCALAR_FIELD(checkForRead);
1578-
COMPARE_SCALAR_FIELD(checkForWrite);
1577+
COMPARE_SCALAR_FIELD(requiredPerms);
15791578
COMPARE_SCALAR_FIELD(checkAsUser);
15801579

15811580
return true;

‎src/backend/nodes/outfuncs.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.229 2004/01/06 04:31:01 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.230 2004/01/14 23:01:55 tgl Exp $
1212
*
1313
* NOTES
1414
* Every node type that can appear in stored rules' parsetrees *must*
@@ -1358,9 +1358,8 @@ _outRangeTblEntry(StringInfo str, RangeTblEntry *node)
13581358

13591359
WRITE_BOOL_FIELD(inh);
13601360
WRITE_BOOL_FIELD(inFromCl);
1361-
WRITE_BOOL_FIELD(checkForRead);
1362-
WRITE_BOOL_FIELD(checkForWrite);
1363-
WRITE_OID_FIELD(checkAsUser);
1361+
WRITE_UINT_FIELD(requiredPerms);
1362+
WRITE_UINT_FIELD(checkAsUser);
13641363
}
13651364

13661365
staticvoid

‎src/backend/nodes/readfuncs.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.164 2004/01/07 18:56:26 neilc Exp $
11+
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.165 2004/01/14 23:01:55 tgl Exp $
1212
*
1313
* NOTES
1414
* Path and Plan nodes do not have any readfuncs support, because we
@@ -939,9 +939,8 @@ _readRangeTblEntry(void)
939939

940940
READ_BOOL_FIELD(inh);
941941
READ_BOOL_FIELD(inFromCl);
942-
READ_BOOL_FIELD(checkForRead);
943-
READ_BOOL_FIELD(checkForWrite);
944-
READ_OID_FIELD(checkAsUser);
942+
READ_UINT_FIELD(requiredPerms);
943+
READ_UINT_FIELD(checkAsUser);
945944

946945
READ_DONE();
947946
}

‎src/backend/optimizer/path/allpaths.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.111 2004/01/05 05:07:35 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.112 2004/01/14 23:01:55 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -227,8 +227,7 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel,
227227
* it examines the parent's inheritlist entry. There's no need to
228228
* check twice, so turn off access check bits in the original RTE.
229229
*/
230-
rte->checkForRead= false;
231-
rte->checkForWrite= false;
230+
rte->requiredPerms=0;
232231

233232
/*
234233
* Initialize to compute size estimates for whole inheritance tree

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp