include/osl/file.h | 48 ++++++++++++++++ include/osl/file.hxx | 52 ++++++++++++++++++ sal/osl/unx/file.cxx | 124 +++++++++++++++++++++++++++++++++++++++++++ sal/osl/unx/file_impl.hxx | 2 sal/osl/unx/file_misc.cxx | 34 +++++++++++ sal/osl/unx/file_stat.cxx | 6 ++ sal/osl/unx/file_volume.cxx | 4 + sal/osl/unx/pipe.cxx | 4 + sal/osl/unx/process.cxx | 5 + sal/osl/unx/profile.cxx | 5 + sal/qa/osl/file/osl_File.cxx | 118 ++++++++++++++++++++++++++++++++++++++++ sal/util/sal.map | 6 ++ 12 files changed, 407 insertions(+), 1 deletion(-)
New commits: commit de81e7d933fbab6fe1546b513900e1c50a9aab38 Author: Michael Meeks <[email protected]> AuthorDate: Wed Nov 22 19:37:38 2023 +0000 Commit: Michael Meeks <[email protected]> CommitDate: Wed Nov 29 20:21:33 2023 +0100 sal: initial osl::File sand-boxing commit for Unix. Change-Id: If2c106fef9640499b82b5cf350cb5169beb219fb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159838 Reviewed-by: Szymon Kłos <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Michael Meeks <[email protected]> diff --git a/include/osl/file.h b/include/osl/file.h index 07d2beb2ae1f..98ad568550b9 100644 --- a/include/osl/file.h +++ b/include/osl/file.h @@ -960,6 +960,54 @@ SAL_DLLPUBLIC oslFileError SAL_CALL osl_readFile( SAL_DLLPUBLIC oslFileError SAL_CALL osl_isEndOfFile( oslFileHandle Handle, sal_Bool *pIsEOF ); +/** Resets the list of paths and associated permissions for osl + + @param[in] pustrFileURLs + Contains a ':' delimited list of control strings and paths. + Control segments are a short path that refers to the following + segments and contain either: + + r: read-only paths follow (the default) + w: read & write paths follow + x: executable paths follow + + Any real paths (ie. having resolved all symlinks) + accessed outside of these paths will cause an + osl_File_E_ACCESS error in the relevant method calls. + + This method is Unix specific. + + @see osl_isForbiddenPath + + @since LibreOffice 7.7 +*/ +SAL_DLLPUBLIC void SAL_CALL osl_setAllowedPaths( + rtl_uString *pustrFileURLs + ); + +/** + Determine if the passed in path is not contained inside + the allowed paths, or if no allowed paths are set it + will not forbid any access. + + @param[in] pustrFileURL + A URL (or path) that we want to check if it is forbidden + to access. + + @param[in] nFlags + Flags to determine what type of access is requested, + osl_File_OpenFlag_Read | Write, or 0x80 for 'execute'. + + This method is Unix specific. + + @see osl_setAllowedPaths + + @since LibreOffice 7.7 + */ +SAL_DLLPUBLIC sal_Bool SAL_CALL osl_isForbiddenPath( + rtl_uString *pustrFileURL, int nFlags + ); + /** Write a number of bytes to a file. Writes a number of bytes to a file. diff --git a/include/osl/file.hxx b/include/osl/file.hxx index fcbabe96d674..6330247ba818 100644 --- a/include/osl/file.hxx +++ b/include/osl/file.hxx @@ -313,6 +313,58 @@ public: return static_cast< RC >( osl_createTempFile(pustr_dir_url, pHandle, ppustr_tmp_file_url) ); } + + + /** Resets the list of paths and associated permissions for osl + + @param[in] rPaths + Contains a ':' delimited list of control strings and paths. + Control segments are a short path that refers to the following + segments and contain either: + + r: read-only paths follow (the default) + w: read & write paths follow + x: executable paths follow + + Any real paths (ie. having resolved all symlinks) + accessed outside of these paths will cause an + osl_File_E_ACCESS error in the relevant method calls. + + This method is Unix specific. + + @see osl_isForbiddenPath + + @since LibreOffice 7.7 + */ + + static void setAllowedPaths(const OUString &rPaths) + { + osl_setAllowedPaths(rPaths.pData); + } + + /** + Determine if the passed in path is not contained inside + the allowed paths, or if no allowed paths are set it + will not forbid any access. + + @param[in] pustrFileURL + A URL (or path) that we want to check if it is forbidden + to access. + + @param[in] nFlags + Flags to determine what type of access is requested, + osl_File_OpenFlag_Read | Write, or 0x80 for 'execute'. + + This method is Unix specific. + + @see osl_setAllowedPaths + + @since LibreOffice 7.7 + */ + static bool isForbidden(const OUString &rPath, int nFlags) + { + return osl_isForbiddenPath(rPath.pData, nFlags); + } }; diff --git a/sal/osl/unx/file.cxx b/sal/osl/unx/file.cxx index a39365b9b115..0556be7fc97a 100644 --- a/sal/osl/unx/file.cxx +++ b/sal/osl/unx/file.cxx @@ -783,6 +783,125 @@ static bool osl_file_queryLocking(sal_uInt32 uFlags) return false; } +static bool abortOnForbidden = false; +static std::vector<OString> allowedPathsRead; +static std::vector<OString> allowedPathsReadWrite; +static std::vector<OString> allowedPathsExecute; + +SAL_DLLPUBLIC void osl_setAllowedPaths( + rtl_uString *pustrFilePaths + ) +{ + allowedPathsRead.clear(); + allowedPathsReadWrite.clear(); + allowedPathsExecute.clear(); + + if (!pustrFilePaths) + return; + + char eType = 'r'; + sal_Int32 nIndex = 0; + OUString aPaths(pustrFilePaths); + do + { + OString aPath = rtl::OUStringToOString( + aPaths.getToken(0, ':', nIndex), + RTL_TEXTENCODING_UTF8); + + if (aPath.getLength() == 0) + continue; + + if (aPath.getLength() == 1) + { + eType = aPath[0]; + continue; + } + + char resolvedPath[PATH_MAX]; + if (realpath(aPath.getStr(), resolvedPath)) + { + OString aPushPath = OString(resolvedPath, strlen(resolvedPath)); + if (eType == 'r') + allowedPathsRead.push_back(aPushPath); + else if (eType == 'w') + { + allowedPathsRead.push_back(aPushPath); + allowedPathsReadWrite.push_back(aPushPath); + } + else if (eType == 'x') + allowedPathsExecute.push_back(aPushPath); + } + } + while (nIndex != -1); + + abortOnForbidden = !!getenv("SAL_ABORT_ON_FORBIDDEN"); +} + +bool isForbidden(const OString &filePath, int nFlags) +{ + // avoid realpath cost unless configured + if (allowedPathsRead.size() == 0) + return false; + + char resolvedPath[PATH_MAX]; + if (!realpath(filePath.getStr(), resolvedPath)) + { + // write calls path a non-existent path that realpath will + // fail to resolve. Thankfully our I/O APIs don't allow + // symlink creation to race here. + sal_Int32 n = filePath.lastIndexOf('/'); + OString folderPath; + if (n < 1) + folderPath = "."; + else + folderPath = filePath.copy(0, n); + if (!realpath(folderPath.getStr(), resolvedPath) || + strlen(resolvedPath) + filePath.getLength() - n + 1 >= PATH_MAX) + return true; // too bad + else + strcat(resolvedPath, filePath.getStr() + n); + } + + const std::vector<OString> *pCheckPaths = &allowedPathsRead; + if (nFlags & osl_File_OpenFlag_Write || + nFlags & osl_File_OpenFlag_Create) + pCheckPaths = &allowedPathsReadWrite; + else if (nFlags & 0x80) + pCheckPaths = &allowedPathsExecute; + + bool allowed = false; + for (const auto &it : *pCheckPaths) { + if (!strncmp(resolvedPath, it.getStr(), it.getLength())) + { + allowed = true; + break; + } + } + + if (!allowed) + SAL_WARN("sal.osl", "access outside sandbox to " << + ((nFlags & osl_File_OpenFlag_Write || + nFlags & osl_File_OpenFlag_Create) ? "w" : + (nFlags & 0x80) ? "x" : "r") << ":" << + filePath << " which is really " << resolvedPath << + (allowed ? " allowed " : " forbidden") << + " check list: " << pCheckPaths->size()); + + if (abortOnForbidden && !allowed) + abort(); // a bit abrupt - but don't try to escape. + + return !allowed; +} + +SAL_DLLPUBLIC sal_Bool SAL_CALL osl_isForbiddenPath( + rtl_uString *pustrFileURL, int nFlags + ) +{ + return isForbidden( + rtl::OUStringToOString(OUString(pustrFileURL), + RTL_TEXTENCODING_UTF8), nFlags); +} + #ifdef HAVE_O_EXLOCK #define OPEN_WRITE_FLAGS ( O_RDWR | O_EXLOCK | O_NONBLOCK ) #define OPEN_CREATE_FLAGS ( O_CREAT | O_RDWR | O_EXLOCK | O_NONBLOCK ) @@ -987,6 +1106,10 @@ oslFileError openFilePath(const OString& filePath, oslFileHandle* pHandle, if (flags & O_EXCL && !(flags & O_CREAT)) flags &= ~O_EXCL; + // Sandboxing hook + if (isForbidden( filePath, uFlags )) + return osl_File_E_ACCES; + /* open the file */ int fd = open_c( filePath, flags, mode ); if (fd == -1) @@ -1601,4 +1724,5 @@ oslFileError SAL_CALL osl_setFileSize(oslFileHandle Handle, sal_uInt64 uSize) return pImpl->setSize(uSize); } + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sal/osl/unx/file_impl.hxx b/sal/osl/unx/file_impl.hxx index 2b374cb68ac0..3b4b5d58025b 100644 --- a/sal/osl/unx/file_impl.hxx +++ b/sal/osl/unx/file_impl.hxx @@ -41,6 +41,8 @@ struct DirectoryItem_Impl oslFileType getFileType() const; }; +bool isForbidden(const OString &filePath, int nFlags); + oslFileError openFile( rtl_uString * pustrFileURL, oslFileHandle * pHandle, sal_uInt32 uFlags, mode_t mode); diff --git a/sal/osl/unx/file_misc.cxx b/sal/osl/unx/file_misc.cxx index 01842dc73154..dc9a41de9fc9 100644 --- a/sal/osl/unx/file_misc.cxx +++ b/sal/osl/unx/file_misc.cxx @@ -150,6 +150,9 @@ oslFileError SAL_CALL osl_openDirectory(rtl_uString* ustrDirectoryURL, oslDirect osl_systemPathRemoveSeparator(path.pData); + if (isForbidden(path.getStr(), osl_File_OpenFlag_Read)) + return osl_File_E_ACCES; + #ifdef MACOSX { auto const n = std::max(int(path.getLength() + 1), int(PATH_MAX)); @@ -353,6 +356,9 @@ oslFileError SAL_CALL osl_getDirectoryItem(rtl_uString* ustrFileURL, oslDirector osl_systemPathRemoveSeparator(strSystemPath.pData); + if (isForbidden(strSystemPath, osl_File_OpenFlag_Read)) + return osl_File_E_ACCES; + if (osl::access(strSystemPath, F_OK) == -1) { osl_error = oslTranslateFileError(errno); @@ -436,6 +442,9 @@ oslFileError SAL_CALL osl_removeDirectory( rtl_uString* ustrDirectoryURL ) oslFileError osl_psz_createDirectory(char const * pszPath, sal_uInt32 flags) { + if (isForbidden(pszPath, osl_File_OpenFlag_Create)) + return osl_File_E_ACCES; + int nRet=0; int mode = (((flags & osl_File_OpenFlag_Read) == 0 @@ -465,6 +474,9 @@ oslFileError osl_psz_createDirectory(char const * pszPath, sal_uInt32 flags) static oslFileError osl_psz_removeDirectory( const char* pszPath ) { + if (isForbidden(pszPath, osl_File_OpenFlag_Write)) + return osl_File_E_ACCES; + int nRet = rmdir(pszPath); if ( nRet < 0 ) @@ -560,6 +572,9 @@ oslFileError SAL_CALL osl_createDirectoryPath( osl::systemPathRemoveSeparator(sys_path); + if (isForbidden(sys_path.getStr(), osl_File_OpenFlag_Create)) + return osl_File_E_ACCES; + // const_cast because sys_path is a local copy which we want to modify inplace instead of // copy it into another buffer on the heap again return create_dir_recursively_(sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData); @@ -594,6 +609,10 @@ oslFileError SAL_CALL osl_moveFile( rtl_uString* ustrFileURL, rtl_uString* ustrD if( eRet != osl_File_E_None ) return eRet; + if (isForbidden(srcPath, osl_File_OpenFlag_Read) || + isForbidden(destPath, osl_File_OpenFlag_Create)) + return osl_File_E_ACCES; + #ifdef MACOSX if ( macxp_resolveAlias( srcPath, PATH_MAX ) != 0 || macxp_resolveAlias( destPath, PATH_MAX ) != 0 ) return oslTranslateFileError( errno ); @@ -607,6 +626,10 @@ oslFileError SAL_CALL osl_replaceFile(rtl_uString* ustrFileURL, rtl_uString* ust int nGid = -1; char destPath[PATH_MAX]; oslFileError eRet = FileURLToPath(destPath, PATH_MAX, ustrDestURL); + + if (isForbidden(destPath, osl_File_OpenFlag_Create)) + return osl_File_E_ACCES; + if (eRet == osl_File_E_None) { struct stat aFileStat; @@ -683,6 +706,9 @@ oslFileError SAL_CALL osl_removeFile(rtl_uString* ustrFileURL) return oslTranslateFileError(errno); #endif/* MACOSX */ + if (isForbidden(path, osl_File_OpenFlag_Write)) + return osl_File_E_ACCES; + return osl_unlinkFile(path); } @@ -738,6 +764,10 @@ static oslFileError osl_unlinkFile(const char* pszPath) static oslFileError osl_psz_moveFile(const char* pszPath, const char* pszDestPath) { + if (isForbidden(pszPath, osl_File_OpenFlag_Read) || + isForbidden(pszDestPath, osl_File_OpenFlag_Create)) + return osl_File_E_ACCES; + int nRet = rename(pszPath,pszDestPath); if (nRet < 0) @@ -765,6 +795,10 @@ static oslFileError osl_psz_copyFile( const char* pszPath, const char* pszDestPa size_t nSourceSize=0; bool DestFileExists=true; + if (isForbidden(pszPath, osl_File_OpenFlag_Read) || + isForbidden(pszDestPath, osl_File_OpenFlag_Create)) + return osl_File_E_ACCES; + /* mfe: does the source file really exists? */ nRet = lstat_c(pszPath,&aFileStat); diff --git a/sal/osl/unx/file_stat.cxx b/sal/osl/unx/file_stat.cxx index 3b702905cb99..b695f6093a2d 100644 --- a/sal/osl/unx/file_stat.cxx +++ b/sal/osl/unx/file_stat.cxx @@ -273,6 +273,9 @@ static oslFileError osl_psz_setFileAttributes( const char* pszFilePath, sal_uInt OSL_ENSURE(!(osl_File_Attribute_Hidden & uAttributes), "osl_File_Attribute_Hidden doesn't work under Unix"); + if (isForbidden(pszFilePath, osl_File_OpenFlag_Write)) + return osl_File_E_ACCES; + if (uAttributes & osl_File_Attribute_OwnRead) nNewMode |= S_IRUSR; @@ -338,6 +341,9 @@ static oslFileError osl_psz_setFileTime ( struct tm* pTM=0; #endif + if (isForbidden(pszFilePath, osl_File_OpenFlag_Write)) + return osl_File_E_ACCES; + nRet = lstat_c(pszFilePath,&aFileStat); if ( nRet < 0 ) diff --git a/sal/osl/unx/file_volume.cxx b/sal/osl/unx/file_volume.cxx index 5e661bd656c3..07e5e08b4f50 100644 --- a/sal/osl/unx/file_volume.cxx +++ b/sal/osl/unx/file_volume.cxx @@ -27,6 +27,7 @@ #include "file_error_transl.hxx" #include "file_url.hxx" +#include "file_impl.hxx" #include "system.hxx" #include <errno.h> @@ -199,6 +200,9 @@ static oslFileError osl_psz_getVolumeInformation ( if (!pInfo) return osl_File_E_INVAL; + if (isForbidden(pszDirectory, osl_File_OpenFlag_Read)) + return osl_File_E_ACCES; + pInfo->uValidFields = 0; pInfo->uAttributes = 0; pInfo->uTotalSpace = 0; diff --git a/sal/osl/unx/pipe.cxx b/sal/osl/unx/pipe.cxx index 45d31e00826b..9c91c49cf5cc 100644 --- a/sal/osl/unx/pipe.cxx +++ b/sal/osl/unx/pipe.cxx @@ -31,6 +31,7 @@ #include "sockimpl.hxx" #include "secimpl.hxx" +#include "file_impl.hxx" #include "unixerrnostring.hxx" #include <cassert> @@ -208,6 +209,9 @@ static oslPipe osl_psz_createPipe(const char *pszPipeName, oslPipeOptions Option SAL_INFO("sal.osl.pipe", "new pipe on fd " << pPipe->m_Socket << " '" << name << "'"); + if (isForbidden(name.getStr(), osl_File_OpenFlag_Create)) + return nullptr; + addr.sun_family = AF_UNIX; // coverity[fixed_size_dest : FALSE] - safe, see check above strcpy(addr.sun_path, name.getStr()); diff --git a/sal/osl/unx/process.cxx b/sal/osl/unx/process.cxx index f75534fdc311..20a6844b8495 100644 --- a/sal/osl/unx/process.cxx +++ b/sal/osl/unx/process.cxx @@ -19,7 +19,7 @@ #include <sal/config.h> #include <rtl/ustring.hxx> - +#include "file_impl.hxx" #include <cassert> /* @@ -593,6 +593,9 @@ oslProcessError osl_psz_executeProcess(char *pszImageName, return osl_Process_E_NotFound; } + if (isForbidden(pszImageName, 0x80 /* execute */)) + return osl_Process_E_NoPermission; + Data.m_pszArgs[0] = strdup(pszImageName); Data.m_pszArgs[1] = nullptr; diff --git a/sal/osl/unx/profile.cxx b/sal/osl/unx/profile.cxx index 354fe626f390..8f0422fb71b0 100644 --- a/sal/osl/unx/profile.cxx +++ b/sal/osl/unx/profile.cxx @@ -20,12 +20,14 @@ #include "system.hxx" #include "readwrite_helper.hxx" #include "file_url.hxx" +#include "file_impl.hxx" #include "unixerrnostring.hxx" #include <osl/diagnose.h> #include <osl/profile.h> #include <osl/process.h> #include <osl/thread.h> +#include <osl/file.h> #include <rtl/alloc.h> #include <sal/log.hxx> @@ -934,6 +936,9 @@ static osl_TFile* openFileImpl(const char* pszFilename, oslProfileOption Profile osl_TFile* pFile = static_cast<osl_TFile*>(calloc(1, sizeof(osl_TFile))); bool bWriteable = false; + if ( isForbidden( pszFilename, osl_File_OpenFlag_Write ) ) + return nullptr; + if ( ProfileFlags & ( osl_Profile_WRITELOCK | osl_Profile_FLUSHWRITE ) ) { bWriteable = true; diff --git a/sal/qa/osl/file/osl_File.cxx b/sal/qa/osl/file/osl_File.cxx index 718fb65423d1..0703e89493b9 100644 --- a/sal/qa/osl/file/osl_File.cxx +++ b/sal/qa/osl/file/osl_File.cxx @@ -1317,6 +1317,124 @@ namespace osl_FileBase CPPUNIT_REGISTRY_ADD_TO_DEFAULT("osl_osl::FileBase"); } +#if (defined UNX) + +namespace osl_Forbidden +{ + + class Forbidden : public CppUnit::TestFixture + { + OUString maScratchBad; + OUString maScratchGood; + public: + void setUp() override + { + // create a directory to play in + createTestDirectory(aTmpName3); + OUString aBadURL = aTmpName3 + "/bad"; + OUString aGoodURL = aTmpName3 + "/good"; + createTestDirectory(aBadURL); + createTestDirectory(aGoodURL); + File::getSystemPathFromFileURL(aBadURL, maScratchBad); + File::getSystemPathFromFileURL(aGoodURL, maScratchGood); + } + + void tearDown() override + { + osl_setAllowedPaths(nullptr); + OUString aBadURL = aTmpName3 + "/bad"; + OUString aGoodURL = aTmpName3 + "/good"; + deleteTestDirectory(aBadURL); + deleteTestDirectory(aGoodURL); + deleteTestDirectory(aTmpName3); + } + + void forbidden() + { + File::setAllowedPaths(maScratchGood); + CPPUNIT_ASSERT_EQUAL_MESSAGE("read bad should be forbidden", + true, File::isForbidden(maScratchBad, osl_File_OpenFlag_Read)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("read from good should be allowed", + false, File::isForbidden(maScratchGood, osl_File_OpenFlag_Read)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("write to good should be forbidden", + true, File::isForbidden(maScratchGood, osl_File_OpenFlag_Write)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("create in good should be forbidden", + true, File::isForbidden(maScratchGood, osl_File_OpenFlag_Create)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("exec from good should be forbidden", + true, File::isForbidden(maScratchGood, 0x80)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("write to non-existent should be forbidden", + true, File::isForbidden(maScratchBad + "/notthere", osl_File_OpenFlag_Write)); + + File::setAllowedPaths("w:" + maScratchGood + ":x:" + maScratchBad); + CPPUNIT_ASSERT_EQUAL_MESSAGE("read bad should be forbidden", + true, File::isForbidden(maScratchBad, osl_File_OpenFlag_Read)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("read from good should be allowed", // w implies 'r' + false, File::isForbidden(maScratchGood, osl_File_OpenFlag_Read)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("write to good should be allowed", + false, File::isForbidden(maScratchGood, osl_File_OpenFlag_Write)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("exec from good should be forbidden", + true, File::isForbidden(maScratchGood, 0x80)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("exec from bad should be allowed", + false, File::isForbidden(maScratchBad, 0x80)); + } + + void open() + { + File::setAllowedPaths(maScratchGood); + File testFile(maScratchBad + "/open"); + auto nError1 = testFile.open(osl_File_OpenFlag_Read | osl_File_OpenFlag_Write); + CPPUNIT_ASSERT_EQUAL_MESSAGE("disabled path allowed", osl::FileBase::E_ACCES, nError1); + deleteTestFile(testFile.getURL()); + } + + void copy() + { + File::setAllowedPaths("w:" + maScratchGood); + File testGood(maScratchGood + "/good"); + File testGoodTo(maScratchGood + "/good_to"); + File testBad(maScratchBad + "/bad"); + + auto nError1 = testGood.open(osl_File_OpenFlag_Create); + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nError1); + + auto nErrorCopy = File::copy(maScratchGood + "/good", maScratchGood + "/good_to"); + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, nErrorCopy); + + auto nErrorCopyBad = File::copy(maScratchGood + "/good_to", maScratchBad + "/bad"); + CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_ACCES, nErrorCopyBad); + + deleteTestFile(maScratchGood + "/good_to"); + deleteTestFile(maScratchGood + "/good"); + } + + void nextTests() + { + // more entry points to test +#if 0 + auto nError1 = File::move(aTmpName4, aCanURL1); + auto nError2 = File::remove(aTmpName4); + auto nError3 = File::setAttributes(aTmpName6, osl_File_Attribute_ReadOnly); + bool bOk = osl_getSystemTime(pTV_current); + CPPUNIT_ASSERT(bOk); + auto nError4 = File::setTime(aTmpName6, *pTV_current, *pTV_current, *pTV_current); + CPPUNIT_ASSERT_EQUAL_MESSAGE(errorToStr(nError2).getStr(), osl::FileBase::E_None, nError2); +#endif + } + + CPPUNIT_TEST_SUITE(Forbidden); + CPPUNIT_TEST(forbidden); +// CPPUNIT_TEST(open); +// CPPUNIT_TEST(copy); +// CPPUNIT_TEST(nextTests); + CPPUNIT_TEST_SUITE_END(); + }; + + CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Forbidden::Forbidden, "osl_Forbidden"); + + CPPUNIT_REGISTRY_ADD_TO_DEFAULT("osl_Forbidden"); +} +#endif + namespace osl_FileStatus { // testing the method diff --git a/sal/util/sal.map b/sal/util/sal.map index c5c3e4d55641..586a41ee997d 100644 --- a/sal/util/sal.map +++ b/sal/util/sal.map @@ -761,6 +761,12 @@ PRIVATE_1.8 { # LibreOffice 7.3 rtl_uString_newReplaceStrAtUtf16L; } PRIVATE_1.7; +PRIVATE_1.9 { # LibreOffice 7.7 + global: + osl_setAllowedPaths; + osl_isForbiddenPath; +} PRIVATE_1.8; + PRIVATE_textenc.1 { # LibreOffice 3.6 global: _ZN3sal6detail7textenc20convertCharToUnicode*;
