Let’s talk about Improper Resource Shutdown
2020-10-30 02:57:56 Author: medium.com(查看原文) 阅读量:233 收藏

MRunal

The program does not release or incorrectly releases a resource before it is made available for re-use.the function fails to release a lock it acquires, which might lead to deadlock.

Image for post

The Android activity fails to release the Android database handler in its onPause(), onStop(), or onDestroy() event handlers.An Android activity fails to release the Android database handler in its onPause(), onStop(), or onDestroy() event handlers.

The Android activity maintains an Android SQLite database handler that is not closed in onPause(), onStop(), or onDestroy() callback. The Android OS invokes these callbacks whenever it needs to send the current activity to the background, or when it needs to temporarily destroy the activity when system resources are low. By failing to close the database properly, the activity can potentially exhaust the device of available cursors if the activity is constantly restarted. In addition, depending on the implementation, the Android operating system can also throws DatabaseObjectNotClosedException, which crashes the application if the exception is not caught.

The following code describes an Android activity that caches user data and writes the data to disk when the activity is stopped. Note that does not override the base onPause(), which should be used to release the database object, nor does it properly release it during its shutdown sequence.

public class MyDBHelper extends SQLiteOpenHelper {
...
}
public class UnreleasedDBActivity extends Activity {
private myDBHelper dbHelper;
private SQLiteDatabase db;
@Override
public void onCreate(Bundle state) {
...
db = dbHelper.getWritableDatabase();
...
}
@Override
public void onRestart() {
...
}
@Override
public void onStop() {
db.insert(cached_data); // flush cached data
}
}

If the application uses a SQLite database, it must always override the onPause() method of your activity, as well as at least one of the onStop() and onDestroy() methods. In each of these methods, ensure that you call close() on the database handler or object to conserve system resources. After calling close() on the database, you can continue using Android's SQLite storage capabilities by reconfiguring and reacquiring the instance in the onResume() callback.

In addition, it is generally a good idea to close the database object whenever it won't be used for an extended amount of time during your application's execution. When the application requires the resource again, simply reconfigure and reacquire it as before.

Resource leaks have at least two common causes:

- Error conditions and other exceptional circumstances.

- Confusion over which part of the program is responsible for releasing the resource.

Most unreleased resource issues result in general software reliability problems, but if an attacker can intentionally trigger a resource leak, the attacker may be able to launch a denial of service attack by depleting the resource pool.

The following method never closes the file handle it opens. The finalize() method for FileInputStream eventually calls close(), but there is no guarantee as to how long it will take before the finalize() method will be invoked. In a busy environment, this can result in the JVM using up all of its file handles.

private void processFile(String fName) throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream(fName);
int sz;
byte[] byteArray = new byte[BLOCK_SIZE];
while ((sz = fis.read(byteArray)) != -1) {
processBytes(byteArray, sz);
}
}

1. Never rely on finalize() to reclaim resources. In order for an object's finalize() method to be invoked, the garbage collector must determine that the object is eligible for garbage collection. Because the garbage collector is not required to run unless the JVM is low on memory, there is no guarantee that an object's finalize() method will be invoked in an expedient fashion. When the garbage collector finally does run, it may cause a large number of resources to be reclaimed in a short period of time, which can lead to "bursty" performance and lower overall system throughput. This effect becomes more pronounced as the load on the system increases.

Finally, if it is possible for a resource reclamation operation to hang (if it requires communicating over a network to a database, for example), then the thread that is executing the finalize() method will hang.

2. Release resources in a finally block. The code for the Example should be rewritten as follows:

public void processFile(String fName) throws FileNotFoundException, IOException {
FileInputStream fis;
try {
fis = new FileInputStream(fName);
int sz;
byte[] byteArray = new byte[BLOCK_SIZE];
while ((sz = fis.read(byteArray)) != -1) {
processBytes(byteArray, sz);
}
}
finally {
if (fis != null) {
safeClose(fis);
}
}
}

public static void safeClose(FileInputStream fis) {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
log(e);
}
}
}

This solution uses a helper function to log the exceptions that might occur when trying to close the stream. Presumably this helper function will be reused whenever a stream needs to be closed.

Also, the processFile method does not initialize the fis object to null. Instead, it checks to ensure that fis is not null before calling safeClose(). Without the null check, the Java compiler reports that fis might not be initialized. This choice takes advantage of Java's ability to detect uninitialized variables. If fis is initialized to null in a more complex method, cases in which fis is used without being initialized will not be detected by the compiler.

The following code establishes a lock before performOperationInCriticalSection(), but fails to release the lock if an exception is thrown in that method.

ReentrantLock  myLock = new ReentrantLock ();myLock.lock();
performOperationInCriticalSection();
myLock.unlock();

Because resource leaks can be hard to track down, establish a set of resource management patterns and idioms for your software and do not tolerate deviations from your conventions.

One good pattern for addressing the error handling mistake in this example is to release the lock in a finally block.

The following code will always release the lock.

ReentrantLock  myLock = new ReentrantLock ();try {
myLock.lock();
performOperationInCriticalSection();
myLock.unlock();
}
finally {
if (myLock != null) {
myLock.unlock();
}
}

文章来源: https://medium.com/bugbountywriteup/lets-talk-about-improper-resource-shutdown-73e940bed427?source=rss----7b722bfd1b8d--bug_bounty
如有侵权请联系:admin#unsafe.sh