Re: Allow non-superuser to cancel superuser tasks.

Nathan Bossart <nathandbossart@gmail.com>

From: Nathan Bossart <nathandbossart@gmail.com>
To: "Leung, Anthony" <antholeu@amazon.com>
Cc: "Andrey M. Borodin" <x4mmm@yandex-team.ru>, Kirill Reshke <reshkekirill@gmail.com>, "pgsql-hackers@postgresql.org" <pgsql-hackers@postgresql.org>
Date: 2024-04-04T18:15:33Z
Lists: pgsql-hackers
On Thu, Apr 04, 2024 at 12:30:51AM +0000, Leung, Anthony wrote:
>>	if (pg_stat_is_backend_autovac_worker(proc->backendId) &&
>>	    !has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_AUTOVACUUM))
>>	    return SIGNAL_BACKEND_NOAUTOVACUUM;
> 
> I tried to add them above the existing code. When I test it locally, a
> user without pg_signal_autovacuum will actually fail at this block
> because the user is not superuser and !OidIsValid(proc->roleId) is also
> true in the following:

Good catch.

> This is what Im planning to do - If the backend is autovacuum worker and
> the user is not superuser or has pg_signal_autovacuum role, we return the
> new value and provide the relevant error message
> 
>               /*
> 	 * If the backend is autovacuum worker, allow user with privileges of the 
>                * pg_signal_autovacuum role to signal the backend.
> 	 */
> 	if (pgstat_get_backend_type(proc->backendId) == B_AUTOVAC_WORKER)
> 	{
> 		if (!has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_AUTOVACUUM) || !superuser())
> 			return SIGNAL_BACKEND_NOAUTOVACUUM;
> 	}
> 	/*
> 	 * Only allow superusers to signal superuser-owned backends.  Any process
> 	 * not advertising a role might have the importance of a superuser-owned
> 	 * backend, so treat it that way.
> 	*/
> 	else if ((!OidIsValid(proc->roleId) || superuser_arg(proc->roleId)) &&
> 			 !superuser())
> 	{
> 		return SIGNAL_BACKEND_NOSUPERUSER;
> 	}
> 	/* Users can signal backends they have role membership in. */
> 	else if (!has_privs_of_role(GetUserId(), proc->roleId) &&
> 			 !has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_BACKEND))
> 	{
> 		return SIGNAL_BACKEND_NOPERMISSION;
> 	}

There's no need for the explicit superuser() check in the
pg_signal_autovacuum section.  That's built into has_privs_of_role()
already.

-- 
Nathan Bossart
Amazon Web Services: https://aws.amazon.com



Commits

  1. Look up backend type in pg_signal_backend() more cheaply.

  2. Add tap test for pg_signal_autovacuum role

  3. Introduce pg_signal_autovacuum_worker.

  4. Add a slot synchronization function.

  5. Ban role pg_signal_backend from more superuser backend types.