diff options
Diffstat (limited to 'security/sandbox/chromium-shim/patches/after_update')
9 files changed, 1439 insertions, 0 deletions
diff --git a/security/sandbox/chromium-shim/patches/after_update/add_WOW64_flags_to_allowed_registry_read_flags.patch b/security/sandbox/chromium-shim/patches/after_update/add_WOW64_flags_to_allowed_registry_read_flags.patch new file mode 100644 index 0000000000..7eb643719e --- /dev/null +++ b/security/sandbox/chromium-shim/patches/after_update/add_WOW64_flags_to_allowed_registry_read_flags.patch @@ -0,0 +1,34 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1482405067 0 +# Thu Dec 22 11:11:07 2016 +0000 +# Node ID 43d0efc18f586e1ed90b95c4a52235c4648e96a9 +# Parent 266ef86795979f2ef9b6650d1bb35fb27d11ad86 +Add KEY_WOW64_64Key and KEY_WOW64_32KEY to the Chromium sandbox allowed registry read flags. r=aklotz + +Originally landed as changeset: +https://hg.mozilla.org/mozilla-central/rev/d24db55deb85 + +diff --git a/security/sandbox/chromium/sandbox/win/src/registry_policy.cc b/security/sandbox/chromium/sandbox/win/src/registry_policy.cc +--- a/security/sandbox/chromium/sandbox/win/src/registry_policy.cc ++++ b/security/sandbox/chromium/sandbox/win/src/registry_policy.cc +@@ -15,17 +15,18 @@ + #include "sandbox/win/src/sandbox_types.h" + #include "sandbox/win/src/sandbox_utils.h" + #include "sandbox/win/src/win_utils.h" + + namespace { + + static const uint32_t kAllowedRegFlags = + KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY | KEY_READ | +- GENERIC_READ | GENERIC_EXECUTE | READ_CONTROL; ++ GENERIC_READ | GENERIC_EXECUTE | READ_CONTROL | KEY_WOW64_64KEY | ++ KEY_WOW64_32KEY; + + // Opens the key referenced by |obj_attributes| with |access| and + // checks what permission was given. Remove the WRITE flags and update + // |access| with the new value. + NTSTATUS TranslateMaximumAllowed(OBJECT_ATTRIBUTES* obj_attributes, + DWORD* access) { + NtOpenKeyFunction NtOpenKey = nullptr; + ResolveNTFunctionPtr("NtOpenKey", &NtOpenKey); diff --git a/security/sandbox/chromium-shim/patches/after_update/add_interception_logging.patch b/security/sandbox/chromium-shim/patches/after_update/add_interception_logging.patch new file mode 100644 index 0000000000..344fd569d7 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/after_update/add_interception_logging.patch @@ -0,0 +1,810 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1417281138 0 +# Sat Nov 29 17:12:18 2014 +0000 +# Node ID 4ea2e332affe4b74bd37fbf2fee8da0b1c94e115 +# Parent 5eec91873c96c2cbfc856ba86335fa068c89d6ce +Re-apply - Logging changes to the Chromium interception code. r=tabraldes + +Originally landed as changset: +https://hg.mozilla.org/mozilla-central/rev/0f763c186855 + +diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.cc b/security/sandbox/chromium/sandbox/win/src/filesystem_interception.cc +--- a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.cc ++++ b/security/sandbox/chromium/sandbox/win/src/filesystem_interception.cc +@@ -10,16 +10,17 @@ + #include "sandbox/win/src/filesystem_policy.h" + #include "sandbox/win/src/ipc_tags.h" + #include "sandbox/win/src/policy_params.h" + #include "sandbox/win/src/policy_target.h" + #include "sandbox/win/src/sandbox_factory.h" + #include "sandbox/win/src/sandbox_nt_util.h" + #include "sandbox/win/src/sharedmem_ipc_client.h" + #include "sandbox/win/src/target_services.h" ++#include "mozilla/sandboxing/sandboxLogging.h" + + // This status occurs when trying to access a network share on the machine from + // which it is shared. + #define STATUS_NETWORK_OPEN_RESTRICTION ((NTSTATUS)0xC0000201L) + + namespace sandbox { + + NTSTATUS WINAPI TargetNtCreateFile(NtCreateFileFunction orig_CreateFile, +@@ -37,16 +38,20 @@ NTSTATUS WINAPI TargetNtCreateFile(NtCre + // Check if the process can open it first. + NTSTATUS status = orig_CreateFile( + file, desired_access, object_attributes, io_status, allocation_size, + file_attributes, sharing, disposition, options, ea_buffer, ea_length); + if (STATUS_ACCESS_DENIED != status && + STATUS_NETWORK_OPEN_RESTRICTION != status) + return status; + ++ mozilla::sandboxing::LogBlocked("NtCreateFile", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + if (!ValidParameter(file, sizeof(HANDLE), WRITE)) + break; + if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE)) +@@ -96,16 +101,19 @@ NTSTATUS WINAPI TargetNtCreateFile(NtCre + + __try { + *file = answer.handle; + io_status->Status = answer.nt_status; + io_status->Information = answer.extended[0].ulong_ptr; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } ++ mozilla::sandboxing::LogAllowed("NtCreateFile", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); + } while (false); + + return status; + } + + NTSTATUS WINAPI TargetNtOpenFile(NtOpenFileFunction orig_OpenFile, + PHANDLE file, + ACCESS_MASK desired_access, +@@ -115,16 +123,20 @@ NTSTATUS WINAPI TargetNtOpenFile(NtOpenF + ULONG options) { + // Check if the process can open it first. + NTSTATUS status = orig_OpenFile(file, desired_access, object_attributes, + io_status, sharing, options); + if (STATUS_ACCESS_DENIED != status && + STATUS_NETWORK_OPEN_RESTRICTION != status) + return status; + ++ mozilla::sandboxing::LogBlocked("NtOpenFile", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + if (!ValidParameter(file, sizeof(HANDLE), WRITE)) + break; + if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE)) +@@ -171,31 +183,38 @@ NTSTATUS WINAPI TargetNtOpenFile(NtOpenF + + __try { + *file = answer.handle; + io_status->Status = answer.nt_status; + io_status->Information = answer.extended[0].ulong_ptr; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } ++ mozilla::sandboxing::LogAllowed("NtOpenFile", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); + } while (false); + + return status; + } + + NTSTATUS WINAPI + TargetNtQueryAttributesFile(NtQueryAttributesFileFunction orig_QueryAttributes, + POBJECT_ATTRIBUTES object_attributes, + PFILE_BASIC_INFORMATION file_attributes) { + // Check if the process can query it first. + NTSTATUS status = orig_QueryAttributes(object_attributes, file_attributes); + if (STATUS_ACCESS_DENIED != status && + STATUS_NETWORK_OPEN_RESTRICTION != status) + return status; + ++ mozilla::sandboxing::LogBlocked("NtQueryAttributesFile", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + if (!ValidParameter(file_attributes, sizeof(FILE_BASIC_INFORMATION), WRITE)) + break; + +@@ -227,32 +246,39 @@ TargetNtQueryAttributesFile(NtQueryAttri + ResultCode code = CrossCall(ipc, IpcTag::NTQUERYATTRIBUTESFILE, name.get(), + attributes, file_info, &answer); + + if (SBOX_ALL_OK != code) + break; + + status = answer.nt_status; + ++ mozilla::sandboxing::LogAllowed("NtQueryAttributesFile", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); + } while (false); + + return status; + } + + NTSTATUS WINAPI TargetNtQueryFullAttributesFile( + NtQueryFullAttributesFileFunction orig_QueryFullAttributes, + POBJECT_ATTRIBUTES object_attributes, + PFILE_NETWORK_OPEN_INFORMATION file_attributes) { + // Check if the process can query it first. + NTSTATUS status = + orig_QueryFullAttributes(object_attributes, file_attributes); + if (STATUS_ACCESS_DENIED != status && + STATUS_NETWORK_OPEN_RESTRICTION != status) + return status; + ++ mozilla::sandboxing::LogBlocked("NtQueryFullAttributesFile", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + if (!ValidParameter(file_attributes, sizeof(FILE_NETWORK_OPEN_INFORMATION), + WRITE)) + break; +@@ -284,16 +310,20 @@ NTSTATUS WINAPI TargetNtQueryFullAttribu + CrossCallReturn answer = {0}; + ResultCode code = CrossCall(ipc, IpcTag::NTQUERYFULLATTRIBUTESFILE, + name.get(), attributes, file_info, &answer); + + if (SBOX_ALL_OK != code) + break; + + status = answer.nt_status; ++ ++ mozilla::sandboxing::LogAllowed("NtQueryFullAttributesFile", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); + } while (false); + + return status; + } + + NTSTATUS WINAPI + TargetNtSetInformationFile(NtSetInformationFileFunction orig_SetInformationFile, + HANDLE file, +@@ -302,16 +332,18 @@ TargetNtSetInformationFile(NtSetInformat + ULONG length, + FILE_INFORMATION_CLASS file_info_class) { + // Check if the process can open it first. + NTSTATUS status = orig_SetInformationFile(file, io_status, file_info, length, + file_info_class); + if (STATUS_ACCESS_DENIED != status) + return status; + ++ mozilla::sandboxing::LogBlocked("NtSetInformationFile"); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + void* memory = GetGlobalIPCMemory(); + if (!memory) + break; +@@ -366,14 +398,15 @@ TargetNtSetInformationFile(NtSetInformat + ResultCode code = + CrossCall(ipc, IpcTag::NTSETINFO_RENAME, file, io_status_buffer, + file_info_buffer, length, file_info_class, &answer); + + if (SBOX_ALL_OK != code) + break; + + status = answer.nt_status; ++ mozilla::sandboxing::LogAllowed("NtSetInformationFile"); + } while (false); + + return status; + } + + } // namespace sandbox +diff --git a/security/sandbox/chromium/sandbox/win/src/handle_interception.cc b/security/sandbox/chromium/sandbox/win/src/handle_interception.cc +--- a/security/sandbox/chromium/sandbox/win/src/handle_interception.cc ++++ b/security/sandbox/chromium/sandbox/win/src/handle_interception.cc +@@ -5,16 +5,17 @@ + #include "sandbox/win/src/handle_interception.h" + + #include "sandbox/win/src/crosscall_client.h" + #include "sandbox/win/src/ipc_tags.h" + #include "sandbox/win/src/sandbox_factory.h" + #include "sandbox/win/src/sandbox_nt_util.h" + #include "sandbox/win/src/sharedmem_ipc_client.h" + #include "sandbox/win/src/target_services.h" ++#include "mozilla/sandboxing/sandboxLogging.h" + + namespace sandbox { + + ResultCode DuplicateHandleProxy(HANDLE source_handle, + DWORD target_process_id, + HANDLE* target_handle, + DWORD desired_access, + DWORD options) { +@@ -29,17 +30,19 @@ ResultCode DuplicateHandleProxy(HANDLE s + ResultCode code = CrossCall(ipc, IpcTag::DUPLICATEHANDLEPROXY, + source_handle, target_process_id, + desired_access, options, &answer); + if (SBOX_ALL_OK != code) + return code; + + if (answer.win32_result) { + ::SetLastError(answer.win32_result); ++ mozilla::sandboxing::LogBlocked("DuplicateHandle"); + return SBOX_ERROR_GENERIC; + } + + *target_handle = answer.handle; ++ mozilla::sandboxing::LogAllowed("DuplicateHandle"); + return SBOX_ALL_OK; + } + + } // namespace sandbox + +diff --git a/security/sandbox/chromium/sandbox/win/src/named_pipe_interception.cc b/security/sandbox/chromium/sandbox/win/src/named_pipe_interception.cc +--- a/security/sandbox/chromium/sandbox/win/src/named_pipe_interception.cc ++++ b/security/sandbox/chromium/sandbox/win/src/named_pipe_interception.cc +@@ -7,16 +7,17 @@ + #include "sandbox/win/src/crosscall_client.h" + #include "sandbox/win/src/ipc_tags.h" + #include "sandbox/win/src/policy_params.h" + #include "sandbox/win/src/policy_target.h" + #include "sandbox/win/src/sandbox_factory.h" + #include "sandbox/win/src/sandbox_nt_util.h" + #include "sandbox/win/src/sharedmem_ipc_client.h" + #include "sandbox/win/src/target_services.h" ++#include "mozilla/sandboxing/sandboxLogging.h" + + namespace sandbox { + + HANDLE WINAPI + TargetCreateNamedPipeW(CreateNamedPipeWFunction orig_CreateNamedPipeW, + LPCWSTR pipe_name, + DWORD open_mode, + DWORD pipe_mode, +@@ -26,16 +27,18 @@ TargetCreateNamedPipeW(CreateNamedPipeWF + DWORD default_timeout, + LPSECURITY_ATTRIBUTES security_attributes) { + HANDLE pipe = orig_CreateNamedPipeW( + pipe_name, open_mode, pipe_mode, max_instance, out_buffer_size, + in_buffer_size, default_timeout, security_attributes); + if (INVALID_HANDLE_VALUE != pipe) + return pipe; + ++ mozilla::sandboxing::LogBlocked("CreateNamedPipeW", pipe_name); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return INVALID_HANDLE_VALUE; + + DWORD original_error = ::GetLastError(); + + // We don't support specific Security Attributes. + if (security_attributes) +@@ -61,16 +64,17 @@ TargetCreateNamedPipeW(CreateNamedPipeWF + if (SBOX_ALL_OK != code) + break; + + ::SetLastError(answer.win32_result); + + if (ERROR_SUCCESS != answer.win32_result) + return INVALID_HANDLE_VALUE; + ++ mozilla::sandboxing::LogAllowed("CreateNamedPipeW", pipe_name); + return answer.handle; + } while (false); + + ::SetLastError(original_error); + return INVALID_HANDLE_VALUE; + } + + } // namespace sandbox +diff --git a/security/sandbox/chromium/sandbox/win/src/process_thread_interception.cc b/security/sandbox/chromium/sandbox/win/src/process_thread_interception.cc +--- a/security/sandbox/chromium/sandbox/win/src/process_thread_interception.cc ++++ b/security/sandbox/chromium/sandbox/win/src/process_thread_interception.cc +@@ -10,16 +10,17 @@ + #include "sandbox/win/src/crosscall_client.h" + #include "sandbox/win/src/ipc_tags.h" + #include "sandbox/win/src/policy_params.h" + #include "sandbox/win/src/policy_target.h" + #include "sandbox/win/src/sandbox_factory.h" + #include "sandbox/win/src/sandbox_nt_util.h" + #include "sandbox/win/src/sharedmem_ipc_client.h" + #include "sandbox/win/src/target_services.h" ++#include "mozilla/sandboxing/sandboxLogging.h" + + namespace sandbox { + + SANDBOX_INTERCEPT NtExports g_nt; + + // Hooks NtOpenThread and proxy the call to the broker if it's trying to + // open a thread in the same process. + NTSTATUS WINAPI TargetNtOpenThread(NtOpenThreadFunction orig_OpenThread, +@@ -27,16 +28,17 @@ NTSTATUS WINAPI TargetNtOpenThread(NtOpe + ACCESS_MASK desired_access, + POBJECT_ATTRIBUTES object_attributes, + PCLIENT_ID client_id) { + NTSTATUS status = + orig_OpenThread(thread, desired_access, object_attributes, client_id); + if (NT_SUCCESS(status)) + return status; + ++ mozilla::sandboxing::LogBlocked("NtOpenThread"); + do { + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + break; + if (!client_id) + break; + + uint32_t thread_id = 0; + bool should_break = false; +@@ -91,16 +93,17 @@ NTSTATUS WINAPI TargetNtOpenThread(NtOpe + + __try { + // Write the output parameters. + *thread = answer.handle; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } + ++ mozilla::sandboxing::LogAllowed("NtOpenThread"); + return answer.nt_status; + } while (false); + + return status; + } + + // Hooks NtOpenProcess and proxy the call to the broker if it's trying to + // open the current process. +@@ -176,16 +179,17 @@ NTSTATUS WINAPI + TargetNtOpenProcessToken(NtOpenProcessTokenFunction orig_OpenProcessToken, + HANDLE process, + ACCESS_MASK desired_access, + PHANDLE token) { + NTSTATUS status = orig_OpenProcessToken(process, desired_access, token); + if (NT_SUCCESS(status)) + return status; + ++ mozilla::sandboxing::LogBlocked("NtOpenProcessToken"); + do { + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + break; + + if (CURRENT_PROCESS != process) + break; + + if (!ValidParameter(token, sizeof(HANDLE), WRITE)) +@@ -207,16 +211,17 @@ TargetNtOpenProcessToken(NtOpenProcessTo + + __try { + // Write the output parameters. + *token = answer.handle; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } + ++ mozilla::sandboxing::LogAllowed("NtOpenProcessToken"); + return answer.nt_status; + } while (false); + + return status; + } + + NTSTATUS WINAPI + TargetNtOpenProcessTokenEx(NtOpenProcessTokenExFunction orig_OpenProcessTokenEx, +@@ -224,16 +229,17 @@ TargetNtOpenProcessTokenEx(NtOpenProcess + ACCESS_MASK desired_access, + ULONG handle_attributes, + PHANDLE token) { + NTSTATUS status = orig_OpenProcessTokenEx(process, desired_access, + handle_attributes, token); + if (NT_SUCCESS(status)) + return status; + ++ mozilla::sandboxing::LogBlocked("NtOpenProcessTokenEx"); + do { + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + break; + + if (CURRENT_PROCESS != process) + break; + + if (!ValidParameter(token, sizeof(HANDLE), WRITE)) +@@ -255,16 +261,17 @@ TargetNtOpenProcessTokenEx(NtOpenProcess + + __try { + // Write the output parameters. + *token = answer.handle; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } + ++ mozilla::sandboxing::LogAllowed("NtOpenProcessTokenEx"); + return answer.nt_status; + } while (false); + + return status; + } + + BOOL WINAPI TargetCreateProcessW(CreateProcessWFunction orig_CreateProcessW, + LPCWSTR application_name, +@@ -280,16 +287,18 @@ BOOL WINAPI TargetCreateProcessW(CreateP + if (SandboxFactory::GetTargetServices()->GetState()->IsCsrssConnected() && + orig_CreateProcessW(application_name, command_line, process_attributes, + thread_attributes, inherit_handles, flags, + environment, current_directory, startup_info, + process_information)) { + return true; + } + ++ mozilla::sandboxing::LogBlocked("CreateProcessW", application_name); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return false; + + // Don't call GetLastError before InitCalled() succeeds because kernel32 may + // not be mapped yet. + DWORD original_error = ::GetLastError(); + +@@ -320,16 +329,17 @@ BOOL WINAPI TargetCreateProcessW(CreateP + cur_dir, current_directory, proc_info, &answer); + if (SBOX_ALL_OK != code) + break; + + ::SetLastError(answer.win32_result); + if (ERROR_SUCCESS != answer.win32_result) + return false; + ++ mozilla::sandboxing::LogAllowed("CreateProcessW", application_name); + return true; + } while (false); + + ::SetLastError(original_error); + return false; + } + + BOOL WINAPI TargetCreateProcessA(CreateProcessAFunction orig_CreateProcessA, +@@ -346,16 +356,18 @@ BOOL WINAPI TargetCreateProcessA(CreateP + if (SandboxFactory::GetTargetServices()->GetState()->IsCsrssConnected() && + orig_CreateProcessA(application_name, command_line, process_attributes, + thread_attributes, inherit_handles, flags, + environment, current_directory, startup_info, + process_information)) { + return true; + } + ++ mozilla::sandboxing::LogBlocked("CreateProcessA", application_name); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return false; + + // Don't call GetLastError before InitCalled() succeeds because kernel32 may + // not be mapped yet. + DWORD original_error = ::GetLastError(); + +@@ -420,16 +432,17 @@ BOOL WINAPI TargetCreateProcessA(CreateP + + if (SBOX_ALL_OK != code) + break; + + ::SetLastError(answer.win32_result); + if (ERROR_SUCCESS != answer.win32_result) + return false; + ++ mozilla::sandboxing::LogAllowed("CreateProcessA", application_name); + return true; + } while (false); + + ::SetLastError(original_error); + return false; + } + + HANDLE WINAPI TargetCreateThread(CreateThreadFunction orig_CreateThread, +diff --git a/security/sandbox/chromium/sandbox/win/src/registry_interception.cc b/security/sandbox/chromium/sandbox/win/src/registry_interception.cc +--- a/security/sandbox/chromium/sandbox/win/src/registry_interception.cc ++++ b/security/sandbox/chromium/sandbox/win/src/registry_interception.cc +@@ -9,16 +9,17 @@ + #include "sandbox/win/src/crosscall_client.h" + #include "sandbox/win/src/ipc_tags.h" + #include "sandbox/win/src/policy_params.h" + #include "sandbox/win/src/policy_target.h" + #include "sandbox/win/src/sandbox_factory.h" + #include "sandbox/win/src/sandbox_nt_util.h" + #include "sandbox/win/src/sharedmem_ipc_client.h" + #include "sandbox/win/src/target_services.h" ++#include "mozilla/sandboxing/sandboxLogging.h" + + namespace sandbox { + + NTSTATUS WINAPI TargetNtCreateKey(NtCreateKeyFunction orig_CreateKey, + PHANDLE key, + ACCESS_MASK desired_access, + POBJECT_ATTRIBUTES object_attributes, + ULONG title_index, +@@ -27,16 +28,22 @@ NTSTATUS WINAPI TargetNtCreateKey(NtCrea + PULONG disposition) { + // Check if the process can create it first. + NTSTATUS status = + orig_CreateKey(key, desired_access, object_attributes, title_index, + class_name, create_options, disposition); + if (NT_SUCCESS(status)) + return status; + ++ if (STATUS_OBJECT_NAME_NOT_FOUND != status) { ++ mozilla::sandboxing::LogBlocked("NtCreateKey", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); ++ } ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + if (!ValidParameter(key, sizeof(HANDLE), WRITE)) + break; + +@@ -114,16 +121,19 @@ NTSTATUS WINAPI TargetNtCreateKey(NtCrea + + if (disposition) + *disposition = answer.extended[0].unsigned_int; + + status = answer.nt_status; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } ++ mozilla::sandboxing::LogAllowed("NtCreateKey", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); + } while (false); + + return status; + } + + NTSTATUS WINAPI CommonNtOpenKey(NTSTATUS status, + PHANDLE key, + ACCESS_MASK desired_access, +@@ -193,30 +203,39 @@ NTSTATUS WINAPI CommonNtOpenKey(NTSTATUS + break; + + __try { + *key = answer.handle; + status = answer.nt_status; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } ++ mozilla::sandboxing::LogAllowed("NtOpenKey[Ex]", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); + } while (false); + + return status; + } + + NTSTATUS WINAPI TargetNtOpenKey(NtOpenKeyFunction orig_OpenKey, + PHANDLE key, + ACCESS_MASK desired_access, + POBJECT_ATTRIBUTES object_attributes) { + // Check if the process can open it first. + NTSTATUS status = orig_OpenKey(key, desired_access, object_attributes); + if (NT_SUCCESS(status)) + return status; + ++ if (STATUS_OBJECT_NAME_NOT_FOUND != status) { ++ mozilla::sandboxing::LogBlocked("NtOpenKey", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); ++ } ++ + return CommonNtOpenKey(status, key, desired_access, object_attributes); + } + + NTSTATUS WINAPI TargetNtOpenKeyEx(NtOpenKeyExFunction orig_OpenKeyEx, + PHANDLE key, + ACCESS_MASK desired_access, + POBJECT_ATTRIBUTES object_attributes, + ULONG open_options) { +@@ -225,12 +244,18 @@ NTSTATUS WINAPI TargetNtOpenKeyEx(NtOpen + orig_OpenKeyEx(key, desired_access, object_attributes, open_options); + + // We do not support open_options at this time. The 2 current known values + // are REG_OPTION_CREATE_LINK, to open a symbolic link, and + // REG_OPTION_BACKUP_RESTORE to open the key with special privileges. + if (NT_SUCCESS(status) || open_options != 0) + return status; + ++ if (STATUS_OBJECT_NAME_NOT_FOUND != status) { ++ mozilla::sandboxing::LogBlocked("NtOpenKeyEx", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); ++ } ++ + return CommonNtOpenKey(status, key, desired_access, object_attributes); + } + + } // namespace sandbox +diff --git a/security/sandbox/chromium/sandbox/win/src/signed_interception.cc b/security/sandbox/chromium/sandbox/win/src/signed_interception.cc +--- a/security/sandbox/chromium/sandbox/win/src/signed_interception.cc ++++ b/security/sandbox/chromium/sandbox/win/src/signed_interception.cc +@@ -9,16 +9,17 @@ + #include "sandbox/win/src/crosscall_client.h" + #include "sandbox/win/src/ipc_tags.h" + #include "sandbox/win/src/policy_params.h" + #include "sandbox/win/src/policy_target.h" + #include "sandbox/win/src/sandbox_factory.h" + #include "sandbox/win/src/sandbox_nt_util.h" + #include "sandbox/win/src/sharedmem_ipc_client.h" + #include "sandbox/win/src/target_services.h" ++#include "mozilla/sandboxing/sandboxLogging.h" + + namespace sandbox { + + NTSTATUS WINAPI + TargetNtCreateSection(NtCreateSectionFunction orig_CreateSection, + PHANDLE section_handle, + ACCESS_MASK desired_access, + POBJECT_ATTRIBUTES object_attributes, +@@ -37,16 +38,18 @@ TargetNtCreateSection(NtCreateSectionFun + break; + if (maximum_size) + break; + if (section_page_protection != PAGE_EXECUTE) + break; + if (allocation_attributes != SEC_IMAGE) + break; + ++ mozilla::sandboxing::LogBlocked("NtCreateSection"); ++ + // IPC must be fully started. + void* memory = GetGlobalIPCMemory(); + if (!memory) + break; + + std::unique_ptr<wchar_t, NtAllocDeleter> path; + + if (!NtGetPathFromHandle(file_handle, &path)) +@@ -73,16 +76,17 @@ TargetNtCreateSection(NtCreateSectionFun + if (code != SBOX_ALL_OK) + break; + + if (!NT_SUCCESS(answer.nt_status)) + break; + + __try { + *section_handle = answer.handle; ++ mozilla::sandboxing::LogAllowed("NtCreateSection"); + return answer.nt_status; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } + } while (false); + + // Fall back to the original API in all failure cases. + return orig_CreateSection(section_handle, desired_access, object_attributes, +diff --git a/security/sandbox/chromium/sandbox/win/src/sync_interception.cc b/security/sandbox/chromium/sandbox/win/src/sync_interception.cc +--- a/security/sandbox/chromium/sandbox/win/src/sync_interception.cc ++++ b/security/sandbox/chromium/sandbox/win/src/sync_interception.cc +@@ -9,16 +9,17 @@ + #include "sandbox/win/src/crosscall_client.h" + #include "sandbox/win/src/ipc_tags.h" + #include "sandbox/win/src/policy_params.h" + #include "sandbox/win/src/policy_target.h" + #include "sandbox/win/src/sandbox_factory.h" + #include "sandbox/win/src/sandbox_nt_util.h" + #include "sandbox/win/src/sharedmem_ipc_client.h" + #include "sandbox/win/src/target_services.h" ++#include "mozilla/sandboxing/sandboxLogging.h" + + namespace sandbox { + + ResultCode ProxyCreateEvent(LPCWSTR name, + uint32_t initial_state, + EVENT_TYPE event_type, + void* ipc_memory, + CrossCallReturn* answer) { +@@ -59,16 +60,20 @@ NTSTATUS WINAPI TargetNtCreateEvent(NtCr + EVENT_TYPE event_type, + BOOLEAN initial_state) { + NTSTATUS status = + orig_CreateEvent(event_handle, desired_access, object_attributes, + event_type, initial_state); + if (status != STATUS_ACCESS_DENIED || !object_attributes) + return status; + ++ mozilla::sandboxing::LogBlocked("NtCreatEvent", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + if (!ValidParameter(event_handle, sizeof(HANDLE), WRITE)) + break; + +@@ -97,30 +102,37 @@ NTSTATUS WINAPI TargetNtCreateEvent(NtCr + break; + } + __try { + *event_handle = answer.handle; + status = STATUS_SUCCESS; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } ++ mozilla::sandboxing::LogAllowed("NtCreateEvent", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); + } while (false); + + return status; + } + + NTSTATUS WINAPI TargetNtOpenEvent(NtOpenEventFunction orig_OpenEvent, + PHANDLE event_handle, + ACCESS_MASK desired_access, + POBJECT_ATTRIBUTES object_attributes) { + NTSTATUS status = + orig_OpenEvent(event_handle, desired_access, object_attributes); + if (status != STATUS_ACCESS_DENIED || !object_attributes) + return status; + ++ mozilla::sandboxing::LogBlocked("NtOpenEvent", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + if (!ValidParameter(event_handle, sizeof(HANDLE), WRITE)) + break; + +@@ -149,14 +161,17 @@ NTSTATUS WINAPI TargetNtOpenEvent(NtOpen + break; + } + __try { + *event_handle = answer.handle; + status = STATUS_SUCCESS; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } ++ mozilla::sandboxing::LogAllowed("NtOpenEvent", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); + } while (false); + + return status; + } + + } // namespace sandbox diff --git a/security/sandbox/chromium-shim/patches/after_update/allow_ntpath_in_SignedPolicy_GenerateRules.patch b/security/sandbox/chromium-shim/patches/after_update/allow_ntpath_in_SignedPolicy_GenerateRules.patch new file mode 100644 index 0000000000..8e6a951467 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/after_update/allow_ntpath_in_SignedPolicy_GenerateRules.patch @@ -0,0 +1,82 @@ +# HG changeset patch +# User Toshihito Kikuchi <tkikuchi@mozilla.com> +# Date 1605814807 28800 +# Thu Nov 19 11:40:07 2020 -0800 +# Node ID 29b049665db1f28ffdfce319ad48912d4a024e23 +# Parent 94435953fb89c1fe147c6b76a9ecb61f59625d30 +Bug 1620114 - Allow an NT path string to be passed to SignedPolicy::GenerateRules. r=bobowen +so that our SandboxBroker can add a policy rule with an NT path directly. + +diff --git a/security/sandbox/chromium/sandbox/win/src/signed_policy.cc b/security/sandbox/chromium/sandbox/win/src/signed_policy.cc +--- a/security/sandbox/chromium/sandbox/win/src/signed_policy.cc ++++ b/security/sandbox/chromium/sandbox/win/src/signed_policy.cc +@@ -7,39 +7,63 @@ + #include <stdint.h> + + #include <string> + + #include "sandbox/win/src/ipc_tags.h" + #include "sandbox/win/src/policy_engine_opcodes.h" + #include "sandbox/win/src/policy_params.h" + #include "sandbox/win/src/sandbox_policy.h" ++#include "sandbox/win/src/sandbox_utils.h" + #include "sandbox/win/src/win_utils.h" + ++namespace { ++ ++bool IsValidNtPath(const base::FilePath& name) { ++ UNICODE_STRING uni_name; ++ OBJECT_ATTRIBUTES obj_attr; ++ sandbox::InitObjectAttribs(name.value(), OBJ_CASE_INSENSITIVE, nullptr, ++ &obj_attr, &uni_name, nullptr); ++ ++ NtQueryAttributesFileFunction NtQueryAttributesFile = nullptr; ++ ResolveNTFunctionPtr("NtQueryAttributesFile", &NtQueryAttributesFile); ++ FILE_BASIC_INFORMATION file_info; ++ return NtQueryAttributesFile && ++ NT_SUCCESS(NtQueryAttributesFile(&obj_attr, &file_info)); ++} ++ ++} // namespace ++ + namespace sandbox { + + bool SignedPolicy::GenerateRules(const wchar_t* name, + TargetPolicy::Semantics semantics, + LowLevelPolicy* policy) { + // Only support one semantic. + if (TargetPolicy::SIGNED_ALLOW_LOAD != semantics) { + return false; + } + + base::FilePath file_path(name); ++ base::FilePath nt_filename; + std::wstring nt_path_name; +- if (!GetNtPathFromWin32Path(file_path.DirName().value().c_str(), +- &nt_path_name)) ++ if (GetNtPathFromWin32Path(file_path.DirName().value().c_str(), ++ &nt_path_name)) { ++ base::FilePath nt_path(nt_path_name); ++ nt_filename = nt_path.Append(file_path.BaseName()); ++ } else if (IsValidNtPath(file_path)) { ++ nt_filename = std::move(file_path); ++ } else { + return false; +- base::FilePath nt_path(nt_path_name); +- std::wstring nt_filename = nt_path.Append(file_path.BaseName()).value(); ++ } ++ + // Create a rule to ASK_BROKER if name matches. + PolicyRule signed_policy(ASK_BROKER); +- if (!signed_policy.AddStringMatch(IF, NameBased::NAME, nt_filename.c_str(), +- CASE_INSENSITIVE)) { ++ if (!signed_policy.AddStringMatch( ++ IF, NameBased::NAME, nt_filename.value().c_str(), CASE_INSENSITIVE)) { + return false; + } + if (!policy->AddRule(IpcTag::NTCREATESECTION, &signed_policy)) { + return false; + } + + return true; + } diff --git a/security/sandbox/chromium-shim/patches/after_update/allow_rules_for_network_drive_and_non_file_devices.patch b/security/sandbox/chromium-shim/patches/after_update/allow_rules_for_network_drive_and_non_file_devices.patch new file mode 100644 index 0000000000..8d497e1ff9 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/after_update/allow_rules_for_network_drive_and_non_file_devices.patch @@ -0,0 +1,190 @@ +# 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: +https://hg.mozilla.org/mozilla-central/rev/c70d06fa5302 + +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) { diff --git a/security/sandbox/chromium-shim/patches/after_update/arm64_set_LoaderThreads.patch b/security/sandbox/chromium-shim/patches/after_update/arm64_set_LoaderThreads.patch new file mode 100644 index 0000000000..4d1817db17 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/after_update/arm64_set_LoaderThreads.patch @@ -0,0 +1,99 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1549645620 0 +# Fri Feb 08 17:07:00 2019 +0000 +# Node ID fb5e7c1090a7ddfde22fd2fb5f8a957ccc61fa64 +# Parent 5ef34aa8c8918649528048dd60907862a4355e29 +Bug 1515088 Part 2: Set LoaderThreads to 1 in the RTL_USER_PROCESS_PARAMETERS structure on child process start-up. r=aklotz + +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 +@@ -456,20 +456,21 @@ bool GetNtPathFromWin32Path(const std::w + bool rv = GetPathFromHandle(file, nt_path); + ::CloseHandle(file); + return rv; + } + + bool WriteProtectedChildMemory(HANDLE child_process, + void* address, + const void* buffer, +- size_t length) { ++ size_t length, ++ DWORD writeProtection) { + // First, remove the protections. + DWORD old_protection; +- if (!::VirtualProtectEx(child_process, address, length, PAGE_WRITECOPY, ++ if (!::VirtualProtectEx(child_process, address, length, writeProtection, + &old_protection)) + return false; + + SIZE_T written; + bool ok = + ::WriteProcessMemory(child_process, address, buffer, length, &written) && + (length == written); + +@@ -544,16 +545,40 @@ void* GetProcessBaseAddress(HANDLE proce + &bytes_read) || + (sizeof(magic) != bytes_read)) { + return nullptr; + } + + if (magic[0] != 'M' || magic[1] != 'Z') + return nullptr; + ++#if defined(_M_ARM64) ++ // Windows 10 on ARM64 has multi-threaded DLL loading that does not work with ++ // the sandbox. (On x86 this gets disabled by hook detection code that was not ++ // ported to ARM64). This overwrites the LoaderThreads value in the process ++ // parameters part of the PEB, if it is set to the default of 0 (which ++ // actually means it defaults to 4 loading threads). This is an undocumented ++ // field so there is a, probably small, risk that it might change or move in ++ // the future. In order to slightly guard against that we only update if the ++ // value is currently 0. ++ auto processParameters = reinterpret_cast<uint8_t*>(peb.ProcessParameters); ++ const uint32_t loaderThreadsOffset = 0x40c; ++ uint32_t maxLoaderThreads = 0; ++ BOOL memoryRead = ::ReadProcessMemory( ++ process, processParameters + loaderThreadsOffset, &maxLoaderThreads, ++ sizeof(maxLoaderThreads), &bytes_read); ++ if (memoryRead && (sizeof(maxLoaderThreads) == bytes_read) && ++ (maxLoaderThreads == 0)) { ++ maxLoaderThreads = 1; ++ WriteProtectedChildMemory(process, processParameters + loaderThreadsOffset, ++ &maxLoaderThreads, sizeof(maxLoaderThreads), ++ PAGE_READWRITE); ++ } ++#endif ++ + return base_address; + } + + DWORD GetTokenInformation(HANDLE token, + TOKEN_INFORMATION_CLASS info_class, + std::unique_ptr<BYTE[]>* buffer) { + // Get the required buffer size. + DWORD size = 0; +diff --git a/security/sandbox/chromium/sandbox/win/src/win_utils.h b/security/sandbox/chromium/sandbox/win/src/win_utils.h +--- a/security/sandbox/chromium/sandbox/win/src/win_utils.h ++++ b/security/sandbox/chromium/sandbox/win/src/win_utils.h +@@ -111,17 +111,18 @@ HKEY GetReservedKeyFromName(const std::w + bool ResolveRegistryName(std::wstring name, std::wstring* resolved_name); + + // Writes |length| bytes from the provided |buffer| into the address space of + // |child_process|, at the specified |address|, preserving the original write + // protection attributes. Returns true on success. + bool WriteProtectedChildMemory(HANDLE child_process, + void* address, + const void* buffer, +- size_t length); ++ size_t length, ++ DWORD writeProtection = PAGE_WRITECOPY); + + // Allocates |buffer_bytes| in child (PAGE_READWRITE) and copies data + // from |local_buffer| in this process into |child|. |remote_buffer| + // contains the address in the chile. If a zero byte copy is + // requested |true| is returned and no allocation or copying is + // attempted. Returns false if allocation or copying fails. If + // copying fails, the allocation will be reversed. + bool CopyToChildMemory(HANDLE child, diff --git a/security/sandbox/chromium-shim/patches/after_update/change_to_DCHECK_in_CloseHandleWrapper.patch b/security/sandbox/chromium-shim/patches/after_update/change_to_DCHECK_in_CloseHandleWrapper.patch new file mode 100644 index 0000000000..3d6bfaa54f --- /dev/null +++ b/security/sandbox/chromium-shim/patches/after_update/change_to_DCHECK_in_CloseHandleWrapper.patch @@ -0,0 +1,38 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1563194469 -3600 +# Mon Jul 15 13:41:09 2019 +0100 +# Node ID 6d4e1a08b36e4191bd5ba7a338965f42f09162a6 +# Parent 7d9b5d8c9b9b36b135237292785537fc13f40226 +Bug 1564899: Make CloseHandleWrapper CHECK a DCHECK on non-Nightly builds. r=handyman! + +This is because we are hitting it frequently during PolicyBase::OnJobEmpty and +currently we can't work out how this can happen. + +diff --git a/security/sandbox/chromium/base/win/scoped_handle_verifier.cc b/security/sandbox/chromium/base/win/scoped_handle_verifier.cc +--- a/security/sandbox/chromium/base/win/scoped_handle_verifier.cc ++++ b/security/sandbox/chromium/base/win/scoped_handle_verifier.cc +@@ -65,17 +65,23 @@ ScopedHandleVerifier* ScopedHandleVerifi + if (!g_active_verifier) + ScopedHandleVerifier::InstallVerifier(); + + return g_active_verifier; + } + + bool CloseHandleWrapper(HANDLE handle) { + if (!::CloseHandle(handle)) ++ // Making this DCHECK on non-Nighly as we are hitting this frequently, ++ // looks like we are closing handles twice somehow. See bug 1564899. ++#if defined(NIGHTLY_BUILD) + CHECK(false); // CloseHandle failed. ++#else ++ DCHECK(false); // CloseHandle failed. ++#endif + return true; + } + + // Assigns the g_active_verifier global within the GetLock() lock. + // If |existing_verifier| is non-null then |enabled| is ignored. + void ThreadSafeAssignOrCreateScopedHandleVerifier( + ScopedHandleVerifier* existing_verifier, + bool enabled) { diff --git a/security/sandbox/chromium-shim/patches/after_update/linux_32bit_arg_fixup.patch b/security/sandbox/chromium-shim/patches/after_update/linux_32bit_arg_fixup.patch new file mode 100644 index 0000000000..5cc66ad09b --- /dev/null +++ b/security/sandbox/chromium-shim/patches/after_update/linux_32bit_arg_fixup.patch @@ -0,0 +1,84 @@ +commit e0a00891b67ec162a17aa241a83b171b313de9fe +Author: Jed Davis <jld@mozilla.com> +Date: Mon Apr 18 18:00:10 2022 -0600 + + Make the sandbox fix up non-extended 32-bit types. + +diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.cc b/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.cc +index 347304889eae4..b909fc37f6174 100644 +--- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.cc ++++ b/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.cc +@@ -19,6 +19,7 @@ + #include "sandbox/linux/bpf_dsl/policy.h" + #include "sandbox/linux/bpf_dsl/seccomp_macros.h" + #include "sandbox/linux/bpf_dsl/syscall_set.h" ++#include "sandbox/linux/seccomp-bpf/syscall.h" + #include "sandbox/linux/system_headers/linux_filter.h" + #include "sandbox/linux/system_headers/linux_seccomp.h" + #include "sandbox/linux/system_headers/linux_syscalls.h" +@@ -318,8 +319,7 @@ CodeGen::Node PolicyCompiler::MaskedEqualHalf(int argno, + // Special logic for sanity checking the upper 32-bits of 32-bit system + // call arguments. + +- // TODO(mdempsky): Compile Unexpected64bitArgument() just per program. +- CodeGen::Node invalid_64bit = Unexpected64bitArgument(); ++ CodeGen::Node invalid_64bit = Unexpected64bitArgument(argno); + + const uint32_t upper = SECCOMP_ARG_MSB_IDX(argno); + const uint32_t lower = SECCOMP_ARG_LSB_IDX(argno); +@@ -335,8 +335,13 @@ CodeGen::Node PolicyCompiler::MaskedEqualHalf(int argno, + BPF_JMP + BPF_JEQ + BPF_K, 0, passed, invalid_64bit)); + } + +- // On 64-bit platforms, the upper 32-bits may be 0 or ~0; but we only allow +- // ~0 if the sign bit of the lower 32-bits is set too: ++ // On 64-bit platforms, the ABI (at least on x86_64) allows any value ++ // for the upper half, but to avoid potential vulnerabilties if an ++ // argument is incorrectly tested as a 32-bit type, we require it to be ++ // either zero-extended or sign-extended. That is, the upper 32-bits ++ // may be 0 or ~0; but we only allow ~0 if the sign bit of the lower ++ // 32-bits is set too: ++ // + // LDW [upper] + // JEQ 0, passed, (next) + // JEQ ~0, (next), invalid +@@ -424,8 +429,18 @@ CodeGen::Node PolicyCompiler::MaskedEqualHalf(int argno, + BPF_JMP + BPF_JEQ + BPF_K, value, passed, failed))); + } + +-CodeGen::Node PolicyCompiler::Unexpected64bitArgument() { +- return CompileResult(panic_func_("Unexpected 64bit argument detected")); ++CodeGen::Node PolicyCompiler::Unexpected64bitArgument(int argno) { ++ // This situation is unlikely, but possible. Return to userspace, ++ // zero-extend the problematic argument, and re-issue the syscall. ++ return CompileResult(bpf_dsl::Trap( ++ [](const arch_seccomp_data& args_ref, void* aux) -> intptr_t { ++ arch_seccomp_data args = args_ref; ++ int argno = (int)(intptr_t)aux; ++ args.args[argno] &= 0xFFFFFFFF; ++ return Syscall::Call(args.nr, args.args[0], args.args[1], args.args[2], ++ args.args[3], args.args[4], args.args[5]); ++ }, ++ (void*)(intptr_t)argno)); + } + + CodeGen::Node PolicyCompiler::Return(uint32_t ret) { +diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.h b/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.h +index 48b1d780d956f..2acf878474a7d 100644 +--- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.h ++++ b/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.h +@@ -132,9 +132,11 @@ class SANDBOX_EXPORT PolicyCompiler { + CodeGen::Node passed, + CodeGen::Node failed); + +- // Returns the fatal CodeGen::Node that is used to indicate that somebody +- // attempted to pass a 64bit value in a 32bit system call argument. +- CodeGen::Node Unexpected64bitArgument(); ++ // Returns the CodeGen::Node that is used to handle the case where a ++ // system call argument was expected to be a 32-bit type, but the ++ // value in the 64-bit register doesn't correspond to a ++ // zero-extended or sign-extended 32-bit value. ++ CodeGen::Node Unexpected64bitArgument(int argno); + + const Policy* policy_; + TrapRegistry* registry_; diff --git a/security/sandbox/chromium-shim/patches/after_update/move_shared_memory_duplication_after_initialization.patch b/security/sandbox/chromium-shim/patches/after_update/move_shared_memory_duplication_after_initialization.patch new file mode 100644 index 0000000000..f8250b788d --- /dev/null +++ b/security/sandbox/chromium-shim/patches/after_update/move_shared_memory_duplication_after_initialization.patch @@ -0,0 +1,94 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1577387989 0 +# Thu Dec 26 19:19:49 2019 +0000 +# Node ID 32adf437117bdca54be4959813acbb604f65137f +# Parent 214214029beb6cca606e11ba519d11cc7dbb37af +Bug 1605867: Don't duplicate IPC shared memory when we might fail to launch the process correctly. r=handyman + +Differential Revision: https://phabricator.services.mozilla.com/D58271 + +diff --git a/security/sandbox/chromium/sandbox/win/src/target_process.cc b/security/sandbox/chromium/sandbox/win/src/target_process.cc +--- a/security/sandbox/chromium/sandbox/win/src/target_process.cc ++++ b/security/sandbox/chromium/sandbox/win/src/target_process.cc +@@ -286,45 +286,28 @@ ResultCode TargetProcess::Init(Dispatche + shared_section_.Set(::CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, + PAGE_READWRITE | SEC_COMMIT, 0, + shared_mem_size, nullptr)); + if (!shared_section_.IsValid()) { + *win_error = ::GetLastError(); + return SBOX_ERROR_CREATE_FILE_MAPPING; + } + +- DWORD access = FILE_MAP_READ | FILE_MAP_WRITE | SECTION_QUERY; +- HANDLE target_shared_section; +- if (!::DuplicateHandle(::GetCurrentProcess(), shared_section_.Get(), +- sandbox_process_info_.process_handle(), +- &target_shared_section, access, false, 0)) { +- *win_error = ::GetLastError(); +- return SBOX_ERROR_DUPLICATE_SHARED_SECTION; +- } +- + void* shared_memory = ::MapViewOfFile( + shared_section_.Get(), FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0); + if (!shared_memory) { + *win_error = ::GetLastError(); + return SBOX_ERROR_MAP_VIEW_OF_SHARED_SECTION; + } + + CopyPolicyToTarget(policy, shared_policy_size, + reinterpret_cast<char*>(shared_memory) + shared_IPC_size); + + ResultCode ret; + // Set the global variables in the target. These are not used on the broker. +- g_shared_section = target_shared_section; +- ret = TransferVariable("g_shared_section", &g_shared_section, +- sizeof(g_shared_section)); +- g_shared_section = nullptr; +- if (SBOX_ALL_OK != ret) { +- *win_error = ::GetLastError(); +- return ret; +- } + g_shared_IPC_size = shared_IPC_size; + ret = TransferVariable("g_shared_IPC_size", &g_shared_IPC_size, + sizeof(g_shared_IPC_size)); + g_shared_IPC_size = 0; + if (SBOX_ALL_OK != ret) { + *win_error = ::GetLastError(); + return ret; + } +@@ -339,16 +322,34 @@ ResultCode TargetProcess::Init(Dispatche + + ipc_server_.reset(new SharedMemIPCServer( + sandbox_process_info_.process_handle(), + sandbox_process_info_.process_id(), thread_pool_, ipc_dispatcher)); + + if (!ipc_server_->Init(shared_memory, shared_IPC_size, kIPCChannelSize)) + return SBOX_ERROR_NO_SPACE; + ++ DWORD access = FILE_MAP_READ | FILE_MAP_WRITE | SECTION_QUERY; ++ HANDLE target_shared_section; ++ if (!::DuplicateHandle(::GetCurrentProcess(), shared_section_.Get(), ++ sandbox_process_info_.process_handle(), ++ &target_shared_section, access, false, 0)) { ++ *win_error = ::GetLastError(); ++ return SBOX_ERROR_DUPLICATE_SHARED_SECTION; ++ } ++ ++ g_shared_section = target_shared_section; ++ ret = TransferVariable("g_shared_section", &g_shared_section, ++ sizeof(g_shared_section)); ++ g_shared_section = nullptr; ++ if (SBOX_ALL_OK != ret) { ++ *win_error = ::GetLastError(); ++ return ret; ++ } ++ + // After this point we cannot use this handle anymore. + ::CloseHandle(sandbox_process_info_.TakeThreadHandle()); + + return SBOX_ALL_OK; + } + + void TargetProcess::Terminate() { + if (!sandbox_process_info_.IsValid()) diff --git a/security/sandbox/chromium-shim/patches/after_update/patch_order.txt b/security/sandbox/chromium-shim/patches/after_update/patch_order.txt new file mode 100644 index 0000000000..4266bee9c0 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/after_update/patch_order.txt @@ -0,0 +1,8 @@ +add_interception_logging.patch +allow_rules_for_network_drive_and_non_file_devices.patch +add_WOW64_flags_to_allowed_registry_read_flags.patch +arm64_set_LoaderThreads.patch +change_to_DCHECK_in_CloseHandleWrapper.patch +move_shared_memory_duplication_after_initialization.patch +allow_ntpath_in_SignedPolicy_GenerateRules.patch +linux_32bit_arg_fixup.patch |