1e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao/* 2e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao * Copyright (C) 2016 The Android Open Source Project 3e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao * 4e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao * Licensed under the Apache License, Version 2.0 (the "License"); 5e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao * you may not use this file except in compliance with the License. 6e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao * You may obtain a copy of the License at 7e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao * 8e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao * http://www.apache.org/licenses/LICENSE-2.0 9e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao * 10e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao * Unless required by applicable law or agreed to in writing, software 11e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao * distributed under the License is distributed on an "AS IS" BASIS, 12e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao * See the License for the specific language governing permissions and 14e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao * limitations under the License. 15e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao */ 16e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 17e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao#include <errno.h> 18e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao#include <signal.h> 1970335deb59cc3c5d639213c04af4708901829938Josh Gao#include <stdlib.h> 20e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao#include <string.h> 21e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao#include <sys/socket.h> 22e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao#include <sys/syscall.h> 23e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao#include <sys/types.h> 24e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao#include <sys/wait.h> 25e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao#include <unistd.h> 26e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 27e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao#include <log/logger.h> 28e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 29e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao#include "signal_sender.h" 30e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 31e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gaostatic int signal_fd = -1; 32e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gaostatic pid_t signal_pid; 33e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gaostruct signal_message { 34e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao pid_t pid; 35e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao pid_t tid; 36e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao int signal; 37e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao}; 38e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 3970335deb59cc3c5d639213c04af4708901829938Josh Gaostatic void set_signal_sender_process_name() { 4070335deb59cc3c5d639213c04af4708901829938Josh Gao#if defined(__LP64__) 4170335deb59cc3c5d639213c04af4708901829938Josh Gao static constexpr char long_process_name[] = "debuggerd64:signaller"; 4270335deb59cc3c5d639213c04af4708901829938Josh Gao static constexpr char short_process_name[] = "debuggerd64:sig"; 4370335deb59cc3c5d639213c04af4708901829938Josh Gao static_assert(sizeof(long_process_name) <= sizeof("/system/bin/debuggerd64"), ""); 4470335deb59cc3c5d639213c04af4708901829938Josh Gao#else 4570335deb59cc3c5d639213c04af4708901829938Josh Gao static constexpr char long_process_name[] = "debuggerd:signaller"; 4670335deb59cc3c5d639213c04af4708901829938Josh Gao static constexpr char short_process_name[] = "debuggerd:sig"; 4770335deb59cc3c5d639213c04af4708901829938Josh Gao static_assert(sizeof(long_process_name) <= sizeof("/system/bin/debuggerd"), ""); 4870335deb59cc3c5d639213c04af4708901829938Josh Gao#endif 4970335deb59cc3c5d639213c04af4708901829938Josh Gao 5070335deb59cc3c5d639213c04af4708901829938Josh Gao // pthread_setname_np has a maximum length of 16 chars, including null terminator. 5170335deb59cc3c5d639213c04af4708901829938Josh Gao static_assert(sizeof(short_process_name) <= 16, ""); 5270335deb59cc3c5d639213c04af4708901829938Josh Gao pthread_setname_np(pthread_self(), short_process_name); 5370335deb59cc3c5d639213c04af4708901829938Josh Gao 5470335deb59cc3c5d639213c04af4708901829938Josh Gao char* progname = const_cast<char*>(getprogname()); 5570335deb59cc3c5d639213c04af4708901829938Josh Gao if (strlen(progname) <= strlen(long_process_name)) { 5670335deb59cc3c5d639213c04af4708901829938Josh Gao ALOGE("debuggerd: unexpected progname %s", progname); 5770335deb59cc3c5d639213c04af4708901829938Josh Gao return; 5870335deb59cc3c5d639213c04af4708901829938Josh Gao } 5970335deb59cc3c5d639213c04af4708901829938Josh Gao 6070335deb59cc3c5d639213c04af4708901829938Josh Gao memset(progname, 0, strlen(progname)); 6170335deb59cc3c5d639213c04af4708901829938Josh Gao strcpy(progname, long_process_name); 6270335deb59cc3c5d639213c04af4708901829938Josh Gao} 6370335deb59cc3c5d639213c04af4708901829938Josh Gao 64e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao// Fork a process to send signals for the worker processes to use after they've dropped privileges. 65e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gaobool start_signal_sender() { 66a951f4ca5507f43485b9efdc61570e0c5e7c7d8bJosh Gao if (signal_pid != 0) { 67e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: attempted to start signal sender multiple times"); 68e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 69e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 70e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 71e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao int sfd[2]; 72e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sfd) != 0) { 73e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: failed to create socketpair for signal sender: %s", strerror(errno)); 74e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 75e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 76e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 77e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao pid_t parent = getpid(); 78e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao pid_t fork_pid = fork(); 79e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (fork_pid == -1) { 80e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: failed to initialize signal sender: fork failed: %s", strerror(errno)); 81e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 82e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } else if (fork_pid == 0) { 83e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao close(sfd[1]); 84e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 8570335deb59cc3c5d639213c04af4708901829938Josh Gao set_signal_sender_process_name(); 8670335deb59cc3c5d639213c04af4708901829938Josh Gao 87e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao while (true) { 88e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao signal_message msg; 89e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao int rc = TEMP_FAILURE_RETRY(read(sfd[0], &msg, sizeof(msg))); 90e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (rc < 0) { 91e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: signal sender failed to read from socket"); 92e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao break; 93e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } else if (rc != sizeof(msg)) { 94e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: signal sender read unexpected number of bytes: %d", rc); 95e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao break; 96e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 97e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 98e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao // Report success after sending a signal 99e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao int err = 0; 100e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (msg.tid > 0) { 101e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (syscall(SYS_tgkill, msg.pid, msg.tid, msg.signal) != 0) { 102e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao err = errno; 103e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 104e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } else { 105e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (kill(msg.pid, msg.signal) != 0) { 106e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao err = errno; 107e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 108e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 109e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 110e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (TEMP_FAILURE_RETRY(write(sfd[0], &err, sizeof(err))) < 0) { 111e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: signal sender failed to write: %s", strerror(errno)); 112e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 113e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 114e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 115e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao // Our parent proably died, but if not, kill them. 116e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (getppid() == parent) { 117e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao kill(parent, SIGKILL); 118e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 119e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao _exit(1); 120e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } else { 121e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao close(sfd[0]); 122e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao signal_fd = sfd[1]; 123e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao signal_pid = fork_pid; 124e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return true; 125e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 126e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao} 127e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 128e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gaobool stop_signal_sender() { 129e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (signal_pid <= 0) { 130e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 131e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 132e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 133e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (kill(signal_pid, SIGKILL) != 0) { 134e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: failed to kill signal sender: %s", strerror(errno)); 135e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 136e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 137e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 138e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao close(signal_fd); 139e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao signal_fd = -1; 140e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 141e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao int status; 142e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao waitpid(signal_pid, &status, 0); 143e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao signal_pid = 0; 144e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 145e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return true; 146e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao} 147e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 148e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gaobool send_signal(pid_t pid, pid_t tid, int signal) { 149e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (signal_fd == -1) { 150e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: attempted to send signal before signal sender was started"); 151e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao errno = EHOSTUNREACH; 152e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 153e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 154e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 155e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao signal_message msg = {.pid = pid, .tid = tid, .signal = signal }; 156e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (TEMP_FAILURE_RETRY(write(signal_fd, &msg, sizeof(msg))) < 0) { 157e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: failed to send message to signal sender: %s", strerror(errno)); 158e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao errno = EHOSTUNREACH; 159e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 160e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 161e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 162e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao int response; 163e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ssize_t rc = TEMP_FAILURE_RETRY(read(signal_fd, &response, sizeof(response))); 164e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (rc == 0) { 165e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: received EOF from signal sender"); 166e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao errno = EHOSTUNREACH; 167e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 168e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } else if (rc < 0) { 169e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: failed to receive response from signal sender: %s", strerror(errno)); 170e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao errno = EHOSTUNREACH; 171e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 172e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 173e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 174e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (response == 0) { 175e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return true; 176e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 177e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 178e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao errno = response; 179e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 180e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao} 181