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