signal_sender.cpp revision e5dbdd09c74b2f62e5a633f76613c6341bc9ab17
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> 19e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao#include <string.h> 20e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao#include <sys/socket.h> 21e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao#include <sys/syscall.h> 22e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao#include <sys/types.h> 23e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao#include <sys/wait.h> 24e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao#include <unistd.h> 25e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 26e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao#include <log/logger.h> 27e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 28e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao#include "signal_sender.h" 29e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 30e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gaostatic int signal_fd = -1; 31e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gaostatic pid_t signal_pid; 32e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gaostruct signal_message { 33e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao pid_t pid; 34e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao pid_t tid; 35e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao int signal; 36e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao}; 37e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 38e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao// Fork a process to send signals for the worker processes to use after they've dropped privileges. 39e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gaobool start_signal_sender() { 40e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (signal_pid == 0) { 41e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: attempted to start signal sender multiple times"); 42e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 43e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 44e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 45e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao int sfd[2]; 46e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sfd) != 0) { 47e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: failed to create socketpair for signal sender: %s", strerror(errno)); 48e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 49e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 50e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 51e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao pid_t parent = getpid(); 52e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao pid_t fork_pid = fork(); 53e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (fork_pid == -1) { 54e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: failed to initialize signal sender: fork failed: %s", strerror(errno)); 55e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 56e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } else if (fork_pid == 0) { 57e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao close(sfd[1]); 58e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 59e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao while (true) { 60e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao signal_message msg; 61e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao int rc = TEMP_FAILURE_RETRY(read(sfd[0], &msg, sizeof(msg))); 62e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (rc < 0) { 63e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: signal sender failed to read from socket"); 64e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao break; 65e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } else if (rc != sizeof(msg)) { 66e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: signal sender read unexpected number of bytes: %d", rc); 67e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao break; 68e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 69e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 70e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao // Report success after sending a signal 71e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao int err = 0; 72e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (msg.tid > 0) { 73e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (syscall(SYS_tgkill, msg.pid, msg.tid, msg.signal) != 0) { 74e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao err = errno; 75e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 76e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } else { 77e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (kill(msg.pid, msg.signal) != 0) { 78e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao err = errno; 79e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 80e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 81e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 82e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (TEMP_FAILURE_RETRY(write(sfd[0], &err, sizeof(err))) < 0) { 83e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: signal sender failed to write: %s", strerror(errno)); 84e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 85e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 86e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 87e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao // Our parent proably died, but if not, kill them. 88e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (getppid() == parent) { 89e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao kill(parent, SIGKILL); 90e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 91e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao _exit(1); 92e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } else { 93e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao close(sfd[0]); 94e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao signal_fd = sfd[1]; 95e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao signal_pid = fork_pid; 96e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return true; 97e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 98e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao} 99e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 100e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gaobool stop_signal_sender() { 101e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (signal_pid <= 0) { 102e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 103e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 104e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 105e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (kill(signal_pid, SIGKILL) != 0) { 106e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: failed to kill signal sender: %s", strerror(errno)); 107e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 108e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 109e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 110e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao close(signal_fd); 111e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao signal_fd = -1; 112e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 113e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao int status; 114e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao waitpid(signal_pid, &status, 0); 115e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao signal_pid = 0; 116e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 117e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return true; 118e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao} 119e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 120e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gaobool send_signal(pid_t pid, pid_t tid, int signal) { 121e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (signal_fd == -1) { 122e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: attempted to send signal before signal sender was started"); 123e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao errno = EHOSTUNREACH; 124e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 125e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 126e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 127e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao signal_message msg = {.pid = pid, .tid = tid, .signal = signal }; 128e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (TEMP_FAILURE_RETRY(write(signal_fd, &msg, sizeof(msg))) < 0) { 129e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: failed to send message to signal sender: %s", strerror(errno)); 130e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao errno = EHOSTUNREACH; 131e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 132e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 133e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 134e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao int response; 135e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ssize_t rc = TEMP_FAILURE_RETRY(read(signal_fd, &response, sizeof(response))); 136e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (rc == 0) { 137e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: received EOF from signal sender"); 138e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao errno = EHOSTUNREACH; 139e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 140e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } else if (rc < 0) { 141e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao ALOGE("debuggerd: failed to receive response from signal sender: %s", strerror(errno)); 142e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao errno = EHOSTUNREACH; 143e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 144e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 145e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 146e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao if (response == 0) { 147e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return true; 148e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao } 149e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao 150e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao errno = response; 151e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao return false; 152e5dbdd09c74b2f62e5a633f76613c6341bc9ab17Josh Gao} 153