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

Commit5d35438

Browse files
committed
Adjust behavior of row_security GUC to match the docs.
Some time back we agreed that row_security=off should not be a way tobypass RLS entirely, but only a way to get an error if it was beingapplied. However, the code failed to act that way for table owners.Per discussion, this is a must-fix bug for 9.5.0.Adjust the logic in rls.c to behave as expected; also, modify theerror message to be more consistent with the new interpretation.The regression tests need minor corrections as well. Also updatethe comments about row_security in ddl.sgml to be correct. (Theofficial description of the GUC in config.sgml is already correct.)I failed to resist the temptation to do some other very minorcleanup as well, such as getting rid of a duplicate extern declaration.
1 parent8978eb0 commit5d35438

File tree

4 files changed

+78
-92
lines changed

4 files changed

+78
-92
lines changed

‎doc/src/sgml/ddl.sgml

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,11 +1572,7 @@ REVOKE ALL ON accounts FROM PUBLIC;
15721572
bypass the row security system when accessing a table. Table owners
15731573
normally bypass row security as well, though a table owner can choose to
15741574
be subject to row security with <link linkend="sql-altertable">ALTER
1575-
TABLE ... FORCE ROW LEVEL SECURITY</>. Even in a table with that option
1576-
selected, the table owner will bypass row security if the
1577-
<xref linkend="guc-row-security"> configuration parameter is set
1578-
to <literal>off</>; this setting is typically used for purposes such as
1579-
backup and restore.
1575+
TABLE ... FORCE ROW LEVEL SECURITY</>.
15801576
</para>
15811577

15821578
<para>
@@ -1606,14 +1602,6 @@ REVOKE ALL ON accounts FROM PUBLIC;
16061602
of all roles that they are a member of.
16071603
</para>
16081604

1609-
<para>
1610-
Referential integrity checks, such as unique or primary key constraints
1611-
and foreign key references, always bypass row security to ensure that
1612-
data integrity is maintained. Care must be taken when developing
1613-
schemas and row level policies to avoid <quote>covert channel</> leaks of
1614-
information through such referential integrity checks.
1615-
</para>
1616-
16171605
<para>
16181606
As a simple example, here is how to create a policy on
16191607
the <literal>account</> relation to allow only members of
@@ -1773,6 +1761,26 @@ postgres=&gt; update passwd set pwhash = 'abc';
17731761
UPDATE 1
17741762
</programlisting>
17751763

1764+
<para>
1765+
Referential integrity checks, such as unique or primary key constraints
1766+
and foreign key references, always bypass row security to ensure that
1767+
data integrity is maintained. Care must be taken when developing
1768+
schemas and row level policies to avoid <quote>covert channel</> leaks of
1769+
information through such referential integrity checks.
1770+
</para>
1771+
1772+
<para>
1773+
In some contexts it is important to be sure that row security is
1774+
not being applied. For example, when taking a backup, it could be
1775+
disastrous if row security silently caused some rows to be omitted
1776+
from the backup. In such a situation, you can set the
1777+
<xref linkend="guc-row-security"> configuration parameter
1778+
to <literal>off</>. This does not in itself bypass row security;
1779+
what it does is throw an error if any query's results would get filtered
1780+
by a policy. The reason for the error can then be investigated and
1781+
fixed.
1782+
</para>
1783+
17761784
<para>
17771785
For additional details see <xref linkend="sql-createpolicy">
17781786
and <xref linkend="sql-altertable">.

‎src/backend/utils/misc/rls.c

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,17 @@
1717
#include"access/htup.h"
1818
#include"access/htup_details.h"
1919
#include"access/transam.h"
20-
#include"catalog/pg_class.h"
2120
#include"catalog/namespace.h"
21+
#include"catalog/pg_class.h"
2222
#include"miscadmin.h"
2323
#include"utils/acl.h"
2424
#include"utils/builtins.h"
2525
#include"utils/elog.h"
26+
#include"utils/lsyscache.h"
2627
#include"utils/rls.h"
2728
#include"utils/syscache.h"
2829

2930

30-
externintcheck_enable_rls(Oidrelid,OidcheckAsUser,boolnoError);
31-
3231
/*
3332
* check_enable_rls
3433
*
@@ -52,20 +51,21 @@ extern intcheck_enable_rls(Oid relid, Oid checkAsUser, bool noError);
5251
int
5352
check_enable_rls(Oidrelid,OidcheckAsUser,boolnoError)
5453
{
54+
Oiduser_id=checkAsUser ?checkAsUser :GetUserId();
5555
HeapTupletuple;
5656
Form_pg_classclassform;
5757
boolrelrowsecurity;
5858
boolrelforcerowsecurity;
59-
Oiduser_id=checkAsUser ?checkAsUser :GetUserId();
59+
boolamowner;
6060

6161
/* Nothing to do for built-in relations */
62-
if (relid<FirstNormalObjectId)
62+
if (relid<(Oid)FirstNormalObjectId)
6363
returnRLS_NONE;
6464

65+
/* Fetch relation's relrowsecurity and relforcerowsecurity flags */
6566
tuple=SearchSysCache1(RELOID,ObjectIdGetDatum(relid));
6667
if (!HeapTupleIsValid(tuple))
6768
returnRLS_NONE;
68-
6969
classform= (Form_pg_class)GETSTRUCT(tuple);
7070

7171
relrowsecurity=classform->relrowsecurity;
@@ -88,41 +88,45 @@ check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
8888
returnRLS_NONE_ENV;
8989

9090
/*
91-
* Table owners generally bypass RLS, except ifrow_security=true and the
92-
*table has been set (byan owner) to FORCE ROW SECURITY, and this is not
93-
*a referentialintegrity check.
91+
* Table owners generally bypass RLS, except ifthe table has been set (by
92+
* an owner) to FORCE ROW SECURITY, and this is not a referential
93+
* integrity check.
9494
*
9595
* Return RLS_NONE_ENV to indicate that this decision depends on the
9696
* environment (in this case, the user_id).
9797
*/
98-
if (pg_class_ownercheck(relid,user_id))
98+
amowner=pg_class_ownercheck(relid,user_id);
99+
if (amowner)
99100
{
100101
/*
101-
* Ifrow_security=true andFORCE ROW LEVEL SECURITY has been set on
102-
*the relation then wereturn RLS_ENABLED to indicate that RLS should
103-
*still be applied. Ifwe are ina SECURITY_NOFORCE_RLS context or if
104-
*row_security=false then we returnRLS_NONE_ENV.
102+
* If FORCE ROW LEVEL SECURITY has been set on the relation then we
103+
*shouldreturn RLS_ENABLED to indicate that RLS should be applied.
104+
*If not, or ifwe are inan InNoForceRLSOperation context, we return
105+
* RLS_NONE_ENV.
105106
*
106-
*The SECURITY_NOFORCE_RLS indicates that we should not apply RLS even
107-
* if the table has FORCE RLS set- IF the current user is the owner.
108-
* This is specifically to ensure that referential integrity checks are
109-
* able to still run correctly.
107+
*InNoForceRLSOperation indicates that we should not apply RLS even
108+
* if the table has FORCE RLS set- IF the current user is the owner.
109+
* This is specifically to ensure that referential integrity checks
110+
*areable to still run correctly.
110111
*
111112
* This is intentionally only done after we have checked that the user
112113
* is the table owner, which should always be the case for referential
113114
* integrity checks.
114115
*/
115-
if (row_security&&relforcerowsecurity&& !InNoForceRLSOperation())
116-
returnRLS_ENABLED;
117-
else
116+
if (!relforcerowsecurity||InNoForceRLSOperation())
118117
returnRLS_NONE_ENV;
119118
}
120119

121-
/* row_security GUC says to bypass RLS, but user lacks permission */
120+
/*
121+
* We should apply RLS. However, the user may turn off the row_security
122+
* GUC to get a forced error instead.
123+
*/
122124
if (!row_security&& !noError)
123125
ereport(ERROR,
124126
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
125-
errmsg("insufficient privilege to bypass row-level security")));
127+
errmsg("query would be affected by row-level security policy for table \"%s\"",
128+
get_rel_name(relid)),
129+
amowner ?errhint("To disable the policy for the table's owner, use ALTER TABLE NO FORCE ROW LEVEL SECURITY.") :0));
126130

127131
/* RLS should be fully enabled for this relation. */
128132
returnRLS_ENABLED;

‎src/test/regress/expected/rowsecurity.out

Lines changed: 21 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2728,8 +2728,8 @@ COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ',';
27282728
-- Check COPY TO as user with permissions.
27292729
SET SESSION AUTHORIZATION rls_regress_user1;
27302730
SET row_security TO OFF;
2731-
COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --fail -insufficient to bypass rls
2732-
ERROR:insufficient privilege to bypassrow-level security
2731+
COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --fail -would be affected by RLS
2732+
ERROR:query would be affected byrow-level security policy for table "copy_t"
27332733
SET row_security TO ON;
27342734
COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --ok
27352735
0,cfcd208495d565ef66e7dff9f98764da
@@ -2769,8 +2769,8 @@ COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --ok
27692769
-- Check COPY TO as user without permissions. SET row_security TO OFF;
27702770
SET SESSION AUTHORIZATION rls_regress_user2;
27712771
SET row_security TO OFF;
2772-
COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --fail -insufficient to bypass rls
2773-
ERROR:insufficient privilege to bypassrow-level security
2772+
COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --fail -would be affected by RLS
2773+
ERROR:query would be affected byrow-level security policy for table "copy_t"
27742774
SET row_security TO ON;
27752775
COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --fail - permission denied
27762776
ERROR: permission denied for relation copy_t
@@ -2793,8 +2793,8 @@ COPY copy_rel_to TO STDOUT WITH DELIMITER ',';
27932793
-- Check COPY TO as user with permissions.
27942794
SET SESSION AUTHORIZATION rls_regress_user1;
27952795
SET row_security TO OFF;
2796-
COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail -insufficient to bypass rls
2797-
ERROR:insufficient privilege to bypassrow-level security
2796+
COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --fail -would be affected by RLS
2797+
ERROR:query would be affected byrow-level security policy for table "copy_rel_to"
27982798
SET row_security TO ON;
27992799
COPY copy_rel_to TO STDOUT WITH DELIMITER ','; --ok
28002800
-- Check COPY TO as user with permissions and BYPASSRLS
@@ -2822,8 +2822,8 @@ COPY copy_t FROM STDIN; --ok
28222822
-- Check COPY FROM as user with permissions.
28232823
SET SESSION AUTHORIZATION rls_regress_user1;
28242824
SET row_security TO OFF;
2825-
COPY copy_t FROM STDIN; --fail -insufficient privilege to bypass rls.
2826-
ERROR:insufficient privilege to bypassrow-level security
2825+
COPY copy_t FROM STDIN; --fail -would be affected by RLS.
2826+
ERROR:query would be affected byrow-level security policy for table "copy_t"
28272827
SET row_security TO ON;
28282828
COPY copy_t FROM STDIN; --fail - COPY FROM not supported by RLS.
28292829
ERROR: COPY FROM not supported with row-level security
@@ -3181,8 +3181,7 @@ SET SESSION AUTHORIZATION rls_regress_user0;
31813181
DROP TABLE r1;
31823182
DROP TABLE r2;
31833183
--
3184-
-- FORCE ROW LEVEL SECURITY applies RLS to owners but
3185-
-- only when row_security = on
3184+
-- FORCE ROW LEVEL SECURITY applies RLS to owners too
31863185
--
31873186
SET SESSION AUTHORIZATION rls_regress_user0;
31883187
SET row_security = on;
@@ -3215,30 +3214,16 @@ TABLE r1;
32153214
(0 rows)
32163215

32173216
SET row_security = off;
3218-
--Shows allrows
3217+
--these allfail, would be affected by RLS
32193218
TABLE r1;
3220-
a
3221-
----
3222-
10
3223-
20
3224-
(2 rows)
3225-
3226-
-- Update all rows
3219+
ERROR: query would be affected by row-level security policy for table "r1"
3220+
HINT: To disable the policy for the table's owner, use ALTER TABLE NO FORCE ROW LEVEL SECURITY.
32273221
UPDATE r1 SET a = 1;
3228-
TABLE r1;
3229-
a
3230-
---
3231-
1
3232-
1
3233-
(2 rows)
3234-
3235-
-- Delete all rows
3222+
ERROR: query would be affected by row-level security policy for table "r1"
3223+
HINT: To disable the policy for the table's owner, use ALTER TABLE NO FORCE ROW LEVEL SECURITY.
32363224
DELETE FROM r1;
3237-
TABLE r1;
3238-
a
3239-
---
3240-
(0 rows)
3241-
3225+
ERROR: query would be affected by row-level security policy for table "r1"
3226+
HINT: To disable the policy for the table's owner, use ALTER TABLE NO FORCE ROW LEVEL SECURITY.
32423227
DROP TABLE r1;
32433228
--
32443229
-- FORCE ROW LEVEL SECURITY does not break RI
@@ -3349,14 +3334,10 @@ TABLE r1;
33493334
(0 rows)
33503335

33513336
SET row_security = off;
3352-
--Rows shown now
3337+
--fail, would be affected by RLS
33533338
TABLE r1;
3354-
a
3355-
----
3356-
10
3357-
20
3358-
(2 rows)
3359-
3339+
ERROR: query would be affected by row-level security policy for table "r1"
3340+
HINT: To disable the policy for the table's owner, use ALTER TABLE NO FORCE ROW LEVEL SECURITY.
33603341
SET row_security = on;
33613342
-- Error
33623343
INSERT INTO r1 VALUES (10), (20) RETURNING *;
@@ -3377,7 +3358,7 @@ ALTER TABLE r1 FORCE ROW LEVEL SECURITY;
33773358
-- Works fine
33783359
UPDATE r1 SET a = 30;
33793360
-- Show updated rows
3380-
SET row_security = off;
3361+
ALTER TABLE r1 NO FORCE ROW LEVEL SECURITY;
33813362
TABLE r1;
33823363
a
33833364
----
@@ -3393,7 +3374,7 @@ TABLE r1;
33933374
10
33943375
(1 row)
33953376

3396-
SET row_security = on;
3377+
ALTER TABLE r1 FORCE ROW LEVEL SECURITY;
33973378
-- Error
33983379
UPDATE r1 SET a = 30 RETURNING *;
33993380
ERROR: new row violates row-level security policy for table "r1"

‎src/test/regress/sql/rowsecurity.sql

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,7 +1014,7 @@ COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ',';
10141014
-- Check COPY TO as user with permissions.
10151015
SET SESSION AUTHORIZATION rls_regress_user1;
10161016
SET row_security TO OFF;
1017-
COPY (SELECT*FROM copy_tORDER BY aASC) TO STDOUT WITH DELIMITER',';--fail -insufficient to bypass rls
1017+
COPY (SELECT*FROM copy_tORDER BY aASC) TO STDOUT WITH DELIMITER',';--fail -would be affected by RLS
10181018
SET row_security TOON;
10191019
COPY (SELECT*FROM copy_tORDER BY aASC) TO STDOUT WITH DELIMITER',';--ok
10201020

@@ -1028,7 +1028,7 @@ COPY (SELECT * FROM copy_t ORDER BY a ASC) TO STDOUT WITH DELIMITER ','; --ok
10281028
-- Check COPY TO as user without permissions. SET row_security TO OFF;
10291029
SET SESSION AUTHORIZATION rls_regress_user2;
10301030
SET row_security TO OFF;
1031-
COPY (SELECT*FROM copy_tORDER BY aASC) TO STDOUT WITH DELIMITER',';--fail -insufficient to bypass rls
1031+
COPY (SELECT*FROM copy_tORDER BY aASC) TO STDOUT WITH DELIMITER',';--fail -would be affected by RLS
10321032
SET row_security TOON;
10331033
COPY (SELECT*FROM copy_tORDER BY aASC) TO STDOUT WITH DELIMITER',';--fail - permission denied
10341034

@@ -1054,7 +1054,7 @@ COPY copy_rel_to TO STDOUT WITH DELIMITER ',';
10541054
-- Check COPY TO as user with permissions.
10551055
SET SESSION AUTHORIZATION rls_regress_user1;
10561056
SET row_security TO OFF;
1057-
COPY copy_rel_to TO STDOUT WITH DELIMITER',';--fail -insufficient to bypass rls
1057+
COPY copy_rel_to TO STDOUT WITH DELIMITER',';--fail -would be affected by RLS
10581058
SET row_security TOON;
10591059
COPY copy_rel_to TO STDOUT WITH DELIMITER',';--ok
10601060

@@ -1092,7 +1092,7 @@ COPY copy_t FROM STDIN; --ok
10921092
-- Check COPY FROM as user with permissions.
10931093
SET SESSION AUTHORIZATION rls_regress_user1;
10941094
SET row_security TO OFF;
1095-
COPY copy_tFROM STDIN;--fail -insufficient privilege to bypass rls.
1095+
COPY copy_tFROM STDIN;--fail -would be affected by RLS.
10961096
SET row_security TOON;
10971097
COPY copy_tFROM STDIN;--fail - COPY FROM not supported by RLS.
10981098

@@ -1315,8 +1315,7 @@ DROP TABLE r1;
13151315
DROPTABLE r2;
13161316

13171317
--
1318-
-- FORCE ROW LEVEL SECURITY applies RLS to owners but
1319-
-- only when row_security = on
1318+
-- FORCE ROW LEVEL SECURITY applies RLS to owners too
13201319
--
13211320
SET SESSION AUTHORIZATION rls_regress_user0;
13221321
SET row_security=on;
@@ -1342,16 +1341,10 @@ DELETE FROM r1;
13421341
TABLE r1;
13431342

13441343
SET row_security= off;
1345-
--Shows allrows
1344+
--these allfail, would be affected by RLS
13461345
TABLE r1;
1347-
1348-
-- Update all rows
13491346
UPDATE r1SET a=1;
1350-
TABLE r1;
1351-
1352-
-- Delete all rows
13531347
DELETEFROM r1;
1354-
TABLE r1;
13551348

13561349
DROPTABLE r1;
13571350

@@ -1469,7 +1462,7 @@ INSERT INTO r1 VALUES (10), (20);
14691462
TABLE r1;
14701463

14711464
SET row_security= off;
1472-
--Rows shown now
1465+
--fail, would be affected by RLS
14731466
TABLE r1;
14741467

14751468
SET row_security=on;
@@ -1497,15 +1490,15 @@ ALTER TABLE r1 FORCE ROW LEVEL SECURITY;
14971490
UPDATE r1SET a=30;
14981491

14991492
-- Show updated rows
1500-
SET row_security= off;
1493+
ALTERTABLE r1 NO FORCE ROW LEVEL SECURITY;
15011494
TABLE r1;
15021495
-- reset value in r1 for test with RETURNING
15031496
UPDATE r1SET a=10;
15041497

15051498
-- Verify row reset
15061499
TABLE r1;
15071500

1508-
SET row_security=on;
1501+
ALTERTABLE r1 FORCE ROW LEVEL SECURITY;
15091502

15101503
-- Error
15111504
UPDATE r1SET a=30 RETURNING*;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp