forked from mozilla/gecko-dev
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bug 1752703 - Add interposers for functions manipulating the environm…
…ent to prevent crashes r=glandium This add interposers for getenv(), putenv(), setenv(), unsetenv() and clearenv(). All interposers use a single lock for synchronization while internally using the libc-provided functions. This is done to prevent races that typically happen in Firefox code when multiple threads call getenv() while others are changing variables using setenv() and putenv(). Differential Revision: https://phabricator.services.mozilla.com/D164471
- Loading branch information
1 parent
0b0dd83
commit 74e740b
Showing
2 changed files
with
82 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
#include <pthread.h> | ||
#include <unistd.h> | ||
|
||
#include "InterposerHelper.h" | ||
|
||
// The interposers in this file cover all the functions used to access the | ||
// environment (getenv(), putenv(), setenv(), unsetenv() and clearenv()). They | ||
// all use the mutex below for synchronization to prevent races that caused | ||
// startup crashes, see bug 1752703. | ||
static pthread_mutex_t gEnvLock = PTHREAD_MUTEX_INITIALIZER; | ||
|
||
static char* internal_getenv(const char* aName) { | ||
if (environ == nullptr || aName[0] == '\0') { | ||
return nullptr; | ||
} | ||
|
||
size_t len = strlen(aName); | ||
for (char** env_ptr = environ; *env_ptr != nullptr; ++env_ptr) { | ||
if ((aName[0] == (*env_ptr)[0]) && (strncmp(aName, *env_ptr, len) == 0) && | ||
((*env_ptr)[len] == '=')) { | ||
return *env_ptr + len + 1; | ||
} | ||
} | ||
|
||
return nullptr; | ||
} | ||
|
||
extern "C" { | ||
|
||
MFBT_API char* getenv(const char* name) { | ||
pthread_mutex_lock(&gEnvLock); | ||
char* result = internal_getenv(name); | ||
pthread_mutex_unlock(&gEnvLock); | ||
|
||
return result; | ||
} | ||
|
||
MFBT_API int putenv(char* string) { | ||
static const auto real_putenv = GET_REAL_SYMBOL(putenv); | ||
|
||
pthread_mutex_lock(&gEnvLock); | ||
int result = real_putenv(string); | ||
pthread_mutex_unlock(&gEnvLock); | ||
return result; | ||
} | ||
|
||
MFBT_API int setenv(const char* name, const char* value, int replace) { | ||
static const auto real_setenv = GET_REAL_SYMBOL(setenv); | ||
|
||
pthread_mutex_lock(&gEnvLock); | ||
int result = real_setenv(name, value, replace); | ||
pthread_mutex_unlock(&gEnvLock); | ||
return result; | ||
} | ||
|
||
MFBT_API int unsetenv(const char* name) { | ||
static const auto real_unsetenv = GET_REAL_SYMBOL(unsetenv); | ||
|
||
pthread_mutex_lock(&gEnvLock); | ||
int result = real_unsetenv(name); | ||
pthread_mutex_unlock(&gEnvLock); | ||
return result; | ||
} | ||
|
||
MFBT_API int clearenv(void) { | ||
static const auto real_clearenv = GET_REAL_SYMBOL(clearenv); | ||
|
||
pthread_mutex_lock(&gEnvLock); | ||
int result = real_clearenv(); | ||
pthread_mutex_unlock(&gEnvLock); | ||
return result; | ||
} | ||
|
||
} // extern "C" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters