Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wzOY5-003zPe-2y for pgsql-hackers@arkaria.postgresql.org; Thu, 27 Aug 2026 01:04:58 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wzOY3-00GkQN-2S for pgsql-hackers@arkaria.postgresql.org; Thu, 27 Aug 2026 01:04:55 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wzOY3-00GkQF-1U for pgsql-hackers@lists.postgresql.org; Thu, 27 Aug 2026 01:04:55 +0000 Received: from mail-oa1-x31.google.com ([2001:4860:4864:20::31]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wzOY1-00000002bOI-36PG for pgsql-hackers@lists.postgresql.org; Thu, 27 Aug 2026 01:04:54 +0000 Received: by mail-oa1-x31.google.com with SMTP id 586e51a60fabf-4583b1703d3so1162494fac.3 for ; Wed, 26 Aug 2026 18:04:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787792692; x=1788397492; darn=lists.postgresql.org; h=content-transfer-encoding:content-type:in-reply-to:references :subject:to:from:user-agent:mime-version:date:message-id:from:to:cc :subject:date:message-id:reply-to:content-type; bh=qSn2d4VL5ai8Z2MLuPB4HR0jdGxg6Lxht3fR3PnCLcE=; b=Hdmjry4ldpXOZdWsBuFyIobHGvs7ougwp7+LiAJIV5TlKb1ZbBq7Ocjuu1O1B3fFMi 1P2Vf3tBwjNkizErOXllCqhQrzz7Tc7Kb59yws3zZG1EwYLumMbwy2y7nIvd3veJOj5f EWTc0vF7VadZHVkEirRVz/oyFmC0kWKCoXc3PPUE/EHDILTBdZpRjRtZkU2Rl/FvhfjP UZcUGBAuNM6XBwP84ypnKibOKuvz6zwTrv0UVIXkCCNywOT54IxL92o001TEKInOuk1+ +4zo+vwRbXS/jrpHuoHtC2Do+6pLgis9PnbJF10nRZllKcHdRoz8Ch9aIonG5vWyvIZQ aEfQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787792692; x=1788397492; h=content-transfer-encoding:content-type:in-reply-to:references :subject:to:from:user-agent:mime-version:date:message-id:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=qSn2d4VL5ai8Z2MLuPB4HR0jdGxg6Lxht3fR3PnCLcE=; b=YUNZbCmB38r9AqzpvtBp8fI67rKg6Mo8+GuYIWGkwzLf6wfCvnKM3ulZQSuq4jm4Tu NRywXmZHXh7W4wTz4vLW8Ef9oxPTmw0oSG2s0iXqGvfzDjUUY0js6Hg2PKl/Lx1I8C/I gUOIs/W9kSPvILR6FSobfimFT3VKk8+DQvovX8eYdBISmB6BqH7SNvpJGwOW0ax2w/NT IZLgiX9077rYDay6rLllMD4fdtCjoM+FHYIns5zoaOrj6BU5YbTa0TjFES8ZwI2bg1JH kOajb5p+8E4V6G+vfJOdJgNQzdxO2O6zIhOhMXmjBw94ggPm11G8cWXy7xnB/elC4mMH go6g== X-Gm-Message-State: AFuF++lZNdbbcyiZ2+6+CY2RsiZXEbUuPnr+rjl81AlOfZJjCf74/mBF oUyAoOErovKID/NhUENrLwUO4XWXL9uJiZq4aEycLuBu7KQkGiCWxomxQobVueer X-Gm-Gg: AR+sD10uRurlv0Lf50ePhrjdvv/Y2yjQYpEM2AtTevpdXVWz7MwdRI9cZG9fKI6HqM/ 8UbN2jzE2I5agUIbj+G408iUiyi15xro1Ci7c1wUJ7Z4gfDfsfkUMY7S37r100P7Hf3l1scwASj VL+Imp9MlmnZxe6gVLLVohVV25J4hcnAHeVTA1YeNX63nLBCWuJyQlpAFHCbZEoacf1Aa+gFQRL /ATLbFhESRbRo92ZUVy1Iy206n6Hl0UTwa/deYvEevpHPnI9t/mC7WdRuX8vCw7zAc8Eo8tnAil H7ltCrhJL3++AJ0fsNq1rCtg+ExrID2CwwLUAkB+Q86w7+sdyCN+UN27IIV7kDH7kPbRt9xYgrb BpJYVTii6bDaQBcYhFqk/HkZXD9ocgCQ6y2nNlupbuCX6e8HpZaoY6LVdCHC4ydRg1tpBh8GZYP NhqTCGwMWv1bTxrbl5qeOIIwg7E0kvcB0njmVUoVEzr3e3rDdE7fZMCuZnPnZvU2zYOcDjL23jy uzI8tW1ZklMDSRZ3wJZJoCOsRbG0wMjHeOjuD0n5taf2/MWa+fz X-Received: by 2002:a05:6808:c3cb:b0:4b2:8e1c:5920 with SMTP id 5614622812f47-4b366a1892bmr12779518b6e.9.1787792692508; Wed, 26 Aug 2026 18:04:52 -0700 (PDT) Received: from [192.168.1.193] ([150.220.93.59]) by smtp.gmail.com with ESMTPSA id 5614622812f47-4b36ab734c1sm2956384b6e.15.2026.08.26.18.04.50 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 26 Aug 2026 18:04:51 -0700 (PDT) Message-ID: <2e3ed175-8618-46a9-847b-b7e54597aa83@gmail.com> Date: Wed, 26 Aug 2026 20:04:15 -0500 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird From: dbryan.green@gmail.com To: pgsql-hackers@lists.postgresql.org Subject: Re: COPY FROM with RLS References: <70d4ee07.f25.19f161ce6b2.Coremail.jiezhilove@126.com> <1266b6dc.6689.19fa801caa0.Coremail.jiezhilove@126.com> In-Reply-To: <1266b6dc.6689.19fa801caa0.Coremail.jiezhilove@126.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On 7/28/26 4:15 AM, Yilin Zhang wrote: > At 2026-07-13 16:13:58, "jian he" wrote: > > Hi. > > While v2 has extensive failure test cases, it doesn't have a single > > successful test case, > > that's why this issue wasn't found. > > The 2 issues you reported are fixed in the attached v3. > > > > Also, previously in v2: > > +COPY r1 FROM STDIN WITH (DELIMITER ','); -- fail > > +ERROR: new row violates row-level security policy "p2" for table "r1" > > +CONTEXT: COPY r1, line 1: "4" > > > > it's better to remove the CONTEXT line. > > because ExecWithCheckOptions has comments like: > > /* > > * For WITH CHECK OPTIONs coming from views, we might be > > * able to provide the details on the row, depending on > > * the permissions on the relation (that is, if the user > > * could view it directly anyway). For RLS violations, we > > * don't include the data since we don't know if the user > > * should be able to view the tuple as that depends on the > > * USING policy. > > */ > > > > Hi, > I have reviewed the latest version of the patch, LGTM. > > > Best regards, > > -- > > Yilin Zhang > The RLS enforcement in v3 looks right. The WITH CHECK runs in the per-row path for both the single and batched inserts, and row_security=off against a forced policy errors the way INSERT does. The patch has two other problems: it can crash the backend, and it changes how COPY treats rules. CopyFrom pushes the error-context callback under a guard and pops it without one. In master both are unconditional. The patch wraps the push at copyfrom.c:1211 in "if (queryDesc == NULL)" but leaves the pop at 1574, "error_context_stack = errcallback.previous". On the RLS path queryDesc is set, so errcallback is never initialized, and the pop stores a garbage stack value into error_context_stack. The next ereport in CopyFrom walks it. COPY with ON_ERROR ignore and one bad row gets there through the "rows skipped" NOTICE at 1580: CREATE ROLE alice LOGIN; CREATE TABLE t (id int, v text); ALTER TABLE t ENABLE ROW LEVEL SECURITY; CREATE POLICY p ON t USING (true) WITH CHECK (true); GRANT INSERT ON t TO alice; -- as alice, with a file whose second line has a non-integer id: COPY t FROM '...' WITH (ON_ERROR ignore); That crashes a non-assert backend and takes the cluster into recovery, so any role with INSERT on the table its policy applies to can crash the server. The same guard also drops the line-number context for every error on an RLS table, not just policy violations. Registering the callback unconditionally and scoping relname_only to the ExecWithCheckOptions call balances the push and pop and limits the suppression to the policy violation. Separately, getting the WITH CHECK expressions from a full rewrite of a dummy INSERT runs the target's ON INSERT rules on the RLS path, so the same COPY behaves differently depending on whether the table has RLS enabled: COPY into non-RLS table COPY into RLS table DO ALSO loads target, rule ignored ERROR (unsupported) DO INSTEAD (uncond.) loads the named table loads the redirect target DO INSTEAD (cond.) loads target, rule ignored ERROR (unsupported) The length check rejects the rewrites that fan out past one query, but a single unconditional DO INSTEAD passes it, so COPY into an RLS table lands the rows in the rule's redirect target rather than the named table. The remaining point is cosmetic. The query_string is only sourceText, but it is built with raw %s and no quote-doubling, so it is malformed for a name like foo"bar. quote_qualified_identifier() would build it correctly. bg