mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Fix documentation about DROP DATABASE FORCE process termination rights.
Specifically, it terminates a background worker even if the caller
couldn't terminate the background worker with pg_terminate_backend().
Commit 3a9b18b309 neglected to update
this.  Back-patch to v13, which introduced DROP DATABASE FORCE.
Reviewed by Amit Kapila.  Reported by Kirill Reshke.
Discussion: https://postgr.es/m/20240429212756.60.nmisch@google.com
			
			
This commit is contained in:
		@@ -79,12 +79,14 @@ DROP DATABASE [ IF EXISTS ] <replaceable class="parameter">name</replaceable> [
 | 
				
			|||||||
      It doesn't terminate if prepared transactions, active logical replication
 | 
					      It doesn't terminate if prepared transactions, active logical replication
 | 
				
			||||||
      slots or subscriptions are present in the target database.
 | 
					      slots or subscriptions are present in the target database.
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
 | 
					     <!-- not mentioning exception for autovacuum workers, since those are an
 | 
				
			||||||
 | 
					     implementation detail and the exception is not specific to FORCE -->
 | 
				
			||||||
     <para>
 | 
					     <para>
 | 
				
			||||||
      This will fail if the current user has no permissions to terminate other
 | 
					      This terminates background worker connections and connections that the
 | 
				
			||||||
      connections. Required permissions are the same as with
 | 
					      current user has permission to terminate
 | 
				
			||||||
      <literal>pg_terminate_backend</literal>, described in
 | 
					      with <function>pg_terminate_backend</function>, described in
 | 
				
			||||||
      <xref linkend="functions-admin-signal"/>.  This will also fail if we
 | 
					      <xref linkend="functions-admin-signal"/>.  If connections would remain,
 | 
				
			||||||
      are not able to terminate connections.
 | 
					      this command will fail.
 | 
				
			||||||
     </para>
 | 
					     </para>
 | 
				
			||||||
    </listitem>
 | 
					    </listitem>
 | 
				
			||||||
   </varlistentry>
 | 
					   </varlistentry>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3808,8 +3808,8 @@ CountOtherDBBackends(Oid databaseId, int *nbackends, int *nprepared)
 | 
				
			|||||||
 * The current backend is always ignored; it is caller's responsibility to
 | 
					 * The current backend is always ignored; it is caller's responsibility to
 | 
				
			||||||
 * check whether the current backend uses the given DB, if it's important.
 | 
					 * check whether the current backend uses the given DB, if it's important.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * It doesn't allow to terminate the connections even if there is a one
 | 
					 * If the target database has a prepared transaction or permissions checks
 | 
				
			||||||
 * backend with the prepared transaction in the target database.
 | 
					 * fail for a connection, this fails without terminating anything.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
TerminateOtherDBBackends(Oid databaseId)
 | 
					TerminateOtherDBBackends(Oid databaseId)
 | 
				
			||||||
@@ -3854,14 +3854,19 @@ TerminateOtherDBBackends(Oid databaseId)
 | 
				
			|||||||
		ListCell   *lc;
 | 
							ListCell   *lc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Check whether we have the necessary rights to terminate other
 | 
							 * Permissions checks relax the pg_terminate_backend checks in two
 | 
				
			||||||
		 * sessions.  We don't terminate any session until we ensure that we
 | 
							 * ways, both by omitting the !OidIsValid(proc->roleId) check:
 | 
				
			||||||
		 * have rights on all the sessions to be terminated.  These checks are
 | 
					 | 
				
			||||||
		 * the same as we do in pg_terminate_backend.
 | 
					 | 
				
			||||||
		 *
 | 
							 *
 | 
				
			||||||
		 * In this case we don't raise some warnings - like "PID %d is not a
 | 
							 * - Accept terminating autovacuum workers, since DROP DATABASE
 | 
				
			||||||
		 * PostgreSQL server process", because for us already finished session
 | 
							 * without FORCE terminates them.
 | 
				
			||||||
		 * is not a problem.
 | 
							 *
 | 
				
			||||||
 | 
							 * - Accept terminating bgworkers.  For bgworker authors, it's
 | 
				
			||||||
 | 
							 * convenient to be able to recommend FORCE if a worker is blocking
 | 
				
			||||||
 | 
							 * DROP DATABASE unexpectedly.
 | 
				
			||||||
 | 
							 *
 | 
				
			||||||
 | 
							 * Unlike pg_terminate_backend, we don't raise some warnings - like
 | 
				
			||||||
 | 
							 * "PID %d is not a PostgreSQL server process", because for us already
 | 
				
			||||||
 | 
							 * finished session is not a problem.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		foreach(lc, pids)
 | 
							foreach(lc, pids)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -3870,13 +3875,11 @@ TerminateOtherDBBackends(Oid databaseId)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			if (proc != NULL)
 | 
								if (proc != NULL)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				/* Only allow superusers to signal superuser-owned backends. */
 | 
					 | 
				
			||||||
				if (superuser_arg(proc->roleId) && !superuser())
 | 
									if (superuser_arg(proc->roleId) && !superuser())
 | 
				
			||||||
					ereport(ERROR,
 | 
										ereport(ERROR,
 | 
				
			||||||
							(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 | 
												(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 | 
				
			||||||
							 errmsg("must be a superuser to terminate superuser process")));
 | 
												 errmsg("must be a superuser to terminate superuser process")));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				/* Users can signal backends they have role membership in. */
 | 
					 | 
				
			||||||
				if (!has_privs_of_role(GetUserId(), proc->roleId) &&
 | 
									if (!has_privs_of_role(GetUserId(), proc->roleId) &&
 | 
				
			||||||
					!has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_BACKEND))
 | 
										!has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_BACKEND))
 | 
				
			||||||
					ereport(ERROR,
 | 
										ereport(ERROR,
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user