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 1wcVb7-003POJ-0n for pgsql-bugs@arkaria.postgresql.org; Wed, 24 Jun 2026 21:57:29 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wcVb6-002jD3-0Q for pgsql-bugs@arkaria.postgresql.org; Wed, 24 Jun 2026 21:57:28 +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 1wcVb5-002jCu-2n for pgsql-bugs@lists.postgresql.org; Wed, 24 Jun 2026 21:57:27 +0000 Received: from mail-qv1-xf33.google.com ([2607:f8b0:4864:20::f33]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wcVb3-000000005Um-0hrX for pgsql-bugs@lists.postgresql.org; Wed, 24 Jun 2026 21:57:26 +0000 Received: by mail-qv1-xf33.google.com with SMTP id 6a1803df08f44-8dc87f7d68bso17210256d6.3 for ; Wed, 24 Jun 2026 14:57:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1782338244; cv=none; d=google.com; s=arc-20240605; b=ZG2sPfgiek6JTAdcSWuEszAiVIVhYGIe/gEVcJ3sEvf/romhsqsm01l/HzHsElKusO /6wUsmHdOnJvxZw5WUBhon+wJqOdJHOBouF+MzRmVqgAaVGp3PoNZJCJHQpEp390Vh4Q ApvDbXaQRlarLdIvHxW6fIPFZO1lTKk8zLqSZA1w1/3Pw19qmmaQSdAJuh32Vrf+5LJm eDRRZyXBoQ2f45/V9WwGW6cvzvY2N7ZPsNnuto0susi1TDyW1ed3ZtxNHN/CMrFKqnB6 w1vKZ3AABzN8TxnAbfYMHBREgT9gRwHlW40GQazbBpP5KpInG3MQ+rv9UqRJo6i89f5x jZig== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=to:subject:message-id:date:from:mime-version:dkim-signature; bh=+cbDZGI7ZpaYfznyHbpvYfsB+RL8XKVHWKZX5RecnMU=; fh=/gQe77b11iMZdcPj/nJr/Ghqi6rQp5FPrPbdO93bmOA=; b=OffA/K5gGjlIcgjJgnHCYWZpILuwEteoNH6Fgz6dozenLn4mebiJa6jsugg7tJNaux 5xu5OtKKsdLfK+Be2culrivKVAyMbu2O2/zis8xWocrR8uit0FnTECaFh0FPA3/91HTX gxqgRe2rSLuFriVLwU9TD/wiI+XupaFv3+oOrs3k24wuHgeqgLr2UVIPa8F5N6m7Xljs 8FZwAQnzL1JRmjXMlFqJvqj/kGU8cdRUXe4mpELwAwchGdm4AsyZimyt27C0heHfSVLZ p0jTOZetcLXhSvTyVB6l4kYIYDaoEYLW5X6g1MPDGTKbODKFRspJcl0W4aCM2nJu70sD axOg==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enterprisedb.com; s=google; t=1782338244; x=1782943044; darn=lists.postgresql.org; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=+cbDZGI7ZpaYfznyHbpvYfsB+RL8XKVHWKZX5RecnMU=; b=XWoLs7pip28ojioyVh10pKMg+kzQk0I9KPqfDbIIGA9ajqXbR7am5KgpN5K+q3BZhm wIHJo9QeBmAbIam09oA01jhRN2I1pSjbovaSlDDdtod8r79cNDk7RGXbMeRMm1FKaT53 pK5XDtKq7WaBYVUmq0dVvSx5a2C0c6n7W4SmxBZkTdDH1cCLsq6R5wFhFmvgB5Pc/Oet 8NaQZ6bLT9IVQi0HgZxqfEe+rNG9tzbqSTKZJSnRcLtuldwSlYi/9ROssJGZZfOjFr0X K0OoktAmDTJ93s5YkG2Z3aZULK/Yav+g4uDJvpJE4oUwC0BGfhJdDnmIIMjyT5clBTCl X/iQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1782338244; x=1782943044; h=to:subject:message-id:date:from:mime-version:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=+cbDZGI7ZpaYfznyHbpvYfsB+RL8XKVHWKZX5RecnMU=; b=JelKQb/73gJzBro09hsmLN+Czxnb2X6FSCdydquX5xolwzHS+wQS1kR8leP+C2XsZ3 pIKG8+ktideixQ7SGc2FYj+Q4anyhmu0ypC27ss8wrppgxvvbbEe7fKWJh8/HuF4dmES S9QDsSgciImZCg01YW5aRnreTwZ4FMjq5NQ4P0u7PH6MUrOskK15TJgD1gNpNeQBkHRj 4UVax+j/M4lGbyusaEuRN86FpE5PBvl5Y0kdwICMNvaozr1g/7eBfFdkuHUAAEuOFAWp t/JtciHY4KSwdKpuHNQRaFxcfGc0kP/NAFAlXy1iv8kMUcLPH3tX2U2sPrqha99TxkmF 51Pg== X-Gm-Message-State: AOJu0YxdlbF3VzqJnk7nFnKaZW4qBEnnuz4UxhEfzgp1d4DreqidnVzA o4EqjbRzAszeNYxito8ZhO/Sp2RxdyHCNnfRbM+omm5Nh5ftnhWtMNymtOwNYRLHY5xrgX2dsjX GzmMcJpGCb8rRo3ye06EF9cj5QwFaBYPgdNsqcOhgiUb/HjYd5lCD0ctZ X-Gm-Gg: AfdE7cnHm4N+s5s8Ryej8p0mqKjw3KMan4THVzxcBHCnqhjam/SAe1V98/LPoia5pZY 6twom6lwjD9dDL0k66MToH9cjmjHrkPo7DSSnzth0wISSQmZIQlPWXZ7gjKY0yCWSd6edsXC1Ni Danp67SP46H1bCElb8Ts7FV0X8EgVe83iC1EhmU+U6jcV1aXtBywA4hr7AlxVDk33FqcY7fHx+B O9ZXWwEKAVcuNdJ+0sP4dVSaudSPD7IOGE49S8vWtkbqlpSXJkYR2Uvfq0eMtqbZl39nnOuGhw= X-Received: by 2002:a05:6214:3988:b0:8dc:2c21:32bd with SMTP id 6a1803df08f44-8e6ce8f6544mr1445216d6.1.1782338244162; Wed, 24 Jun 2026 14:57:24 -0700 (PDT) MIME-Version: 1.0 From: Jacob Champion Date: Wed, 24 Jun 2026 14:57:13 -0700 X-Gm-Features: AVVi8Cfje6g-w8xhisbv7eCRZykbJLNd73BxwKNFBl1Er340vU6L25mr6VYa_vg Message-ID: Subject: REVOKE's CASCADE protection doesn't work with INHERITed table owners To: pgsql-bugs@lists.postgresql.org Content-Type: text/plain; charset="UTF-8" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Hi all, I'm pretty sure the following is unintended behavior. It looks potentially related to [1] as well. TL;DR: The protection in recursive_revoke() against broken GRANT OPTION chains doesn't seem to work properly when the grantee also holds the privileges of the grantor. = Setup = With the following (contrived, minimized from the actual) setup: -- Set up a role hierarchy (as superuser "jacob") CREATE ROLE admins; CREATE ROLE bob; GRANT admins TO bob; -- Create two tables with different ownership CREATE TABLE my_table(i int); CREATE TABLE admin_table(i int); ALTER TABLE admin_table OWNER TO admins; -- Create a grant option chain on both tables GRANT ALL ON TABLE my_table TO bob WITH GRANT OPTION; GRANT ALL ON TABLE admin_table TO bob WITH GRANT OPTION; SET ROLE bob; GRANT ALL ON TABLE my_table TO bob; GRANT ALL ON TABLE admin_table TO bob; RESET ROLE; Now we have the following ACLs: =# SELECT relname, relowner::regrole, relacl FROM pg_class WHERE relname LIKE '%_table'; -[ RECORD 1 ]------------------------------------------------------------------- relname | my_table relowner | jacob relacl | {jacob=arwdDxtm/jacob,bob=a*r*w*d*D*x*t*m*/jacob,bob=arwdDxtm/bob} -[ RECORD 2 ]------------------------------------------------------------------- relname | admin_table relowner | admins relacl | {admins=arwdDxtm/admins,bob=a*r*w*d*D*x*t*m*/admins,bob=arwdDxtm/bob} = Bug = With that grant option chain, we try to prevent REVOKE [RESTRICT] invocations that would cause problems: =# REVOKE ALL ON TABLE my_table FROM bob; ERROR: dependent privileges exist HINT: Use CASCADE to revoke them too. But this protection doesn't work for the admin_table... =# REVOKE ALL ON TABLE admin_table FROM bob; REVOKE ...resulting in an orphaned ACL. -[ RECORD 2 ]---------------------------------------------------------------- relname | admin_table relowner | admins relacl | {admins=arwdDxtm/admins,bob=arwdDxtm/bob} Dump/restores of this situation result in complaints, since user "bob" isn't able to recreate the grant. I think the issue is in recursive_revoke()'s usage of aclmask(), which in turn uses has_privs_of_role(). It doesn't seem like that's what was wanted in this particular case... thoughts? Thanks, --Jacob [1] https://postgr.es/m/CAM6Zo8wD7RtQNhbQHODc9DobiW+GpT=tnqOSMz4+mnzA9m0zMg@mail.gmail.com