1 /*
   2  * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2012, 2015 SAP SE. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.  Oracle designates this
   9  * particular file as subject to the "Classpath" exception as provided
  10  * by Oracle in the LICENSE file that accompanied this code.
  11  *
  12  * This code is distributed in the hope that it will be useful, but WITHOUT
  13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15  * version 2 for more details (a copy is included in the LICENSE file that
  16  * accompanied this code).
  17  *
  18  * You should have received a copy of the GNU General Public License version
  19  * 2 along with this work; if not, write to the Free Software Foundation,
  20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  21  *
  22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  23  * or visit www.oracle.com if you need additional information or have any
  24  * questions.
  25  *
  26  */
  27 
  28 /* This is a special library that should be loaded before libc &
  29  * libthread to interpose the signal handler installation functions:
  30  * sigaction(), signal(), sigset().
  31  * Used for signal-chaining. See RFE 4381843.
  32  */
  33 
  34 #include "jni.h"
  35 
  36 #ifdef SOLARIS
  37 /* Our redeclarations of the system functions must not have a less
  38  * restrictive linker scoping, so we have to declare them as JNIEXPORT
  39  * before including signal.h */
  40 #include "sys/signal.h"
  41 JNIEXPORT void (*signal(int sig, void (*disp)(int)))(int);
  42 JNIEXPORT void (*sigset(int sig, void (*disp)(int)))(int);
  43 JNIEXPORT int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
  44 #endif
  45 
  46 #include <dlfcn.h>
  47 #include <errno.h>
  48 #include <pthread.h>
  49 #include <signal.h>
  50 #include <stdio.h>
  51 #include <stdlib.h>
  52 #include <string.h>
  53 
  54 #if (__STDC_VERSION__ >= 199901L)
  55   #include <stdbool.h>
  56 #else
  57   #define bool int
  58   #define true 1
  59   #define false 0
  60 #endif
  61 
  62 #ifdef SOLARIS
  63 #define MAX_SIGNALS (SIGRTMAX+1)
  64 
  65 /* On solaris, MAX_SIGNALS is a macro, not a constant, so we must allocate sact dynamically. */
  66 static struct sigaction *sact = (struct sigaction *)NULL; /* saved signal handlers */
  67 #else
  68 #define MAX_SIGNALS NSIG
  69 
  70 static struct sigaction sact[MAX_SIGNALS]; /* saved signal handlers */
  71 #endif
  72 
  73 static sigset_t jvmsigs; /* Signals used by jvm. */
  74 
  75 #ifdef MACOSX
  76 static __thread bool reentry = false; /* prevent reentry deadlock (per-thread) */
  77 #endif
  78 
  79 /* Used to synchronize the installation of signal handlers. */
  80 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  81 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  82 static pthread_t tid;
  83 
  84 typedef void (*sa_handler_t)(int);
  85 typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
  86 typedef sa_handler_t (*signal_function_t)(int, sa_handler_t);
  87 typedef int (*sigaction_t)(int, const struct sigaction *, struct sigaction *);
  88 
  89 static signal_function_t os_signal = 0; /* os's version of signal()/sigset() */
  90 static sigaction_t os_sigaction = 0; /* os's version of sigaction() */
  91 
  92 static bool jvm_signal_installing = false;
  93 static bool jvm_signal_installed = false;
  94 
  95 
  96 /* assume called within signal_lock */
  97 static void allocate_sact() {
  98 #ifdef SOLARIS
  99   if (sact == NULL) {
 100     sact = (struct sigaction *)malloc((MAX_SIGNALS) * (size_t)sizeof(struct sigaction));
 101     if (sact == NULL) {
 102       printf("%s\n", "libjsig.so unable to allocate memory");
 103       exit(0);
 104     }
 105     memset(sact, 0, (MAX_SIGNALS) * (size_t)sizeof(struct sigaction));
 106   }
 107 #endif
 108 }
 109 
 110 static void signal_lock() {
 111   pthread_mutex_lock(&mutex);
 112   /* When the jvm is installing its set of signal handlers, threads
 113    * other than the jvm thread should wait. */
 114   if (jvm_signal_installing) {
 115     /* tid is not initialized until jvm_signal_installing is set to true. */
 116     if (pthread_equal(tid, pthread_self()) == 0) {
 117       do {
 118         pthread_cond_wait(&cond, &mutex);
 119       } while (jvm_signal_installing);
 120     }
 121   }
 122 }
 123 
 124 static void signal_unlock() {
 125   pthread_mutex_unlock(&mutex);
 126 }
 127 
 128 static sa_handler_t call_os_signal(int sig, sa_handler_t disp,
 129                                    bool is_sigset) {
 130   sa_handler_t res;
 131 
 132   if (os_signal == NULL) {
 133     if (!is_sigset) {
 134       os_signal = (signal_function_t)dlsym(RTLD_NEXT, "signal");
 135     } else {
 136       os_signal = (signal_function_t)dlsym(RTLD_NEXT, "sigset");
 137     }
 138     if (os_signal == NULL) {
 139       printf("%s\n", dlerror());
 140       exit(0);
 141     }
 142   }
 143 
 144 #ifdef MACOSX
 145   /* On macosx, the OS implementation of signal calls sigaction.
 146    * Make sure we do not deadlock with ourself. (See JDK-8072147). */
 147   reentry = true;
 148 #endif
 149 
 150   res = (*os_signal)(sig, disp);
 151 
 152 #ifdef MACOSX
 153   reentry = false;
 154 #endif
 155 
 156   return res;
 157 }
 158 
 159 static void save_signal_handler(int sig, sa_handler_t disp, bool is_sigset) {
 160   sigset_t set;
 161 
 162   sact[sig].sa_handler = disp;
 163   sigemptyset(&set);
 164   sact[sig].sa_mask = set;
 165   if (!is_sigset) {
 166 #ifdef SOLARIS
 167     sact[sig].sa_flags = SA_NODEFER;
 168     if (sig != SIGILL && sig != SIGTRAP && sig != SIGPWR) {
 169       sact[sig].sa_flags |= SA_RESETHAND;
 170     }
 171 #else
 172     sact[sig].sa_flags = 0;
 173 #endif
 174   } else {
 175     sact[sig].sa_flags = 0;
 176   }
 177 }
 178 
 179 static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
 180   sa_handler_t oldhandler;
 181   bool sigused;
 182   bool sigblocked;
 183 
 184   signal_lock();
 185   allocate_sact();
 186 
 187   sigused = sigismember(&jvmsigs, sig);
 188   if (jvm_signal_installed && sigused) {
 189     /* jvm has installed its signal handler for this signal. */
 190     /* Save the handler. Don't really install it. */
 191     if (is_sigset) {
 192       sigblocked = sigismember(&(sact[sig].sa_mask), sig);
 193     }
 194     oldhandler = sact[sig].sa_handler;
 195     save_signal_handler(sig, disp, is_sigset);
 196 
 197 #ifdef SOLARIS
 198     if (is_sigset && sigblocked) {
 199       /* We won't honor the SIG_HOLD request to change the signal mask */
 200       oldhandler = SIG_HOLD;
 201     }
 202 #endif
 203 
 204     signal_unlock();
 205     return oldhandler;
 206   } else if (jvm_signal_installing) {
 207     /* jvm is installing its signal handlers. Install the new
 208      * handlers and save the old ones. jvm uses sigaction().
 209      * Leave the piece here just in case. */
 210     oldhandler = call_os_signal(sig, disp, is_sigset);
 211     save_signal_handler(sig, oldhandler, is_sigset);
 212 
 213     /* Record the signals used by jvm */
 214     sigaddset(&jvmsigs, sig);
 215 
 216     signal_unlock();
 217     return oldhandler;
 218   } else {
 219     /* jvm has no relation with this signal (yet). Install the
 220      * the handler. */
 221     oldhandler = call_os_signal(sig, disp, is_sigset);
 222 
 223     signal_unlock();
 224     return oldhandler;
 225   }
 226 }
 227 
 228 JNIEXPORT sa_handler_t signal(int sig, sa_handler_t disp) {
 229   if (sig < 0 || sig >= MAX_SIGNALS) {
 230     errno = EINVAL;
 231     return SIG_ERR;
 232   }
 233 
 234   return set_signal(sig, disp, false);
 235 }
 236 
 237 JNIEXPORT sa_handler_t sigset(int sig, sa_handler_t disp) {
 238 #ifdef _ALLBSD_SOURCE
 239   printf("sigset() is not supported by BSD");
 240   exit(0);
 241 #else
 242   if (sig < 0 || sig >= MAX_SIGNALS) {
 243     errno = EINVAL;
 244     return (sa_handler_t)-1;
 245   }
 246 
 247   return set_signal(sig, disp, true);
 248 #endif
 249 }
 250 
 251 static int call_os_sigaction(int sig, const struct sigaction  *act,
 252                              struct sigaction *oact) {
 253   if (os_sigaction == NULL) {
 254     os_sigaction = (sigaction_t)dlsym(RTLD_NEXT, "sigaction");
 255     if (os_sigaction == NULL) {
 256       printf("%s\n", dlerror());
 257       exit(0);
 258     }
 259   }
 260   return (*os_sigaction)(sig, act, oact);
 261 }
 262 
 263 JNIEXPORT int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
 264   int res;
 265   bool sigused;
 266   struct sigaction oldAct;
 267 
 268   if (sig < 0 || sig >= MAX_SIGNALS) {
 269     errno = EINVAL;
 270     return -1;
 271   }
 272 
 273 #ifdef MACOSX
 274   if (reentry) {
 275     return call_os_sigaction(sig, act, oact);
 276   }
 277 #endif
 278 
 279   signal_lock();
 280 
 281   allocate_sact();
 282   sigused = sigismember(&jvmsigs, sig);
 283   if (jvm_signal_installed && sigused) {
 284     /* jvm has installed its signal handler for this signal. */
 285     /* Save the handler. Don't really install it. */
 286     if (oact != NULL) {
 287       *oact = sact[sig];
 288     }
 289     if (act != NULL) {
 290       sact[sig] = *act;
 291     }
 292 
 293     signal_unlock();
 294     return 0;
 295   } else if (jvm_signal_installing) {
 296     /* jvm is installing its signal handlers. Install the new
 297      * handlers and save the old ones. */
 298     res = call_os_sigaction(sig, act, &oldAct);
 299     sact[sig] = oldAct;
 300     if (oact != NULL) {
 301       *oact = oldAct;
 302     }
 303 
 304     /* Record the signals used by jvm. */
 305     sigaddset(&jvmsigs, sig);
 306 
 307     signal_unlock();
 308     return res;
 309   } else {
 310     /* jvm has no relation with this signal (yet). Install the
 311      * the handler. */
 312     res = call_os_sigaction(sig, act, oact);
 313 
 314     signal_unlock();
 315     return res;
 316   }
 317 }
 318 
 319 /* The three functions for the jvm to call into. */
 320 JNIEXPORT void JVM_begin_signal_setting() {
 321   signal_lock();
 322   sigemptyset(&jvmsigs);
 323   jvm_signal_installing = true;
 324   tid = pthread_self();
 325   signal_unlock();
 326 }
 327 
 328 JNIEXPORT void JVM_end_signal_setting() {
 329   signal_lock();
 330   jvm_signal_installed = true;
 331   jvm_signal_installing = false;
 332   pthread_cond_broadcast(&cond);
 333   signal_unlock();
 334 }
 335 
 336 JNIEXPORT struct sigaction *JVM_get_signal_action(int sig) {
 337   allocate_sact();
 338   /* Does race condition make sense here? */
 339   if (sigismember(&jvmsigs, sig)) {
 340     return &sact[sig];
 341   }
 342   return NULL;
 343 }