[Kernel] Reject IO for invalid characters.

[Kernel] Reject IO for paths with invalid characters.
This commit is contained in:
gibbed 2020-07-12 09:48:17 -05:00 committed by Rick Gibbed
parent 41cf7c7a63
commit c99c430665
2 changed files with 62 additions and 2 deletions

View File

@ -39,6 +39,41 @@ struct CreateOptions {
static const uint32_t FILE_RANDOM_ACCESS = 0x00000800; static const uint32_t FILE_RANDOM_ACCESS = 0x00000800;
}; };
static bool IsValidPath(const std::string_view s, bool is_pattern) {
// TODO(gibbed): validate path components individually
for (const auto& c : s) {
if (c <= 31 || c >= 127) {
return false;
}
switch (c) {
case '"':
// case '*':
case '+':
case ',':
// case ':':
case ';':
case '<':
case '=':
case '>':
// case '?':
case '|': {
return false;
}
case '*':
case '?': {
// Pattern-specific (for NtQueryDirectoryFile)
if (!is_pattern) {
return false;
}
}
default: {
break;
}
}
}
return true;
}
dword_result_t NtCreateFile(lpdword_t handle_out, dword_t desired_access, dword_result_t NtCreateFile(lpdword_t handle_out, dword_t desired_access,
pointer_t<X_OBJECT_ATTRIBUTES> object_attrs, pointer_t<X_OBJECT_ATTRIBUTES> object_attrs,
pointer_t<X_IO_STATUS_BLOCK> io_status_block, pointer_t<X_IO_STATUS_BLOCK> io_status_block,
@ -64,6 +99,12 @@ dword_result_t NtCreateFile(lpdword_t handle_out, dword_t desired_access,
// Compute path, possibly attrs relative. // Compute path, possibly attrs relative.
auto target_path = util::TranslateAnsiString(kernel_memory(), object_name); auto target_path = util::TranslateAnsiString(kernel_memory(), object_name);
// Enforce that the path is ASCII.
if (!IsValidPath(target_path, false)) {
return X_STATUS_OBJECT_NAME_INVALID;
}
if (object_attrs->root_directory != 0xFFFFFFFD && // ObDosDevices if (object_attrs->root_directory != 0xFFFFFFFD && // ObDosDevices
object_attrs->root_directory != 0) { object_attrs->root_directory != 0) {
auto root_file = kernel_state()->object_table()->LookupObject<XFile>( auto root_file = kernel_state()->object_table()->LookupObject<XFile>(
@ -341,9 +382,15 @@ dword_result_t NtQueryFullAttributesFile(
assert_always(); assert_always();
} }
auto target_path = util::TranslateAnsiString(kernel_memory(), object_name);
// Enforce that the path is ASCII.
if (!IsValidPath(target_path, false)) {
return X_STATUS_OBJECT_NAME_INVALID;
}
// Resolve the file using the virtual file system. // Resolve the file using the virtual file system.
auto entry = kernel_state()->file_system()->ResolvePath( auto entry = kernel_state()->file_system()->ResolvePath(target_path);
util::TranslateAnsiString(kernel_memory(), object_name));
if (entry) { if (entry) {
// Found. // Found.
file_info->creation_time = entry->create_timestamp(); file_info->creation_time = entry->create_timestamp();
@ -375,6 +422,12 @@ dword_result_t NtQueryDirectoryFile(
auto file = kernel_state()->object_table()->LookupObject<XFile>(file_handle); auto file = kernel_state()->object_table()->LookupObject<XFile>(file_handle);
auto name = util::TranslateAnsiString(kernel_memory(), file_name); auto name = util::TranslateAnsiString(kernel_memory(), file_name);
// Enforce that the path is ASCII.
if (!IsValidPath(name, true)) {
return X_STATUS_OBJECT_NAME_INVALID;
}
if (file) { if (file) {
X_FILE_DIRECTORY_INFORMATION dir_info = {0}; X_FILE_DIRECTORY_INFORMATION dir_info = {0};
result = result =
@ -427,6 +480,12 @@ dword_result_t NtOpenSymbolicLinkObject(
std::string target_path = std::string target_path =
util::TranslateAnsiString(kernel_memory(), object_name); util::TranslateAnsiString(kernel_memory(), object_name);
// Enforce that the path is ASCII.
if (!IsValidPath(target_path, false)) {
return X_STATUS_OBJECT_NAME_INVALID;
}
if (object_attrs->root_directory != 0) { if (object_attrs->root_directory != 0) {
assert_always(); assert_always();
} }

View File

@ -56,6 +56,7 @@ typedef uint32_t X_STATUS;
#define X_STATUS_ACCESS_DENIED ((X_STATUS)0xC0000022L) #define X_STATUS_ACCESS_DENIED ((X_STATUS)0xC0000022L)
#define X_STATUS_BUFFER_TOO_SMALL ((X_STATUS)0xC0000023L) #define X_STATUS_BUFFER_TOO_SMALL ((X_STATUS)0xC0000023L)
#define X_STATUS_OBJECT_TYPE_MISMATCH ((X_STATUS)0xC0000024L) #define X_STATUS_OBJECT_TYPE_MISMATCH ((X_STATUS)0xC0000024L)
#define X_STATUS_OBJECT_NAME_INVALID ((X_STATUS)0xC0000033L)
#define X_STATUS_OBJECT_NAME_NOT_FOUND ((X_STATUS)0xC0000034L) #define X_STATUS_OBJECT_NAME_NOT_FOUND ((X_STATUS)0xC0000034L)
#define X_STATUS_OBJECT_NAME_COLLISION ((X_STATUS)0xC0000035L) #define X_STATUS_OBJECT_NAME_COLLISION ((X_STATUS)0xC0000035L)
#define X_STATUS_INVALID_PAGE_PROTECTION ((X_STATUS)0xC0000045L) #define X_STATUS_INVALID_PAGE_PROTECTION ((X_STATUS)0xC0000045L)