diff --git a/src/backend/rewrite/rowsecurity.c b/src/backend/rewrite/rowsecurity.c
index 2386cf016fbc52cbe4f9ac6cc64a4abc1f3e7158..562dbc90e9fdf7f1d0a29227873ce4ff75dc1471 100644
--- a/src/backend/rewrite/rowsecurity.c
+++ b/src/backend/rewrite/rowsecurity.c
@@ -147,8 +147,18 @@ get_row_security_policies(Query *root, CmdType commandType, RangeTblEntry *rte,
 		return;
 	}
 
-	/* Grab the built-in policies which should be applied to this relation. */
+	/*
+	 * RLS is enabled for this relation.
+	 *
+	 * Get the security policies that should be applied, based on the command
+	 * type.  Note that if this isn't the target relation, we actually want
+	 * the relation's SELECT policies, regardless of the query command type,
+	 * for example in UPDATE t1 ... FROM t2 we need to apply t1's UPDATE
+	 * policies and t2's SELECT policies.
+	 */
 	rel = heap_open(rte->relid, NoLock);
+	if (rt_index != root->resultRelation)
+		commandType = CMD_SELECT;
 
 	rowsec_policies = pull_row_security_policies(commandType, rel,
 												 user_id);
diff --git a/src/test/regress/expected/rowsecurity.out b/src/test/regress/expected/rowsecurity.out
index b0556c2ff1f47654aa06d02c8085cc94c27a4e04..6fc80af30ee438ada4b2e99c782e46826d3967ec 100644
--- a/src/test/regress/expected/rowsecurity.out
+++ b/src/test/regress/expected/rowsecurity.out
@@ -3033,6 +3033,89 @@ CREATE POLICY p ON t USING (max(c)); -- fails: aggregate functions are not allow
 ERROR:  aggregate functions are not allowed in policy expressions
 ROLLBACK;
 --
+-- Non-target relations are only subject to SELECT policies
+--
+SET SESSION AUTHORIZATION rls_regress_user0;
+CREATE TABLE r1 (a int);
+CREATE TABLE r2 (a int);
+INSERT INTO r1 VALUES (10), (20);
+INSERT INTO r2 VALUES (10), (20);
+GRANT ALL ON r1, r2 TO rls_regress_user1;
+CREATE POLICY p1 ON r1 USING (true);
+ALTER TABLE r1 ENABLE ROW LEVEL SECURITY;
+CREATE POLICY p1 ON r2 FOR SELECT USING (true);
+CREATE POLICY p2 ON r2 FOR INSERT WITH CHECK (false);
+CREATE POLICY p3 ON r2 FOR UPDATE USING (false);
+CREATE POLICY p4 ON r2 FOR DELETE USING (false);
+ALTER TABLE r2 ENABLE ROW LEVEL SECURITY;
+SET SESSION AUTHORIZATION rls_regress_user1;
+SELECT * FROM r1;
+ a  
+----
+ 10
+ 20
+(2 rows)
+
+SELECT * FROM r2;
+ a  
+----
+ 10
+ 20
+(2 rows)
+
+-- r2 is read-only
+INSERT INTO r2 VALUES (2); -- Not allowed
+ERROR:  new row violates row level security policy for "r2"
+UPDATE r2 SET a = 2 RETURNING *; -- Updates nothing
+ a 
+---
+(0 rows)
+
+DELETE FROM r2 RETURNING *; -- Deletes nothing
+ a 
+---
+(0 rows)
+
+-- r2 can be used as a non-target relation in DML
+INSERT INTO r1 SELECT a + 1 FROM r2 RETURNING *; -- OK
+ a  
+----
+ 11
+ 21
+(2 rows)
+
+UPDATE r1 SET a = r2.a + 2 FROM r2 WHERE r1.a = r2.a RETURNING *; -- OK
+ a  | a  
+----+----
+ 12 | 10
+ 22 | 20
+(2 rows)
+
+DELETE FROM r1 USING r2 WHERE r1.a = r2.a + 2 RETURNING *; -- OK
+ a  | a  
+----+----
+ 12 | 10
+ 22 | 20
+(2 rows)
+
+SELECT * FROM r1;
+ a  
+----
+ 11
+ 21
+(2 rows)
+
+SELECT * FROM r2;
+ a  
+----
+ 10
+ 20
+(2 rows)
+
+SET SESSION AUTHORIZATION rls_regress_user0;
+DROP TABLE r1;
+DROP TABLE r2;
+--
 -- Clean up objects
 --
 RESET SESSION AUTHORIZATION;
diff --git a/src/test/regress/sql/rowsecurity.sql b/src/test/regress/sql/rowsecurity.sql
index 300f34ad4bf219ade921d081b8dbe7dbd966eaec..e8c09e9043135949112bfc1155c981f514ae6166 100644
--- a/src/test/regress/sql/rowsecurity.sql
+++ b/src/test/regress/sql/rowsecurity.sql
@@ -1298,6 +1298,46 @@ CREATE TABLE t (c) AS VALUES ('bar'::text);
 CREATE POLICY p ON t USING (max(c)); -- fails: aggregate functions are not allowed in policy expressions
 ROLLBACK;
 
+--
+-- Non-target relations are only subject to SELECT policies
+--
+SET SESSION AUTHORIZATION rls_regress_user0;
+CREATE TABLE r1 (a int);
+CREATE TABLE r2 (a int);
+INSERT INTO r1 VALUES (10), (20);
+INSERT INTO r2 VALUES (10), (20);
+
+GRANT ALL ON r1, r2 TO rls_regress_user1;
+
+CREATE POLICY p1 ON r1 USING (true);
+ALTER TABLE r1 ENABLE ROW LEVEL SECURITY;
+
+CREATE POLICY p1 ON r2 FOR SELECT USING (true);
+CREATE POLICY p2 ON r2 FOR INSERT WITH CHECK (false);
+CREATE POLICY p3 ON r2 FOR UPDATE USING (false);
+CREATE POLICY p4 ON r2 FOR DELETE USING (false);
+ALTER TABLE r2 ENABLE ROW LEVEL SECURITY;
+
+SET SESSION AUTHORIZATION rls_regress_user1;
+SELECT * FROM r1;
+SELECT * FROM r2;
+
+-- r2 is read-only
+INSERT INTO r2 VALUES (2); -- Not allowed
+UPDATE r2 SET a = 2 RETURNING *; -- Updates nothing
+DELETE FROM r2 RETURNING *; -- Deletes nothing
+
+-- r2 can be used as a non-target relation in DML
+INSERT INTO r1 SELECT a + 1 FROM r2 RETURNING *; -- OK
+UPDATE r1 SET a = r2.a + 2 FROM r2 WHERE r1.a = r2.a RETURNING *; -- OK
+DELETE FROM r1 USING r2 WHERE r1.a = r2.a + 2 RETURNING *; -- OK
+SELECT * FROM r1;
+SELECT * FROM r2;
+
+SET SESSION AUTHORIZATION rls_regress_user0;
+DROP TABLE r1;
+DROP TABLE r2;
+
 --
 -- Clean up objects
 --