SA_ONSTACK flag for sigaction() is ignored by libjsig.so

XMLWordPrintable

    • Type: Bug
    • Resolution: Won't Fix
    • Priority: P4
    • 9
    • Affects Version/s: 6u14
    • Component/s: hotspot
    • x86
    • solaris_2.5.1

      FULL PRODUCT VERSION :
      [dani@youwish javastack]$ java -version
      java version "1.6.0_14"
      Java(TM) SE Runtime Environment (build 1.6.0_14-b08)
      Java HotSpot(TM) Server VM (build 14.0-b16, mixed mode)

      also occurs with 1.6.0_07 (and probably any other version since libjsig.so was introduced)

      FULL OS VERSION :
      Red Hat Enterprise Linux ES release 4 (Nahant Update 8):
      Linux youwish.esri.com 2.6.9-89.ELsmp #1 SMP Mon Apr 20 10:34:33 EDT 2009 i686 i686 i386 GNU/Linux

      Red Hat Enterprise Linux Server release 5.3 (Tikanga):
      Linux RHEL5VM0 2.6.18-128.el5 #1 SMP Wed Dec 17 11:42:39 EST 2008 i686 i686 i386 GNU/Linux


      A DESCRIPTION OF THE PROBLEM :
      When libjsig.so is preloaded, the SA_ONSTACK flag to sigaction() is ignored, so sigaltstack() does not work.

      THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: Did not try

      THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Did not try

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      paste the following into a script and run:

      #!/bin/sh

      PATH=$JAVA_HOME/bin:$PATH
      LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH
      export PATH
      export LD_LIBRARY_PATH

      javac test.java
      gcc -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -shared -o libtest.so test.c

      LD_PRELOAD=$JAVA_HOME/jre/lib/i386/libjsig.so
      export LD_PRELOAD
      echo "LD_PRELOAD: $LD_PRELOAD"
      java test onstack
      java test notonstack

      echo "LD_PRELOAD unset:"
      unset LD_PRELOAD
      java test onstack


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      Actual behavior:
      LD_PRELOAD: /youwish1/Linux/jdk1.6.0/jre/lib/i386/libjsig.so
          using SA_ONSTACK: sigaltstack ss = 0x08108c40, signal handler ss = 0xb74b387c, siginfo = 0xb74b3b98
      NOT using SA_ONSTACK: sigaltstack ss = 0x08108c20, signal handler ss = 0xb74b387c, siginfo = 0xb74b3b98
      LD_PRELOAD unset:
          using SA_ONSTACK: sigaltstack ss = 0x08108b90, signal handler ss = 0x0810a804, siginfo = 0x0810a820

      Expected behavior: When libjsig.so is preloaded, the signal handler uses the given stack provided in sigaltstack(). So the above results would look something kinda like:

      LD_PRELOAD: /youwish1/Linux/jdk1.6.0/jre/lib/i386/libjsig.so
          using SA_ONSTACK: sigaltstack ss = 0x08108c40, signal handler ss = 0x810A8B4, siginfo = 0x810A8CC
      NOT using SA_ONSTACK: sigaltstack ss = 0x08108c20, signal handler ss = 0xb74b387c, siginfo = 0xb74b3b98
      LD_PRELOAD unset:
          using SA_ONSTACK: sigaltstack ss = 0x08108b90, signal handler ss = 0x0810a804, siginfo = 0x0810a820
      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      3 files are needed: test.java, test.c, test.h

      //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      test.java:
      //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      class test
      {
        static private native void doit(int use_onstack);

        static {
          System.loadLibrary("test");
        }

        static public void main(String args[])
        {
          int use_onstack = 0;
          if( args.length != 1 ) {
            System.out.println("usage: java test <onstack|anything else>");
            System.out.println("\tonstack - use SA_ONSTACK/sigaltstack()");
            System.out.println("\tanything else - don't use SA_ONSTACK/sigaltstack()");
            return;
          }

          if( args[0].equalsIgnoreCase("onstack") )
            use_onstack = 1;

          doit(use_onstack);
        }
      }

      //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      test.c:
      //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      #include <stdio.h>
      #include <stdlib.h>
      #include <signal.h>

      #include "test.h"

      #define GET_STACK( x ) __asm__ __volatile("movl %%esp, %0\n\t" : "=q" (x) : :"%0" )

      void the_handler(int sig, siginfo_t *info, void *context) {
        unsigned long ss_sp;
        struct ucontext_t *ctx = (struct ucontext_t *)context;

        GET_STACK( ss_sp );
        printf("signal handler ss = 0x%08x, siginfo = 0x%08x\n", ss_sp, info);

        exit(0);
      }

      /*
       * Class: test
       * Method: doit
       * Signature: (I)V
       */
      JNIEXPORT void JNICALL Java_test_doit(JNIEnv *env, jclass cls, jint use_onstack) {
        int ret = 0;
        struct sigaction sa = {0};
        struct sigaltstack sas = {0};

        sas.ss_sp = malloc(SIGSTKSZ);
        sas.ss_size = SIGSTKSZ;
        ret = sigaltstack(&sas, NULL);
        printf("%s SA_ONSTACK: sigaltstack ss = 0x%08x, ", use_onstack ? " using" : "NOT using", sas.ss_sp);

        sa.sa_sigaction = the_handler;
        sa.sa_flags = SA_SIGINFO;
        if( use_onstack )
          sa.sa_flags |= SA_ONSTACK;
        ret = sigaction(11, &sa, 0);

        raise(SIGSEGV);
      }


      //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      test.h: (or just run javah test)
      //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      /* DO NOT EDIT THIS FILE - it is machine generated */
      #include <jni.h>
      /* Header for class test */

      #ifndef _Included_test
      #define _Included_test
      #ifdef __cplusplus
      extern "C" {
      #endif
      /*
       * Class: test
       * Method: doit
       * Signature: (I)V
       */
      JNIEXPORT void JNICALL Java_test_doit
        (JNIEnv *, jclass, jint);

      #ifdef __cplusplus
      }
      #endif
      #endif

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      I modified the openjdk jsig.c to pass the flag and built my own custom libjsig.so which seems to work. However, I'm not sure this is the cleanest solution.

            Assignee:
            Unassigned
            Reporter:
            Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: