Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1p334e-0002xM-UY for pgsql-hackers@arkaria.postgresql.org; Wed, 07 Dec 2022 22:39:32 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1p334d-0004Zl-24 for pgsql-hackers@arkaria.postgresql.org; Wed, 07 Dec 2022 22:39:31 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1p334c-0004Zc-NM for pgsql-hackers@lists.postgresql.org; Wed, 07 Dec 2022 22:39:30 +0000 Received: from mail-pj1-x1032.google.com ([2607:f8b0:4864:20::1032]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1p334a-0006Pc-86 for pgsql-hackers@postgresql.org; Wed, 07 Dec 2022 22:39:29 +0000 Received: by mail-pj1-x1032.google.com with SMTP id w4-20020a17090ac98400b002186f5d7a4cso2837947pjt.0 for ; Wed, 07 Dec 2022 14:39:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-disposition:mime-version:message-id:subject:to:from:date :from:to:cc:subject:date:message-id:reply-to; bh=p+4+3BWY1imYVTa9Gq2hst04EGPjvYmx3lrp6x2hjSk=; b=MhrWbsO8+VJAH0DgFwhKuNLUp0zFAGNs2mD1kdYq4QsS1BWe9j22UynEP/mlj2hbQt Ej7/Vc8tU0wBGWvHN5gOTfxToCbd+o19LMbzcvUS81W8JNCyh2mFwlM5JFrpqj5l5FBB tI5scepMfH8mQSXVEVZiajXHfF/YYs0G56JUgt2QOttUVOcQ95NRZUezC/4bNisRbmvm h90g85LyKvFWeXznsXWoRb7VEngl1PCbiKbkePoUBhNH1YKlA++r2II9W014MRHcnAbp k2B4Q7vwlAWmZVd/IZS2wCuTLDqnZYJ6qrQsncUYqYkLXv0vDM2h8zFcuX+4yeLzpyyp 3rNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-disposition:mime-version:message-id:subject:to:from:date :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=p+4+3BWY1imYVTa9Gq2hst04EGPjvYmx3lrp6x2hjSk=; b=WDnpFrB1JCwECxqglBRv7k5HufIIKQMugVbuqpu+cIFCsxHXazeodLG+fEojJgHAou yrlTv9XcD/p4Psj4SaColdxdRjzocMxEH2cC6NWUgWvodenGvZ747bwfS6McKMuBkUl/ iWKgcXsmSHgAyakRk/Vst7LJCaWHTAGH6+GTbkntMkegEJcgFsAc6iXt9PF/J+OV02F/ 3hhilmIQlD+TxoHyV+SnCjFDPh/ssnqe8lps8bnWMVSLXqPryRPOwkMGH9H5h0AbLsrB jORsDRURRThTw3B+TSUS8o3DFftSEbi7Gxz6y8eotYzy9VgWeoGQ1FtCpyy5WK0qfMbz t1fg== X-Gm-Message-State: ANoB5plFvarB46bB0qpO6KwZBuJpiY/tGihP+fNKkxVkMDPT7K37IVHj CIqbsMCD+8hFjZ/zNKoBDvsQwqdShbE= X-Google-Smtp-Source: AA0mqf7JIzOUYpab3EoB1V63AKjQszaOKqQktPIanUQfWYdz2amg93N5i49pB2gwM47brRtqboXa1g== X-Received: by 2002:a17:90a:fb89:b0:218:ec4a:782e with SMTP id cp9-20020a17090afb8900b00218ec4a782emr72412034pjb.7.1670452766671; Wed, 07 Dec 2022 14:39:26 -0800 (PST) Received: from nathanxps13 ([50.47.162.83]) by smtp.gmail.com with ESMTPSA id f13-20020a170902f38d00b001868bf6a7b8sm15048980ple.146.2022.12.07.14.39.25 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Dec 2022 14:39:25 -0800 (PST) Date: Wed, 7 Dec 2022 14:39:24 -0800 From: Nathan Bossart To: pgsql-hackers@postgresql.org Subject: fix and document CLUSTER privileges Message-ID: <20221207223924.GA4182184@nathanxps13> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="mYCpIKhGyMATD0i+" Content-Disposition: inline List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --mYCpIKhGyMATD0i+ Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi hackers, While looking into other opportunities for per-table permissions, I noticed a weird discrepancy in CLUSTER. When evaluating whether the current user has permission to CLUSTER a table, we ordinarily just check for ownership. However, the database owner is also allowed to CLUSTER all partitions that are not shared. This was added in 3f19e17, and I didn't see any discussion about it in the corresponding thread [0]. My first instinct is that we should just remove the database ownership check, which is what I've done in the attached patch. I don't see any strong reason to complicate matters with special database-owner-but-not-shared checks like other commands (e.g., VACUUM). But perhaps we should do so just for consistency's sake. Thoughts? It was also noted elsewhere [1] that the privilege requirements for CLUSTER are not documented. The attached patch adds such documentation. [0] https://postgr.es/m/20220411140609.GF26620%40telsasoft.com [1] https://postgr.es/m/661148f4-c7f1-dec1-2bc8-29f3bd58e242%40postgrespro.ru -- Nathan Bossart Amazon Web Services: https://aws.amazon.com --mYCpIKhGyMATD0i+ Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="fix_cluster_privs.patch" diff --git a/doc/src/sgml/ref/cluster.sgml b/doc/src/sgml/ref/cluster.sgml index c37f4236f1..feb61e6ec2 100644 --- a/doc/src/sgml/ref/cluster.sgml +++ b/doc/src/sgml/ref/cluster.sgml @@ -67,7 +67,8 @@ CLUSTER [VERBOSE] - CLUSTER without any parameter reclusters all the + CLUSTER without a + table_name reclusters all the previously-clustered tables in the current database that the calling user owns, or all such tables if called by a superuser. This form of CLUSTER cannot be executed inside a transaction @@ -132,6 +133,13 @@ CLUSTER [VERBOSE] Notes + + To cluster a table, one must be the table's owner or a superuser. + Database-wide clusters and clusters on partitioned tables will silently + skip over any tables that the calling user does not have permission to + cluster. + + In cases where you are accessing single rows randomly within a table, the actual order of the data in the diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index 07e091bb87..a8a51cc674 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -1693,9 +1693,7 @@ get_tables_to_cluster_partitioned(MemoryContext cluster_context, Oid indexOid) continue; /* Silently skip partitions which the user has no access to. */ - if (!object_ownercheck(RelationRelationId, relid, GetUserId()) && - (!object_ownercheck(DatabaseRelationId, MyDatabaseId, GetUserId()) || - IsSharedRelation(relid))) + if (!object_ownercheck(RelationRelationId, relid, GetUserId())) continue; /* Use a permanent memory context for the result list */ --mYCpIKhGyMATD0i+--