From bcb793d37b1e20d0329ea5bafa5095198fa8f7d2 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Wed, 14 Jan 2015 11:47:51 +0100 Subject: [PATCH] Fix driver_settings in kernel mode outside of drivers. The API allows to create driver settings which are not added to the global list, however those were left partially uninitialized, and there was no way to cleanly delete them. Tag such unattached settings with a ref_count of -1, and have delete_driver_settings check for this and handle the case correctly. Note: #10494 comment 2 says the settings for packagefs shouldn't be added to the kernel driver settings list, which is why I went with this solution. An alternative would be always using the list and the reference counting, but I don't know what the consequences are. Fixes #10494. --- src/system/libroot/os/driver_settings.cpp | 28 +++++++++++++++-------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/system/libroot/os/driver_settings.cpp b/src/system/libroot/os/driver_settings.cpp index 9a986ae3c4..065092e4dc 100644 --- a/src/system/libroot/os/driver_settings.cpp +++ b/src/system/libroot/os/driver_settings.cpp @@ -77,6 +77,8 @@ typedef struct settings_handle { list_link link; char name[B_OS_NAME_LENGTH]; int32 ref_count; + // A negative ref_count means the node is not reference counted and not + // stored in the list. #endif int32 magic; struct driver_settings settings; @@ -101,8 +103,9 @@ static mutex sLock = MUTEX_INITIALIZER("driver settings"); /*! - Returns true for any characters that separate parameters - - those are ignored in the input stream and won't be added + \brief Returns true for any characters that separate parameters + + Those characters are ignored in the input stream and won't be added to any words. */ static inline bool @@ -112,9 +115,8 @@ is_parameter_separator(char c) } -/** Indicates if "c" begins a new word or not. - */ - +/*! Indicates if "c" begins a new word or not. +*/ static inline bool is_word_break(char c) { @@ -413,6 +415,9 @@ new_settings(char *buffer, const char *driverName) if (driverName != NULL) { handle->ref_count = 1; strlcpy(handle->name, driverName, sizeof(handle->name)); + } else { + handle->ref_count = -1; + handle->name[0] = 0; } #endif @@ -687,11 +692,14 @@ unload_driver_settings(void *_handle) #ifdef _KERNEL_MODE mutex_lock(&sLock); - if (--handle->ref_count == 0 && gBootDevice > 0) { - // don't unload an handle when /boot is not available - list_remove_link(&handle->link); - } else - handle = NULL; + + if (handle->ref_count > 0) { + if (--handle->ref_count == 0 && gBootDevice > 0) { + // don't unload an handle when /boot is not available + list_remove_link(&handle->link); + } else + handle = NULL; + } mutex_unlock(&sLock); #endif