Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6855655

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

    XMLWordPrintable

Details

    • Bug
    • Resolution: Won't Fix
    • P4
    • 9
    • 6u14
    • hotspot
    • x86
    • solaris_2.5.1

    Description

      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.

      Attachments

        Activity

          People

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

            Dates

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: