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