From eba0c790c65778dc84d65d018203e370a72d68f2 Mon Sep 17 00:00:00 2001 From: hunili Date: Wed, 13 Nov 2024 14:17:55 +0800 Subject: [PATCH] Check forbidden path issue: https://gitee.com/openharmony/filemanagement_app_file_service/issues/IB40WX Signed-off-by: hunili --- .../native/backup_ext/include/ext_extension.h | 3 + .../native/backup_ext/include/untar_file.h | 17 +- .../native/backup_ext/src/ext_extension.cpp | 282 +++++++++--------- .../backup_ext/src/sub_ext_extension.cpp | 55 ++++ .../native/backup_ext/src/untar_file.cpp | 66 +++- utils/include/b_filesystem/b_dir.h | 8 + utils/src/b_filesystem/b_dir.cpp | 8 + 7 files changed, 279 insertions(+), 160 deletions(-) diff --git a/frameworks/native/backup_ext/include/ext_extension.h b/frameworks/native/backup_ext/include/ext_extension.h index 9c450efb4..0c078b75a 100644 --- a/frameworks/native/backup_ext/include/ext_extension.h +++ b/frameworks/native/backup_ext/include/ext_extension.h @@ -284,6 +284,9 @@ private: std::function ReportErrFileByProc(wptr obj, BackupRestoreScenario scenario); + ErrCode GetIncreFileHandleForNormalVersion(const std::string &fileName); + void RestoreOneBigFile(const std::string &path, const ExtManageInfo &item, const bool appendTargetPath); + int DealIncreRestoreBigAndTarFile(); private: std::shared_mutex lock_; diff --git a/frameworks/native/backup_ext/include/untar_file.h b/frameworks/native/backup_ext/include/untar_file.h index ecdee79b6..b997490fb 100644 --- a/frameworks/native/backup_ext/include/untar_file.h +++ b/frameworks/native/backup_ext/include/untar_file.h @@ -99,10 +99,8 @@ private: * @brief creat a file * * @param path 文件路径名 - * @param mode 文件打开模式 - * @param fileType 文件类型 */ - FILE *CreateFile(std::string &path, mode_t mode, char fileType); + FILE *CreateFile(std::string &path); /** * @brief parse regular file @@ -110,7 +108,7 @@ private: * @param info 文件属性结构体 * @param typeFlag 文件类型标志 */ - ErrFileInfo ParseRegularFile(FileStatInfo &info, char typeFlag); + ErrFileInfo ParseRegularFile(FileStatInfo &info); /** * @brief handle tar buffer @@ -182,6 +180,17 @@ private: */ bool CheckIfTarBlockValid(char *buff, size_t buffLen, TarHeader *header, int &ret); + /** + * @brief deal file tag info + * + * @param errFileInfo out param, err file info + * @param info out param, file info + * @param isFilter out param, is Filter + * @param tmpFullPath in param, tmpFullPath + */ + bool DealFileTag(ErrFileInfo &errFileInfo, + FileStatInfo &info, bool &isFilter, const std::string &tmpFullPath); + private: std::string rootPath_ {}; diff --git a/frameworks/native/backup_ext/src/ext_extension.cpp b/frameworks/native/backup_ext/src/ext_extension.cpp index e2e6fae9e..3c6079d7e 100644 --- a/frameworks/native/backup_ext/src/ext_extension.cpp +++ b/frameworks/native/backup_ext/src/ext_extension.cpp @@ -315,6 +315,43 @@ static string GetIncrementalFileHandlePath(const string &fileName, const string return tarName; } +ErrCode BackupExtExtension::GetIncreFileHandleForNormalVersion(const std::string &fileName) +{ + HILOGI("extension: GetIncrementalFileHandle single to single Name:%{public}s", GetAnonyPath(fileName).c_str()); + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr) { + throw BError(BError::Codes::EXT_BROKEN_IPC, string("Failed to AGetInstance")); + } + string tarName = GetIncrementalFileHandlePath(fileName, bundleName_); + int32_t errCode = ERR_OK; + if (access(tarName.c_str(), F_OK) == 0) { + HILOGE("The file already exists, tarname = %{private}s, err =%{public}d", tarName.c_str(), errno); + errCode = errno; + } + UniqueFd fd(open(tarName.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); + if (fd < 0) { + HILOGE("Failed to open tar file = %{private}s, err = %{public}d", tarName.c_str(), errno); + errCode = errno; + } + // 对应的简报文件 + string reportName = GetReportFileName(tarName); + if (access(reportName.c_str(), F_OK) == 0) { + HILOGE("The report file already exists, Name = %{private}s, err =%{public}d", reportName.c_str(), errno); + errCode = errno; + } + UniqueFd reportFd(open(reportName.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); + if (reportFd < 0) { + HILOGE("Failed to open report file = %{private}s, err = %{public}d", reportName.c_str(), errno); + errCode = errno; + } + HILOGI("extension: Will notify AppIncrementalFileReady"); + auto ret = proxy->AppIncrementalFileReady(fileName, move(fd), move(reportFd), errCode); + if (ret != ERR_OK) { + HILOGE("Failed to AppIncrementalFileReady %{public}d", ret); + } + return ERR_OK; +} + ErrCode BackupExtExtension::GetIncrementalFileHandle(const string &fileName) { HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); @@ -325,43 +362,22 @@ ErrCode BackupExtExtension::GetIncrementalFileHandle(const string &fileName) throw BError(BError::Codes::EXT_INVAL_ARG, "Action is invalid"); } VerifyCaller(); - + if (BDir::CheckFilePathInvalid(fileName)) { + auto proxy = ServiceProxy::GetInstance(); + if (proxy == nullptr) { + throw BError(BError::Codes::EXT_BROKEN_IPC, string("Failed to AGetInstance")); + } + HILOGE("Check file path : %{public}s err, path is forbidden", GetAnonyPath(fileName).c_str()); + auto ret = proxy->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG)); + if (ret != ERR_OK) { + HILOGE("Failed to notify app incre done. err = %{public}d", ret); + } + return BError(BError::Codes::EXT_INVAL_ARG).GetCode(); + } if (extension_->SpecialVersionForCloneAndCloud()) { return GetIncreFileHandleForSpecialVersion(fileName); } - HILOGI("extension: GetIncrementalFileHandle single to single Name:%{public}s", GetAnonyPath(fileName).c_str()); - string tarName = GetIncrementalFileHandlePath(fileName, bundleName_); - int32_t errCode = ERR_OK; - if (access(tarName.c_str(), F_OK) == 0) { - HILOGE("The file already exists, tarname = %{private}s, err =%{public}d", tarName.c_str(), errno); - errCode = errno; - } - UniqueFd fd(open(tarName.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); - if (fd < 0) { - HILOGE("Failed to open tar file = %{private}s, err = %{public}d", tarName.c_str(), errno); - errCode = errno; - } - // 对应的简报文件 - string reportName = GetReportFileName(tarName); - if (access(reportName.c_str(), F_OK) == 0) { - HILOGE("The report file already exists, Name = %{private}s, err =%{public}d", reportName.c_str(), errno); - errCode = errno; - } - UniqueFd reportFd(open(reportName.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); - if (reportFd < 0) { - HILOGE("Failed to open report file = %{private}s, err = %{public}d", reportName.c_str(), errno); - errCode = errno; - } - HILOGI("extension: Will notify AppIncrementalFileReady"); - auto proxy = ServiceProxy::GetInstance(); - if (proxy == nullptr) { - throw BError(BError::Codes::EXT_BROKEN_IPC, string("Failed to AGetInstance")); - } - auto ret = proxy->AppIncrementalFileReady(fileName, move(fd), move(reportFd), errCode); - if (ret != ERR_OK) { - HILOGE("Failed to AppIncrementalFileReady %{public}d", ret); - } - return ERR_OK; + return GetIncreFileHandleForNormalVersion(fileName); } catch (...) { HILOGE("Failed to get incremental file handle"); DoClear(); @@ -844,6 +860,10 @@ int BackupExtExtension::DoIncrementalRestore() string tarName = path + item; // 当用户指定fullBackupOnly字段或指定版本的恢复,解压目录当前在/backup/restore + if (BDir::CheckFilePathInvalid(tarName)) { + HILOGE("Check incre tarfile path : %{public}s err, path is forbidden", GetAnonyPath(tarName).c_str()); + return ERR_INVALID_VALUE; + } unordered_map result = GetTarIncludes(tarName); if ((!extension_->SpecialVersionForCloneAndCloud()) && (!extension_->UseFullBackupOnly())) { path = "/"; @@ -925,6 +945,11 @@ void BackupExtExtension::RestoreBigFilesForSpecialCloneCloud(const ExtManageInfo } const struct stat &sta = item.sta; string fileName = item.hashName; + if (BDir::CheckFilePathInvalid(fileName)) { + HILOGE("Check big spec file path : %{public}s err, path is forbidden", GetAnonyPath(fileName).c_str()); + errFileInfos_[fileName].push_back(DEFAULT_INVAL_VALUE); + return; + } if (chmod(fileName.c_str(), sta.st_mode) != 0) { HILOGE("Failed to chmod filePath, err = %{public}d", errno); errFileInfos_[fileName].push_back(errno); @@ -957,6 +982,14 @@ ErrCode BackupExtExtension::RestoreTarForSpecialCloneCloud(const ExtManageInfo & } HILOGI("Start to untar file = %{public}s, untarPath = %{public}s", GetAnonyPath(item.hashName).c_str(), GetAnonyPath(untarPath).c_str()); + if (BDir::CheckFilePathInvalid(tarName)) { + HILOGE("Check spec tarfile hash path : %{public}s err, path is forbidden", GetAnonyPath(tarName).c_str()); + return ERR_INVALID_VALUE; + } + if (BDir::CheckFilePathInvalid(untarPath)) { + HILOGE("Check spec tarfile path : %{public}s err, path is forbidden", GetAnonyPath(untarPath).c_str()); + return ERR_INVALID_VALUE; + } auto [err, fileInfos, errInfos] = UntarFile::GetInstance().UnPacket(tarName, untarPath); if (isDebug_) { if (err != 0) { @@ -1066,6 +1099,46 @@ void BackupExtExtension::RestoreBigFileAfter(const string &filePath, const struc } } +void BackupExtExtension::RestoreOneBigFile(const std::string &path, + const ExtManageInfo &item, const bool appendTargetPath) +{ + radarRestoreInfo_.bigFileNum++; + radarRestoreInfo_.bigFileSize += static_cast(item.sta.st_size); + string itemHashName = item.hashName; + string itemFileName = item.fileName; + // check if item.hasName and fileName need decode by report item attribute + string reportPath = GetReportFileName(path + item.hashName); + UniqueFd fd(open(reportPath.data(), O_RDONLY)); + if (fd < 0) { + HILOGE("Failed to open report file = %{public}s, err = %{public}d", reportPath.c_str(), errno); + errFileInfos_[item.hashName].push_back(errno); + throw BError(BError::Codes::EXT_INVAL_ARG, string("open report file failed")); + } + BReportEntity rp(move(fd)); + rp.CheckAndUpdateIfReportLineEncoded(itemFileName); + + string fileName = path + itemHashName; + string filePath = appendTargetPath ? (path + itemFileName) : itemFileName; + if (BDir::CheckFilePathInvalid(filePath)) { + HILOGE("Check big file path : %{public}s err, path is forbidden", GetAnonyPath(filePath).c_str()); + return; + } + if (isDebug_) { + endFileInfos_[filePath] = item.sta.st_size; + } + + if (!RestoreBigFilePrecheck(fileName, path, item.hashName, filePath)) { + return; + } + if (!BFile::MoveFile(fileName, filePath)) { + errFileInfos_[filePath].push_back(errno); + HILOGE("failed to move the file. err = %{public}d", errno); + return; + } + + RestoreBigFileAfter(filePath, item.sta); +} + void BackupExtExtension::RestoreBigFiles(bool appendTargetPath) { HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); @@ -1086,38 +1159,7 @@ void BackupExtExtension::RestoreBigFiles(bool appendTargetPath) if (item.hashName.empty() || (!item.isUserTar && !item.isBigFile)) { continue; } - radarRestoreInfo_.bigFileNum++; - radarRestoreInfo_.bigFileSize += static_cast(item.sta.st_size); - string itemHashName = item.hashName; - string itemFileName = item.fileName; - // check if item.hasName and fileName need decode by report item attribute - string reportPath = GetReportFileName(path + item.hashName); - UniqueFd fd(open(reportPath.data(), O_RDONLY)); - if (fd < 0) { - HILOGE("Failed to open report file = %{public}s, err = %{public}d", reportPath.c_str(), errno); - errFileInfos_[item.hashName].push_back(errno); - throw BError(BError::Codes::EXT_INVAL_ARG, string("open report file failed")); - } - BReportEntity rp(move(fd)); - rp.CheckAndUpdateIfReportLineEncoded(itemFileName); - - string fileName = path + itemHashName; - string filePath = appendTargetPath ? (path + itemFileName) : itemFileName; - - if (isDebug_) { - endFileInfos_[filePath] = item.sta.st_size; - } - - if (!RestoreBigFilePrecheck(fileName, path, item.hashName, filePath)) { - continue; - } - if (!BFile::MoveFile(fileName, filePath)) { - errFileInfos_[filePath].push_back(errno); - HILOGE("failed to move the file. err = %{public}d", errno); - continue; - } - - RestoreBigFileAfter(filePath, item.sta); + RestoreOneBigFile(path, item, appendTargetPath); } auto end = std::chrono::system_clock::now(); radarRestoreInfo_.bigFileSpendTime = std::chrono::duration_cast(end - start).count(); @@ -1252,6 +1294,37 @@ void BackupExtExtension::AsyncTaskRestore(std::set fileSet, }); } +int BackupExtExtension::DealIncreRestoreBigAndTarFile() +{ + if (isDebug_) { + CheckTmpDirFileInfos(); + } + auto startTime = std::chrono::system_clock::now(); + // 解压 + int ret = ERR_OK; + ret = DoIncrementalRestore(); + if (ret != ERR_OK) { + HILOGE("Do incremental restore err"); + return ret; + } + // 恢复用户tar包以及大文件 + // 目的地址是否需要拼接path(临时目录),FullBackupOnly为true并且非特殊场景 + bool appendTargetPath = + extension_->UseFullBackupOnly() && !extension_->SpecialVersionForCloneAndCloud(); + RestoreBigFiles(appendTargetPath); + // delete 1.tar/manage.json + DeleteBackupIncrementalIdxFile(); + if (isDebug_) { + CheckRestoreFileInfos(); + } + auto endTime = std::chrono::system_clock::now(); + radarRestoreInfo_.totalFileSpendTime = + std::chrono::duration_cast(endTime - startTime).count(); + RecordDoRestoreRes(bundleName_, "BackupExtExtension::AsyncTaskIncrementalRestore", + radarRestoreInfo_); + return ret; +} + void BackupExtExtension::AsyncTaskIncrementalRestore() { auto task = [obj {wptr(this)}]() { @@ -1259,27 +1332,7 @@ void BackupExtExtension::AsyncTaskIncrementalRestore() BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released"); BExcepUltils::BAssert(ptr->extension_, BError::Codes::EXT_INVAL_ARG, "Extension handle have been released"); try { - if (ptr != nullptr && ptr->isDebug_) { - ptr->CheckTmpDirFileInfos(); - } - auto startTime = std::chrono::system_clock::now(); - // 解压 - int ret = ptr->DoIncrementalRestore(); - // 恢复用户tar包以及大文件 - // 目的地址是否需要拼接path(临时目录),FullBackupOnly为true并且非特殊场景 - bool appendTargetPath = - ptr->extension_->UseFullBackupOnly() && !ptr->extension_->SpecialVersionForCloneAndCloud(); - ptr->RestoreBigFiles(appendTargetPath); - // delete 1.tar/manage.json - ptr->DeleteBackupIncrementalIdxFile(); - if (ptr != nullptr && ptr->isDebug_) { - ptr->CheckRestoreFileInfos(); - } - auto endTime = std::chrono::system_clock::now(); - ptr->radarRestoreInfo_.totalFileSpendTime = - std::chrono::duration_cast(endTime - startTime).count(); - RecordDoRestoreRes(ptr->bundleName_, "BackupExtExtension::AsyncTaskIncrementalRestore", - ptr->radarRestoreInfo_); + int ret = ptr->DealIncreRestoreBigAndTarFile(); if (ret == ERR_OK) { HILOGI("after extra, do incremental restore."); ptr->AsyncTaskIncrementalRestoreForUpgrade(); @@ -2113,59 +2166,4 @@ int BackupExtExtension::DoIncrementalBackup(const vector smallFiles.size(), allFiles.size()); return err; } - -ErrCode BackupExtExtension::User0OnBackup() -{ - HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); - if (!IfAllowToBackupRestore()) { - return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore") - .GetCode(); - } - AsyncTaskUser0Backup(); - return ERR_OK; -} - -void BackupExtExtension::AsyncTaskUser0Backup() -{ - HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); - auto task = [obj {wptr(this)}]() { - auto ptr = obj.promote(); - BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released"); - const string config = ptr->extension_->GetUsrConfig(); - try { - HILOGI("Do backup, start fwk timer begin."); - bool isFwkStart; - ptr->StartFwkTimer(isFwkStart); - if (!isFwkStart) { - HILOGE("Do backup, start fwk timer fail."); - return; - } - HILOGI("Do backup, start fwk timer end."); - BJsonCachedEntity cachedEntity(config); - auto cache = cachedEntity.Structuralize(); - auto ret = ptr->User0DoBackup(cache); - if (ret != ERR_OK) { - HILOGE("User0DoBackup, err = %{pubilc}d", ret); - ptr->AppIncrementalDone(BError::GetCodeByErrno(ret)); - } - } catch (const BError &e) { - HILOGE("extension: AsyncTaskBackup error, err code:%{public}d", e.GetCode()); - ptr->AppIncrementalDone(e.GetCode()); - } catch (const exception &e) { - HILOGE("Catched an unexpected low-level exception %{public}s", e.what()); - ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode()); - } catch (...) { - HILOGE("Failed to restore the ext bundle"); - ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode()); - } - }; - - threadPool_.AddTask([task]() { - try { - task(); - } catch (...) { - HILOGE("Failed to add task to thread pool"); - } - }); -} } // namespace OHOS::FileManagement::Backup diff --git a/frameworks/native/backup_ext/src/sub_ext_extension.cpp b/frameworks/native/backup_ext/src/sub_ext_extension.cpp index 540cb94ac..b950f4d2c 100644 --- a/frameworks/native/backup_ext/src/sub_ext_extension.cpp +++ b/frameworks/native/backup_ext/src/sub_ext_extension.cpp @@ -821,6 +821,61 @@ bool BackupExtExtension::IfAllowToBackupRestore() return true; } +ErrCode BackupExtExtension::User0OnBackup() +{ + HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); + if (!IfAllowToBackupRestore()) { + return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore") + .GetCode(); + } + AsyncTaskUser0Backup(); + return ERR_OK; +} + +void BackupExtExtension::AsyncTaskUser0Backup() +{ + HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); + auto task = [obj {wptr(this)}]() { + auto ptr = obj.promote(); + BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released"); + const string config = ptr->extension_->GetUsrConfig(); + try { + HILOGI("Do backup, start fwk timer begin."); + bool isFwkStart; + ptr->StartFwkTimer(isFwkStart); + if (!isFwkStart) { + HILOGE("Do backup, start fwk timer fail."); + return; + } + HILOGI("Do backup, start fwk timer end."); + BJsonCachedEntity cachedEntity(config); + auto cache = cachedEntity.Structuralize(); + auto ret = ptr->User0DoBackup(cache); + if (ret != ERR_OK) { + HILOGE("User0DoBackup, err = %{pubilc}d", ret); + ptr->AppIncrementalDone(BError::GetCodeByErrno(ret)); + } + } catch (const BError &e) { + HILOGE("extension: AsyncTaskBackup error, err code:%{public}d", e.GetCode()); + ptr->AppIncrementalDone(e.GetCode()); + } catch (const exception &e) { + HILOGE("Catched an unexpected low-level exception %{public}s", e.what()); + ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode()); + } catch (...) { + HILOGE("Failed to restore the ext bundle"); + ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode()); + } + }; + + threadPool_.AddTask([task]() { + try { + task(); + } catch (...) { + HILOGE("Failed to add task to thread pool"); + } + }); +} + void BackupExtExtension::DoUser0Backup(const BJsonEntityExtensionConfig &usrConfig) { HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); diff --git a/frameworks/native/backup_ext/src/untar_file.cpp b/frameworks/native/backup_ext/src/untar_file.cpp index da3723215..84dacb0e1 100644 --- a/frameworks/native/backup_ext/src/untar_file.cpp +++ b/frameworks/native/backup_ext/src/untar_file.cpp @@ -18,6 +18,7 @@ #include #include "b_anony/b_anony.h" +#include "b_filesystem/b_dir.h" #include "directory_ex.h" #include "filemgmt_libhilog.h" #include "securec.h" @@ -26,6 +27,7 @@ namespace OHOS::FileManagement::Backup { using namespace std; const int32_t PATH_MAX_LEN = 4096; const int32_t OCTAL = 8; +const int DEFAULT_ERR = -1; static bool IsEmptyBlock(const char *p) { @@ -334,18 +336,31 @@ tuple UntarFile::ParseFileByTypeFlag(char typeFlag, File case REGTYPE: case AREGTYPE: info.fullPath = GenRealPath(rootPath_, info.fullPath); - errFileInfo = ParseRegularFile(info, typeFlag); + if (BDir::CheckFilePathInvalid(info.fullPath)) { + HILOGE("Check file path : %{public}s err, path is forbidden", GetAnonyPath(info.fullPath).c_str()); + return {DEFAULT_ERR, true, {{info.fullPath, {DEFAULT_ERR}}}}; + } + errFileInfo = ParseRegularFile(info); isFilter = false; break; case SYMTYPE: break; case DIRTYPE: info.fullPath = GenRealPath(rootPath_, info.fullPath); + if (BDir::CheckFilePathInvalid(info.fullPath)) { + HILOGE("Check file path : %{public}s err, path is forbidden", GetAnonyPath(info.fullPath).c_str()); + return {DEFAULT_ERR, true, {{info.fullPath, {DEFAULT_ERR}}}}; + } errFileInfo = CreateDir(info.fullPath, info.mode); isFilter = false; break; case GNUTYPE_LONGNAME: { auto result = ReadLongName(info); + if (BDir::CheckFilePathInvalid(info.fullPath) || BDir::CheckFilePathInvalid(info.longName)) { + HILOGE("Check file path : %{public}s or long name : %{public}s err, path is forbidden", + GetAnonyPath(info.fullPath).c_str(), GetAnonyPath(info.longName).c_str()); + return {DEFAULT_ERR, true, {{info.fullPath, {DEFAULT_ERR}}}}; + } errFileInfo = std::get(result); return {std::get(result), isFilter, errFileInfo}; break; @@ -361,6 +376,28 @@ tuple UntarFile::ParseFileByTypeFlag(char typeFlag, File return {0, isFilter, errFileInfo}; } +bool UntarFile::DealFileTag(ErrFileInfo &errFileInfo, + FileStatInfo &info, bool &isFilter, const std::string &tmpFullPath) +{ + if (!includes_.empty() && includes_.find(tmpFullPath) == includes_.end()) { // not in includes + if (fseeko(tarFilePtr_, pos_ + tarFileBlockCnt_ * BLOCK_SIZE, SEEK_SET) != 0) { + HILOGE("Failed to fseeko of %{private}s, err = %{public}d", info.fullPath.c_str(), errno); + errFileInfo[info.fullPath].push_back(DEFAULT_ERR); + } + return false; + } + info.fullPath = GenRealPath(rootPath_, info.fullPath); + if (BDir::CheckFilePathInvalid(info.fullPath)) { + HILOGE("Check file path : %{public}s err, path is forbidden", GetAnonyPath(info.fullPath).c_str()); + errFileInfo[info.fullPath].push_back(DEFAULT_ERR); + return false; + } + errFileInfo = ParseRegularFile(info); + isFilter = false; + return true; +} + + std::tuple UntarFile::ParseIncrementalFileByTypeFlag(char typeFlag, FileStatInfo &info) { HILOGD("untar file: %{public}s, rootPath: %{public}s", GetAnonyPath(info.fullPath).c_str(), rootPath_.c_str()); @@ -371,34 +408,35 @@ std::tuple UntarFile::ParseIncrementalFileByTypeFlag(cha switch (typeFlag) { case REGTYPE: case AREGTYPE: { - if (!includes_.empty() && includes_.find(tmpFullPath) == includes_.end()) { // not in includes - if (fseeko(tarFilePtr_, pos_ + tarFileBlockCnt_ * BLOCK_SIZE, SEEK_SET) != 0) { - HILOGE("Failed to fseeko of %{private}s, err = %{public}d", info.fullPath.c_str(), errno); - return {-1, true, {}}; - } - break; + if (!DealFileTag(errFileInfo, info, isFilter, tmpFullPath)) { + return {DEFAULT_ERR, true, errFileInfo}; } - info.fullPath = GenRealPath(rootPath_, info.fullPath); - errFileInfo = ParseRegularFile(info, typeFlag); - isFilter = false; break; } case SYMTYPE: break; case DIRTYPE: info.fullPath = GenRealPath(rootPath_, info.fullPath); + if (BDir::CheckFilePathInvalid(info.fullPath)) { + HILOGE("Check file path : %{public}s err, path is forbidden", GetAnonyPath(info.fullPath).c_str()); + return {DEFAULT_ERR, true, {{info.fullPath, {DEFAULT_ERR}}}}; + } errFileInfo = CreateDir(info.fullPath, info.mode); isFilter = false; break; case GNUTYPE_LONGNAME: { auto result = ReadLongName(info); + if (BDir::CheckFilePathInvalid(info.fullPath)) { + HILOGE("Check file path : %{public}s err, path is forbidden", GetAnonyPath(info.fullPath).c_str()); + return {DEFAULT_ERR, true, {{info.fullPath, {DEFAULT_ERR}}}}; + } return {std::get(result), isFilter, std::get(result)}; break; } default: { if (fseeko(tarFilePtr_, tarFileBlockCnt_ * BLOCK_SIZE, SEEK_CUR) != 0) { HILOGE("Failed to fseeko of %{private}s, err = %{public}d", info.fullPath.c_str(), errno); - return {-1, true, {}}; + return {DEFAULT_ERR, true, {{info.fullPath, {DEFAULT_ERR}}}}; } break; } @@ -407,10 +445,10 @@ std::tuple UntarFile::ParseIncrementalFileByTypeFlag(cha return {0, isFilter, errFileInfo}; } -ErrFileInfo UntarFile::ParseRegularFile(FileStatInfo &info, char typeFlag) +ErrFileInfo UntarFile::ParseRegularFile(FileStatInfo &info) { ErrFileInfo errFileInfo; - FILE *destFile = CreateFile(info.fullPath, info.mode, typeFlag); + FILE *destFile = CreateFile(info.fullPath); if (destFile != nullptr) { string destStr(""); destStr.resize(READ_BUFF_SIZE); @@ -519,7 +557,7 @@ ErrFileInfo UntarFile::CreateDir(string &path, mode_t mode) return errFileInfo; } -FILE *UntarFile::CreateFile(string &filePath, mode_t mode, char fileType) +FILE *UntarFile::CreateFile(string &filePath) { FILE *f = fopen(filePath.c_str(), "wb+"); if (f != nullptr) { diff --git a/utils/include/b_filesystem/b_dir.h b/utils/include/b_filesystem/b_dir.h index 576cbc80e..5f4670a67 100644 --- a/utils/include/b_filesystem/b_dir.h +++ b/utils/include/b_filesystem/b_dir.h @@ -83,6 +83,14 @@ public: std::vector &allFiles, std::vector &smallFiles, std::vector &bigFiles); + + /** + * @brief 核实文件是否为异常无效路径 + * + * @param filePath 待核实的路径 + * @return 是否是异常无效路径 + */ + static bool CheckFilePathInvalid(const std::string &filePath); }; } // namespace OHOS::FileManagement::Backup diff --git a/utils/src/b_filesystem/b_dir.cpp b/utils/src/b_filesystem/b_dir.cpp index 5fb354b9e..9a462c098 100644 --- a/utils/src/b_filesystem/b_dir.cpp +++ b/utils/src/b_filesystem/b_dir.cpp @@ -496,4 +496,12 @@ vector BDir::GetDirs(const vector &paths) vector dirs(inc.begin(), inc.end()); return dirs; } + +bool BDir::CheckFilePathInvalid(const std::string &filePath) +{ + if (filePath.find("../") != std::string::npos) { + return true; + } + return false; +} } // namespace OHOS::FileManagement::Backup \ No newline at end of file -- Gitee