public inbox for [email protected]
help / color / mirror / Atom feedFrom: Alexander Korotkov <[email protected]>
To: Soumya S Murali <[email protected]>
Cc: Jim Jones <[email protected]>
Cc: Daniil Davydov <[email protected]>
Cc: Tom Lane <[email protected]>
Cc: Stepan Neretin <[email protected]>
Cc: PostgreSQL Hackers <[email protected]>
Subject: Re: Fix bug with accessing to temporary tables of other sessions
Date: Tue, 21 Apr 2026 13:54:47 +0300
Message-ID: <CAPpHfdvLCgXgdhSvuPCkek+r=P4E-WiNceWfh7UQztiMzfFcvg@mail.gmail.com> (raw)
In-Reply-To: <CAMtXxw8J7L0r8aXt9NBFfqqSnaNyU=-_Uq4tW4aO3PHyVeXLAQ@mail.gmail.com>
References: <CAJDiXghdFcZ8=nh4G69te7iRr3Q0uFyXxb3ZdG09_GTNZXwH0g@mail.gmail.com>
<CAMtXxw_ta_9i=uPJMvGueOBc04crmraJXcyJhN0K=Wu9aa2rog@mail.gmail.com>
<[email protected]>
<[email protected]>
<CAJDiXgh9g4TEyF3kWCiBgHX6QbpATZtxTfrQuBCKxUO5=nZBOw@mail.gmail.com>
<[email protected]>
<CAJDiXgihovkP6DMAFyJtYF4JSAjvKmiRVbF5R5n3SA=Yag32_w@mail.gmail.com>
<CAMtXxw8pHLH9+mG3wxsF8f=Y+pHqTNP8X1UmZQPkRL9pZ5aF2w@mail.gmail.com>
<[email protected]>
<[email protected]>
<CAJDiXgiAObr4c+PTWSS19vcohrFSDLK3MC5FK3TekMB3U3DjfQ@mail.gmail.com>
<[email protected]>
<CAJDiXghBO_TqvHOSui8MOxiFmwLT20+SAnH5nW1rpWHk7Jwffg@mail.gmail.com>
<[email protected]>
<CAJDiXgi0JFk0f2KWWQkzLBC5P7erX9WP18qqnbi-rjZ-K-P=3w@mail.gmail.com>
<CAMtXxw_hBNuAWQUdSRMpoeRVRYr+5+S7p0bSzuqtHxfpzJPd3w@mail.gmail.com>
<[email protected]>
<CAMtXxw_2VnP5U7U+2ObOCC2voEkAzUqAgH=rPTQBXrb_8K=pyA@mail.gmail.com>
<CAPpHfdtsGSywUExfKMakAuRz8-+61d-4XHkVf=pNQeYTZTVYoA@mail.gmail.com>
<CAMtXxw8J7L0r8aXt9NBFfqqSnaNyU=-_Uq4tW4aO3PHyVeXLAQ@mail.gmail.com>
On Tue, Apr 21, 2026 at 8:44 AM Soumya S Murali
<[email protected]> wrote:
> Thank you for reviewing the patch and for the detailed explanation.
>
> On Tue, Apr 21, 2026 at 1:37 AM Alexander Korotkov <[email protected]> wrote:
> >
> > Hi!
> >
> > I've checked the thread. Thanks to all the participants for their
> > work. I think there is a general agreement on the design.
> >
> > On Thu, Apr 16, 2026 at 9:41 AM Soumya S Murali
> > <[email protected]> wrote:
> > > Thank you for the guidance and the updated patch.
> > >
> > > On Mon, Apr 13, 2026 at 7:26 PM Jim Jones <[email protected]> wrote:
> > > >
> > > > Hi
> > > >
> > > > On 13/04/2026 14:40, Soumya S Murali wrote:
> > > > > Please let me know if there are additional scenarios I should
> > > > > validate. Looking forward to more feedback.
> > > >
> > > > Thanks for testing it. You can take a look at
> > > > 012_temp_obj_multisession.pl and check if we missed any path.
> > > >
> > > > Due to changes introduced in b2a17ba7a5d the patch was no longer
> > > > applying. See rebased v18 attached.
> > > >
> > >
> > >
> > > I tested the rebased v18 patch on a clean tree and verified that it
> > > applies cleanly and behaves consistently with previous results.
> > > Cross-session access is correctly blocked with: ERROR: cannot access
> > > temporary relations of other sessions
> > > Index scan paths are also properly restricted, and same-session access
> > > continues to work as expected.
> > > The updated test changes look good. Everything works as expected, +1
> > > from my side.
> >
> > I see the patch changes the error wording. Previously the error was
> > "cannot access temporary tables of other sessions", but we change it
> > to "cannot access temporary relation of other sessions". I see the
> > intention here: we trigger an error while accessing some relation (not
> > necessarily a table) then we should reflect this directly to the error
> > message. However, old message is already here for quite a while and
> > translated into many languages. Also, is old message incorrect? We
> > trigger an error on buffer access. That is, we trigger an error only
> > for relation with a storage: table, index, sequence or matview.
> > Matview can't be temporary. Also, if you access an index with a
> > query, that means you're querying its table. But sequence can be
> > temporary and it can be not directly associated with a table. So,
> > yes, new error message is more correct. But I would prefer to make it
> > a separate patch, and replace all the occurrences including contrib.
> >
>
>
> This makes sense. While the new wording is indeed more precise, I
> agree that changing an existing error message, especially one that has
> been present for a long time and is already translated, should be
> handled
> separately from the bug fix. Keeping the current message for this
> patch and addressing wording improvements in a dedicated follow-up
> patch sounds like the right approach.
> Thanks for pointing this out.
OK. I'm going to push and backpatch if no objections.
------
Regards,
Alexander Korotkov
Supabase
Attachments:
[application/octet-stream] v19-0001-Prevent-access-to-other-sessions-temp-tables.patch (7.9K, 2-v19-0001-Prevent-access-to-other-sessions-temp-tables.patch)
download | inline diff:
From d5395013b151ce8494e4f2086f4f87f0d04a6a0d Mon Sep 17 00:00:00 2001
From: Alexander Korotkov <[email protected]>
Date: Tue, 21 Apr 2026 13:17:32 +0300
Subject: [PATCH v19] Prevent access to other sessions' temp tables
Commit b7b0f3f2724 ("Use streaming I/O in sequential scans") routed
sequential scans through read_stream_next_buffer(), bypassing the
RELATION_IS_OTHER_TEMP() check in ReadBufferExtended(). As a result,
a superuser can attempt to access temp tables of other sessions, even
though the buffer manager is incapable of dealing with them correctly.
Fix by adding the same check at two additional points:
- read_stream_begin_impl() covers sequential and bitmap scans that
go through the read-stream path.
- StartReadBuffersImpl() and ReadBuffer_common() cover index scans
and any remaining direct buffer accesses.
Also add a TAP test in src/test/modules/test_misc exercising access to
another session's temp table.
Author: Jim Jones <[email protected]>
Discussion: https://postgr.es/m/CAJDiXghdFcZ8%3Dnh4G69te7iRr3Q0uFyXxb3ZdG09_GTNZXwH0g%40mail.gmail.com
Author: Daniil Davydov <[email protected]>
Co-authored-by: Jim Jones <[email protected]>
Reviewed-by: Soumya S Murali <[email protected]>
Reviewed-by: Tom Lane <[email protected]>
Reviewed-by: Alexander Korotkov <[email protected]>
Backpatch-through: 17
---
src/backend/storage/aio/read_stream.c | 10 ++
src/backend/storage/buffer/bufmgr.c | 12 ++
src/test/modules/test_misc/meson.build | 1 +
.../test_misc/t/012_temp_obj_multisession.pl | 117 ++++++++++++++++++
4 files changed, 140 insertions(+)
create mode 100644 src/test/modules/test_misc/t/012_temp_obj_multisession.pl
diff --git a/src/backend/storage/aio/read_stream.c b/src/backend/storage/aio/read_stream.c
index 2374b4cd507..a318539e56c 100644
--- a/src/backend/storage/aio/read_stream.c
+++ b/src/backend/storage/aio/read_stream.c
@@ -776,6 +776,16 @@ read_stream_begin_impl(int flags,
uint32 max_possible_buffer_limit;
Oid tablespace_id;
+ /*
+ * Reject attempts to read non-local temporary relations; we would be
+ * likely to get wrong data since we have no visibility into the owning
+ * session's local buffers.
+ */
+ if (rel && RELATION_IS_OTHER_TEMP(rel))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot access temporary tables of other sessions")));
+
/*
* Decide how many I/Os we will allow to run at the same time. This
* number also affects how far we look ahead for opportunities to start
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 3cc0b0bdd92..676d8000e1e 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -1292,6 +1292,12 @@ ReadBuffer_common(Relation rel, SMgrRelation smgr, char smgr_persistence,
int flags;
char persistence;
+ /* see comments in ReadBufferExtended */
+ if (rel && RELATION_IS_OTHER_TEMP(rel))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot access temporary tables of other sessions")));
+
/*
* Backward compatibility path, most code should use ExtendBufferedRel()
* instead, as acquiring the extension lock inside ExtendBufferedRel()
@@ -1382,6 +1388,12 @@ StartReadBuffersImpl(ReadBuffersOperation *operation,
Assert(*nblocks > 0);
Assert(*nblocks <= MAX_IO_COMBINE_LIMIT);
+ /* see comments in ReadBufferExtended */
+ if (operation->rel && RELATION_IS_OTHER_TEMP(operation->rel))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot access temporary tables of other sessions")));
+
if (operation->persistence == RELPERSISTENCE_TEMP)
{
io_context = IOCONTEXT_NORMAL;
diff --git a/src/test/modules/test_misc/meson.build b/src/test/modules/test_misc/meson.build
index 1b25d98f7f3..a54599cc301 100644
--- a/src/test/modules/test_misc/meson.build
+++ b/src/test/modules/test_misc/meson.build
@@ -20,6 +20,7 @@ tests += {
't/009_log_temp_files.pl',
't/010_index_concurrently_upsert.pl',
't/011_lock_stats.pl',
+ 't/012_temp_obj_multisession.pl',
],
# The injection points are cluster-wide, so disable installcheck
'runningcheck': false,
diff --git a/src/test/modules/test_misc/t/012_temp_obj_multisession.pl b/src/test/modules/test_misc/t/012_temp_obj_multisession.pl
new file mode 100644
index 00000000000..43cfe625738
--- /dev/null
+++ b/src/test/modules/test_misc/t/012_temp_obj_multisession.pl
@@ -0,0 +1,117 @@
+# Copyright (c) 2026, PostgreSQL Global Development Group
+
+# Verify that one session cannot access another session's temporary table.
+#
+# A session creates a temporary table and a separate session attempts to
+# read and modify it through various code paths: SELECT, UPDATE, DELETE,
+# TRUNCATE, INSERT, COPY, and an index scan. Each attempt is expected to
+# fail with "cannot access temporary tables of other sessions" (or the
+# analogous TRUNCATE error).
+
+use strict;
+use warnings;
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use PostgreSQL::Test::BackgroundPsql;
+use Test::More;
+
+# Set up a fresh node
+my $node = PostgreSQL::Test::Cluster->new('temp_lock');
+$node->init;
+$node->start;
+
+# Create a long-lived session
+my $psql1 = $node->background_psql('postgres');
+
+$psql1->query_safe(q(CREATE TEMP TABLE foo AS SELECT 42 AS val;));
+
+$psql1->query_safe(q(CREATE INDEX ON foo(val);));
+
+my $tempschema = $node->safe_psql(
+ 'postgres',
+ q{
+ SELECT n.nspname
+ FROM pg_class c
+ JOIN pg_namespace n ON n.oid = c.relnamespace
+ WHERE relname = 'foo' AND relpersistence = 't';
+ }
+);
+chomp $tempschema;
+ok($tempschema =~ /^pg_temp_\d+$/, "got temp schema: $tempschema");
+
+
+# SELECT TEMPORARY TABLE from other session
+my ($stdout, $stderr);
+$node->psql(
+ 'postgres',
+ "SELECT val FROM $tempschema.foo;",
+ stdout => \$stdout,
+ stderr => \$stderr);
+like(
+ $stderr,
+ qr/cannot access temporary tables of other sessions/,
+ 'SELECT on other session temp table is not allowed');
+
+# UPDATE TEMPORARY TABLE from other session
+$node->psql(
+ 'postgres',
+ "UPDATE $tempschema.foo SET val = NULL;",
+ stderr => \$stderr);
+like(
+ $stderr,
+ qr/cannot access temporary tables of other sessions/,
+ 'UPDATE on other session temp table is not allowed');
+
+# DELETE records from TEMPORARY TABLE from other session
+$node->psql('postgres', "DELETE FROM $tempschema.foo;", stderr => \$stderr);
+like(
+ $stderr,
+ qr/cannot access temporary tables of other sessions/,
+ 'DELETE on other session temp table is not allowed');
+
+# TRUNCATE TEMPORARY TABLE from other session
+$node->psql('postgres', "TRUNCATE TABLE $tempschema.foo;",
+ stderr => \$stderr);
+like(
+ $stderr,
+ qr/cannot truncate temporary tables of other sessions/,
+ 'TRUNCATE on other session temp table is not allowed');
+
+# INSERT INTO TEMPORARY TABLE from other session
+$node->psql(
+ 'postgres',
+ "INSERT INTO $tempschema.foo VALUES (73);",
+ stderr => \$stderr);
+like(
+ $stderr,
+ qr/cannot access temporary tables of other sessions/,
+ 'INSERT INTO on other session temp table is not allowed');
+
+# COPY TEMPORARY TABLE from other session
+$node->psql('postgres', "COPY $tempschema.foo TO STDOUT;",
+ stderr => \$stderr);
+like(
+ $stderr,
+ qr/cannot access temporary tables of other sessions/,
+ 'COPY on other session temp table is blocked');
+
+# Index scans can use a different code path from the one sequential scans are
+# following. Make sure that we cannot access other sessions' temp tables during
+# index scan either.
+$node->psql(
+ 'postgres',
+ "SET enable_seqscan = off; SELECT val FROM $tempschema.foo WHERE val = 42;",
+ stderr => \$stderr);
+like(
+ $stderr,
+ qr/cannot access temporary tables of other sessions/,
+ 'index scan on other session temp table is not allowed (exercises ReadBufferExtended path)'
+);
+
+# DROP TEMPORARY TABLE from other session
+$node->safe_psql('postgres', "DROP TABLE $tempschema.foo;");
+
+# Clean up
+$psql1->quit;
+
+done_testing();
--
2.39.5 (Apple Git-154)
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
Subject: Re: Fix bug with accessing to temporary tables of other sessions
In-Reply-To: <CAPpHfdvLCgXgdhSvuPCkek+r=P4E-WiNceWfh7UQztiMzfFcvg@mail.gmail.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox