diff -Nru dosbox-0.74/debian/changelog dosbox-0.74/debian/changelog --- dosbox-0.74/debian/changelog 2017-09-25 17:42:37.000000000 +0000 +++ dosbox-0.74/debian/changelog 2022-03-30 10:03:50.000000000 +0000 @@ -1,3 +1,19 @@ +dosbox (0.74-4.3ubuntu0.1) bionic-security; urgency=medium + + * SECURITY UPDATE: code execution through buffer overflow + - debian/patches/cve-2019-7165.patch: add boundary checks + in shell_batch.cpp + - CVE-2019-7165 + * SECURITY UPDATE: incorrect access control + - debian/patches/cve-2019-12594.patch: add check function + when opening files to prevent access to /proc content in + include/cross.h, src/dos/dos_programs.cpp, + src/dos/drive_fat.cpp, src/dos/drive_local.cpp and + src/misc/cross.cpp + - CVE-2019-12594 + + -- David Fernandez Gonzalez Wed, 30 Mar 2022 12:03:50 +0200 + dosbox (0.74-4.3) unstable; urgency=medium * non-maintainer upload. diff -Nru dosbox-0.74/debian/control dosbox-0.74/debian/control --- dosbox-0.74/debian/control 2015-10-13 08:20:00.000000000 +0000 +++ dosbox-0.74/debian/control 2022-03-30 10:03:50.000000000 +0000 @@ -1,7 +1,8 @@ Source: dosbox Section: otherosfs Priority: optional -Maintainer: Jan Dittberner +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Jan Dittberner Homepage: http://www.dosbox.com/ Build-Depends: debhelper (>= 9), libsdl1.2-dev, libpng-dev, libsdl-net1.2-dev, libsdl-sound1.2-dev, libasound2-dev, autotools-dev diff -Nru dosbox-0.74/debian/patches/cve-2019-12594.patch dosbox-0.74/debian/patches/cve-2019-12594.patch --- dosbox-0.74/debian/patches/cve-2019-12594.patch 1970-01-01 00:00:00.000000000 +0000 +++ dosbox-0.74/debian/patches/cve-2019-12594.patch 2022-03-30 10:03:50.000000000 +0000 @@ -0,0 +1,195 @@ +commit 3927312fd714c6511e0796b6153b8cd1ac546dbe +Author: qbix79 +Date: Tue Jun 25 18:04:08 2019 +0000 +Subject: 0_74_3 add basic (linux) access control here as well. + + git-svn-id: https://svn.code.sf.net/p/dosbox/code-0/dosbox/branches/0_74_3@4246 ed541006-0bf7-43e9-8c4d-6fc63c346d47 + +--- a/include/cross.h ++++ b/include/cross.h +@@ -105,4 +105,5 @@ + bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory); + void close_directory(dir_information* dirp); + ++FILE *fopen_wrap(const char *path, const char *mode); + #endif +--- a/src/dos/dos_programs.cpp ++++ b/src/dos/dos_programs.cpp +@@ -528,9 +528,9 @@ + //File not found on mounted filesystem. Try regular filesystem + std::string filename_s(filename); + Cross::ResolveHomedir(filename_s); +- tmpfile = fopen(filename_s.c_str(),"rb+"); ++ tmpfile = fopen_wrap(filename_s.c_str(),"rb+"); + if(!tmpfile) { +- if( (tmpfile = fopen(filename_s.c_str(),"rb")) ) { ++ if( (tmpfile = fopen_wrap(filename_s.c_str(),"rb")) ) { + //File exists; So can't be opened in correct mode => error 2 + // fclose(tmpfile); + // if(tryload) error = 2; +@@ -1196,7 +1196,7 @@ + + if(fstype=="fat") { + if (imgsizedetect) { +- FILE * diskfile = fopen(temp_line.c_str(), "rb+"); ++ FILE * diskfile = fopen_wrap(temp_line.c_str(), "rb+"); + if(!diskfile) { + WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_IMAGE")); + return; +@@ -1231,7 +1231,7 @@ + } + } else if (fstype=="iso") { + } else { +- FILE *newDisk = fopen(temp_line.c_str(), "rb+"); ++ FILE *newDisk = fopen_wrap(temp_line.c_str(), "rb+"); + fseek(newDisk,0L, SEEK_END); + imagesize = (ftell(newDisk) / 1024); + +--- a/src/dos/drive_fat.cpp ++++ b/src/dos/drive_fat.cpp +@@ -639,7 +639,7 @@ + imgDTA = new DOS_DTA(imgDTAPtr); + } + +- diskfile = fopen(sysFilename, "rb+"); ++ diskfile = fopen_wrap(sysFilename, "rb+"); + if(!diskfile) {created_successfully = false;return;} + fseek(diskfile, 0L, SEEK_END); + filesize = (Bit32u)ftell(diskfile) / 1024L; +--- a/src/dos/drive_local.cpp ++++ b/src/dos/drive_local.cpp +@@ -56,16 +56,16 @@ + CROSS_FILENAME(newname); + char* temp_name = dirCache.GetExpandName(newname); //Can only be used in till a new drive_cache action is preformed */ + /* Test if file exists (so we need to truncate it). don't add to dirCache then */ +- bool existing_file=false; ++ bool existing_file = false; + +- FILE * test=fopen(temp_name,"rb+"); ++ FILE * test = fopen_wrap(temp_name,"rb+"); + if(test) { + fclose(test); + existing_file=true; + + } + +- FILE * hand=fopen(temp_name,"wb+"); ++ FILE * hand = fopen_wrap(temp_name,"wb+"); + if (!hand){ + LOG_MSG("Warning: file creation failed: %s",newname); + return false; +@@ -95,11 +95,11 @@ + CROSS_FILENAME(newname); + dirCache.ExpandName(newname); + +- FILE * hand=fopen(newname,type); ++ FILE * hand = fopen_wrap(newname,type); + // Bit32u err=errno; + if (!hand) { + if((flags&0xf) != OPEN_READ) { +- FILE * hmm=fopen(newname,"rb"); ++ FILE * hmm = fopen_wrap(newname,"rb"); + if (hmm) { + fclose(hmm); + LOG_MSG("Warning: file %s exists and failed to open in write mode.\nPlease Remove write-protection",newname); +@@ -122,7 +122,7 @@ + CROSS_FILENAME(newname); + dirCache.ExpandName(newname); + +- return fopen(newname,type); ++ return fopen_wrap(newname,type); + } + + bool localDrive::GetSystemFilename(char *sysName, char const * const dosName) { +@@ -145,7 +145,7 @@ + struct stat buffer; + if(stat(fullname,&buffer)) return false; // File not found. + +- FILE* file_writable = fopen(fullname,"rb+"); ++ FILE* file_writable = fopen_wrap(fullname,"rb+"); + if(!file_writable) return false; //No acces ? ERROR MESSAGE NOT SET. FIXME ? + fclose(file_writable); + +--- a/src/misc/cross.cpp ++++ b/src/misc/cross.cpp +@@ -22,6 +22,7 @@ + #include "cross.h" + #include "support.h" + #include ++#include + #include + + #ifdef WIN32 +@@ -252,3 +253,60 @@ + } + + #endif ++ ++FILE *fopen_wrap(const char *path, const char *mode) { ++#if defined(WIN32) || defined(OS2) ++ ; ++#elif defined (MACOSX) ++ ; ++#else ++#if defined (HAVE_REALPATH) ++ char work[CROSS_LEN] = {0}; ++ strncpy(work,path,CROSS_LEN-1); ++ char* last = strrchr(work,'/'); ++ ++ if (last) { ++ if (last != work) { ++ *last = 0; ++ //If this compare fails, then we are dealing with files in / ++ //Which is outside the scope, but test anyway. ++ //However as realpath only works for exising files. The testing is ++ //in that case not done against new files. ++ } ++ char* check = realpath(work,NULL); ++ if (check) { ++ if ( ( strlen(check) == 5 && strcmp(check,"/proc") == 0) || strncmp(check,"/proc/",6) == 0) { ++// LOG_MSG("lst hit %s blocking!",path); ++ free(check); ++ return NULL; ++ } ++ free(check); ++ } ++ } ++ ++#if 0 ++//Lightweight version, but then existing files can still be read, which is not ideal ++ if (strpbrk(mode,"aw+") != NULL) { ++ LOG_MSG("pbrk ok"); ++ char* check = realpath(path,NULL); ++ //Will be null if file doesn't exist.... ENOENT ++ //TODO What about unlink /proc/self/mem and then create it ? ++ //Should be safe for what we want.. ++ if (check) { ++ if (strncmp(check,"/proc/",6) == 0) { ++ free(check); ++ return NULL; ++ } ++ free(check); ++ } ++ } ++*/ ++#endif //0 ++ ++#endif //HAVE_REALPATH ++#endif ++ ++ return fopen(path,mode); ++} ++ ++ +--- a/configure.in ++++ b/configure.in +@@ -436,6 +436,9 @@ + AC_CHECK_FUNC([mprotect],[AC_DEFINE(C_HAVE_MPROTECT,1)]) + ]) + ++dnl Check for realpath. Used on Linux ++AC_CHECK_FUNCS([realpath]) ++ + dnl Setpriority + AH_TEMPLATE(C_SET_PRIORITY,[Define to 1 if you have setpriority support]) + AC_MSG_CHECKING(for setpriority support) diff -Nru dosbox-0.74/debian/patches/cve-2019-7165.patch dosbox-0.74/debian/patches/cve-2019-7165.patch --- dosbox-0.74/debian/patches/cve-2019-7165.patch 1970-01-01 00:00:00.000000000 +0000 +++ dosbox-0.74/debian/patches/cve-2019-7165.patch 2022-03-30 10:03:50.000000000 +0000 @@ -0,0 +1,149 @@ +commit 899d06ca59e3d82e15618f230c30542b3efb0f15 +Author: qbix79 +Date: Wed Jul 15 16:31:35 2015 +0000 +Subject: Ignore/remove single % in batchfiles. (Fixes B13Demo batchfiles on pcgamer coverdisc 1995-08) + Remove magic constants. + Add some boundary checks. + + git-svn-id: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3925 ed541006-0bf7-43e9-8c4d-6fc63c346d47 + +--- a/src/shell/shell_batch.cpp ++++ b/src/shell/shell_batch.cpp +@@ -35,7 +35,7 @@ + filename = totalname; + + //Test if file is openable +- if (!DOS_OpenFile(totalname,128,&file_handle)) { ++ if (!DOS_OpenFile(totalname,(DOS_NOT_INHERIT|OPEN_READ),&file_handle)) { + //TODO Come up with something better + E_Exit("SHELL:Can't open BatchFile %s",totalname); + } +@@ -50,7 +50,7 @@ + + bool BatchFile::ReadLine(char * line) { + //Open the batchfile and seek to stored postion +- if (!DOS_OpenFile(filename.c_str(),128,&file_handle)) { ++ if (!DOS_OpenFile(filename.c_str(),(DOS_NOT_INHERIT|OPEN_READ),&file_handle)) { + LOG(LOG_MISC,LOG_ERROR)("ReadLine Can't open BatchFile %s",filename.c_str()); + delete this; + return false; +@@ -69,8 +69,12 @@ + * Exclusion list: tab for batch files + * escape for ansi + * backspace for alien odyssey */ +- if (c>31 || c==0x1b || c=='\t' || c==8) +- *cmd_write++=c; ++ if (c>31 || c==0x1b || c=='\t' || c==8) { ++ //Only add it if room for it (and trailing zero) in the buffer, but do the check here instead at the end ++ //So we continue reading till EOL/EOF ++ if (((cmd_write - temp) + 1) < (CMD_MAXLINE - 1)) ++ *cmd_write++ = c; ++ } + } + } while (c!='\n' && n); + *cmd_write=0; +@@ -86,55 +90,64 @@ + /* Now parse the line read from the bat file for % stuff */ + cmd_write=line; + char * cmd_read=temp; +- char env_name[256];char * env_write; + while (*cmd_read) { +- env_write=env_name; +- if (*cmd_read=='%') { ++ if (*cmd_read == '%') { + cmd_read++; + if (cmd_read[0] == '%') { + cmd_read++; +- *cmd_write++='%'; ++ if (((cmd_write - line) + 1) < (CMD_MAXLINE - 1)) ++ *cmd_write++ = '%'; + continue; + } + if (cmd_read[0] == '0') { /* Handle %0 */ + const char *file_name = cmd->GetFileName(); + cmd_read++; +- strcpy(cmd_write,file_name); +- cmd_write+=strlen(file_name); ++ size_t name_len = strlen(file_name); ++ if (((cmd_write - line) + name_len) < (CMD_MAXLINE - 1)) { ++ strcpy(cmd_write,file_name); ++ cmd_write += name_len; ++ } + continue; + } + char next = cmd_read[0]; +- if(next > '0' && next <= '9') { ++ if(next > '0' && next <= '9') { + /* Handle %1 %2 .. %9 */ + cmd_read++; //Progress reader + next -= '0'; + if (cmd->GetCount()<(unsigned int)next) continue; + std::string word; + if (!cmd->FindCommand(next,word)) continue; +- strcpy(cmd_write,word.c_str()); +- cmd_write+=strlen(word.c_str()); ++ size_t name_len = strlen(word.c_str()); ++ if (((cmd_write - line) + name_len) < (CMD_MAXLINE - 1)) { ++ strcpy(cmd_write,word.c_str()); ++ cmd_write += name_len; ++ } + continue; + } else { + /* Not a command line number has to be an environment */ +- char * first=strchr(cmd_read,'%'); +- /* No env afterall.Somewhat of a hack though as %% and % aren't handled consistent in dosbox. Maybe echo needs to parse % and %% as well. */ +- if (!first) {*cmd_write++ = '%';continue;} ++ char * first = strchr(cmd_read,'%'); ++ /* No env afterall. Ignore a single % */ ++ if (!first) {/* *cmd_write++ = '%';*/continue;} + *first++ = 0; + std::string env; + if (shell->GetEnvStr(cmd_read,env)) { +- const char * equals=strchr(env.c_str(),'='); ++ const char* equals = strchr(env.c_str(),'='); + if (!equals) continue; + equals++; +- strcpy(cmd_write,equals); +- cmd_write+=strlen(equals); ++ size_t name_len = strlen(equals); ++ if (((cmd_write - line) + name_len) < (CMD_MAXLINE - 1)) { ++ strcpy(cmd_write,equals); ++ cmd_write += name_len; ++ } + } +- cmd_read=first; ++ cmd_read = first; + } + } else { +- *cmd_write++=*cmd_read++; ++ if (((cmd_write - line) + 1) < (CMD_MAXLINE - 1)) ++ *cmd_write++ = *cmd_read++; + } + } +- *cmd_write=0; ++ *cmd_write = 0; + //Store current location and close bat file + this->location = 0; + DOS_SeekFile(file_handle,&(this->location),DOS_SEEK_CUR); +@@ -144,7 +157,7 @@ + + bool BatchFile::Goto(char * where) { + //Open bat file and search for the where string +- if (!DOS_OpenFile(filename.c_str(),128,&file_handle)) { ++ if (!DOS_OpenFile(filename.c_str(),(DOS_NOT_INHERIT|OPEN_READ),&file_handle)) { + LOG(LOG_MISC,LOG_ERROR)("SHELL:Goto Can't open BatchFile %s",filename.c_str()); + delete this; + return false; +@@ -161,8 +174,10 @@ + n=1; + DOS_ReadFile(file_handle,&c,&n); + if (n>0) { +- if (c>31) +- *cmd_write++=c; ++ if (c>31) { ++ if (((cmd_write - cmd_buffer) + 1) < (CMD_MAXLINE - 1)) ++ *cmd_write++ = c; ++ } + } + } while (c!='\n' && n); + *cmd_write++ = 0; diff -Nru dosbox-0.74/debian/patches/series dosbox-0.74/debian/patches/series --- dosbox-0.74/debian/patches/series 2017-09-25 17:41:02.000000000 +0000 +++ dosbox-0.74/debian/patches/series 2022-03-30 10:03:36.000000000 +0000 @@ -4,3 +4,5 @@ wine-move-z-mount-svn3736.patch wine-style-namemangling-svn3742.patch update-64bit-recompiler.patch +cve-2019-7165.patch +cve-2019-12594.patch