Date: Tue, 7 Dec 2010 06:06:58 GMT From: Bob Frazier <bobf@mrp3.com> To: freebsd-gnats-submit@FreeBSD.org Subject: ports/152882: comms/rxtx page fault/crash Message-ID: <201012070606.oB766w57065041@red.freebsd.org> Resent-Message-ID: <201012070610.oB76AAUS060248@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 152882 >Category: ports >Synopsis: comms/rxtx page fault/crash >Confidential: no >Severity: serious >Priority: high >Responsible: freebsd-ports-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Dec 07 06:10:10 UTC 2010 >Closed-Date: >Last-Modified: >Originator: Bob Frazier >Release: 7.3-STABLE >Organization: S.F.T. Inc. >Environment: FreeBSD BSDSilver.SFT.local 7.3-STABLE FreeBSD 7.3-STABLE #12: Tue Nov 23 20:43:00 PST 2010 root@BSDSilver.SFT.local:/usr/obj/usr/src/sys/GENERIC amd64 >Description: A software coding error in comms/rxtx causes a page fault when attempting to access a java variable by reference. The error is due to incorrect use of GetIntField instead of GetObjectField. A set of patches have been included that appear to correct the problem when placed into the 'files' directory of the port prior to building the port. >How-To-Repeat: using a java COMM application (such as devel/arduino) attempt to do serial I/O on a comm port. In my case it was a USB comm port '/dev/ttyU0'. Simply attempting a transfer is enough to cause the crash. >Fix: the three files src/SerialImp.c src/SerialImp.cpp and src/SerialImp.h must be patched using the attached files (or similar). Patch attached with submission follows: # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # rxtx # rxtx/files # rxtx/files/patch-SerialImp.h # rxtx/files/patch-SerialImp.cpp # rxtx/files/patch-SerialImp.c # echo c - rxtx mkdir -p rxtx > /dev/null 2>&1 echo c - rxtx/files mkdir -p rxtx/files > /dev/null 2>&1 echo x - rxtx/files/patch-SerialImp.h sed 's/^X//' >rxtx/files/patch-SerialImp.h << '375c7bbc64083cac744fa1f2532d67e4' X--- src/SerialImp.h.orig 2005-07-05 10:47:21.000000000 -0700 X+++ src/SerialImp.h 2010-12-05 21:47:42.000000000 -0800 X@@ -438,8 +438,13 @@ X void system_does_not_unlock( const char *, int ); X int check_group_uucp(); X int check_lock_pid( const char *, int ); X int printj(JNIEnv *env, wchar_t *fmt, ...); X X+// BBB added X+void deref_java_object( JNIEnv *env, jobject jobj ); X+void * get_java_varP( JNIEnv *env, jobject jobj, char *id, char *type ); X+ X+ X #define UNEXPECTED_LOCK_FILE "RXTX Error: Unexpected lock file: %s\n Please report to the RXTX developers\n" X #define LINUX_KERNEL_VERSION_ERROR "\n\n\nRXTX WARNING: This library was compiled to run with OS release %s and you are currently running OS release %s. In some cases this can be a problem. Try recompiling RXTX if you notice strange behavior. If you just compiled RXTX make sure /usr/include/linux is a symbolic link to the include files that came with the kernel source and not an older copy.\n\n\npress enter to continue\n" X #define UUCP_ERROR "\n\n\nRXTX WARNING: This library requires the user running applications to be in\ngroup uucp. Please consult the INSTALL documentation. More information is\navaiable under the topic 'How can I use Lock Files with rxtx?'\n" 375c7bbc64083cac744fa1f2532d67e4 echo x - rxtx/files/patch-SerialImp.cpp sed 's/^X//' >rxtx/files/patch-SerialImp.cpp << '29e44cd8508495ee769fe53c84b57552' X--- src/SerialImp.cpp.orig 2004-10-12 01:59:27.000000000 -0700 X+++ src/SerialImp.cpp 2010-12-06 21:48:20.000000000 -0800 X@@ -1736,10 +1736,50 @@ X report("invalid file descriptor\n"); X #endif X return result; X } X X+void deref_java_object( JNIEnv *env, jobject jobj ) X+{ X+ jclass jclazz = env->GetObjectClass( env, jobj ); X+ env->DeleteLocalRef( env, jclazz ); X+} X+ X+void * get_java_varP( JNIEnv *env, jobject jobj, char *id, char *type ) X+{ X+ X+ X+ ////////////////// Open Log File ///////////////////// X+ fp = fopen("RXTXOut.log", "a"); X+ fprintf(fp, "Brian is inside get_java_varP\n"); // !!! X+ fclose(fp); X+ ////////////////// Close Log File //////////////////// X+ X+ void * result = 0; X+ //jclass jclazz = (*env)->GetObjectClass( env, jobj ); X+ jclass jclazz = env->GetObjectClass( jobj ); // !!! X+ //jfieldID jfd = (*env)->GetFieldID( env, jclazz, id, type ); X+ jfieldID jfd = env->GetFieldID( jclazz, id, type ); // !!! X+ X+ if( !jfd ) { X+ //(*env)->ExceptionDescribe( env ); X+ env->ExceptionDescribe(); // !!! X+ //(*env)->ExceptionClear( env ); X+ env->ExceptionClear(); // !!! X+ return result; X+ } X+ //result = (int)( (*env)->GetIntField( env, jobj, jfd ) ); X+ result = (void *)( env->GetIntField( jobj, jfd ) ); // !!! X+/* ct7 & gel * Added DeleteLocalRef */ X+ //(*env)->DeleteLocalRef( env, jclazz ); X+// env->DeleteLocalRef( jclazz ); // !!! X+#ifdef DEBUG X+ if(!strncmp("fd",id,2) && result == 0) X+ report("invalid file descriptor\n"); X+#endif X+ return result; X+} X /*---------------------------------------------------------- X throw_java_exception X X accept: env (keyhole to java) X *exc (exception class name) 29e44cd8508495ee769fe53c84b57552 echo x - rxtx/files/patch-SerialImp.c sed 's/^X//' >rxtx/files/patch-SerialImp.c << '5ac5e6c673ede56f265b5168ecba1897' X--- src/SerialImp.c.orig 2006-01-29 14:19:04.000000000 -0800 X+++ src/SerialImp.c 2010-12-05 22:41:39.000000000 -0800 X@@ -1528,11 +1528,11 @@ X ----------------------------------------------------------*/ X JNIEXPORT jboolean JNICALL RXTXPort(nativeDrain)( JNIEnv *env, X jobject jobj, jboolean interrupted ) X { X int fd = get_java_var( env, jobj,"fd","I" ); X- struct event_info_struct *eis = ( struct event_info_struct * ) get_java_var( env, jobj, "eis", "J" ); X+ struct event_info_struct *eis = ( struct event_info_struct * ) get_java_varP( env, jobj, "eis", "J" ); // does not deref X int result, count=0; X X char message[80]; X X ENTER( "SerialImp.c:drain()" ); X@@ -1545,16 +1545,21 @@ X X sprintf( message, "RXTXPort:drain() returns: %i\n", result ); X report_verbose( message ); X #if defined(__sun__) X /* FIXME: No time to test on all OS's for production */ X+ deref_java_object(env, jobj); X return( JNI_TRUE ); X #endif /* __sun__ */ X LEAVE( "RXTXPort:drain()" ); X if( result ) throw_java_exception( env, IO_EXCEPTION, "nativeDrain", X strerror( errno ) ); X- if( interrupted ) return( JNI_FALSE ); X+ if( interrupted ) X+ { X+ deref_java_object(env, jobj); X+ return( JNI_FALSE ); X+ } X #if !defined(TIOCSERGETLSR) && !defined(WIN32) X if( eis && eis->writing ) X { X eis->writing=JNI_FALSE; X eis->output_buffer_empty_flag = 0; X@@ -1565,10 +1570,12 @@ X struct event_info_struct myeis = X build_threadsafe_eis( env, &jobj, eis ); X send_event( &myeis, SPE_OUTPUT_BUFFER_EMPTY, 1 ); X } X report_time_end( ); X+ X+ deref_java_object(env, jobj); X return( JNI_FALSE ); X } X X /*---------------------------------------------------------- X RXTXPort.sendBreak X@@ -2937,11 +2944,11 @@ X struct timeval tv, *tvP; X fd_set rset; X /* TRENT */ X int flag, count = 0; X struct event_info_struct *eis = ( struct event_info_struct * ) X- get_java_var( env, *jobj,"eis","J" ); X+ get_java_varP( env, *jobj,"eis","J" ); // does not dereference object (pointer remains valid) X X report_time_start(); X flag = eis->eventflags[SPE_DATA_AVAILABLE]; X eis->eventflags[SPE_DATA_AVAILABLE] = 0; X /* X@@ -2957,10 +2964,11 @@ X if (timeout >= 0) { X now = GetTickCount(); X if ( now-start >= timeout ) X { X eis->eventflags[SPE_DATA_AVAILABLE] = flag; X+ deref_java_object( env, *jobj ); X return bytes; X } X } X X FD_ZERO(&rset); X@@ -2983,22 +2991,25 @@ X #endif /* WIN32 */ X if (ret == -1){ X report( "read_byte_array: select returned -1\n" ); X LEAVE( "read_byte_array" ); X eis->eventflags[SPE_DATA_AVAILABLE] = flag; X+ deref_java_object( env, *jobj ); X return -1; X } X else if (ret > 0) X { X if ((ret = READ( fd, buffer + bytes, left )) < 0 ){ X if (errno != EINTR && errno != EAGAIN){ X report( "read_byte_array: read returned -1\n" ); X LEAVE( "read_byte_array" ); X eis->eventflags[SPE_DATA_AVAILABLE] = flag; X+ deref_java_object( env, *jobj ); X return -1; X } X eis->eventflags[SPE_DATA_AVAILABLE] = flag; X+ deref_java_object( env, *jobj ); X return -1; X } X else if ( ret ) { X bytes += ret; X left -= ret; X@@ -3031,10 +3042,12 @@ X report( msg ); X LEAVE( "read_byte_array" ); X report_time_end(); X */ X eis->eventflags[SPE_DATA_AVAILABLE] = flag; X+ X+ deref_java_object( env, *jobj ); X return bytes; X } X X #ifdef asdf X int read_byte_array( JNIEnv *env, X@@ -4898,10 +4911,43 @@ X LEAVE( "get_java_var" ); X */ X return result; X } X X+void deref_java_object( JNIEnv *env, jobject jobj ) X+{ X+ jclass jclazz = (*env)->GetObjectClass( env, jobj ); X+ (*env)->DeleteLocalRef( env, jclazz ); X+} X+ X+void * get_java_varP( JNIEnv *env, jobject jobj, char *id, char *type ) X+{ X+ void * result = 0; X+ jclass jclazz = (*env)->GetObjectClass( env, jobj ); X+ jfieldID jfd = (*env)->GetFieldID( env, jclazz, id, type ); X+ X+/* X+ ENTER( "get_java_var" ); X+*/ X+ if( !jfd ) { X+ (*env)->ExceptionDescribe( env ); X+ (*env)->ExceptionClear( env ); X+ (*env)->DeleteLocalRef( env, jclazz ); X+ LEAVE( "get_java_var" ); X+ return result; X+ } X+ result = (void *)( (*env)->GetObjectField( env, jobj, jfd ) ); X+/* ct7 & gel * Added DeleteLocalRef */ X+// (*env)->DeleteLocalRef( env, jclazz ); X+ if(!strncmp( "fd",id,2) && result == 0) X+ report_error( "get_java_var: invalid file descriptor\n" ); X+/* X+ LEAVE( "get_java_var" ); X+*/ X+ return result; X+} X+ X /*---------------------------------------------------------- X throw_java_exception X X accept: env (keyhole to java) X *exc (exception class name) 5ac5e6c673ede56f265b5168ecba1897 exit >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201012070606.oB766w57065041>