mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2025-11-11 11:08:02 -06:00
Linux/FreeBSD: Prevent mounting volumes on system directories and PATH (CVE-2025-23021, reported by SivertPL @__tfr)
Added security checks to prevent mounting VeraCrypt volumes on system directories (like /usr/bin) or directories in the user's PATH, which could theoretically allow execution of malicious binaries instead of legitimate system binaries. Key changes: - Block mounting on protected system directories (/usr, /bin, /lib, etc.) This restriction cannot be overridden - Block mounting on directories present in user's PATH environment variable This can be overridden with --allow-insecure-mount flag - Add visual warnings (red border, "[INSECURE MODE]") when mounting on PATH directories is allowed - Handle symlinks properly when checking paths - Add new error messages for blocked mount points To override PATH-based restrictions only (system directories remain protected): veracrypt --allow-insecure-mount [options] volume mountpoint Security Impact: Low to Medium The attack requires either: - User explicitly choosing a system directory as mount point instead of using VeraCrypt's default mount points - Or attacker having both filesystem access to modify favorites configuration AND knowledge of the volume password Default mount points are not affected by this vulnerability. Security: CVE-2025-23021
This commit is contained in:
@@ -1641,6 +1641,9 @@
|
||||
<entry lang="en" key="ERR_XTS_MASTERKEY_VULNERABLE">WARNING: The volume's master key is vulnerable to an attack that compromises data security.\n\nPlease create a new volume and transfer the data to it.</entry>
|
||||
<entry lang="en" key="ERR_SYSENC_XTS_MASTERKEY_VULNERABLE">WARNING: The encrypted system's master key is vulnerable to an attack that compromises data security.\nPlease decrypt the system partition/drive and then re-encrypt it.</entry>
|
||||
<entry lang="en" key="ERR_XTS_MASTERKEY_VULNERABLE_SHORT">WARNING: The volume's master key has a security vulnerability.</entry>
|
||||
<entry lang="en" key="MOUNTPOINT_BLOCKED">ERROR: The volume mount point is blocked because it overrides a protected system directory.\n\nPlease choose a different mount point.</entry>
|
||||
<entry lang="en" key="MOUNTPOINT_NOTALLOWED">ERROR: The volume mount point is not allowed because it overrides a directory that is part of the PATH environment variable.\n\nPlease choose a different mount point.</entry>
|
||||
<entry lang="en" key="INSECURE_MODE">[INSECURE MODE]</entry>
|
||||
</localization>
|
||||
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="VeraCrypt">
|
||||
|
||||
@@ -22,6 +22,9 @@ namespace VeraCrypt
|
||||
: DeviceChangeInProgress (false)
|
||||
#if defined(TC_LINUX ) || defined (TC_FREEBSD)
|
||||
, UseDummySudoPassword (false)
|
||||
#endif
|
||||
#if defined(TC_UNIX)
|
||||
,AllowInsecureMount (false)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
@@ -80,6 +80,16 @@ namespace VeraCrypt
|
||||
virtual void ForceUseDummySudoPassword (bool useDummySudoPassword) { UseDummySudoPassword = useDummySudoPassword;}
|
||||
virtual bool GetUseDummySudoPassword () const { return UseDummySudoPassword;}
|
||||
|
||||
#if defined(TC_UNIX)
|
||||
virtual bool IsProtectedSystemDirectory (const DirectoryPath &directory) const = 0;
|
||||
virtual bool IsDirectoryOnUserPath(const DirectoryPath &directory) const = 0;
|
||||
virtual void SetAllowInsecureMount (bool allowInsecureMount) { AllowInsecureMount = allowInsecureMount; }
|
||||
virtual bool GetAllowInsecureMount () const { return AllowInsecureMount; }
|
||||
#endif
|
||||
|
||||
virtual void SetUserEnvPATH (const string &path) { UserEnvPATH = path; }
|
||||
virtual string GetUserEnvPATH () const { return UserEnvPATH; }
|
||||
|
||||
Event VolumeDismountedEvent;
|
||||
Event VolumeMountedEvent;
|
||||
Event WarningEvent;
|
||||
@@ -89,8 +99,13 @@ namespace VeraCrypt
|
||||
|
||||
bool DeviceChangeInProgress;
|
||||
FilePath ApplicationExecutablePath;
|
||||
string UserEnvPATH;
|
||||
bool UseDummySudoPassword;
|
||||
|
||||
#if defined(TC_UNIX)
|
||||
bool AllowInsecureMount;
|
||||
#endif
|
||||
|
||||
private:
|
||||
CoreBase (const CoreBase &);
|
||||
CoreBase &operator= (const CoreBase &);
|
||||
|
||||
@@ -99,6 +99,11 @@ namespace VeraCrypt
|
||||
{
|
||||
shared_ptr <CoreServiceRequest> request = Serializable::DeserializeNew <CoreServiceRequest> (inputStream);
|
||||
|
||||
// Update Core properties based on the received request
|
||||
Core->SetUserEnvPATH (request->UserEnvPATH);
|
||||
Core->ForceUseDummySudoPassword(request->UseDummySudoPassword);
|
||||
Core->SetAllowInsecureMount(request->AllowInsecureMount);
|
||||
|
||||
try
|
||||
{
|
||||
// ExitRequest
|
||||
@@ -283,12 +288,17 @@ namespace VeraCrypt
|
||||
static Mutex mutex;
|
||||
ScopeLock lock (mutex);
|
||||
|
||||
// Copy Core properties to the request so that they can be transferred to the elevated process
|
||||
request.ApplicationExecutablePath = Core->GetApplicationExecutablePath();
|
||||
request.UserEnvPATH = Core->GetUserEnvPATH();
|
||||
request.UseDummySudoPassword = Core->GetUseDummySudoPassword();
|
||||
request.AllowInsecureMount = Core->GetAllowInsecureMount();
|
||||
|
||||
if (request.RequiresElevation())
|
||||
{
|
||||
request.ElevateUserPrivileges = true;
|
||||
request.FastElevation = !ElevatedServiceAvailable;
|
||||
request.ApplicationExecutablePath = Core->GetApplicationExecutablePath();
|
||||
|
||||
|
||||
while (!ElevatedServiceAvailable)
|
||||
{
|
||||
// Test if the user has an active "sudo" session.
|
||||
|
||||
@@ -23,6 +23,9 @@ namespace VeraCrypt
|
||||
ApplicationExecutablePath = sr.DeserializeWString ("ApplicationExecutablePath");
|
||||
sr.Deserialize ("ElevateUserPrivileges", ElevateUserPrivileges);
|
||||
sr.Deserialize ("FastElevation", FastElevation);
|
||||
sr.Deserialize ("UserEnvPATH", UserEnvPATH);
|
||||
sr.Deserialize ("UseDummySudoPassword", UseDummySudoPassword);
|
||||
sr.Deserialize ("AllowInsecureMount", AllowInsecureMount);
|
||||
}
|
||||
|
||||
void CoreServiceRequest::Serialize (shared_ptr <Stream> stream) const
|
||||
@@ -33,6 +36,9 @@ namespace VeraCrypt
|
||||
sr.Serialize ("ApplicationExecutablePath", wstring (ApplicationExecutablePath));
|
||||
sr.Serialize ("ElevateUserPrivileges", ElevateUserPrivileges);
|
||||
sr.Serialize ("FastElevation", FastElevation);
|
||||
sr.Serialize ("UserEnvPATH", UserEnvPATH);
|
||||
sr.Serialize ("UseDummySudoPassword", UseDummySudoPassword);
|
||||
sr.Serialize ("AllowInsecureMount", AllowInsecureMount);
|
||||
}
|
||||
|
||||
// CheckFilesystemRequest
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace VeraCrypt
|
||||
{
|
||||
struct CoreServiceRequest : public Serializable
|
||||
{
|
||||
CoreServiceRequest () : ElevateUserPrivileges (false), FastElevation (false) { }
|
||||
CoreServiceRequest () : ElevateUserPrivileges (false), FastElevation (false), UseDummySudoPassword (false), AllowInsecureMount (false) { }
|
||||
TC_SERIALIZABLE (CoreServiceRequest);
|
||||
|
||||
virtual bool RequiresElevation () const { return false; }
|
||||
@@ -29,6 +29,9 @@ namespace VeraCrypt
|
||||
FilePath ApplicationExecutablePath;
|
||||
bool ElevateUserPrivileges;
|
||||
bool FastElevation;
|
||||
string UserEnvPATH;
|
||||
bool UseDummySudoPassword;
|
||||
bool AllowInsecureMount;
|
||||
};
|
||||
|
||||
struct CheckFilesystemRequest : CoreServiceRequest
|
||||
|
||||
@@ -596,6 +596,17 @@ namespace VeraCrypt
|
||||
if (IsVolumeMounted (*options.Path))
|
||||
throw VolumeAlreadyMounted (SRC_POS);
|
||||
|
||||
if (options.MountPoint && !options.MountPoint->IsEmpty())
|
||||
{
|
||||
// Reject if the mount point is a system directory
|
||||
if (IsProtectedSystemDirectory(*options.MountPoint))
|
||||
throw MountPointBlocked (SRC_POS);
|
||||
|
||||
// Reject if the mount point is in the user's PATH and the user has not explicitly allowed insecure mount points
|
||||
if (!GetAllowInsecureMount() && IsDirectoryOnUserPath(*options.MountPoint))
|
||||
throw MountPointNotAllowed (SRC_POS);
|
||||
}
|
||||
|
||||
Cipher::EnableHwSupport (!options.NoHardwareCrypto);
|
||||
|
||||
shared_ptr <Volume> volume;
|
||||
@@ -828,4 +839,100 @@ namespace VeraCrypt
|
||||
s << GetDefaultMountPointPrefix() << slotNumber;
|
||||
return s.str();
|
||||
}
|
||||
|
||||
bool CoreUnix::IsProtectedSystemDirectory (const DirectoryPath &directory) const
|
||||
{
|
||||
static const char* systemDirs[] = {
|
||||
"/usr",
|
||||
"/bin",
|
||||
"/sbin",
|
||||
"/lib",
|
||||
#ifdef TC_LINUX
|
||||
"/lib32",
|
||||
"/lib64",
|
||||
"/libx32",
|
||||
#endif
|
||||
"/etc",
|
||||
"/boot",
|
||||
"/root",
|
||||
"/proc",
|
||||
"/sys",
|
||||
"/dev",
|
||||
NULL
|
||||
};
|
||||
|
||||
// Resolve any symlinks in the path
|
||||
string path(directory);
|
||||
char* resolvedPathCStr = realpath(path.c_str(), NULL);
|
||||
if (resolvedPathCStr)
|
||||
{
|
||||
path = resolvedPathCStr;
|
||||
free(resolvedPathCStr); // Free the allocated memory
|
||||
}
|
||||
|
||||
// reject of the path is the root directory "/"
|
||||
if (path == "/")
|
||||
return true;
|
||||
|
||||
// Check if resolved path matches any system directory
|
||||
for (int i = 0; systemDirs[i] != NULL; ++i)
|
||||
{
|
||||
if (path == systemDirs[i] || path.find(string(systemDirs[i]) + "/") == 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CoreUnix::IsDirectoryOnUserPath(const DirectoryPath &directory) const
|
||||
{
|
||||
// Obtain the PATH environment variable
|
||||
const char* pathEnv = UserEnvPATH.c_str();
|
||||
if (!pathEnv[0])
|
||||
return false;
|
||||
|
||||
// Resolve the given directory
|
||||
string dirPath(directory);
|
||||
char* resolvedDir = realpath(dirPath.c_str(), NULL);
|
||||
if (resolvedDir)
|
||||
{
|
||||
dirPath = resolvedDir;
|
||||
free(resolvedDir);
|
||||
}
|
||||
|
||||
// Split PATH and compare each entry
|
||||
stringstream ss(pathEnv);
|
||||
string token;
|
||||
while (getline(ss, token, ':'))
|
||||
{
|
||||
// remove any trailing slashes from the token
|
||||
while (!token.empty() && token.back() == '/')
|
||||
token.pop_back();
|
||||
|
||||
if (token.empty())
|
||||
continue;
|
||||
|
||||
// check if the directory is the same as the entry or a subdirectory
|
||||
if (dirPath == token || dirPath.find(token + "/") == 0)
|
||||
return true;
|
||||
|
||||
// handle the case where the PATH entry is a symlink
|
||||
char* resolvedEntry = realpath(token.c_str(), NULL);
|
||||
if (!resolvedEntry)
|
||||
continue; // skip to the next entry since the path does not exist
|
||||
|
||||
string entryPath(resolvedEntry);
|
||||
free(resolvedEntry);
|
||||
|
||||
// remove any trailing slashes from the token
|
||||
while (!entryPath.empty() && entryPath.back() == '/')
|
||||
entryPath.pop_back();
|
||||
|
||||
// perform check again if the resolved path is different from the original (symlink)
|
||||
if (dirPath == entryPath || dirPath.find(entryPath + "/") == 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,8 @@ namespace VeraCrypt
|
||||
virtual void SetFileOwner (const FilesystemPath &path, const UserId &owner) const;
|
||||
virtual DirectoryPath SlotNumberToMountPoint (VolumeSlotNumber slotNumber) const;
|
||||
virtual void WipePasswordCache () const { throw NotApplicable (SRC_POS); }
|
||||
virtual bool IsProtectedSystemDirectory (const DirectoryPath &directory) const;
|
||||
virtual bool IsDirectoryOnUserPath(const DirectoryPath &directory) const;
|
||||
|
||||
protected:
|
||||
virtual DevicePath AttachFileToLoopDevice (const FilePath &filePath, bool readOnly) const { throw NotApplicable (SRC_POS); }
|
||||
|
||||
@@ -33,6 +33,9 @@ namespace VeraCrypt
|
||||
ArgDisableFileSizeCheck (false),
|
||||
ArgUseLegacyPassword (false),
|
||||
ArgUseDummySudoPassword (false),
|
||||
#if defined(TC_UNIX)
|
||||
ArgAllowInsecureMount (false),
|
||||
#endif
|
||||
StartBackgroundTask (false)
|
||||
{
|
||||
wxCmdLineParser parser;
|
||||
@@ -107,6 +110,9 @@ namespace VeraCrypt
|
||||
parser.AddSwitch (L"", L"legacy-password-maxlength", _("Use legacy maximum password length (64 UTF-8 bytes)"));
|
||||
#if defined(TC_LINUX ) || defined (TC_FREEBSD)
|
||||
parser.AddSwitch (L"", L"use-dummy-sudo-password", _("Use dummy password in sudo to detect if it is already authenticated"));
|
||||
#endif
|
||||
#if defined(TC_UNIX)
|
||||
parser.AddSwitch (L"", L"allow-insecure-mount", _("Allow mounting volumes on mount points that are in the user's PATH"));
|
||||
#endif
|
||||
wxString str;
|
||||
bool param1IsVolume = false;
|
||||
@@ -376,6 +382,10 @@ namespace VeraCrypt
|
||||
ArgUseLegacyPassword = parser.Found (L"legacy-password-maxlength");
|
||||
ArgUseDummySudoPassword = parser.Found (L"use-dummy-sudo-password");
|
||||
|
||||
#if defined(TC_UNIX)
|
||||
ArgAllowInsecureMount = parser.Found (L"allow-insecure-mount");
|
||||
#endif
|
||||
|
||||
#if !defined(TC_WINDOWS) && !defined(TC_MACOSX)
|
||||
if (parser.Found (L"fs-options", &str))
|
||||
ArgMountOptions.FilesystemOptions = str;
|
||||
|
||||
@@ -89,6 +89,10 @@ namespace VeraCrypt
|
||||
bool ArgUseLegacyPassword;
|
||||
bool ArgUseDummySudoPassword;
|
||||
|
||||
#if defined(TC_UNIX)
|
||||
bool ArgAllowInsecureMount;
|
||||
#endif
|
||||
|
||||
bool StartBackgroundTask;
|
||||
UserPreferences Preferences;
|
||||
|
||||
|
||||
@@ -34,6 +34,9 @@ namespace VeraCrypt
|
||||
, wxDefaultPosition, wxSize (-1,-1), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER
|
||||
#endif
|
||||
), Options (options)
|
||||
#ifdef TC_UNIX
|
||||
, m_showRedBorder(false)
|
||||
#endif
|
||||
{
|
||||
if (!title.empty())
|
||||
this->SetTitle (title);
|
||||
@@ -42,6 +45,16 @@ namespace VeraCrypt
|
||||
else
|
||||
this->SetTitle (LangString["ENTER_TC_VOL_PASSWORD"]);
|
||||
|
||||
#ifdef TC_UNIX
|
||||
if (Gui->InsecureMountAllowed())
|
||||
{
|
||||
this->SetTitle (LangString["INSECURE_MODE"] + L" - " + this->GetTitle());
|
||||
m_showRedBorder = true;
|
||||
Bind(wxEVT_PAINT, &MountOptionsDialog::OnPaint, this);
|
||||
Bind(wxEVT_SIZE, &MountOptionsDialog::OnSize, this);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (disableMountOptions)
|
||||
OptionsButton->Show (false);
|
||||
|
||||
@@ -230,4 +243,27 @@ namespace VeraCrypt
|
||||
Layout();
|
||||
MainSizer->Fit( this );
|
||||
}
|
||||
|
||||
#ifdef TC_UNIX
|
||||
void MountOptionsDialog::OnPaint(wxPaintEvent& event)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
if (m_showRedBorder)
|
||||
{
|
||||
wxSize size = GetClientSize();
|
||||
wxPen pen(*wxRED, 3); // 3 pixels width
|
||||
dc.SetPen(pen);
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRectangle(0, 0, size.GetWidth(), size.GetHeight());
|
||||
}
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void MountOptionsDialog::OnSize(wxSizeEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
if (m_showRedBorder)
|
||||
Refresh();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -40,7 +40,16 @@ namespace VeraCrypt
|
||||
void OnReadOnlyCheckBoxClick (wxCommandEvent& event) { UpdateDialog(); }
|
||||
void UpdateDialog ();
|
||||
|
||||
#ifdef TC_UNIX
|
||||
// Used for displaying a red border around the dialog window when insecure mode is enabled
|
||||
void OnPaint(wxPaintEvent& event);
|
||||
void OnSize(wxSizeEvent& event);
|
||||
#endif
|
||||
|
||||
MountOptions &Options;
|
||||
#ifdef TC_UNIX
|
||||
bool m_showRedBorder;
|
||||
#endif
|
||||
wxString OptionsButtonLabel;
|
||||
VolumePasswordPanel *PasswordPanel;
|
||||
VolumePasswordPanel *ProtectionPasswordPanel;
|
||||
|
||||
@@ -117,6 +117,9 @@ namespace VeraCrypt
|
||||
VC_CONVERT_EXCEPTION (EMVKeyfileDataNotFound);
|
||||
VC_CONVERT_EXCEPTION (EMVPANNotFound);
|
||||
|
||||
VC_CONVERT_EXCEPTION (MountPointBlocked);
|
||||
VC_CONVERT_EXCEPTION (MountPointNotAllowed);
|
||||
|
||||
throw *ex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1082,7 +1082,12 @@ namespace VeraCrypt
|
||||
#endif
|
||||
|
||||
mMainFrame = new MainFrame (nullptr);
|
||||
|
||||
#if defined(TC_UNIX)
|
||||
if (CmdLine->ArgAllowInsecureMount)
|
||||
{
|
||||
mMainFrame->SetTitle (mMainFrame->GetTitle() + wxT(" ") + LangString["INSECURE_MODE"]);
|
||||
}
|
||||
#endif
|
||||
if (CmdLine->StartBackgroundTask)
|
||||
{
|
||||
UserPreferences prefs = GetPreferences ();
|
||||
|
||||
@@ -541,6 +541,9 @@ namespace VeraCrypt
|
||||
EX2MSG (HigherFuseVersionRequired, LangString["LINUX_EX2MSG_HIGHERFUSEVERSIONREQUIRED"]);
|
||||
#endif
|
||||
|
||||
EX2MSG (MountPointBlocked, LangString["MOUNTPOINT_BLOCKED"]);
|
||||
EX2MSG (MountPointNotAllowed, LangString["MOUNTPOINT_NOTALLOWED"]);
|
||||
|
||||
#undef EX2MSG
|
||||
return L"";
|
||||
}
|
||||
@@ -560,6 +563,7 @@ namespace VeraCrypt
|
||||
SetPreferences (CmdLine->Preferences);
|
||||
|
||||
Core->SetApplicationExecutablePath (Application::GetExecutablePath());
|
||||
Core->SetUserEnvPATH (getenv ("PATH"));
|
||||
|
||||
if (!Preferences.NonInteractive)
|
||||
{
|
||||
@@ -572,6 +576,10 @@ namespace VeraCrypt
|
||||
|
||||
Core->ForceUseDummySudoPassword (CmdLine->ArgUseDummySudoPassword);
|
||||
|
||||
#if defined(TC_UNIX)
|
||||
Core->SetAllowInsecureMount (CmdLine->ArgAllowInsecureMount);
|
||||
#endif
|
||||
|
||||
Core->WarningEvent.Connect (EventConnector <UserInterface> (this, &UserInterface::OnWarning));
|
||||
Core->VolumeMountedEvent.Connect (EventConnector <UserInterface> (this, &UserInterface::OnVolumeMounted));
|
||||
|
||||
@@ -1646,6 +1654,13 @@ const FileManager fileManagers[] = {
|
||||
return sResult;
|
||||
}
|
||||
|
||||
#ifdef TC_UNIX
|
||||
bool UserInterface::InsecureMountAllowed () const
|
||||
{
|
||||
return CmdLine->ArgAllowInsecureMount;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define VC_CONVERT_EXCEPTION(NAME) if (dynamic_cast<NAME*> (ex)) throw (NAME&) *ex;
|
||||
|
||||
void UserInterface::ThrowException (Exception* ex)
|
||||
@@ -1734,6 +1749,9 @@ const FileManager fileManagers[] = {
|
||||
VC_CONVERT_EXCEPTION (EMVKeyfileDataNotFound);
|
||||
VC_CONVERT_EXCEPTION (EMVPANNotFound);
|
||||
|
||||
VC_CONVERT_EXCEPTION (MountPointBlocked);
|
||||
VC_CONVERT_EXCEPTION (MountPointNotAllowed);
|
||||
|
||||
throw *ex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,9 @@ namespace VeraCrypt
|
||||
virtual wxDateTime VolumeTimeToDateTime (VolumeTime volumeTime) const { return wxDateTime ((time_t) (volumeTime / 1000ULL / 1000 / 10 - 134774ULL * 24 * 3600)); }
|
||||
virtual wxString VolumeTimeToString (VolumeTime volumeTime) const;
|
||||
virtual wxString VolumeTypeToString (VolumeType::Enum type, VolumeProtection::Enum protection) const;
|
||||
|
||||
#ifdef TC_UNIX
|
||||
virtual bool InsecureMountAllowed () const;
|
||||
#endif
|
||||
Event PreferencesUpdatedEvent;
|
||||
|
||||
struct BusyScope
|
||||
|
||||
@@ -96,7 +96,9 @@ namespace VeraCrypt
|
||||
TC_EXCEPTION (TestFailed); \
|
||||
TC_EXCEPTION (TimeOut); \
|
||||
TC_EXCEPTION (UnknownException); \
|
||||
TC_EXCEPTION (UserAbort)
|
||||
TC_EXCEPTION (UserAbort); \
|
||||
TC_EXCEPTION (MountPointBlocked); \
|
||||
TC_EXCEPTION (MountPointNotAllowed)
|
||||
|
||||
TC_EXCEPTION_SET;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user