Skip to content

Commit

Permalink
Bug 1752703 - Add interposers for functions manipulating the environm…
Browse files Browse the repository at this point in the history
…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
gabrielesvelto committed May 10, 2023
1 parent 0b0dd83 commit 74e740b
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 0 deletions.
78 changes: 78 additions & 0 deletions mozglue/interposers/env_interposer.cpp
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"
4 changes: 4 additions & 0 deletions mozglue/interposers/moz.build
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ Library("interposers")

DEFINES["IMPL_MFBT"] = True

UNIFIED_SOURCES += [
"env_interposer.cpp",
]

if CONFIG["MOZ_CRASHREPORTER"]:
UNIFIED_SOURCES += [
"pthread_create_interposer.cpp",
Expand Down

0 comments on commit 74e740b

Please sign in to comment.