[Kernel] Reject IO for invalid characters.
[Kernel] Reject IO for paths with invalid characters.
This commit is contained in:
parent
41cf7c7a63
commit
c99c430665
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue