(THIS CODING RULE OR GUIDELINE IS UNDER CONSTRUCTION)
To allow for the proper operation of the garbage collector in Java, the JVM must keep track of all Java objects passed to native code. Consequently, JNI uses local references and global references, see [JNISpec 2014] Chapter 2: Design Overview. While at least one local or global reference to a Java object exists, the object cannot be removed by the garbage collector. However, if the object is moved in memory by the garbage collector then the reference to the object remains valid. Local references are freed automatically when the function in which the local reference is defined returns (although a user may free a local reference before the function returns if they wish). Global references maintain a valid reference to the Java object until they are explicitly freed by the user. (JNI also uses weak global references which are similar to global references but allow the referenced object to be removed by the garbage collector, see: [JNISpec 2014] Chapter 4: JNI Functions.)
Attempting to use a direct pointer to a Java object in native code, rather than a local, global or weak global reference, may have erroneous results because the Java object may be moved or removed by the garbage collector while the direct pointer still exists.
Noncompliant Code Example
This noncompliant code example shows an example where a direct pointer to a Java object is used with erroneous results.
In this compliant solution ..
If a direct pointer to a Java object is used then erroneous results may be obtained that could lead to the code crashing. This, in turn, could be used to mount a denial of service attack. In some circumstances, the direct pointer could become a "dangling pointer" which could result in sensitive information being leaked or malicious execution of arbitrary code.
Direct pointers to Java objects can be detected and replaced by indirect handles automatically.
Android Implementation Details
Before Android version 4.0, "Ice Cream Sandwich", direct pointers to Java objects were used in native code. However, Ice Cream Sandwich introduced the use of indirect handles. This is to facilitate the introduction of a compacting garbage collector in the future. Such a garbage collector moves objects in memory so direct pointers to objects may no longer be valid after a compacting garbage collector has run. For more information on this see [Verify], section "Preventing JNI Issues" and [Hughes 2011].
Android Version Applicability
Applies to Android API versions 14 (ICE_CREAM_SANDWICH) and above, with Native Development Kit (NDK) 7.
|14 and above|
Java Native Interface Specification
|Verify||Preventing JNI Issues|
|Hughes 2011||JNI Local Reference Changes in ICS|
The JNI section is for C code relating to any JVM, not just Android / Dalvik. (yes I know Dalvik != Java, go away!). So this rule needs either a generic introduction (it may mention Android, but talk about what guarantees Java makes, not just Android). Or it should be a DRD rule, not a JNI one.
I think that this must apply to the JVM as well as Dalvik. I'll check and reword as necessary.
Indeed, this does apply to the JVM, and I've made a major revision of this rule accordingly.
One question: I presume that if a direct pointer to an object is used, the GC moves or frees the object, then the pointer becomes dangling, right? Or the memory might be allocated / used for other data. In which case, reading the data via a direct pointer could leak sensitive info. Could modifying the data via direct pointer result in malicious execution?
As you might guess, I suspect the severity is not low, it is medium or maybe high?
Good point. I've changed the Risk Assessment section.