# fix to VFS init called from self test
fixes #157 bitten again by the complex tree_shutdown code. now correctly pull rug (memory) out from under the tree *after* it has emptied itself. also add an 'am i initialized' indicator to VFS to allow multiple init and also provide means of squelching the root-dir-set-multiple times thing This was SVN commit r4588.
This commit is contained in:
parent
751f0ca377
commit
abec0f17b9
@ -138,6 +138,16 @@ LibError file_make_full_portable_path(const char* n_full_path, char* path)
|
||||
}
|
||||
|
||||
|
||||
// security check: only allow attempting to chdir once, so that malicious
|
||||
// code cannot circumvent the VFS checks that disallow access to anything
|
||||
// above the current directory (set here).
|
||||
// this routine is called early at startup, so any subsequent attempts
|
||||
// are likely bogus.
|
||||
// we provide for resetting this from the self-test to allow clean
|
||||
// re-init of the individual tests.
|
||||
static bool root_dir_established;
|
||||
|
||||
|
||||
// establish the root directory from <rel_path>, which is treated as
|
||||
// relative to the executable's directory (determined via argv[0]).
|
||||
// all relative file paths passed to this module will be based from
|
||||
@ -153,15 +163,9 @@ LibError file_make_full_portable_path(const char* n_full_path, char* path)
|
||||
// can only be called once, by design (see below). rel_path is trusted.
|
||||
LibError file_set_root_dir(const char* argv0, const char* rel_path)
|
||||
{
|
||||
// security check: only allow attempting to chdir once, so that malicious
|
||||
// code cannot circumvent the VFS checks that disallow access to anything
|
||||
// above the current directory (set here).
|
||||
// this routine is called early at startup, so any subsequent attempts
|
||||
// are likely bogus.
|
||||
static bool already_attempted;
|
||||
if(already_attempted)
|
||||
if(root_dir_established)
|
||||
WARN_RETURN(ERR::ROOT_DIR_ALREADY_SET);
|
||||
already_attempted = true;
|
||||
root_dir_established = true;
|
||||
|
||||
// get full path to executable
|
||||
char n_path[PATH_MAX];
|
||||
@ -193,6 +197,16 @@ LibError file_set_root_dir(const char* argv0, const char* rel_path)
|
||||
}
|
||||
|
||||
|
||||
void path_reset_root_dir()
|
||||
{
|
||||
// see comment at root_dir_established.
|
||||
debug_assert(root_dir_established);
|
||||
n_root_dir[0] = '\0';
|
||||
n_root_dir_len = 0;
|
||||
root_dir_established = false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// storage for path strings
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -58,6 +58,16 @@ extern bool path_is_atom_fn(const char* fn);
|
||||
|
||||
extern const char* file_get_random_name();
|
||||
|
||||
|
||||
/**
|
||||
* reset root directory that was previously established via file_set_root_dir.
|
||||
*
|
||||
* this function avoids the security complaint that would be raised if
|
||||
* file_set_root_dir is called twice; it is provided for the
|
||||
* legitimate application of a self-test setUp()/tearDown().
|
||||
**/
|
||||
extern void path_reset_root_dir();
|
||||
|
||||
// note: other functions are declared directly in the public file.h header.
|
||||
|
||||
|
||||
|
@ -97,6 +97,7 @@ public:
|
||||
vfs_shutdown();
|
||||
dir_delete("archivetest");
|
||||
file_delete(archive_fn);
|
||||
path_reset_root_dir();
|
||||
}
|
||||
|
||||
void test_create_archive_with_random_files()
|
||||
@ -126,4 +127,12 @@ public:
|
||||
}
|
||||
TS_ASSERT_OK(archive_close(ha));
|
||||
}
|
||||
|
||||
void test_multiple_init_shutdown()
|
||||
{
|
||||
vfs_init();
|
||||
vfs_shutdown();
|
||||
vfs_init();
|
||||
vfs_shutdown();
|
||||
}
|
||||
};
|
||||
|
@ -738,12 +738,13 @@ void vfs_display()
|
||||
}
|
||||
|
||||
|
||||
// allow init more complicated than merely calling mount_init by
|
||||
// splitting this into a separate function.
|
||||
static void vfs_init_once(void)
|
||||
static enum VfsInitState
|
||||
{
|
||||
mount_init();
|
||||
VFS_BEFORE_INIT,
|
||||
VFS_INITIALIZED,
|
||||
VFS_SHUTDOWN
|
||||
}
|
||||
vfs_init_state;
|
||||
|
||||
// make the VFS tree ready for use. must be called before all other
|
||||
// functions below, barring explicit mentions to the contrary.
|
||||
@ -754,14 +755,21 @@ static void vfs_init_once(void)
|
||||
// is necessary anyway and this way is simpler/easier to maintain.
|
||||
void vfs_init()
|
||||
{
|
||||
debug_assert(vfs_init_state == VFS_BEFORE_INIT || vfs_init_state == VFS_SHUTDOWN);
|
||||
|
||||
stats_vfs_init_start();
|
||||
static pthread_once_t once = PTHREAD_ONCE_INIT;
|
||||
WARN_ERR(pthread_once(&once, vfs_init_once));
|
||||
mount_init();
|
||||
stats_vfs_init_finish();
|
||||
|
||||
vfs_init_state = VFS_INITIALIZED;
|
||||
}
|
||||
|
||||
void vfs_shutdown()
|
||||
{
|
||||
debug_assert(vfs_init_state == VFS_INITIALIZED);
|
||||
|
||||
trace_shutdown();
|
||||
mount_shutdown();
|
||||
|
||||
vfs_init_state = VFS_SHUTDOWN;
|
||||
}
|
||||
|
@ -540,6 +540,8 @@ void tree_shutdown()
|
||||
// freeing memory they hold.
|
||||
tree_root->clearR();
|
||||
|
||||
tree_root_shutdown();
|
||||
|
||||
// free memory underlying the nodes themselves.
|
||||
node_shutdown();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user