diff --git a/Changelog.md b/Changelog.md index e666f8d6..855d5b45 100644 --- a/Changelog.md +++ b/Changelog.md @@ -50,14 +50,24 @@ Note: Numbers starting with a "#" like #330 refer to the bugreport with that num * `s_alReverbGain` CVar to reduce EFX reverb effect intensity (#365) * Pause (looped) sounds when entering menu (#330) * Fixes for looped sounds (#390) -* (Optionally) use libbacktrace on non-Windows platforms for more useful - backtraces in case of crashes (usually linked statically) * Replace libjpeg with stb_image and libogg/libvorbis(file) with stb_vorbis - Now the only required external dependencies should be OpenAL, SDL, zlib and optionally libCURL (and of course the C and C++ runtimes) +* (Optionally) use libbacktrace on non-Windows platforms for more useful + backtraces in case of crashes (usually linked statically) * Fixed a deadlock (freeze) on Windows when printing messages from another thread * Fixed some warnings and uninitialized variables (thanks *turol*!) * Work around dmap bug caused by GCC using FMA "optimizations" (#147) +* Prevent dhewm3 from being run as root on Unix-like systems to improve security +* Replaced most usages of `strncpy()` with something safer to prevent buffer overflows + (remaining cases should be safe). + - Just a precaution, I don't know if any of them could actually be exploited, + but there were some compiler warnings in newer GCC versions. +* Console output is now logged to `dhewm3log.txt` (last log is renamed to `dhewm3log-old.txt`) + - On Windows it's in `My Documents/My Games/dhewm3/` + - On Mac it's in `$HOME/Library/Application Support/dhewm3/` + - On other Unix-like systems like Linux it's in `$XDG_DATA_HOME/dhewm3/` + (usually `$HOME/.local/share/dhewm3/`) 1.5.1 (2021-03-14) diff --git a/neo/sys/win32/SDL_win32_main.c b/neo/sys/win32/SDL_win32_main.c index 5f243a65..2dce3193 100644 --- a/neo/sys/win32/SDL_win32_main.c +++ b/neo/sys/win32/SDL_win32_main.c @@ -37,7 +37,7 @@ #endif /* main */ /* The standard output files */ -#define STDOUT_FILE TEXT("stdout.txt") +#define STDOUT_FILE TEXT("dhewm3log.txt") /* DG: renamed this */ #define STDERR_FILE TEXT("stderr.txt") /* Set a variable to tell if the stdio redirect has been enabled. */ @@ -197,7 +197,7 @@ static void cleanup_output(void) { } } -extern int Sys_GetHomeDir(char *dst, size_t size); +extern int Win_GetHomeDir(char *dst, size_t size); /* Redirect the output (stdout and stderr) to a file */ static void redirect_output(void) @@ -209,31 +209,32 @@ static void redirect_output(void) char path[MAX_PATH]; struct _stat st; - // DG: use "My Documents/My Games/dhewm3" to write stdout.txt and stderr.txt - // instead of the binary, which might not be writable - Sys_GetHomeDir(path, sizeof(path)); + /* DG: use "My Documents/My Games/dhewm3" to write stdout.txt and stderr.txt + * instead of the binary, which might not be writable */ + Win_GetHomeDir(path, sizeof(path)); if (_stat(path, &st) == -1) { - // oops, "My Documents/My Games/dhewm3" doesn't exist - does My Games/ at least exist? + /* oops, "My Documents/My Games/dhewm3" doesn't exist - does My Games/ at least exist? */ char myGamesPath[MAX_PATH]; + char* lastslash; memcpy(myGamesPath, path, MAX_PATH); - char* lastslash = strrchr(myGamesPath, '/'); + lastslash = strrchr(myGamesPath, '/'); if (lastslash != NULL) { *lastslash = '\0'; } if (_stat(myGamesPath, &st) == -1) { - // if My Documents/My Games/ doesn't exist, create it + /* if My Documents/My Games/ doesn't exist, create it */ _mkdir(myGamesPath); } - _mkdir(path); // create My Documents/My Games/dhewm3/ + _mkdir(path); /* create My Documents/My Games/dhewm3/ */ } #endif FILE *newfp; -#if 0 // DG: don't do this anymore. +#if 0 /* DG: don't do this anymore. */ DWORD pathlen; pathlen = GetModuleFileName(NULL, path, SDL_arraysize(path)); while ( pathlen > 0 && path[pathlen] != '\\' ) { @@ -250,6 +251,20 @@ static void redirect_output(void) SDL_strlcat( stdoutPath, DIR_SEPERATOR STDOUT_FILE, SDL_arraysize(stdoutPath) ); #endif + { /* DG: rename old stdout log */ +#ifdef _WIN32_WCE + wchar_t stdoutPathBK[MAX_PATH]; + wcsncpy( stdoutPathBK, path, SDL_arraysize(stdoutPath) ); + wcsncat( stdoutPathBK, DIR_SEPERATOR TEXT("dhewm3log-old.txt"), SDL_arraysize(stdoutPath) ); + _wrename( stdoutPath, stdoutpathBK ); +#else + char stdoutPathBK[MAX_PATH]; + SDL_strlcpy( stdoutPathBK, path, SDL_arraysize(stdoutPath) ); + SDL_strlcat( stdoutPathBK, DIR_SEPERATOR TEXT("dhewm3log-old.txt"), SDL_arraysize(stdoutPath) ); + rename( stdoutPath, stdoutPathBK ); +#endif + } /* DG end */ + /* Redirect standard input and standard output */ newfp = freopen(stdoutPath, TEXT("w"), stdout); diff --git a/neo/sys/win32/win_main.cpp b/neo/sys/win32/win_main.cpp index 759c7a60..8b3a1c81 100644 --- a/neo/sys/win32/win_main.cpp +++ b/neo/sys/win32/win_main.cpp @@ -377,7 +377,7 @@ static int WPath2A(char *dst, size_t size, const WCHAR *src) { /* ============== Returns "My Documents"/My Games/dhewm3 directory (or equivalent - "CSIDL_PERSONAL"). -To be used with Sys_DefaultSavePath(), so savegames, screenshots etc will be +To be used with Sys_GetPath(PATH_SAVE), so savegames, screenshots etc will be saved to the users files instead of systemwide. Based on (with kind permission) Yamagi Quake II's Sys_GetHomeDir() @@ -386,7 +386,7 @@ Returns the number of characters written to dst ============== */ extern "C" { // DG: I need this in SDL_win32_main.c - int Sys_GetHomeDir(char *dst, size_t size) + int Win_GetHomeDir(char *dst, size_t size) { int len; WCHAR profile[MAX_OSPATH]; @@ -481,7 +481,7 @@ bool Sys_GetPath(sysPath_t type, idStr &path) { case PATH_CONFIG: case PATH_SAVE: - if (Sys_GetHomeDir(buf, sizeof(buf)) < 1) { + if (Win_GetHomeDir(buf, sizeof(buf)) < 1) { Sys_Error("ERROR: Couldn't get dir to home path"); return false; } @@ -748,6 +748,11 @@ void Sys_Init( void ) { #if 0 cmdSystem->AddCommand( "setAsyncSound", Sys_SetAsyncSound_f, CMD_FL_SYSTEM, "set the async sound option" ); #endif + { + idStr savepath; + Sys_GetPath( PATH_SAVE, savepath ); + common->Printf( "Logging console output to %s/dhewm3log.txt\n", savepath.c_str() ); + } // // Windows version @@ -1002,6 +1007,16 @@ WinMain ================== */ int main(int argc, char *argv[]) { + // SDL_win32_main.c creates the dhewm3log.txt and redirects stdout into it + // so here we can log its (approx.) creation time before anything else is logged: + { + time_t tt = time(NULL); + const struct tm* tms = localtime(&tt); + char timeStr[64] = {}; + strftime(timeStr, sizeof(timeStr), "%F %H:%M:%S", tms); + printf("Opened this log at %s\n", timeStr); + } + const HCURSOR hcurSave = ::SetCursor( LoadCursor( 0, IDC_WAIT ) ); InitializeCriticalSection( &printfCritSect );