1 /*------------------------------------------------------------------------- 2 * 3 * signalfuncs.c 4 * Functions for signaling backends 5 * 6 * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group 7 * Portions Copyright (c) 1994, Regents of the University of California 8 * 9 * 10 * IDENTIFICATION 11 * src/backend/storage/ipc/signalfuncs.c 12 * 13 *------------------------------------------------------------------------- 14 */ 15 #include "postgres.h" 16 17 #include <signal.h> 18 19 #include "catalog/pg_authid.h" 20 #include "miscadmin.h" 21 #include "postmaster/syslogger.h" 22 #include "storage/pmsignal.h" 23 #include "storage/proc.h" 24 #include "storage/procarray.h" 25 #include "utils/acl.h" 26 #include "utils/builtins.h" 27 28 29 /* 30 * Send a signal to another backend. 31 * 32 * The signal is delivered if the user is either a superuser or the same 33 * role as the backend being signaled. For "dangerous" signals, an explicit 34 * check for superuser needs to be done prior to calling this function. 35 * 36 * Returns 0 on success, 1 on general failure, 2 on normal permission error 37 * and 3 if the caller needs to be a superuser. 38 * 39 * In the event of a general failure (return code 1), a warning message will 40 * be emitted. For permission errors, doing that is the responsibility of 41 * the caller. 42 */ 43 #define SIGNAL_BACKEND_SUCCESS 0 44 #define SIGNAL_BACKEND_ERROR 1 45 #define SIGNAL_BACKEND_NOPERMISSION 2 46 #define SIGNAL_BACKEND_NOSUPERUSER 3 47 static int 48 pg_signal_backend(int pid, int sig) 49 { 50 PGPROC *proc = BackendPidGetProc(pid); 51 52 /* 53 * BackendPidGetProc returns NULL if the pid isn't valid; but by the time 54 * we reach kill(), a process for which we get a valid proc here might 55 * have terminated on its own. There's no way to acquire a lock on an 56 * arbitrary process to prevent that. But since so far all the callers of 57 * this mechanism involve some request for ending the process anyway, that 58 * it might end on its own first is not a problem. 59 */ 60 if (proc == NULL) 61 { 62 /* 63 * This is just a warning so a loop-through-resultset will not abort 64 * if one backend terminated on its own during the run. 65 */ 66 ereport(WARNING, 67 (errmsg("PID %d is not a PostgreSQL server process", pid))); 68 return SIGNAL_BACKEND_ERROR; 69 } 70 71 /* Only allow superusers to signal superuser-owned backends. */ 72 if (superuser_arg(proc->roleId) && !superuser()) 73 return SIGNAL_BACKEND_NOSUPERUSER; 74 75 /* Users can signal backends they have role membership in. */ 76 if (!has_privs_of_role(GetUserId(), proc->roleId) && 77 !has_privs_of_role(GetUserId(), DEFAULT_ROLE_SIGNAL_BACKENDID)) 78 return SIGNAL_BACKEND_NOPERMISSION; 79 80 /* 81 * Can the process we just validated above end, followed by the pid being 82 * recycled for a new process, before reaching here? Then we'd be trying 83 * to kill the wrong thing. Seems near impossible when sequential pid 84 * assignment and wraparound is used. Perhaps it could happen on a system 85 * where pid re-use is randomized. That race condition possibility seems 86 * too unlikely to worry about. 87 */ 88 89 /* If we have setsid(), signal the backend's whole process group */ 90 #ifdef HAVE_SETSID 91 if (kill(-pid, sig)) 92 #else 93 if (kill(pid, sig)) 94 #endif 95 { 96 /* Again, just a warning to allow loops */ 97 ereport(WARNING, 98 (errmsg("could not send signal to process %d: %m", pid))); 99 return SIGNAL_BACKEND_ERROR; 100 } 101 return SIGNAL_BACKEND_SUCCESS; 102 } 103 104 /* 105 * Signal to cancel a backend process. This is allowed if you are a member of 106 * the role whose process is being canceled. 107 * 108 * Note that only superusers can signal superuser-owned processes. 109 */ 110 Datum 111 pg_cancel_backend(PG_FUNCTION_ARGS) 112 { 113 int r = pg_signal_backend(PG_GETARG_INT32(0), SIGINT); 114 115 if (r == SIGNAL_BACKEND_NOSUPERUSER) 116 ereport(ERROR, 117 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), 118 errmsg("must be a superuser to cancel superuser query"))); 119 120 if (r == SIGNAL_BACKEND_NOPERMISSION) 121 ereport(ERROR, 122 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), 123 errmsg("must be a member of the role whose query is being canceled or member of pg_signal_backend"))); 124 125 PG_RETURN_BOOL(r == SIGNAL_BACKEND_SUCCESS); 126 } 127 128 /* 129 * Signal to terminate a backend process. This is allowed if you are a member 130 * of the role whose process is being terminated. 131 * 132 * Note that only superusers can signal superuser-owned processes. 133 */ 134 Datum 135 pg_terminate_backend(PG_FUNCTION_ARGS) 136 { 137 int r = pg_signal_backend(PG_GETARG_INT32(0), SIGTERM); 138 139 if (r == SIGNAL_BACKEND_NOSUPERUSER) 140 ereport(ERROR, 141 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), 142 errmsg("must be a superuser to terminate superuser process"))); 143 144 if (r == SIGNAL_BACKEND_NOPERMISSION) 145 ereport(ERROR, 146 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), 147 errmsg("must be a member of the role whose process is being terminated or member of pg_signal_backend"))); 148 149 PG_RETURN_BOOL(r == SIGNAL_BACKEND_SUCCESS); 150 } 151 152 /* 153 * Signal to reload the database configuration 154 * 155 * Permission checking for this function is managed through the normal 156 * GRANT system. 157 */ 158 Datum 159 pg_reload_conf(PG_FUNCTION_ARGS) 160 { 161 if (kill(PostmasterPid, SIGHUP)) 162 { 163 ereport(WARNING, 164 (errmsg("failed to send signal to postmaster: %m"))); 165 PG_RETURN_BOOL(false); 166 } 167 168 PG_RETURN_BOOL(true); 169 } 170 171 172 /* 173 * Rotate log file 174 * 175 * This function is kept to support adminpack 1.0. 176 */ 177 Datum 178 pg_rotate_logfile(PG_FUNCTION_ARGS) 179 { 180 if (!superuser()) 181 ereport(ERROR, 182 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), 183 errmsg("must be superuser to rotate log files with adminpack 1.0"), 184 /* translator: %s is a SQL function name */ 185 errhint("Consider using %s, which is part of core, instead.", 186 "pg_logfile_rotate()"))); 187 188 if (!Logging_collector) 189 { 190 ereport(WARNING, 191 (errmsg("rotation not possible because log collection not active"))); 192 PG_RETURN_BOOL(false); 193 } 194 195 SendPostmasterSignal(PMSIGNAL_ROTATE_LOGFILE); 196 PG_RETURN_BOOL(true); 197 } 198 199 /* 200 * Rotate log file 201 * 202 * Permission checking for this function is managed through the normal 203 * GRANT system. 204 */ 205 Datum 206 pg_rotate_logfile_v2(PG_FUNCTION_ARGS) 207 { 208 if (!Logging_collector) 209 { 210 ereport(WARNING, 211 (errmsg("rotation not possible because log collection not active"))); 212 PG_RETURN_BOOL(false); 213 } 214 215 SendPostmasterSignal(PMSIGNAL_ROTATE_LOGFILE); 216 PG_RETURN_BOOL(true); 217 } 218