Headline
CVE-2022-48579: Updated to 6.2.3 · pmachapman/unrar@2ecab6b
UnRAR before 6.2.3 allows extraction of files outside of the destination folder via symlink chains.
Expand Up @@ -12,6 +12,12 @@ CmdExtract::CmdExtract(CommandData *Cmd) memset(Analyze,0,sizeof(*Analyze));
TotalFileCount=0;
// Common for all archives involved. Set here instead of DoExtract() // to use in unrar.dll too. Allows to avoid LinksToDirs() calls // and save CPU time in no symlinks including “…” in target were extracted. UpLinkExtracted=false;
Unp=new Unpack(&DataIO); #ifdef RAR_SMP Unp->SetThreads(Cmd->Threads); Expand Down Expand Up @@ -125,6 +131,8 @@ void CmdExtract::ExtractArchiveInit(Archive &Arc) ArcAnalyzed=false;
StartTime.SetCurrentTime();
LastCheckedSymlink.clear(); }
Expand Down Expand Up @@ -618,6 +626,10 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) wcsncpyz(DestFileName,Cmd->DllDestName,ASIZE(DestFileName)); #endif
if (ExtrFile && Command!=’P’ && !Cmd->Test && !Cmd->AbsoluteLinks && UpLinkExtracted) ExtrFile=LinksToDirs(DestFileName,Cmd->ExtrPath,LastCheckedSymlink);
File CurFile;
bool LinkEntry=Arc.FileHead.RedirType!=FSREDIR_NONE; Expand Down Expand Up @@ -747,7 +759,17 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) if (Type==FSREDIR_HARDLINK || Type==FSREDIR_FILECOPY) { wchar RedirName[NM]; ConvertPath(Arc.FileHead.RedirName,RedirName,ASIZE(RedirName));
// 2022.11.15: Might be needed when unpacking WinRAR 5.0 links with // Unix RAR. WinRAR 5.0 used \ path separators here, when beginning // from 5.10 even Windows version uses / internally and converts // them to \ when reading FHEXTRA_REDIR. // We must perform this conversion before ConvertPath call, // so paths mixing different slashes like \dir1/dir2\file are // processed correctly. SlashToNative(Arc.FileHead.RedirName,RedirName,ASIZE(RedirName));
ConvertPath(RedirName,RedirName,ASIZE(RedirName));
wchar NameExisting[NM]; ExtrPrepareName(Arc,RedirName,NameExisting,ASIZE(NameExisting)); Expand All @@ -761,7 +783,22 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) if (Type==FSREDIR_UNIXSYMLINK || Type==FSREDIR_WINSYMLINK || Type==FSREDIR_JUNCTION) { if (FileCreateMode) LinkSuccess=ExtractSymlink(Cmd,DataIO,Arc,DestFileName); { bool UpLink; LinkSuccess=ExtractSymlink(Cmd,DataIO,Arc,DestFileName,UpLink); UpLinkExtracted|=LinkSuccess && UpLink;
// We do not actually need to reset the cache here if we cache // only the single last checked path, because at this point // it will always contain the link own path and link can’t // overwrite its parent folder. But if we ever decide to cache // several already checked paths, we’ll need to reset them here. // Otherwise if no files were created in one of such paths, // let’s say because of file create error, it might be possible // to overwrite the path with link and avoid checks. We keep this // code here as a reminder in case of possible modifications. LastCheckedSymlink.clear(); // Reset cache for safety reason. } } else { Expand Down Expand Up @@ -948,8 +985,6 @@ void CmdExtract::UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize)
bool CmdExtract::ExtractFileCopy(File &New,wchar *ArcName,const wchar *RedirName,wchar *NameNew,wchar *NameExisting,size_t NameExistingSize,int64 UnpSize) { SlashToNative(NameExisting,NameExisting,NameExistingSize); // Not needed for RAR 5.1+ archives.
File Existing; if (!Existing.Open(NameExisting)) { Expand Down Expand Up @@ -1269,6 +1304,8 @@ void CmdExtract::ExtrCreateDir(Archive &Arc,const wchar *ArcFileName) DirExist=FileExist(DestFileName) && IsDir(GetFileAttr(DestFileName)); if (!DirExist) { if (!Cmd->AbsoluteLinks && UpLinkExtracted) LinksToDirs(DestFileName,Cmd->ExtrPath,LastCheckedSymlink); CreatePath(DestFileName,true,Cmd->DisableNames); MDCode=MakeDir(DestFileName,!Cmd->IgnoreGeneralAttr,Arc.FileHead.FileAttr); } Expand Down Expand Up @@ -1350,6 +1387,8 @@ bool CmdExtract::ExtrCreateFile(Archive &Arc,File &CurFile)
MakeNameUsable(DestFileName,true);
if (!Cmd->AbsoluteLinks && UpLinkExtracted) LinksToDirs(DestFileName,Cmd->ExtrPath,LastCheckedSymlink); CreatePath(DestFileName,true,Cmd->DisableNames); if (FileCreate(Cmd,&CurFile,DestFileName,ASIZE(DestFileName),&UserReject,Arc.FileHead.UnpSize,&Arc.FileHead.mtime,true)) { Expand Down