(#3767) Some protection from malicious qvms - patches and ideas by Amanieu d'Antras and Ben Millwood
This commit is contained in:
parent
657c791257
commit
8c3f320504
12 changed files with 155 additions and 26 deletions
|
@ -588,6 +588,20 @@ void Cmd_TokenizeStringIgnoreQuotes( const char *text_in ) {
|
|||
Cmd_TokenizeString2( text_in, qtrue );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_FindCommand
|
||||
============
|
||||
*/
|
||||
cmd_function_t *Cmd_FindCommand( const char *cmd_name )
|
||||
{
|
||||
cmd_function_t *cmd;
|
||||
for( cmd = cmd_functions; cmd; cmd = cmd->next )
|
||||
if( !Q_stricmp( cmd_name, cmd->name ) )
|
||||
return cmd;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_AddCommand
|
||||
|
@ -597,14 +611,12 @@ void Cmd_AddCommand( const char *cmd_name, xcommand_t function ) {
|
|||
cmd_function_t *cmd;
|
||||
|
||||
// fail if the command already exists
|
||||
for ( cmd = cmd_functions ; cmd ; cmd=cmd->next ) {
|
||||
if ( !strcmp( cmd_name, cmd->name ) ) {
|
||||
// allow completion-only commands to be silently doubled
|
||||
if ( function != NULL ) {
|
||||
Com_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if( Cmd_FindCommand( cmd_name ) )
|
||||
{
|
||||
// allow completion-only commands to be silently doubled
|
||||
if( function != NULL )
|
||||
Com_Printf( "Cmd_AddCommand: %s already defined\n", cmd_name );
|
||||
return;
|
||||
}
|
||||
|
||||
// use a small malloc to avoid zone fragmentation
|
||||
|
@ -658,6 +670,28 @@ void Cmd_RemoveCommand( const char *cmd_name ) {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_RemoveCommandSafe
|
||||
|
||||
Only remove commands with no associated function
|
||||
============
|
||||
*/
|
||||
void Cmd_RemoveCommandSafe( const char *cmd_name )
|
||||
{
|
||||
cmd_function_t *cmd = Cmd_FindCommand( cmd_name );
|
||||
|
||||
if( !cmd )
|
||||
return;
|
||||
if( cmd->function )
|
||||
{
|
||||
Com_Error( ERR_DROP, "Restricted source tried to remove "
|
||||
"system command \"%s\"\n", cmd_name );
|
||||
return;
|
||||
}
|
||||
|
||||
Cmd_RemoveCommand( cmd_name );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
|
|
|
@ -363,6 +363,18 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
|
|||
flags &= ~CVAR_VM_CREATED;
|
||||
}
|
||||
|
||||
// Make sure servers cannot mark engine-added variables as SERVER_CREATED
|
||||
if(var->flags & CVAR_SERVER_CREATED)
|
||||
{
|
||||
if(!(flags & CVAR_SERVER_CREATED))
|
||||
var->flags &= ~CVAR_SERVER_CREATED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(flags & CVAR_SERVER_CREATED)
|
||||
flags &= ~CVAR_SERVER_CREATED;
|
||||
}
|
||||
|
||||
var->flags |= flags;
|
||||
|
||||
// only allow one non-empty reset string without a warning
|
||||
|
@ -610,6 +622,28 @@ void Cvar_Set( const char *var_name, const char *value) {
|
|||
Cvar_Set2 (var_name, value, qtrue);
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_SetSafe
|
||||
============
|
||||
*/
|
||||
void Cvar_SetSafe( const char *var_name, const char *value )
|
||||
{
|
||||
int flags = Cvar_Flags( var_name );
|
||||
|
||||
if( flags != CVAR_NONEXISTENT && flags & CVAR_PROTECTED )
|
||||
{
|
||||
if( value )
|
||||
Com_Error( ERR_DROP, "Restricted source tried to set "
|
||||
"\"%s\" to \"%s\"\n", var_name, value );
|
||||
else
|
||||
Com_Error( ERR_DROP, "Restricted source tried to "
|
||||
"modify \"%s\"\n", var_name );
|
||||
return;
|
||||
}
|
||||
Cvar_Set( var_name, value );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_SetLatched
|
||||
|
@ -635,6 +669,21 @@ void Cvar_SetValue( const char *var_name, float value) {
|
|||
Cvar_Set (var_name, val);
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_SetValueSafe
|
||||
============
|
||||
*/
|
||||
void Cvar_SetValueSafe( const char *var_name, float value )
|
||||
{
|
||||
char val[32];
|
||||
|
||||
if( Q_isintegral( value ) )
|
||||
Com_sprintf( val, sizeof(val), "%i", (int)value );
|
||||
else
|
||||
Com_sprintf( val, sizeof(val), "%f", value );
|
||||
Cvar_SetSafe( var_name, val );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
|
|
|
@ -2910,13 +2910,13 @@ static void FS_Startup( const char *gameName )
|
|||
fs_packFiles = 0;
|
||||
|
||||
fs_debug = Cvar_Get( "fs_debug", "0", 0 );
|
||||
fs_basepath = Cvar_Get ("fs_basepath", Sys_DefaultInstallPath(), CVAR_INIT );
|
||||
fs_basepath = Cvar_Get ("fs_basepath", Sys_DefaultInstallPath(), CVAR_INIT|CVAR_PROTECTED );
|
||||
fs_basegame = Cvar_Get ("fs_basegame", "", CVAR_INIT );
|
||||
homePath = Sys_DefaultHomePath();
|
||||
if (!homePath || !homePath[0]) {
|
||||
homePath = fs_basepath->string;
|
||||
}
|
||||
fs_homepath = Cvar_Get ("fs_homepath", homePath, CVAR_INIT );
|
||||
fs_homepath = Cvar_Get ("fs_homepath", homePath, CVAR_INIT|CVAR_PROTECTED );
|
||||
fs_gamedirvar = Cvar_Get ("fs_game", "", CVAR_INIT|CVAR_SYSTEMINFO );
|
||||
|
||||
// add search path elements in reverse priority order
|
||||
|
@ -2926,7 +2926,7 @@ static void FS_Startup( const char *gameName )
|
|||
// fs_homepath is somewhat particular to *nix systems, only add if relevant
|
||||
|
||||
#ifdef MACOS_X
|
||||
fs_apppath = Cvar_Get ("fs_apppath", Sys_DefaultAppPath(), CVAR_INIT );
|
||||
fs_apppath = Cvar_Get ("fs_apppath", Sys_DefaultAppPath(), CVAR_INIT|CVAR_PROTECTED );
|
||||
// Make MacOSX also include the base path included with the .app bundle
|
||||
if (fs_apppath->string[0])
|
||||
FS_AddGameDirectory(fs_apppath->string, gameName);
|
||||
|
|
|
@ -815,6 +815,7 @@ default values.
|
|||
|
||||
#define CVAR_SERVER_CREATED 0x0800 // cvar was created by a server the client connected to.
|
||||
#define CVAR_VM_CREATED 0x1000 // cvar was created exclusively in one of the VMs.
|
||||
#define CVAR_PROTECTED 0x2000 // prevent modifying this var from VMs or the server
|
||||
#define CVAR_NONEXISTENT 0xFFFFFFFF // Cvar doesn't exist.
|
||||
|
||||
// nothing outside the Cvar_*() functions should modify these fields!
|
||||
|
|
|
@ -430,6 +430,9 @@ void Cmd_RemoveCommand( const char *cmd_name );
|
|||
|
||||
typedef void (*completionFunc_t)( char *args, int argNum );
|
||||
|
||||
// don't allow VMs to remove system commands
|
||||
void Cmd_RemoveCommandSafe( const char *cmd_name );
|
||||
|
||||
void Cmd_CommandCompletion( void(*callback)(const char *s) );
|
||||
// callback with each valid string
|
||||
void Cmd_SetCommandCompletionFunc( const char *command,
|
||||
|
@ -501,11 +504,15 @@ void Cvar_Update( vmCvar_t *vmCvar );
|
|||
void Cvar_Set( const char *var_name, const char *value );
|
||||
// will create the variable with no flags if it doesn't exist
|
||||
|
||||
void Cvar_SetSafe( const char *var_name, const char *value );
|
||||
// sometimes we set variables from an untrusted source: fail if flags & CVAR_PROTECTED
|
||||
|
||||
void Cvar_SetLatched( const char *var_name, const char *value);
|
||||
// don't set the cvar immediately
|
||||
|
||||
void Cvar_SetValue( const char *var_name, float value );
|
||||
// expands value to a string and calls Cvar_Set
|
||||
void Cvar_SetValueSafe( const char *var_name, float value );
|
||||
// expands value to a string and calls Cvar_Set/Cvar_SetSafe
|
||||
|
||||
float Cvar_VariableValue( const char *var_name );
|
||||
int Cvar_VariableIntegerValue( const char *var_name );
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue