1
1
forked from 0ad/0ad

# 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:
janwas 2006-10-20 17:29:55 +00:00
parent 751f0ca377
commit abec0f17b9
5 changed files with 57 additions and 14 deletions

View File

@ -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
//-----------------------------------------------------------------------------

View File

@ -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.

View File

@ -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();
}
};

View File

@ -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;
}

View File

@ -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();
}