debuggerd: rethrow the full signal we receive, always.

The previous code assumed that returning would be sufficient to rethrow
signals like SIGSEGV. This is not true, for example,  in the case where a
SIGSEGV is sent via kill(2). We were previously only sending the signal
to ourselves in some cases, because using kill(2) would lose information
in the siginfo_t argument. Use rt_tgsigqueueinfo(2) instead to preserve
its contents.

Bug: http://b/27367422
Change-Id: I1be822818d5905461979c7e12dc4e9c25049273b
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index f8fdc3f..8c1e834 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
+#include <errno.h>
 #include <signal.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 #include <gtest/gtest.h>
 
-#include <errno.h>
-
 #include "ScopedSignalHandler.h"
 
 static size_t SIGNAL_MIN() {
@@ -375,3 +377,36 @@
 
   ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL));
 }
+
+#if defined(__BIONIC__)
+TEST(signal, rt_tgsigqueueinfo) {
+  // Test whether rt_tgsigqueueinfo allows sending arbitrary si_code values to self.
+  // If this fails, your kernel needs commit 66dd34a to be backported.
+  static constexpr char error_msg[] =
+    "\nPlease ensure that the following kernel patch has been applied:\n"
+    "* https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=66dd34ad31e5963d72a700ec3f2449291d322921\n";
+  static siginfo received;
+
+  struct sigaction handler = {};
+  handler.sa_sigaction = [](int, siginfo_t* siginfo, void*) { received = *siginfo; };
+  handler.sa_flags = SA_SIGINFO;
+
+  ASSERT_EQ(0, sigaction(SIGUSR1, &handler, nullptr));
+
+  siginfo sent = {};
+
+  sent.si_code = SI_TKILL;
+  ASSERT_EQ(0, syscall(SYS_rt_tgsigqueueinfo, getpid(), gettid(), SIGUSR1, &sent))
+    << "rt_tgsigqueueinfo failed: " << strerror(errno) << error_msg;
+  ASSERT_EQ(sent.si_code, received.si_code) << "rt_tgsigqueueinfo modified si_code, expected "
+                                            << sent.si_code << ", received " << received.si_code
+                                            << error_msg;
+
+  sent.si_code = SI_USER;
+  ASSERT_EQ(0, syscall(SYS_rt_tgsigqueueinfo, getpid(), gettid(), SIGUSR1, &sent))
+    << "rt_tgsigqueueinfo failed: " << strerror(errno) << error_msg;
+  ASSERT_EQ(sent.si_code, received.si_code) << "rt_tgsigqueueinfo modified si_code, expected "
+                                            << sent.si_code << ", received " << received.si_code
+                                            << error_msg;
+}
+#endif