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

Commitdad5bb0

Browse files
committed
Redo permissions-checking code so that it does the right thing at APPEND
nodes. The former version failed to check permissions of relations thatwere referenced in second and later clauses of UNIONs, and it did notcheck permissions of tables referenced via inheritance.
1 parentfd9ff86 commitdad5bb0

File tree

2 files changed

+246
-89
lines changed

2 files changed

+246
-89
lines changed

‎src/backend/executor/execMain.c

Lines changed: 245 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
*
2828
*
2929
* IDENTIFICATION
30-
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.109 2000/02/15 03:36:49 thomas Exp $
30+
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.110 2000/03/09 05:15:33 tgl Exp $
3131
*
3232
*-------------------------------------------------------------------------
3333
*/
@@ -46,9 +46,9 @@
4646
#include"utils/builtins.h"
4747
#include"utils/syscache.h"
4848

49-
voidExecCheckPerms(CmdTypeoperation,intresultRelation,List*rangeTable,
50-
Query*parseTree);
51-
49+
/* XXX no points for style */
50+
externTupleTableSlot*EvalPlanQual(EState*estate,Indexrti,
51+
ItemPointertid);
5252

5353
/* decls for local routines only used within this module */
5454
staticTupleDescInitPlan(CmdTypeoperation,
@@ -72,13 +72,18 @@ static void ExecDelete(TupleTableSlot *slot, ItemPointer tupleid,
7272
EState*estate);
7373
staticvoidExecReplace(TupleTableSlot*slot,ItemPointertupleid,
7474
EState*estate);
75-
76-
TupleTableSlot*EvalPlanQual(EState*estate,Indexrti,ItemPointertid);
7775
staticTupleTableSlot*EvalPlanQualNext(EState*estate);
78-
79-
76+
staticvoidExecCheckQueryPerms(CmdTypeoperation,Query*parseTree,
77+
Plan*plan);
78+
staticvoidExecCheckPlanPerms(Plan*plan,CmdTypeoperation,
79+
intresultRelation,boolresultIsScanned);
80+
staticvoidExecCheckRTPerms(List*rangeTable,CmdTypeoperation,
81+
intresultRelation,boolresultIsScanned);
82+
staticvoidExecCheckRTEPerms(RangeTblEntry*rte,CmdTypeoperation,
83+
boolisResultRelation,boolresultIsScanned);
8084
/* end of local decls */
8185

86+
8287
/* ----------------------------------------------------------------
8388
*ExecutorStart
8489
*
@@ -378,104 +383,257 @@ ExecutorEnd(QueryDesc *queryDesc, EState *estate)
378383
}
379384
}
380385

381-
void
382-
ExecCheckPerms(CmdTypeoperation,
383-
intresultRelation,
384-
List*rangeTable,
385-
Query*parseTree)
386+
387+
/*
388+
* ExecCheckQueryPerms
389+
*Check access permissions for all relations referenced in a query.
390+
*/
391+
staticvoid
392+
ExecCheckQueryPerms(CmdTypeoperation,Query*parseTree,Plan*plan)
386393
{
387-
intrtindex=0;
394+
List*rangeTable=parseTree->rtable;
395+
intresultRelation=parseTree->resultRelation;
396+
boolresultIsScanned= false;
388397
List*lp;
389-
List*qvars,
390-
*tvars;
391-
int32ok=1,
392-
aclcheck_result=-1;
393-
char*opstr;
394-
char*relName=NULL;
395-
char*userName;
396398

397-
#defineCHECK(MODE)pg_aclcheck(relName, userName, MODE)
399+
/*
400+
* If we have a result relation, determine whether the result rel is
401+
* scanned or merely written. If scanned, we will insist on read
402+
* permission as well as modify permission.
403+
*/
404+
if (resultRelation>0)
405+
{
406+
List*qvars=pull_varnos(parseTree->qual);
407+
List*tvars=pull_varnos((Node*)parseTree->targetList);
398408

399-
userName=GetPgUserName();
409+
resultIsScanned= (intMember(resultRelation,qvars)||
410+
intMember(resultRelation,tvars));
411+
freeList(qvars);
412+
freeList(tvars);
413+
}
400414

401-
foreach(lp,rangeTable)
415+
/*
416+
* Check RTEs in the query's primary rangetable.
417+
*/
418+
ExecCheckRTPerms(rangeTable,operation,resultRelation,resultIsScanned);
419+
420+
/*
421+
* Check SELECT FOR UPDATE access rights.
422+
*/
423+
foreach(lp,parseTree->rowMark)
402424
{
403-
RangeTblEntry*rte=lfirst(lp);
425+
RowMark*rm=lfirst(lp);
404426

405-
++rtindex;
427+
if (!(rm->info&ROW_ACL_FOR_UPDATE))
428+
continue;
429+
430+
ExecCheckRTEPerms(rt_fetch(rm->rti,rangeTable),
431+
CMD_UPDATE, true, false);
432+
}
433+
434+
/*
435+
* Search for subplans and APPEND nodes to check their rangetables.
436+
*/
437+
ExecCheckPlanPerms(plan,operation,resultRelation,resultIsScanned);
438+
}
439+
440+
/*
441+
* ExecCheckPlanPerms
442+
*Recursively scan the plan tree to check access permissions in
443+
*subplans.
444+
*
445+
* We also need to look at the local rangetables in Append plan nodes,
446+
* which is pretty bogus --- most likely, those tables should be mentioned
447+
* in the query's main rangetable. But at the moment, they're not.
448+
*/
449+
staticvoid
450+
ExecCheckPlanPerms(Plan*plan,CmdTypeoperation,
451+
intresultRelation,boolresultIsScanned)
452+
{
453+
List*subp;
454+
455+
if (plan==NULL)
456+
return;
457+
458+
/* Check subplans, which we assume are plain SELECT queries */
459+
460+
foreach(subp,plan->initPlan)
461+
{
462+
SubPlan*subplan= (SubPlan*)lfirst(subp);
463+
464+
ExecCheckRTPerms(subplan->rtable,CMD_SELECT,0, false);
465+
ExecCheckPlanPerms(subplan->plan,CMD_SELECT,0, false);
466+
}
467+
foreach(subp,plan->subPlan)
468+
{
469+
SubPlan*subplan= (SubPlan*)lfirst(subp);
470+
471+
ExecCheckRTPerms(subplan->rtable,CMD_SELECT,0, false);
472+
ExecCheckPlanPerms(subplan->plan,CMD_SELECT,0, false);
473+
}
474+
475+
/* Check lower plan nodes */
476+
477+
ExecCheckPlanPerms(plan->lefttree,operation,
478+
resultRelation,resultIsScanned);
479+
ExecCheckPlanPerms(plan->righttree,operation,
480+
resultRelation,resultIsScanned);
481+
482+
/* Do node-type-specific checks */
406483

407-
if (rte->skipAcl)
484+
switch (nodeTag(plan))
485+
{
486+
caseT_Append:
408487
{
488+
Append*app= (Append*)plan;
489+
List*appendplans;
409490

410-
/*
411-
* This happens if the access to this table is due to a view
412-
* query rewriting - the rewrite handler checked the
413-
*permissions against the view owner, so we just skip this
414-
*entry.
415-
*/
416-
continue;
417-
}
491+
if (app->inheritrelid>0)
492+
{
493+
/*
494+
*Append implements expansion of inheritance; all members
495+
*of inheritrtable list will be plugged into same RTE slot.
496+
* Therefore, they are either all result relations or none.
497+
*/
498+
List*rtable;
418499

419-
relName=rte->relname;
420-
if (rtindex==resultRelation)
421-
{/* this is the result relation */
422-
qvars=pull_varnos(parseTree->qual);
423-
tvars=pull_varnos((Node*)parseTree->targetList);
424-
if (intMember(resultRelation,qvars)||
425-
intMember(resultRelation,tvars))
500+
foreach(rtable,app->inheritrtable)
501+
{
502+
ExecCheckRTEPerms((RangeTblEntry*)lfirst(rtable),
503+
operation,
504+
(app->inheritrelid==resultRelation),
505+
resultIsScanned);
506+
}
507+
}
508+
else
426509
{
427-
/* result relation is scanned */
428-
ok= ((aclcheck_result=CHECK(ACL_RD))==ACLCHECK_OK);
429-
opstr="read";
430-
if (!ok)
431-
break;
510+
/* Append implements UNION, which must be a SELECT */
511+
List*rtables;
512+
513+
foreach(rtables,app->unionrtables)
514+
{
515+
ExecCheckRTPerms((List*)lfirst(rtables),
516+
CMD_SELECT,0, false);
517+
}
432518
}
433-
switch (operation)
519+
520+
/* Check appended plans */
521+
foreach(appendplans,app->appendplans)
434522
{
435-
caseCMD_INSERT:
436-
ok= ((aclcheck_result=CHECK(ACL_AP))==ACLCHECK_OK)||
437-
((aclcheck_result=CHECK(ACL_WR))==ACLCHECK_OK);
438-
opstr="append";
439-
break;
440-
caseCMD_DELETE:
441-
caseCMD_UPDATE:
442-
ok= ((aclcheck_result=CHECK(ACL_WR))==ACLCHECK_OK);
443-
opstr="write";
444-
break;
445-
default:
446-
elog(ERROR,"ExecCheckPerms: bogus operation %d",
447-
operation);
523+
ExecCheckPlanPerms((Plan*)lfirst(appendplans),
524+
operation,
525+
resultRelation,
526+
resultIsScanned);
448527
}
528+
break;
449529
}
450-
else
451-
{
452-
ok= ((aclcheck_result=CHECK(ACL_RD))==ACLCHECK_OK);
453-
opstr="read";
454-
}
455-
if (!ok)
530+
531+
default:
456532
break;
457533
}
458-
if (!ok)
459-
elog(ERROR,"%s: %s",relName,aclcheck_error_strings[aclcheck_result]);
534+
}
460535

461-
if (parseTree!=NULL&&parseTree->rowMark!=NULL)
536+
/*
537+
* ExecCheckRTPerms
538+
*Check access permissions for all relations listed in a range table.
539+
*
540+
* If resultRelation is not 0, it is the RT index of the relation to be
541+
* treated as the result relation. All other relations are assumed to be
542+
* read-only for the query.
543+
*/
544+
staticvoid
545+
ExecCheckRTPerms(List*rangeTable,CmdTypeoperation,
546+
intresultRelation,boolresultIsScanned)
547+
{
548+
intrtindex=0;
549+
List*lp;
550+
551+
foreach(lp,rangeTable)
462552
{
463-
foreach(lp,parseTree->rowMark)
464-
{
465-
RowMark*rm=lfirst(lp);
553+
RangeTblEntry*rte=lfirst(lp);
466554

467-
if (!(rm->info&ROW_ACL_FOR_UPDATE))
468-
continue;
555+
++rtindex;
556+
557+
ExecCheckRTEPerms(rte,
558+
operation,
559+
(rtindex==resultRelation),
560+
resultIsScanned);
561+
}
562+
}
563+
564+
/*
565+
* ExecCheckRTEPerms
566+
*Check access permissions for a single RTE.
567+
*/
568+
staticvoid
569+
ExecCheckRTEPerms(RangeTblEntry*rte,CmdTypeoperation,
570+
boolisResultRelation,boolresultIsScanned)
571+
{
572+
char*relName;
573+
char*userName;
574+
int32aclcheck_result;
575+
576+
if (rte->skipAcl)
577+
{
578+
/*
579+
* This happens if the access to this table is due to a view
580+
* query rewriting - the rewrite handler already checked the
581+
* permissions against the view owner, so we just skip this entry.
582+
*/
583+
return;
584+
}
469585

470-
relName=rt_fetch(rm->rti,rangeTable)->relname;
471-
ok= ((aclcheck_result=CHECK(ACL_WR))==ACLCHECK_OK);
472-
opstr="write";
473-
if (!ok)
474-
elog(ERROR,"%s: %s",relName,aclcheck_error_strings[aclcheck_result]);
586+
relName=rte->relname;
587+
588+
/*
589+
* Note: GetPgUserName is presently fast enough that there's no harm
590+
* in calling it separately for each RTE. If that stops being true,
591+
* we could call it once in ExecCheckQueryPerms and pass the userName
592+
* down from there. But for now, no need for the extra clutter.
593+
*/
594+
userName=GetPgUserName();
595+
596+
#defineCHECK(MODE)pg_aclcheck(relName, userName, MODE)
597+
598+
if (isResultRelation)
599+
{
600+
if (resultIsScanned)
601+
{
602+
aclcheck_result=CHECK(ACL_RD);
603+
if (aclcheck_result!=ACLCHECK_OK)
604+
elog(ERROR,"%s: %s",
605+
relName,aclcheck_error_strings[aclcheck_result]);
606+
}
607+
switch (operation)
608+
{
609+
caseCMD_INSERT:
610+
/* Accept either APPEND or WRITE access for this */
611+
aclcheck_result=CHECK(ACL_AP);
612+
if (aclcheck_result!=ACLCHECK_OK)
613+
aclcheck_result=CHECK(ACL_WR);
614+
break;
615+
caseCMD_DELETE:
616+
caseCMD_UPDATE:
617+
aclcheck_result=CHECK(ACL_WR);
618+
break;
619+
default:
620+
elog(ERROR,"ExecCheckRTEPerms: bogus operation %d",
621+
operation);
622+
aclcheck_result=ACLCHECK_OK;/* keep compiler quiet */
623+
break;
475624
}
476625
}
626+
else
627+
{
628+
aclcheck_result=CHECK(ACL_RD);
629+
}
630+
631+
if (aclcheck_result!=ACLCHECK_OK)
632+
elog(ERROR,"%s: %s",
633+
relName,aclcheck_error_strings[aclcheck_result]);
477634
}
478635

636+
479637
/* ===============================================================
480638
* ===============================================================
481639
static routines follow
@@ -514,16 +672,19 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
514672
TupleDesctupType;
515673
List*targetList;
516674

675+
/*
676+
* Do permissions checks.
677+
*/
678+
#ifndefNO_SECURITY
679+
ExecCheckQueryPerms(operation,parseTree,plan);
680+
#endif
681+
517682
/*
518683
* get information from query descriptor
519684
*/
520685
rangeTable=parseTree->rtable;
521686
resultRelation=parseTree->resultRelation;
522687

523-
#ifndefNO_SECURITY
524-
ExecCheckPerms(operation,resultRelation,rangeTable,parseTree);
525-
#endif
526-
527688
/*
528689
* initialize the node's execution state
529690
*/

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp