Source code

Revision control

Copy as Markdown

Other Tools

# HG changeset patch
# User Bob Owen <bobowencode@gmail.com>
# Date 1454317140 0
# Mon Feb 01 08:59:00 2016 +0000
# Node ID 9870a92ea5f352ab5a841003a30ab52c8deb589e
# Parent d62b6a3a0c58528a8bf864bb5ab6bb9faada972b
Change to allow network drives in sandbox rules with non-file device fix. r=aklotz
Originally landed in changeset:
diff --git a/security/sandbox/chromium/sandbox/win/src/win_utils.cc b/security/sandbox/chromium/sandbox/win/src/win_utils.cc
--- a/security/sandbox/chromium/sandbox/win/src/win_utils.cc
+++ b/security/sandbox/chromium/sandbox/win/src/win_utils.cc
@@ -194,61 +194,66 @@ bool ResolveRegistryName(std::wstring na
return false;
}
// |full_path| can have any of the following forms:
// \??\c:\some\foo\bar
// \Device\HarddiskVolume0\some\foo\bar
// \??\HarddiskVolume0\some\foo\bar
+// \??\UNC\SERVER\Share\some\foo\bar
DWORD IsReparsePoint(const std::wstring& full_path) {
// Check if it's a pipe. We can't query the attributes of a pipe.
if (IsPipe(full_path))
return ERROR_NOT_A_REPARSE_POINT;
std::wstring path;
bool nt_path = IsNTPath(full_path, &path);
bool has_drive = StartsWithDriveLetter(path);
bool is_device_path = IsDevicePath(path, &path);
if (!has_drive && !is_device_path && !nt_path)
return ERROR_INVALID_NAME;
- bool added_implied_device = false;
if (!has_drive) {
- path = std::wstring(kNTDotPrefix) + path;
- added_implied_device = true;
+ // Add Win32 device namespace prefix, required for some Windows APIs.
+ path.insert(0, kNTDotPrefix);
}
- std::wstring::size_type last_pos = std::wstring::npos;
- bool passed_once = false;
+ // Ensure that volume path matches start of path.
+ wchar_t vol_path[MAX_PATH];
+ if (!::GetVolumePathNameW(path.c_str(), vol_path, MAX_PATH)) {
+ // This will fail if this is a device that isn't volume related, which can't
+ // then be a reparse point.
+ return is_device_path ? ERROR_NOT_A_REPARSE_POINT : ERROR_INVALID_NAME;
+ }
+
+ // vol_path includes a trailing slash, so reduce size for path and loop check.
+ size_t vol_path_len = wcslen(vol_path) - 1;
+ if (!EqualPath(path, vol_path, vol_path_len)) {
+ return ERROR_INVALID_NAME;
+ }
do {
- path = path.substr(0, last_pos);
-
DWORD attributes = ::GetFileAttributes(path.c_str());
if (INVALID_FILE_ATTRIBUTES == attributes) {
DWORD error = ::GetLastError();
if (error != ERROR_FILE_NOT_FOUND && error != ERROR_PATH_NOT_FOUND &&
+ error != ERROR_INVALID_FUNCTION &&
error != ERROR_INVALID_NAME) {
// Unexpected error.
- if (passed_once && added_implied_device &&
- (path.rfind(L'\\') == kNTDotPrefixLen - 1)) {
- break;
- }
return error;
}
} else if (FILE_ATTRIBUTE_REPARSE_POINT & attributes) {
// This is a reparse point.
return ERROR_SUCCESS;
}
- passed_once = true;
- last_pos = path.rfind(L'\\');
- } while (last_pos > 2); // Skip root dir.
+ path.resize(path.rfind(L'\\'));
+ } while (path.size() > vol_path_len); // Skip root dir.
return ERROR_NOT_A_REPARSE_POINT;
}
// We get a |full_path| of the forms accepted by IsReparsePoint(), and the name
// we'll get from |handle| will be \device\harddiskvolume1\some\foo\bar.
bool SameObject(HANDLE handle, const wchar_t* full_path) {
// Check if it's a pipe.
@@ -258,63 +263,67 @@ bool SameObject(HANDLE handle, const wch
std::wstring actual_path;
if (!GetPathFromHandle(handle, &actual_path))
return false;
std::wstring path(full_path);
DCHECK_NT(!path.empty());
// This may end with a backslash.
- const wchar_t kBackslash = '\\';
- if (path.back() == kBackslash)
- path = path.substr(0, path.length() - 1);
+ if (path.back() == L'\\') {
+ path.pop_back();
+ }
- // Perfect match (case-insesitive check).
+ // Perfect match (case-insensitive check).
if (EqualPath(actual_path, path))
return true;
bool nt_path = IsNTPath(path, &path);
bool has_drive = StartsWithDriveLetter(path);
if (!has_drive && nt_path) {
std::wstring simple_actual_path;
- if (!IsDevicePath(actual_path, &simple_actual_path))
- return false;
-
- // Perfect match (case-insesitive check).
- return (EqualPath(simple_actual_path, path));
+ if (IsDevicePath(path, &path)) {
+ if (IsDevicePath(actual_path, &simple_actual_path)) {
+ // Perfect match (case-insensitive check).
+ return (EqualPath(simple_actual_path, path));
+ } else {
+ return false;
+ }
+ } else {
+ // Add Win32 device namespace for GetVolumePathName.
+ path.insert(0, kNTDotPrefix);
+ }
}
- if (!has_drive)
+ // Get the volume path in the same format as actual_path.
+ wchar_t vol_path[MAX_PATH];
+ if (!::GetVolumePathName(path.c_str(), vol_path, MAX_PATH)) {
return false;
-
- // We only need 3 chars, but let's alloc a buffer for four.
- wchar_t drive[4] = {0};
- wchar_t vol_name[MAX_PATH];
- memcpy(drive, &path[0], 2 * sizeof(*drive));
-
- // We'll get a double null terminated string.
- DWORD vol_length = ::QueryDosDeviceW(drive, vol_name, MAX_PATH);
- if (vol_length < 2 || vol_length == MAX_PATH)
+ }
+ size_t vol_path_len = wcslen(vol_path);
+ base::string16 nt_vol;
+ if (!GetNtPathFromWin32Path(vol_path, &nt_vol)) {
return false;
-
- // Ignore the nulls at the end.
- vol_length = static_cast<DWORD>(wcslen(vol_name));
+ }
// The two paths should be the same length.
- if (vol_length + path.size() - 2 != actual_path.size())
+ if (nt_vol.size() + path.size() - vol_path_len != actual_path.size()) {
return false;
+ }
- // Check up to the drive letter.
- if (!EqualPath(actual_path, vol_name, vol_length))
+ // Check the volume matches.
+ if (!EqualPath(actual_path, nt_vol.c_str(), nt_vol.size())) {
return false;
+ }
- // Check the path after the drive letter.
- if (!EqualPath(actual_path, vol_length, path, 2))
+ // Check the path after the volume matches.
+ if (!EqualPath(actual_path, nt_vol.size(), path, vol_path_len)) {
return false;
+ }
return true;
}
// Just make a best effort here. There are lots of corner cases that we're
// not expecting - and will fail to make long.
bool ConvertToLongPath(std::wstring* native_path,
const std::wstring* drive_letter) {