summaryrefslogtreecommitdiff
path: root/chromium/sandbox
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2022-05-12 15:59:20 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2022-05-25 06:57:22 +0000
commitf7eaed5286974984ba5f9e3189d8f49d03e99f81 (patch)
treecaed19b2af2024f35449fb0b781d0a25e09d4f8f /chromium/sandbox
parent9729c4479fe23554eae6e6dd1f30ff488f470c84 (diff)
downloadqtwebengine-chromium-f7eaed5286974984ba5f9e3189d8f49d03e99f81.tar.gz
BASELINE: Update Chromium to 100.0.4896.167
Change-Id: I98cbeb5d7543d966ffe04d8cefded0c493a11333 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/sandbox')
-rw-r--r--chromium/sandbox/linux/BUILD.gn6
-rw-r--r--chromium/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc16
-rw-r--r--chromium/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc3
-rw-r--r--chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc2
-rw-r--r--chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc9
-rw-r--r--chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc16
-rw-r--r--chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc6
-rw-r--r--chromium/sandbox/linux/seccomp-bpf/die.cc6
-rw-r--r--chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.cc4
-rw-r--r--chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.h3
-rw-r--r--chromium/sandbox/linux/services/credentials.cc5
-rw-r--r--chromium/sandbox/linux/services/credentials.h24
-rw-r--r--chromium/sandbox/linux/services/libc_interceptor.cc9
-rw-r--r--chromium/sandbox/linux/services/namespace_utils.h7
-rw-r--r--chromium/sandbox/linux/services/proc_util.h4
-rw-r--r--chromium/sandbox/linux/services/resource_limits.h12
-rw-r--r--chromium/sandbox/linux/services/resource_limits_unittest.cc (renamed from chromium/sandbox/linux/services/resource_limits_unittests.cc)5
-rw-r--r--chromium/sandbox/linux/services/thread_helpers_unittest.cc (renamed from chromium/sandbox/linux/services/thread_helpers_unittests.cc)0
-rw-r--r--chromium/sandbox/linux/services/yama_unittest.cc (renamed from chromium/sandbox/linux/services/yama_unittests.cc)12
-rw-r--r--chromium/sandbox/linux/suid/client/setuid_sandbox_host_unittest.cc4
-rw-r--r--chromium/sandbox/linux/syscall_broker/broker_client.cc2
-rw-r--r--chromium/sandbox/linux/syscall_broker/broker_process.cc16
-rw-r--r--chromium/sandbox/linux/syscall_broker/broker_process_unittest.cc23
-rw-r--r--chromium/sandbox/linux/syscall_broker/remote_syscall_arg_handler_unittest.cc5
-rw-r--r--chromium/sandbox/linux/system_headers/linux_prctl.h4
-rw-r--r--chromium/sandbox/mac/seatbelt_exec.h12
-rw-r--r--chromium/sandbox/policy/BUILD.gn1
-rw-r--r--chromium/sandbox/policy/features.cc24
-rw-r--r--chromium/sandbox/policy/features.h12
-rw-r--r--chromium/sandbox/policy/fuchsia/sandbox_policy_fuchsia.cc45
-rw-r--r--chromium/sandbox/policy/linux/bpf_gpu_policy_linux.cc2
-rw-r--r--chromium/sandbox/policy/linux/sandbox_debug_handling_linux.cc7
-rw-r--r--chromium/sandbox/policy/linux/sandbox_seccomp_bpf_linux.cc3
-rw-r--r--chromium/sandbox/policy/mac/common.sb34
-rw-r--r--chromium/sandbox/policy/mac/sandbox_mac.mm1
-rw-r--r--chromium/sandbox/policy/mojom/sandbox.mojom5
-rw-r--r--chromium/sandbox/policy/sandbox.cc34
-rw-r--r--chromium/sandbox/policy/sandbox.h10
-rw-r--r--chromium/sandbox/policy/sandbox_delegate.h4
-rw-r--r--chromium/sandbox/policy/sandbox_type.cc65
-rw-r--r--chromium/sandbox/policy/sandbox_type_unittest.cc9
-rw-r--r--chromium/sandbox/policy/switches.cc18
-rw-r--r--chromium/sandbox/policy/switches.h16
-rw-r--r--chromium/sandbox/policy/win/sandbox_policy_feature_test.cc52
-rw-r--r--chromium/sandbox/policy/win/sandbox_policy_feature_test.h18
-rw-r--r--chromium/sandbox/policy/win/sandbox_win.cc7
-rw-r--r--chromium/sandbox/win/BUILD.gn36
-rw-r--r--chromium/sandbox/win/src/app_container.h11
-rw-r--r--chromium/sandbox/win/src/app_container_base.h14
-rw-r--r--chromium/sandbox/win/src/app_container_test.cc11
-rw-r--r--chromium/sandbox/win/src/broker_services.cc5
-rw-r--r--chromium/sandbox/win/src/broker_services.h1
-rw-r--r--chromium/sandbox/win/src/file_policy_test.cc326
-rw-r--r--chromium/sandbox/win/src/filesystem_dispatcher.cc82
-rw-r--r--chromium/sandbox/win/src/filesystem_dispatcher.h6
-rw-r--r--chromium/sandbox/win/src/filesystem_interception.cc141
-rw-r--r--chromium/sandbox/win/src/filesystem_policy.cc103
-rw-r--r--chromium/sandbox/win/src/filesystem_policy.h5
-rw-r--r--chromium/sandbox/win/src/handle_closer.cc29
-rw-r--r--chromium/sandbox/win/src/handle_closer.h3
-rw-r--r--chromium/sandbox/win/src/handle_closer_agent.cc98
-rw-r--r--chromium/sandbox/win/src/handle_closer_test.cc62
-rw-r--r--chromium/sandbox/win/src/integrity_level_test.cc44
-rw-r--r--chromium/sandbox/win/src/interception_agent.cc55
-rw-r--r--chromium/sandbox/win/src/interception_unittest.cc29
-rw-r--r--chromium/sandbox/win/src/interceptors_64.cc1
-rw-r--r--chromium/sandbox/win/src/ipc_ping_test.cc13
-rw-r--r--chromium/sandbox/win/src/job.cc8
-rw-r--r--chromium/sandbox/win/src/named_pipe_policy_test.cc76
-rw-r--r--chromium/sandbox/win/src/nt_internals.h10
-rw-r--r--chromium/sandbox/win/src/policy_broker.cc61
-rw-r--r--chromium/sandbox/win/src/policy_broker.h3
-rw-r--r--chromium/sandbox/win/src/policy_engine_opcodes.cc13
-rw-r--r--chromium/sandbox/win/src/policy_engine_unittest.cc4
-rw-r--r--chromium/sandbox/win/src/policy_low_level.cc2
-rw-r--r--chromium/sandbox/win/src/policy_low_level_unittest.cc14
-rw-r--r--chromium/sandbox/win/src/policy_opcodes_unittest.cc30
-rw-r--r--chromium/sandbox/win/src/policy_params.h17
-rw-r--r--chromium/sandbox/win/src/policy_target.cc6
-rw-r--r--chromium/sandbox/win/src/policy_target_test.cc27
-rw-r--r--chromium/sandbox/win/src/process_mitigations_dyncode_unittest.cc47
-rw-r--r--chromium/sandbox/win/src/process_mitigations_imageload_unittest.cc462
-rw-r--r--chromium/sandbox/win/src/process_mitigations_unittest.cc112
-rw-r--r--chromium/sandbox/win/src/process_thread_interception.cc2
-rw-r--r--chromium/sandbox/win/src/process_thread_policy.cc30
-rw-r--r--chromium/sandbox/win/src/restricted_token_utils.cc12
-rw-r--r--chromium/sandbox/win/src/sandbox_nt_types.h16
-rw-r--r--chromium/sandbox/win/src/sandbox_nt_util.cc247
-rw-r--r--chromium/sandbox/win/src/sandbox_nt_util.h22
-rw-r--r--chromium/sandbox/win/src/sandbox_nt_util_unittest.cc55
-rw-r--r--chromium/sandbox/win/src/sandbox_policy.h2
-rw-r--r--chromium/sandbox/win/src/sandbox_policy_base.cc35
-rw-r--r--chromium/sandbox/win/src/sandbox_policy_base.h17
-rw-r--r--chromium/sandbox/win/src/sandbox_policy_diagnostic.cc30
-rw-r--r--chromium/sandbox/win/src/sandbox_policy_diagnostic.h2
-rw-r--r--chromium/sandbox/win/src/sandbox_types.h11
-rw-r--r--chromium/sandbox/win/src/sharedmem_ipc_client.cc25
-rw-r--r--chromium/sandbox/win/src/sidestep/ia32_modrm_map.cpp92
-rw-r--r--chromium/sandbox/win/src/sidestep/ia32_opcode_map.cpp1159
-rw-r--r--chromium/sandbox/win/src/sidestep/mini_disassembler.cpp396
-rw-r--r--chromium/sandbox/win/src/sidestep/mini_disassembler.h153
-rw-r--r--chromium/sandbox/win/src/sidestep/mini_disassembler_types.h197
-rw-r--r--chromium/sandbox/win/src/sidestep/preamble_patcher.h112
-rw-r--r--chromium/sandbox/win/src/sidestep/preamble_patcher_with_stub.cpp181
-rw-r--r--chromium/sandbox/win/src/sidestep_resolver.cc205
-rw-r--r--chromium/sandbox/win/src/sidestep_resolver.h77
-rw-r--r--chromium/sandbox/win/src/signed_policy.cc14
-rw-r--r--chromium/sandbox/win/src/startup_information_helper.cc2
-rw-r--r--chromium/sandbox/win/src/startup_information_helper.h4
-rw-r--r--chromium/sandbox/win/src/target_interceptions.cc16
-rw-r--r--chromium/sandbox/win/src/target_process.cc17
-rw-r--r--chromium/sandbox/win/src/target_process.h4
-rw-r--r--chromium/sandbox/win/src/unload_dll_test.cc75
-rw-r--r--chromium/sandbox/win/src/win_utils.cc142
-rw-r--r--chromium/sandbox/win/src/win_utils.h23
-rw-r--r--chromium/sandbox/win/src/win_utils_unittest.cc110
116 files changed, 1502 insertions, 4532 deletions
diff --git a/chromium/sandbox/linux/BUILD.gn b/chromium/sandbox/linux/BUILD.gn
index abbcc509692..ec24cd81e27 100644
--- a/chromium/sandbox/linux/BUILD.gn
+++ b/chromium/sandbox/linux/BUILD.gn
@@ -78,11 +78,11 @@ source_set("sandbox_linux_unittests_sources") {
sources = [
"services/proc_util_unittest.cc",
- "services/resource_limits_unittests.cc",
+ "services/resource_limits_unittest.cc",
"services/scoped_process_unittest.cc",
"services/syscall_wrappers_unittest.cc",
- "services/thread_helpers_unittests.cc",
- "services/yama_unittests.cc",
+ "services/thread_helpers_unittest.cc",
+ "services/yama_unittest.cc",
"syscall_broker/broker_file_permission_unittest.cc",
"syscall_broker/broker_process_unittest.cc",
"syscall_broker/broker_simple_message_unittest.cc",
diff --git a/chromium/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc b/chromium/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc
index 61298af943d..d1e018ff66f 100644
--- a/chromium/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc
+++ b/chromium/sandbox/linux/integration_tests/bpf_dsl_seccomp_unittest.cc
@@ -18,8 +18,6 @@
#include <sys/utsname.h>
#include <unistd.h>
-#include "base/memory/raw_ptr.h"
-
#if defined(ANDROID)
// Work-around for buggy headers in Android's NDK
#define __user
@@ -28,6 +26,7 @@
#include "base/bind.h"
#include "base/check.h"
+#include "base/memory/raw_ptr.h"
#include "base/posix/eintr_wrapper.h"
#include "base/synchronization/waitable_event.h"
#include "base/system/sys_info.h"
@@ -183,7 +182,12 @@ bool IsSyscallForTestHarness(int sysno) {
// ASan and MSan don't need any of these for normal operation, but they
// require at least mmap & munmap to print a report if an error is detected.
// ASan requires sigaltstack.
- if (sysno == kMMapNr || sysno == __NR_munmap || sysno == __NR_pipe ||
+ if (sysno == kMMapNr || sysno == __NR_munmap ||
+#if !defined(__aarch64__)
+ sysno == __NR_pipe ||
+#else
+ sysno == __NR_pipe2 ||
+#endif
sysno == __NR_sigaltstack) {
return true;
}
@@ -801,7 +805,7 @@ ResultExpr SimpleCondTestPolicy::EvaluateSyscall(int sysno) const {
#if defined(__NR_open)
case __NR_open:
flags_argument_position = 1;
- FALLTHROUGH;
+ [[fallthrough]];
#endif
case __NR_openat: { // open can be a wrapper for openat(2).
if (sysno == __NR_openat)
@@ -2087,7 +2091,7 @@ SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(SeccompRetTrace)) {
}
// Android does not expose pread64 nor pwrite64.
-#if !defined(OS_ANDROID)
+#if !BUILDFLAG(IS_ANDROID)
bool FullPwrite64(int fd, const char* buffer, size_t count, off64_t offset) {
while (count > 0) {
@@ -2168,7 +2172,7 @@ BPF_TEST_C(SandboxBPF, Pread64, TrapPread64Policy) {
BPF_ASSERT(pread_64_was_forwarded);
}
-#endif // !defined(OS_ANDROID)
+#endif // !BUILDFLAG(IS_ANDROID)
void* TsyncApplyToTwoThreadsFunc(void* cond_ptr) {
base::WaitableEvent* event = static_cast<base::WaitableEvent*>(cond_ptr);
diff --git a/chromium/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc b/chromium/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc
index 0d6b6b377ad..376e855f138 100644
--- a/chromium/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc
+++ b/chromium/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc
@@ -310,7 +310,8 @@ class IPCSyscaller : public Syscaller {
// Only use syscall(...) on x64 to avoid having to reimplement a libc-like
// layer that uses different syscalls on different architectures.
-#if (defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)) && \
+#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
+ BUILDFLAG(IS_ANDROID)) && \
defined(__x86_64__)
#define DIRECT_SYSCALLER_ENABLED
#endif
diff --git a/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
index f9eea2783e1..74ce4c75d4d 100644
--- a/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
+++ b/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
@@ -150,7 +150,7 @@ ResultExpr EvaluateSyscallImpl(int fs_denied_errno,
return Allow();
}
-#if defined(__NR_rseq) && !defined(OS_ANDROID)
+#if defined(__NR_rseq) && !BUILDFLAG(IS_ANDROID)
// See https://crbug.com/1104160. Rseq can only be disabled right before an
// execve, because glibc registers it with the kernel and so far it's unclear
// whether shared libraries (which, during initialization, may observe that
diff --git a/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc b/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
index 2f53b8f4586..ea405e47d75 100644
--- a/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
+++ b/chromium/sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
@@ -24,9 +24,10 @@
#include <time.h>
#include <unistd.h>
+#include <tuple>
+
#include "base/clang_profiling_buildflags.h"
#include "base/files/scoped_file.h"
-#include "base/ignore_result.h"
#include "base/posix/eintr_wrapper.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
@@ -185,7 +186,7 @@ BPF_TEST_C(BaselinePolicy, CreateThread, BaselinePolicy) {
}
// Rseq should be enabled if it exists (i.e. shouldn't receive EPERM).
-#if !defined(OS_ANDROID)
+#if !BUILDFLAG(IS_ANDROID)
BPF_TEST_C(BaselinePolicy, RseqEnabled, BaselinePolicy) {
errno = 0;
int res = syscall(__NR_rseq, 0, 0, 0, 0);
@@ -195,7 +196,7 @@ BPF_TEST_C(BaselinePolicy, RseqEnabled, BaselinePolicy) {
// EINVAL, or ENOSYS if the kernel is too old to recognize the system call.
BPF_ASSERT(EINVAL == errno || ENOSYS == errno);
}
-#endif // !defined(OS_ANDROID)
+#endif // !BUILDFLAG(IS_ANDROID)
BPF_DEATH_TEST_C(BaselinePolicy,
DisallowedCloneFlagCrashes,
@@ -252,7 +253,7 @@ BPF_DEATH_TEST_C(BaselinePolicy,
DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
BaselinePolicy) {
int sv[2];
- ignore_result(socketpair(AF_INET, SOCK_STREAM, 0, sv));
+ std::ignore = socketpair(AF_INET, SOCK_STREAM, 0, sv);
_exit(1);
}
#endif // defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
diff --git a/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
index 36221d24bd0..33112b7c1eb 100644
--- a/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
+++ b/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
@@ -35,8 +35,8 @@
#include "sandbox/linux/system_headers/linux_syscalls.h"
#include "sandbox/linux/system_headers/linux_time.h"
-#if (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \
- !defined(__arm__) && !defined(__aarch64__) && \
+#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \
+ !defined(__arm__) && !defined(__aarch64__) && \
!defined(PTRACE_GET_THREAD_AREA)
// Also include asm/ptrace-abi.h since ptrace.h in older libc (for instance
// the one in Ubuntu 16.04 LTS) is missing PTRACE_GET_THREAD_AREA.
@@ -45,13 +45,13 @@
#include <asm/ptrace-abi.h>
#endif
-#if defined(OS_ANDROID)
+#if BUILDFLAG(IS_ANDROID)
#if !defined(F_DUPFD_CLOEXEC)
#define F_DUPFD_CLOEXEC (F_LINUX_SPECIFIC_BASE + 6)
#endif
-#endif // defined(OS_ANDROID)
+#endif // BUILDFLAG(IS_ANDROID)
#if defined(__arm__) && !defined(MAP_STACK)
#define MAP_STACK 0x20000 // Daisy build environment has old headers.
@@ -87,7 +87,7 @@ inline bool IsArchitectureI386() {
}
inline bool IsAndroid() {
-#if defined(OS_ANDROID)
+#if BUILDFLAG(IS_ANDROID)
return true;
#else
return false;
@@ -172,7 +172,7 @@ ResultExpr RestrictPrctl() {
const Arg<int> option(0);
return Switch(option)
.CASES((PR_GET_NAME, PR_SET_NAME, PR_GET_DUMPABLE, PR_SET_DUMPABLE
-#if defined(OS_ANDROID)
+#if BUILDFLAG(IS_ANDROID)
, PR_SET_VMA, PR_SET_PTRACER, PR_SET_TIMERSLACK
, PR_GET_NO_NEW_PRIVS, PR_PAC_RESET_KEYS
@@ -202,7 +202,7 @@ ResultExpr RestrictPrctl() {
, PR_SET_TIMERSLACK_PID_1
, PR_SET_TIMERSLACK_PID_2
, PR_SET_TIMERSLACK_PID_3
-#endif // defined(OS_ANDROID)
+#endif // BUILDFLAG(IS_ANDROID)
),
Allow())
.Default(CrashSIGSYSPrctl());
@@ -397,7 +397,7 @@ ResultExpr RestrictClockID() {
CLOCK_THREAD_CPUTIME_ID),
Allow())
.Default(CrashSIGSYS()))
-#if defined(OS_ANDROID)
+#if BUILDFLAG(IS_ANDROID)
// Allow per-pid and per-tid clocks.
.ElseIf((clockid & CPUCLOCK_CLOCK_MASK) != CLOCKFD, Allow())
#endif
diff --git a/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc b/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc
index 4adc80bb761..67da5d15c08 100644
--- a/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc
+++ b/chromium/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc
@@ -95,7 +95,7 @@ BPF_TEST_C(ParameterRestrictions,
CheckClock(CLOCK_REALTIME);
CheckClock(CLOCK_REALTIME_COARSE);
CheckClock(CLOCK_THREAD_CPUTIME_ID);
-#if defined(OS_ANDROID)
+#if BUILDFLAG(IS_ANDROID)
clockid_t clock_id;
pthread_getcpuclockid(pthread_self(), &clock_id);
CheckClock(clock_id);
@@ -140,7 +140,7 @@ BPF_DEATH_TEST_C(ParameterRestrictions,
syscall(SYS_clock_nanosleep, (~0) | CLOCKFD, 0, &ts, &out_ts);
}
-#if !defined(OS_ANDROID)
+#if !BUILDFLAG(IS_ANDROID)
BPF_DEATH_TEST_C(ParameterRestrictions,
clock_gettime_crash_cpu_clock,
DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
@@ -154,7 +154,7 @@ BPF_DEATH_TEST_C(ParameterRestrictions,
struct timespec ts;
clock_gettime(kInitCPUClockID, &ts);
}
-#endif // !defined(OS_ANDROID)
+#endif // !BUILDFLAG(IS_ANDROID)
class RestrictSchedPolicy : public bpf_dsl::Policy {
public:
diff --git a/chromium/sandbox/linux/seccomp-bpf/die.cc b/chromium/sandbox/linux/seccomp-bpf/die.cc
index 40c7f8999f5..4e6b1b7146d 100644
--- a/chromium/sandbox/linux/seccomp-bpf/die.cc
+++ b/chromium/sandbox/linux/seccomp-bpf/die.cc
@@ -12,8 +12,8 @@
#include <unistd.h>
#include <string>
+#include <tuple>
-#include "base/ignore_result.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "sandbox/linux/seccomp-bpf/syscall.h"
@@ -83,8 +83,8 @@ void Die::LogToStderr(const char* msg, const char* file, int line) {
// No need to loop. Short write()s are unlikely and if they happen we
// probably prefer them over a loop that blocks.
- ignore_result(
- HANDLE_EINTR(Syscall::Call(__NR_write, 2, s.c_str(), s.length())));
+ std::ignore =
+ HANDLE_EINTR(Syscall::Call(__NR_write, 2, s.c_str(), s.length()));
}
}
diff --git a/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
index 7069cd752d4..30911a50cdd 100644
--- a/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
+++ b/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
@@ -58,7 +58,7 @@ bool KernelSupportsSeccompBPF() {
// flags that are unlikely to ever be used by the kernel. A normal kernel would
// return -EINVAL, but a buggy LG kernel would return 1.
bool KernelHasLGBug() {
-#if defined(OS_ANDROID)
+#if BUILDFLAG(IS_ANDROID)
// sys_set_media will see this as NULL, which should be a safe (non-crashing)
// way to invoke it. A genuine seccomp syscall will see it as
// SECCOMP_SET_MODE_STRICT.
@@ -73,7 +73,7 @@ bool KernelHasLGBug() {
if (rv != -1) {
return true;
}
-#endif // defined(OS_ANDROID)
+#endif // BUILDFLAG(IS_ANDROID)
return false;
}
diff --git a/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.h b/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.h
index b926eaeae13..5b5e0588853 100644
--- a/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.h
+++ b/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf.h
@@ -68,8 +68,7 @@ class SANDBOX_EXPORT SandboxBPF {
//
// |enable_ibpb| controls if the sandbox will forcibly enable indirect branch
// prediction barrier through prctl(2) to mitigate Spectre variant 2.
- bool StartSandbox(SeccompLevel level,
- bool enable_ibpb = true) WARN_UNUSED_RESULT;
+ [[nodiscard]] bool StartSandbox(SeccompLevel level, bool enable_ibpb = true);
// The sandbox needs to be able to access files in "/proc/self/". If
// this directory is not accessible when "StartSandbox()" gets called, the
diff --git a/chromium/sandbox/linux/services/credentials.cc b/chromium/sandbox/linux/services/credentials.cc
index ca6b5954798..c933eafd163 100644
--- a/chromium/sandbox/linux/services/credentials.cc
+++ b/chromium/sandbox/linux/services/credentials.cc
@@ -100,7 +100,10 @@ bool ChrootToSafeEmptyDir() {
// TODO(crbug.com/1247458) Broken in MSan builds after LLVM f1bb30a4956f.
clone_flags |= CLONE_VM | CLONE_VFORK | CLONE_SETTLS;
- char tls_buf[PTHREAD_STACK_MIN] = {0};
+ // PTHREAD_STACK_MIN can be dynamic in glibc2.34+, so it is not possible to
+ // zeroify tls_buf assigning { 0 }
+ char tls_buf[PTHREAD_STACK_MIN];
+ memset(tls_buf, 0, PTHREAD_STACK_MIN);
tls = tls_buf;
#endif
diff --git a/chromium/sandbox/linux/services/credentials.h b/chromium/sandbox/linux/services/credentials.h
index 189d16132fa..17ff667cfd8 100644
--- a/chromium/sandbox/linux/services/credentials.h
+++ b/chromium/sandbox/linux/services/credentials.h
@@ -7,14 +7,13 @@
#include "build/build_config.h"
// Link errors are tedious to track, raise a compile-time error instead.
-#if defined(OS_ANDROID)
+#if BUILDFLAG(IS_ANDROID)
#error "Android is not supported."
-#endif // defined(OS_ANDROID).
+#endif // BUILDFLAG(IS_ANDROID).
#include <string>
#include <vector>
-#include "base/compiler_specific.h"
#include "sandbox/linux/system_headers/capability.h"
#include "sandbox/sandbox_export.h"
@@ -50,21 +49,22 @@ class SANDBOX_EXPORT Credentials {
// when calling this API.
// |proc_fd| must be a file descriptor to /proc/ and remains owned by
// the caller.
- static bool DropAllCapabilities(int proc_fd) WARN_UNUSED_RESULT;
+ [[nodiscard]] static bool DropAllCapabilities(int proc_fd);
// A similar API which assumes that it can open /proc/self/ by itself.
- static bool DropAllCapabilities() WARN_UNUSED_RESULT;
+ [[nodiscard]] static bool DropAllCapabilities();
// Sets the effective and permitted capability sets for the current thread to
// the list of capabiltiies in |caps|. All other capability flags are cleared.
- static bool SetCapabilities(int proc_fd, const std::vector<Capability>& caps)
- WARN_UNUSED_RESULT;
+ [[nodiscard]] static bool SetCapabilities(
+ int proc_fd,
+ const std::vector<Capability>& caps);
// Versions of the above functions which do not check that the process is
// single-threaded. After calling these functions, capabilities of other
// threads will not be changed. This is dangerous, do not use unless you know
// what you are doing.
- static bool DropAllCapabilitiesOnCurrentThread() WARN_UNUSED_RESULT;
- static bool SetCapabilitiesOnCurrentThread(
- const std::vector<Capability>& caps) WARN_UNUSED_RESULT;
+ [[nodiscard]] static bool DropAllCapabilitiesOnCurrentThread();
+ [[nodiscard]] static bool SetCapabilitiesOnCurrentThread(
+ const std::vector<Capability>& caps);
// Returns true if the current thread has either the effective, permitted, or
// inheritable flag set for the given capability.
@@ -88,7 +88,7 @@ class SANDBOX_EXPORT Credentials {
// If this call succeeds, the current process will be granted a full set of
// capabilities in the new namespace.
// This will fail if the process is not mono-threaded.
- static bool MoveToNewUserNS() WARN_UNUSED_RESULT;
+ [[nodiscard]] static bool MoveToNewUserNS();
// Removes the ability of the process to access the file system. File
// descriptors which are already open prior to calling this API remain
@@ -102,7 +102,7 @@ class SANDBOX_EXPORT Credentials {
// - the caller must close |proc_fd| eventually or access to the file
// system can be recovered.
// - DropAllCapabilities() must be called to prevent escapes.
- static bool DropFileSystemAccess(int proc_fd) WARN_UNUSED_RESULT;
+ [[nodiscard]] static bool DropFileSystemAccess(int proc_fd);
// This function returns true if the process can still access the filesystem.
static bool HasFileSystemAccess();
diff --git a/chromium/sandbox/linux/services/libc_interceptor.cc b/chromium/sandbox/linux/services/libc_interceptor.cc
index cc2a52917f3..0a6e5fc6ea4 100644
--- a/chromium/sandbox/linux/services/libc_interceptor.cc
+++ b/chromium/sandbox/linux/services/libc_interceptor.cc
@@ -23,14 +23,12 @@
#include "base/compiler_specific.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
-#include "base/metrics/histogram_functions.h"
#include "base/pickle.h"
#include "base/posix/eintr_wrapper.h"
#include "base/posix/global_descriptors.h"
#include "base/posix/unix_domain_socket.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"
-#include "base/timer/elapsed_timer.h"
namespace sandbox {
@@ -122,8 +120,6 @@ void ProxyLocaltimeCallToBrowser(time_t input,
struct tm* output,
char* timezone_out,
size_t timezone_out_len) {
- base::ElapsedTimer timer;
-
base::Pickle request;
request.WriteInt(METHOD_LOCALTIME);
request.WriteString(
@@ -142,11 +138,6 @@ void ProxyLocaltimeCallToBrowser(time_t input,
if (!ReadTimeStruct(&iter, output, timezone_out, timezone_out_len)) {
memset(output, 0, sizeof(struct tm));
}
-
- base::UmaHistogramCustomMicrosecondsTimes(
- "Linux.ProxyLocaltimeCallToBrowserUs", timer.Elapsed(),
- base::Microseconds(1), base::Seconds(1),
- /*buckets=*/50);
}
// The other side of this call is ProxyLocaltimeCallToBrowser().
diff --git a/chromium/sandbox/linux/services/namespace_utils.h b/chromium/sandbox/linux/services/namespace_utils.h
index c2c3776b81c..398c8e0a98c 100644
--- a/chromium/sandbox/linux/services/namespace_utils.h
+++ b/chromium/sandbox/linux/services/namespace_utils.h
@@ -9,7 +9,6 @@
#include <type_traits>
-#include "base/compiler_specific.h"
#include "sandbox/sandbox_export.h"
namespace sandbox {
@@ -28,8 +27,8 @@ class SANDBOX_EXPORT NamespaceUtils {
// Write a uid or gid mapping from |id| to |id| in |map_file|. This function
// is async-signal-safe.
- static bool WriteToIdMapFile(const char* map_file,
- generic_id_t id) WARN_UNUSED_RESULT;
+ [[nodiscard]] static bool WriteToIdMapFile(const char* map_file,
+ generic_id_t id);
// Returns true if unprivileged namespaces of type |type| is supported
// (meaning that both CLONE_NEWUSER and type are are supported). |type| must
@@ -47,7 +46,7 @@ class SANDBOX_EXPORT NamespaceUtils {
// later, this is required in order to write to /proc/self/gid_map without
// having CAP_SETGID. Callers can determine whether is this needed with
// KernelSupportsDenySetgroups. This function is async-signal-safe.
- static bool DenySetgroups() WARN_UNUSED_RESULT;
+ [[nodiscard]] static bool DenySetgroups();
};
} // namespace sandbox
diff --git a/chromium/sandbox/linux/services/proc_util.h b/chromium/sandbox/linux/services/proc_util.h
index 82052cc15b0..3687199908e 100644
--- a/chromium/sandbox/linux/services/proc_util.h
+++ b/chromium/sandbox/linux/services/proc_util.h
@@ -30,8 +30,8 @@ class SANDBOX_EXPORT ProcUtil {
// /proc/. The file descriptor in |proc_fd| will be ignored by
// HasOpenDirectory() and remains owned by the caller. It is very important
// for the caller to close it.
- static bool HasOpenDirectory(int proc_fd) WARN_UNUSED_RESULT;
- static bool HasOpenDirectory() WARN_UNUSED_RESULT;
+ [[nodiscard]] static bool HasOpenDirectory(int proc_fd);
+ [[nodiscard]] static bool HasOpenDirectory();
// Open /proc/ or crash if not possible.
static base::ScopedFD OpenProc();
diff --git a/chromium/sandbox/linux/services/resource_limits.h b/chromium/sandbox/linux/services/resource_limits.h
index f35482441f0..af8a33e625d 100644
--- a/chromium/sandbox/linux/services/resource_limits.h
+++ b/chromium/sandbox/linux/services/resource_limits.h
@@ -7,7 +7,6 @@
#include <sys/resource.h>
-#include "base/compiler_specific.h"
#include "sandbox/sandbox_export.h"
namespace sandbox {
@@ -21,21 +20,20 @@ class SANDBOX_EXPORT ResourceLimits {
// Lower the soft and hard limit of |resource| to |limit|. If the current
// limit is lower than |limit|, keep it. Returns 0 on success, or |errno|.
- static int Lower(int resource, rlim_t limit) WARN_UNUSED_RESULT;
+ [[nodiscard]] static int Lower(int resource, rlim_t limit);
// Lower the soft limit of |resource| to |limit| and the hard limit to |max|.
// If the current limit is lower than the new values, keep it. Returns 0 on
// success, or |errno|.
- static int LowerSoftAndHardLimits(int resource,
- rlim_t soft_limit,
- rlim_t hard_limit) WARN_UNUSED_RESULT;
+ [[nodiscard]] static int LowerSoftAndHardLimits(int resource,
+ rlim_t soft_limit,
+ rlim_t hard_limit);
// Change soft limit of |resource| to the current limit plus |change|. If
// |resource + change| is larger than the hard limit, the soft limit is set to
// be the same as the hard limit. Fails and returns false if the underlying
// call to setrlimit fails. Returns 0 on success, or |errno|.
- static int AdjustCurrent(int resource,
- long long int change) WARN_UNUSED_RESULT;
+ [[nodiscard]] static int AdjustCurrent(int resource, long long int change);
};
} // namespace sandbox
diff --git a/chromium/sandbox/linux/services/resource_limits_unittests.cc b/chromium/sandbox/linux/services/resource_limits_unittest.cc
index b79404dbc49..805411a1349 100644
--- a/chromium/sandbox/linux/services/resource_limits_unittests.cc
+++ b/chromium/sandbox/linux/services/resource_limits_unittest.cc
@@ -10,6 +10,7 @@
#include <unistd.h>
#include "base/check_op.h"
+#include "build/build_config.h"
#include "sandbox/linux/tests/test_utils.h"
#include "sandbox/linux/tests/unit_tests.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -19,11 +20,11 @@ namespace sandbox {
namespace {
// Fails on Android: crbug.com/459158
-#if !defined(OS_ANDROID)
+#if !BUILDFLAG(IS_ANDROID)
#define MAYBE_NoFork DISABLE_ON_ASAN(NoFork)
#else
#define MAYBE_NoFork DISABLED_NoFork
-#endif // OS_ANDROID
+#endif // BUILDFLAG(IS_ANDROID)
// Not being able to fork breaks LeakSanitizer, so disable on
// all ASAN builds.
diff --git a/chromium/sandbox/linux/services/thread_helpers_unittests.cc b/chromium/sandbox/linux/services/thread_helpers_unittest.cc
index 4ba79f43d12..4ba79f43d12 100644
--- a/chromium/sandbox/linux/services/thread_helpers_unittests.cc
+++ b/chromium/sandbox/linux/services/thread_helpers_unittest.cc
diff --git a/chromium/sandbox/linux/services/yama_unittests.cc b/chromium/sandbox/linux/services/yama_unittest.cc
index 9f576abe2c1..79038574c6e 100644
--- a/chromium/sandbox/linux/services/yama_unittests.cc
+++ b/chromium/sandbox/linux/services/yama_unittest.cc
@@ -31,9 +31,9 @@ bool HasLinux32Bug() {
bool is_kernel_64bit =
base::SysInfo::OperatingSystemArchitecture() == "x86_64";
bool is_linux = base::SysInfo::OperatingSystemName() == "Linux";
- bool is_3_dot_2 = base::StartsWith(
- base::SysInfo::OperatingSystemVersion(), "3.2",
- base::CompareCase::INSENSITIVE_ASCII);
+ bool is_3_dot_2 =
+ base::StartsWith(base::SysInfo::OperatingSystemVersion(), "3.2",
+ base::CompareCase::INSENSITIVE_ASCII);
if (is_kernel_64bit && is_linux && is_3_dot_2)
return true;
#endif // defined(__i386__)
@@ -109,10 +109,8 @@ TEST(Yama, GetStatus) {
EXPECT_EQ(static_cast<bool>(status1 & Yama::STATUS_PRESENT),
Yama::IsPresent());
- fprintf(stdout,
- "Yama present: %s - enforcing: %s\n",
- Yama::IsPresent() ? "Y" : "N",
- Yama::IsEnforcing() ? "Y" : "N");
+ fprintf(stdout, "Yama present: %s - enforcing: %s\n",
+ Yama::IsPresent() ? "Y" : "N", Yama::IsEnforcing() ? "Y" : "N");
}
SANDBOX_TEST(Yama, RestrictPtraceSucceedsWhenYamaPresent) {
diff --git a/chromium/sandbox/linux/suid/client/setuid_sandbox_host_unittest.cc b/chromium/sandbox/linux/suid/client/setuid_sandbox_host_unittest.cc
index c33a1ed9a13..728a2320c50 100644
--- a/chromium/sandbox/linux/suid/client/setuid_sandbox_host_unittest.cc
+++ b/chromium/sandbox/linux/suid/client/setuid_sandbox_host_unittest.cc
@@ -6,9 +6,9 @@
#include <memory>
#include <string>
+#include <tuple>
#include "base/environment.h"
-#include "base/ignore_result.h"
#include "base/strings/string_number_conversions.h"
#include "sandbox/linux/suid/common/sandbox.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -66,7 +66,7 @@ TEST(SetuidSandboxHost, SetupLaunchEnvironment) {
TEST(SetuidSandboxHost, GetSandboxBinaryPath) {
std::unique_ptr<SetuidSandboxHost> setuid_sandbox_host(
SetuidSandboxHost::Create());
- ignore_result(setuid_sandbox_host->GetSandboxBinaryPath());
+ std::ignore = setuid_sandbox_host->GetSandboxBinaryPath();
}
} // namespace sandbox
diff --git a/chromium/sandbox/linux/syscall_broker/broker_client.cc b/chromium/sandbox/linux/syscall_broker/broker_client.cc
index 0147524dc2b..17a85131123 100644
--- a/chromium/sandbox/linux/syscall_broker/broker_client.cc
+++ b/chromium/sandbox/linux/syscall_broker/broker_client.cc
@@ -22,7 +22,7 @@
#include "sandbox/linux/syscall_broker/broker_permission_list.h"
#include "sandbox/linux/syscall_broker/broker_simple_message.h"
-#if defined(OS_ANDROID) && !defined(MSG_CMSG_CLOEXEC)
+#if BUILDFLAG(IS_ANDROID) && !defined(MSG_CMSG_CLOEXEC)
#define MSG_CMSG_CLOEXEC 0x40000000
#endif
diff --git a/chromium/sandbox/linux/syscall_broker/broker_process.cc b/chromium/sandbox/linux/syscall_broker/broker_process.cc
index 51e1e9d59c9..7dd4688011f 100644
--- a/chromium/sandbox/linux/syscall_broker/broker_process.cc
+++ b/chromium/sandbox/linux/syscall_broker/broker_process.cc
@@ -117,44 +117,44 @@ bool BrokerProcess::IsSyscallBrokerable(int sysno, bool fast_check) const {
// and are default disabled in Android. So, we should refuse to broker them
// to be consistent with the platform's restrictions.
switch (sysno) {
-#if !defined(__aarch64__) && !defined(OS_ANDROID)
+#if !defined(__aarch64__) && !BUILDFLAG(IS_ANDROID)
case __NR_access:
#endif
case __NR_faccessat:
case __NR_faccessat2:
return !fast_check || policy_->allowed_command_set.test(COMMAND_ACCESS);
-#if !defined(__aarch64__) && !defined(OS_ANDROID)
+#if !defined(__aarch64__) && !BUILDFLAG(IS_ANDROID)
case __NR_mkdir:
#endif
case __NR_mkdirat:
return !fast_check || policy_->allowed_command_set.test(COMMAND_MKDIR);
-#if !defined(__aarch64__) && !defined(OS_ANDROID)
+#if !defined(__aarch64__) && !BUILDFLAG(IS_ANDROID)
case __NR_open:
#endif
case __NR_openat:
return !fast_check || policy_->allowed_command_set.test(COMMAND_OPEN);
-#if !defined(__aarch64__) && !defined(OS_ANDROID)
+#if !defined(__aarch64__) && !BUILDFLAG(IS_ANDROID)
case __NR_readlink:
#endif
case __NR_readlinkat:
return !fast_check || policy_->allowed_command_set.test(COMMAND_READLINK);
-#if !defined(__aarch64__) && !defined(OS_ANDROID)
+#if !defined(__aarch64__) && !BUILDFLAG(IS_ANDROID)
case __NR_rename:
#endif
case __NR_renameat:
case __NR_renameat2:
return !fast_check || policy_->allowed_command_set.test(COMMAND_RENAME);
-#if !defined(__aarch64__) && !defined(OS_ANDROID)
+#if !defined(__aarch64__) && !BUILDFLAG(IS_ANDROID)
case __NR_rmdir:
return !fast_check || policy_->allowed_command_set.test(COMMAND_RMDIR);
#endif
-#if !defined(__aarch64__) && !defined(OS_ANDROID)
+#if !defined(__aarch64__) && !BUILDFLAG(IS_ANDROID)
case __NR_stat:
case __NR_lstat:
#endif
@@ -179,7 +179,7 @@ bool BrokerProcess::IsSyscallBrokerable(int sysno, bool fast_check) const {
return !fast_check || policy_->allowed_command_set.test(COMMAND_STAT);
#endif
-#if !defined(__aarch64__) && !defined(OS_ANDROID)
+#if !defined(__aarch64__) && !BUILDFLAG(IS_ANDROID)
case __NR_unlink:
return !fast_check || policy_->allowed_command_set.test(COMMAND_UNLINK);
#endif
diff --git a/chromium/sandbox/linux/syscall_broker/broker_process_unittest.cc b/chromium/sandbox/linux/syscall_broker/broker_process_unittest.cc
index 310d705fa24..ad6e502e612 100644
--- a/chromium/sandbox/linux/syscall_broker/broker_process_unittest.cc
+++ b/chromium/sandbox/linux/syscall_broker/broker_process_unittest.cc
@@ -586,7 +586,7 @@ TEST(BrokerProcess, OpenComplexFlagsNoClientCheck) {
// expected.
}
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
// Flaky on Linux NG bots: https://crbug.com/595199.
#define MAYBE_RecvMsgDescriptorLeak DISABLED_RecvMsgDescriptorLeak
#else
@@ -1752,54 +1752,53 @@ TEST(BrokerProcess, UnlinkHost) {
TEST(BrokerProcess, IsSyscallAllowed) {
const base::flat_map<BrokerCommand, base::flat_set<int>> kSysnosForCommand = {
{COMMAND_ACCESS,
- {__NR_faccessat,
- __NR_faccessat2,
-#if defined(__NR_access) && !defined(OS_ANDROID)
+ {__NR_faccessat, __NR_faccessat2,
+#if defined(__NR_access) && !BUILDFLAG(IS_ANDROID)
__NR_access
#endif
}},
{COMMAND_MKDIR,
{__NR_mkdirat,
-#if defined(__NR_mkdir) && !defined(OS_ANDROID)
+#if defined(__NR_mkdir) && !BUILDFLAG(IS_ANDROID)
__NR_mkdir
#endif
}},
{COMMAND_OPEN,
{__NR_openat,
-#if defined(__NR_open) && !defined(OS_ANDROID)
+#if defined(__NR_open) && !BUILDFLAG(IS_ANDROID)
__NR_open
#endif
}},
{COMMAND_READLINK,
{__NR_readlinkat,
-#if defined(__NR_readlink) && !defined(OS_ANDROID)
+#if defined(__NR_readlink) && !BUILDFLAG(IS_ANDROID)
__NR_readlink
#endif
}},
{COMMAND_RENAME,
{__NR_renameat,
-#if defined(__NR_rename) && !defined(OS_ANDROID)
+#if defined(__NR_rename) && !BUILDFLAG(IS_ANDROID)
__NR_rename
#endif
}},
{COMMAND_UNLINK,
{__NR_unlinkat,
-#if defined(__NR_unlink) && !defined(OS_ANDROID)
+#if defined(__NR_unlink) && !BUILDFLAG(IS_ANDROID)
__NR_unlink
#endif
}},
{COMMAND_RMDIR,
{__NR_unlinkat,
-#if defined(__NR_rmdir) && !defined(OS_ANDROID)
+#if defined(__NR_rmdir) && !BUILDFLAG(IS_ANDROID)
__NR_rmdir
#endif
}},
{COMMAND_STAT,
{
-#if defined(__NR_stat) && !defined(OS_ANDROID)
+#if defined(__NR_stat) && !BUILDFLAG(IS_ANDROID)
__NR_stat,
#endif
-#if defined(__NR_lstat) && !defined(OS_ANDROID)
+#if defined(__NR_lstat) && !BUILDFLAG(IS_ANDROID)
__NR_lstat,
#endif
#if defined(__NR_fstatat)
diff --git a/chromium/sandbox/linux/syscall_broker/remote_syscall_arg_handler_unittest.cc b/chromium/sandbox/linux/syscall_broker/remote_syscall_arg_handler_unittest.cc
index 2e7f360a473..2c9492c513c 100644
--- a/chromium/sandbox/linux/syscall_broker/remote_syscall_arg_handler_unittest.cc
+++ b/chromium/sandbox/linux/syscall_broker/remote_syscall_arg_handler_unittest.cc
@@ -6,13 +6,14 @@
#include <sys/mman.h>
#include <sys/types.h>
+
#include <algorithm>
#include <cstring>
+#include <tuple>
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/files/scoped_file.h"
-#include "base/ignore_result.h"
#include "base/memory/page_size.h"
#include "base/posix/unix_domain_socket.h"
#include "base/test/bind.h"
@@ -76,7 +77,7 @@ pid_t ForkWaitingChild(base::OnceCallback<void(int)>
if (parent_sync_fd)
*parent_sync_fd = std::move(parent_sync);
else
- ignore_result(parent_sync.release()); // Closes when parent dies.
+ std::ignore = parent_sync.release(); // Closes when parent dies.
return pid;
}
diff --git a/chromium/sandbox/linux/system_headers/linux_prctl.h b/chromium/sandbox/linux/system_headers/linux_prctl.h
index 50f639b0fef..b2b4baeeb8a 100644
--- a/chromium/sandbox/linux/system_headers/linux_prctl.h
+++ b/chromium/sandbox/linux/system_headers/linux_prctl.h
@@ -15,14 +15,14 @@
#define PR_SET_TIMERSLACK 29
#endif
-#if defined(OS_ANDROID)
+#if BUILDFLAG(IS_ANDROID)
// https://android.googlesource.com/platform/bionic/+/lollipop-release/libc/private/bionic_prctl.h
#if !defined(PR_SET_VMA)
#define PR_SET_VMA 0x53564d41
#endif
-#endif // defined(OS_ANDROID)
+#endif // BUILDFLAG(IS_ANDROID)
#if !defined(PR_SET_PTRACER)
#define PR_SET_PTRACER 0x59616d61
diff --git a/chromium/sandbox/mac/seatbelt_exec.h b/chromium/sandbox/mac/seatbelt_exec.h
index ca9249f356f..fa711bd1201 100644
--- a/chromium/sandbox/mac/seatbelt_exec.h
+++ b/chromium/sandbox/mac/seatbelt_exec.h
@@ -7,7 +7,6 @@
#include <string>
-#include "base/compiler_specific.h" //nogncheck
#include "sandbox/mac/seatbelt.pb.h"
#include "sandbox/mac/seatbelt_export.h"
@@ -39,12 +38,11 @@ class SEATBELT_EXPORT SeatbeltExecClient {
// added successfully.
// Set a boolean parameter in the sandbox profile.
- bool SetBooleanParameter(const std::string& key,
- bool value) WARN_UNUSED_RESULT;
+ [[nodiscard]] bool SetBooleanParameter(const std::string& key, bool value);
// Set a string parameter in the sandbox profile.
- bool SetParameter(const std::string& key,
- const std::string& value) WARN_UNUSED_RESULT;
+ [[nodiscard]] bool SetParameter(const std::string& key,
+ const std::string& value);
// Set the actual sandbox profile, using the scheme-like SBPL.
void SetProfile(const std::string& policy);
@@ -114,8 +112,8 @@ class SEATBELT_EXPORT SeatbeltExecServer {
// server because the process about to initialize a sandbox may need to add
// some extra parameters, such as the path to the executable or the current
// PID. This must be called before InitializeSandbox().
- bool SetParameter(const std::string& key,
- const std::string& value) WARN_UNUSED_RESULT;
+ [[nodiscard]] bool SetParameter(const std::string& key,
+ const std::string& value);
private:
// Reads from the |fd_| and stores the data into a string. This does
diff --git a/chromium/sandbox/policy/BUILD.gn b/chromium/sandbox/policy/BUILD.gn
index 7ed3004ca77..b412c8db4d2 100644
--- a/chromium/sandbox/policy/BUILD.gn
+++ b/chromium/sandbox/policy/BUILD.gn
@@ -145,6 +145,7 @@ component("policy") {
]
deps += [
+ "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.buildinfo",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.camera3",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.fonts",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.intl",
diff --git a/chromium/sandbox/policy/features.cc b/chromium/sandbox/policy/features.cc
index 1a19cdd89d8..f89d9ca72b2 100644
--- a/chromium/sandbox/policy/features.cc
+++ b/chromium/sandbox/policy/features.cc
@@ -12,14 +12,14 @@ namespace sandbox {
namespace policy {
namespace features {
-#if !defined(OS_MAC) && !defined(OS_FUCHSIA)
+#if !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_FUCHSIA)
// Enables network service sandbox.
// (Only causes an effect when feature kNetworkService is enabled.)
const base::Feature kNetworkServiceSandbox{"NetworkServiceSandbox",
base::FEATURE_DISABLED_BY_DEFAULT};
-#endif // !defined(OS_MAC) && !defined(OS_FUCHSIA)
+#endif // !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_FUCHSIA)
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
// Emergency "off switch" for new Windows KTM security mitigation,
// sandbox::MITIGATION_KTM_COMPONENT.
const base::Feature kWinSboxDisableKtmComponent{
@@ -41,12 +41,12 @@ const base::Feature kGpuLPAC{"GpuLPAC", base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kRendererAppContainer{"RendererAppContainer",
base::FEATURE_DISABLED_BY_DEFAULT};
-#endif // defined(OS_WIN)
+#endif // BUILDFLAG(IS_WIN)
-#if !defined(OS_ANDROID)
+#if !BUILDFLAG(IS_ANDROID)
// Controls whether the isolated XR service is sandboxed.
const base::Feature kXRSandbox{"XRSandbox", base::FEATURE_ENABLED_BY_DEFAULT};
-#endif // !defined(OS_ANDROID)
+#endif // !BUILDFLAG(IS_ANDROID)
#if BUILDFLAG(IS_CHROMEOS_ASH)
// Controls whether the Spectre variant 2 mitigation is enabled. We use a USE
@@ -62,7 +62,7 @@ const base::Feature kForceSpectreVariant2Mitigation{
"ForceSpectreVariant2Mitigation", base::FEATURE_DISABLED_BY_DEFAULT};
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
bool IsWinNetworkServiceSandboxSupported() {
// Since some APIs used for LPAC are unsupported below Windows 10 RS2 (1703
// build 15063) so place a check here in a central place.
@@ -70,19 +70,19 @@ bool IsWinNetworkServiceSandboxSupported() {
return false;
return true;
}
-#endif // defined(OS_WIN)
+#endif // BUILDFLAG(IS_WIN)
bool IsNetworkSandboxEnabled() {
-#if defined(OS_MAC) || defined(OS_FUCHSIA)
+#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_FUCHSIA)
return true;
#else
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
if (!IsWinNetworkServiceSandboxSupported())
return false;
-#endif // defined(OS_WIN)
+#endif // BUILDFLAG(IS_WIN)
// Check feature status.
return base::FeatureList::IsEnabled(kNetworkServiceSandbox);
-#endif // defined(OS_MAC) || defined(OS_FUCHSIA)
+#endif // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_FUCHSIA)
}
} // namespace features
diff --git a/chromium/sandbox/policy/features.h b/chromium/sandbox/policy/features.h
index 34f4bb517d1..a9c557e2599 100644
--- a/chromium/sandbox/policy/features.h
+++ b/chromium/sandbox/policy/features.h
@@ -17,21 +17,21 @@ namespace sandbox {
namespace policy {
namespace features {
-#if !defined(OS_MAC) && !defined(OS_FUCHSIA)
+#if !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_FUCHSIA)
SANDBOX_POLICY_EXPORT extern const base::Feature kNetworkServiceSandbox;
#endif
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
SANDBOX_POLICY_EXPORT extern const base::Feature kWinSboxDisableKtmComponent;
SANDBOX_POLICY_EXPORT extern const base::Feature kWinSboxDisableExtensionPoints;
SANDBOX_POLICY_EXPORT extern const base::Feature kGpuAppContainer;
SANDBOX_POLICY_EXPORT extern const base::Feature kGpuLPAC;
SANDBOX_POLICY_EXPORT extern const base::Feature kRendererAppContainer;
-#endif // defined(OS_WIN)
+#endif // BUILDFLAG(IS_WIN)
-#if !defined(OS_ANDROID)
+#if !BUILDFLAG(IS_ANDROID)
SANDBOX_POLICY_EXPORT extern const base::Feature kXRSandbox;
-#endif // !defined(OS_ANDROID)
+#endif // !BUILDFLAG(IS_ANDROID)
#if BUILDFLAG(IS_CHROMEOS_ASH)
SANDBOX_POLICY_EXPORT extern const base::Feature kSpectreVariant2Mitigation;
@@ -39,7 +39,7 @@ SANDBOX_POLICY_EXPORT extern const base::Feature
kForceSpectreVariant2Mitigation;
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
// Returns whether the Network Service Sandbox is supported by the current
// Windows platform. Call this function rather than checking the
// kNetworkServiceSandbox feature directly.
diff --git a/chromium/sandbox/policy/fuchsia/sandbox_policy_fuchsia.cc b/chromium/sandbox/policy/fuchsia/sandbox_policy_fuchsia.cc
index b511e3cde13..9772736124b 100644
--- a/chromium/sandbox/policy/fuchsia/sandbox_policy_fuchsia.cc
+++ b/chromium/sandbox/policy/fuchsia/sandbox_policy_fuchsia.cc
@@ -9,6 +9,7 @@
#include <zircon/processargs.h>
#include <zircon/syscalls/policy.h>
+#include <fuchsia/buildinfo/cpp/fidl.h>
#include <fuchsia/camera3/cpp/fidl.h>
#include <fuchsia/fonts/cpp/fidl.h>
#include <fuchsia/intl/cpp/fidl.h>
@@ -66,6 +67,30 @@ struct SandboxConfig {
uint32_t features;
};
+// Services that are passed to all processes.
+// Prevent incorrect indentation due to the preprocessor lines within `({...})`:
+// clang-format off
+constexpr auto kMinimalServices = base::make_span((const char* const[]){
+ // TODO(crbug.com/1286960): Remove this and/or intl below if an alternative
+ // solution does not require access to the service in all processes.
+ fuchsia::buildinfo::Provider::Name_,
+
+// DebugData service is needed only for profiling.
+#if BUILDFLAG(CLANG_PROFILING)
+ "fuchsia.debugdata.DebugData",
+#endif
+
+ fuchsia::intl::PropertyProvider::Name_,
+ fuchsia::logger::LogSink::Name_,
+});
+// clang-format on
+
+// For processes that only get kMinimalServices and no other capabilities.
+constexpr SandboxConfig kMinimalConfig = {
+ base::span<const char* const>(),
+ 0,
+};
+
constexpr SandboxConfig kGpuConfig = {
base::make_span((const char* const[]){
// TODO(crbug.com/1224707): Use the fuchsia.scheduler API instead.
@@ -109,10 +134,9 @@ constexpr SandboxConfig kVideoCaptureConfig = {
0,
};
-// No-access-to-anything.
-constexpr SandboxConfig kEmptySandboxConfig = {
+constexpr SandboxConfig kServiceWithJitConfig = {
base::span<const char* const>(),
- 0,
+ kAmbientMarkVmoAsExecutable,
};
const SandboxConfig* GetConfigForSandboxType(sandbox::mojom::Sandbox type) {
@@ -127,6 +151,8 @@ const SandboxConfig* GetConfigForSandboxType(sandbox::mojom::Sandbox type) {
return &kRendererConfig;
case sandbox::mojom::Sandbox::kVideoCapture:
return &kVideoCaptureConfig;
+ case sandbox::mojom::Sandbox::kServiceWithJit:
+ return &kServiceWithJitConfig;
// Remaining types receive no-access-to-anything.
case sandbox::mojom::Sandbox::kAudio:
case sandbox::mojom::Sandbox::kCdm:
@@ -134,19 +160,10 @@ const SandboxConfig* GetConfigForSandboxType(sandbox::mojom::Sandbox type) {
case sandbox::mojom::Sandbox::kService:
case sandbox::mojom::Sandbox::kSpeechRecognition:
case sandbox::mojom::Sandbox::kUtility:
- return &kEmptySandboxConfig;
+ return &kMinimalConfig;
}
}
-// Services that are passed to all processes.
-constexpr auto kDefaultServices = base::make_span((const char* const[]) {
-// DebugData service is needed only for profiling.
-#if BUILDFLAG(CLANG_PROFILING)
- "fuchsia.debugdata.DebugData",
-#endif
- fuchsia::intl::PropertyProvider::Name_, fuchsia::logger::LogSink::Name_
-});
-
} // namespace
SandboxPolicyFuchsia::SandboxPolicyFuchsia(sandbox::mojom::Sandbox type) {
@@ -165,7 +182,7 @@ SandboxPolicyFuchsia::SandboxPolicyFuchsia(sandbox::mojom::Sandbox type) {
service_directory_task_runner_ = base::ThreadTaskRunnerHandle::Get();
service_directory_ = std::make_unique<base::FilteredServiceDirectory>(
base::ComponentContextForProcess()->svc().get());
- for (const char* service_name : kDefaultServices) {
+ for (const char* service_name : kMinimalServices) {
zx_status_t status = service_directory_->AddService(service_name);
ZX_CHECK(status == ZX_OK, status)
<< "AddService(" << service_name << ") failed";
diff --git a/chromium/sandbox/policy/linux/bpf_gpu_policy_linux.cc b/chromium/sandbox/policy/linux/bpf_gpu_policy_linux.cc
index 48b16aba593..f8df9dcbd93 100644
--- a/chromium/sandbox/policy/linux/bpf_gpu_policy_linux.cc
+++ b/chromium/sandbox/policy/linux/bpf_gpu_policy_linux.cc
@@ -102,7 +102,7 @@ ResultExpr GpuProcessPolicy::EvaluateSyscall(int sysno) const {
break;
}
-#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
if (SyscallSets::IsSystemVSharedMemory(sysno))
return Allow();
#endif
diff --git a/chromium/sandbox/policy/linux/sandbox_debug_handling_linux.cc b/chromium/sandbox/policy/linux/sandbox_debug_handling_linux.cc
index a1fcded8bfa..e854ef675a0 100644
--- a/chromium/sandbox/policy/linux/sandbox_debug_handling_linux.cc
+++ b/chromium/sandbox/policy/linux/sandbox_debug_handling_linux.cc
@@ -10,8 +10,9 @@
#include <sys/prctl.h>
#include <unistd.h>
+#include <tuple>
+
#include "base/command_line.h"
-#include "base/ignore_result.h"
#include "base/logging.h"
#include "base/strings/safe_sprintf.h"
#include "sandbox/policy/switches.h"
@@ -24,7 +25,7 @@ namespace {
void DoChrootSignalHandler(int) {
const int old_errno = errno;
const char kFirstMessage[] = "Chroot signal handler called.\n";
- ignore_result(write(STDERR_FILENO, kFirstMessage, sizeof(kFirstMessage) - 1));
+ std::ignore = write(STDERR_FILENO, kFirstMessage, sizeof(kFirstMessage) - 1);
const int chroot_ret = chroot("/");
@@ -33,7 +34,7 @@ void DoChrootSignalHandler(int) {
kSecondMessage, "chroot() returned %d. Errno is %d.\n", chroot_ret,
errno);
if (printed > 0 && printed < static_cast<ssize_t>(sizeof(kSecondMessage))) {
- ignore_result(write(STDERR_FILENO, kSecondMessage, printed));
+ std::ignore = write(STDERR_FILENO, kSecondMessage, printed);
}
errno = old_errno;
}
diff --git a/chromium/sandbox/policy/linux/sandbox_seccomp_bpf_linux.cc b/chromium/sandbox/policy/linux/sandbox_seccomp_bpf_linux.cc
index 75ffefc2a72..62c4551fe40 100644
--- a/chromium/sandbox/policy/linux/sandbox_seccomp_bpf_linux.cc
+++ b/chromium/sandbox/policy/linux/sandbox_seccomp_bpf_linux.cc
@@ -186,6 +186,8 @@ std::unique_ptr<BPFBasePolicy> SandboxSeccompBPF::PolicyForSandboxType(
return std::make_unique<AudioProcessPolicy>();
case sandbox::mojom::Sandbox::kService:
return std::make_unique<ServiceProcessPolicy>();
+ case sandbox::mojom::Sandbox::kServiceWithJit:
+ return std::make_unique<ServiceProcessPolicy>();
case sandbox::mojom::Sandbox::kSpeechRecognition:
return std::make_unique<SpeechRecognitionProcessPolicy>();
#if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -259,6 +261,7 @@ void SandboxSeccompBPF::RunSandboxSanityChecks(
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
case sandbox::mojom::Sandbox::kAudio:
case sandbox::mojom::Sandbox::kService:
+ case sandbox::mojom::Sandbox::kServiceWithJit:
case sandbox::mojom::Sandbox::kSpeechRecognition:
case sandbox::mojom::Sandbox::kNetwork:
#if BUILDFLAG(ENABLE_OOP_PRINTING)
diff --git a/chromium/sandbox/policy/mac/common.sb b/chromium/sandbox/policy/mac/common.sb
index 84c7e99b329..1c5319884c0 100644
--- a/chromium/sandbox/policy/mac/common.sb
+++ b/chromium/sandbox/policy/mac/common.sb
@@ -111,6 +111,40 @@
; All processes can read the bundle contents.
(allow file-read* (subpath (param bundle-path)))
+; A sandbox bug on macOS 11 and 12 causes the sandbox to see any paths within
+; the data volume (/System/Volumes/Data) outside of system firm link locations
+; (listed in /usr/share/firmlinks) as though they were not on the data volume,
+; causing it to deny access to user paths containing the data volume mount point
+; as a prefix. This is filed as https://openradar.appspot.com/FB9738355 and
+; tracked at https://crbug.com/1266490. Although macOS 10.15 also has the root
+; volume split, this bug does not appear to affect that OS version.
+;
+; When the bundle path appears in the data volume, this causes the sandbox to
+; deny access to the bundle.
+;
+; This is not a problem in normal use, as typical bundle paths, while on the
+; data volume, will be in system firm link locations such as /Applications or
+; /Users. As a workaround for other cases where the bundle may be present on the
+; data volume but not in a system firm link location, configure the sandbox with
+; an alternate bundle path so that it permits access to the bundle.
+(define (string-prefix? str prefix)
+ (let ((l (string-length prefix)))
+ (if (< (string-length str) l)
+ #f
+ (equal? (substring str 0 l) prefix)
+ )
+ )
+)
+(define data-volume-root "/System/Volumes/Data/")
+(when (string-prefix? (param bundle-path) data-volume-root)
+ (define (strip-leading-chars str count)
+ (substring str count (string-length str))
+ )
+ (allow file-read*
+ (subpath (strip-leading-chars (param bundle-path)
+ (- (string-length data-volume-root) 1))))
+)
+
; Allow reads of system libraries and frameworks.
(allow file-read*
(subpath "/System/Library/CoreServices/CoreTypes.bundle")
diff --git a/chromium/sandbox/policy/mac/sandbox_mac.mm b/chromium/sandbox/policy/mac/sandbox_mac.mm
index 248f5714db4..34f8b003c96 100644
--- a/chromium/sandbox/policy/mac/sandbox_mac.mm
+++ b/chromium/sandbox/policy/mac/sandbox_mac.mm
@@ -85,6 +85,7 @@ std::string GetSandboxProfile(sandbox::mojom::Sandbox sandbox_type) {
break;
// kService and kUtility are the same on OS_MAC, so fallthrough.
case sandbox::mojom::Sandbox::kService:
+ case sandbox::mojom::Sandbox::kServiceWithJit:
case sandbox::mojom::Sandbox::kUtility:
profile += kSeatbeltPolicyString_utility;
break;
diff --git a/chromium/sandbox/policy/mojom/sandbox.mojom b/chromium/sandbox/policy/mojom/sandbox.mojom
index 6ee006b2a94..916ead93bbc 100644
--- a/chromium/sandbox/policy/mojom/sandbox.mojom
+++ b/chromium/sandbox/policy/mojom/sandbox.mojom
@@ -16,6 +16,11 @@ enum Sandbox {
// if possible.
kService,
+ // |kServiceWithJit| hosts computation only services that make use of
+ // dynamic code (e.g. v8 or wasm) but do not need access to OS resources.
+ // Prefer |kService| if possible.
+ kServiceWithJit,
+
// Hosts generic utilities with limited access to system services.
// On some platforms, may be slightly less locked down than |kService|.
// For instance, it allows dynamic code and wider access to APIs on Windows.
diff --git a/chromium/sandbox/policy/sandbox.cc b/chromium/sandbox/policy/sandbox.cc
index 3b31605f49f..d76a6162a5b 100644
--- a/chromium/sandbox/policy/sandbox.cc
+++ b/chromium/sandbox/policy/sandbox.cc
@@ -9,37 +9,37 @@
#include "sandbox/policy/mojom/sandbox.mojom.h"
#include "sandbox/policy/switches.h"
-#if defined(OS_ANDROID)
+#if BUILDFLAG(IS_ANDROID)
#include "base/android/jni_android.h"
-#endif // defined(OS_ANDROID)
+#endif // BUILDFLAG(IS_ANDROID)
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#include "sandbox/policy/linux/sandbox_linux.h"
-#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
+#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-#if defined(OS_MAC)
+#if BUILDFLAG(IS_MAC)
#include "sandbox/mac/seatbelt.h"
-#endif // defined(OS_MAC)
+#endif // BUILDFLAG(IS_MAC)
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
#include "base/process/process_info.h"
#include "sandbox/policy/win/sandbox_win.h"
#include "sandbox/win/src/sandbox.h"
-#endif // defined(OS_WIN)
+#endif // BUILDFLAG(IS_WIN)
namespace sandbox {
namespace policy {
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
bool Sandbox::Initialize(sandbox::mojom::Sandbox sandbox_type,
SandboxLinux::PreSandboxHook hook,
const SandboxLinux::Options& options) {
return SandboxLinux::GetInstance()->InitializeSandbox(
sandbox_type, std::move(hook), options);
}
-#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
+#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
bool Sandbox::Initialize(sandbox::mojom::Sandbox sandbox_type,
SandboxInterfaceInfo* sandbox_info) {
BrokerServices* broker_services = sandbox_info->broker_services;
@@ -65,7 +65,7 @@ bool Sandbox::Initialize(sandbox::mojom::Sandbox sandbox_type,
return IsUnsandboxedSandboxType(sandbox_type) ||
SandboxWin::InitTargetServices(sandbox_info->target_services);
}
-#endif // defined(OS_WIN)
+#endif // BUILDFLAG(IS_WIN)
// static
bool Sandbox::IsProcessSandboxed() {
@@ -80,7 +80,7 @@ bool Sandbox::IsProcessSandboxed() {
return true;
}
-#if defined(OS_ANDROID)
+#if BUILDFLAG(IS_ANDROID)
// Note that this does not check the status of the Seccomp sandbox. Call
// https://developer.android.com/reference/android/os/Process#isIsolated().
JNIEnv* env = base::android::AttachCurrentThread();
@@ -90,12 +90,12 @@ bool Sandbox::IsProcessSandboxed() {
base::android::MethodID::Get<base::android::MethodID::TYPE_STATIC>(
env, process_class.obj(), "isIsolated", "()Z");
return env->CallStaticBooleanMethod(process_class.obj(), is_isolated);
-#elif defined(OS_FUCHSIA)
+#elif BUILDFLAG(IS_FUCHSIA)
// TODO(https://crbug.com/1071420): Figure out what to do here. Process
// launching controls the sandbox and there are no ambient capabilities, so
// basically everything but the browser is considered sandboxed.
return !is_browser;
-#elif defined(OS_LINUX) || defined(OS_CHROMEOS)
+#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
int status = SandboxLinux::GetInstance()->GetStatus();
constexpr int kLayer1Flags = SandboxLinux::Status::kSUID |
SandboxLinux::Status::kPIDNS |
@@ -103,9 +103,9 @@ bool Sandbox::IsProcessSandboxed() {
constexpr int kLayer2Flags =
SandboxLinux::Status::kSeccompBPF | SandboxLinux::Status::kSeccompTSYNC;
return (status & kLayer1Flags) != 0 && (status & kLayer2Flags) != 0;
-#elif defined(OS_MAC)
+#elif BUILDFLAG(IS_MAC)
return Seatbelt::IsSandboxed();
-#elif defined(OS_WIN)
+#elif BUILDFLAG(IS_WIN)
return base::GetCurrentProcessIntegrityLevel() < base::MEDIUM_INTEGRITY;
#else
return false;
diff --git a/chromium/sandbox/policy/sandbox.h b/chromium/sandbox/policy/sandbox.h
index 4212646e997..b003a1febe3 100644
--- a/chromium/sandbox/policy/sandbox.h
+++ b/chromium/sandbox/policy/sandbox.h
@@ -8,7 +8,7 @@
#include "build/build_config.h"
#include "sandbox/policy/export.h"
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#include "sandbox/policy/linux/sandbox_linux.h"
#endif
@@ -32,16 +32,16 @@ namespace policy {
class SANDBOX_POLICY_EXPORT Sandbox {
public:
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
static bool Initialize(sandbox::mojom::Sandbox sandbox_type,
SandboxLinux::PreSandboxHook hook,
const SandboxLinux::Options& options);
-#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
+#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
static bool Initialize(sandbox::mojom::Sandbox sandbox_type,
SandboxInterfaceInfo* sandbox_info);
-#endif // defined(OS_WIN)
+#endif // BUILDFLAG(IS_WIN)
// Returns true if the current process is running with a sandbox, and false
// if the process is not sandboxed. This should be used to assert that code is
diff --git a/chromium/sandbox/policy/sandbox_delegate.h b/chromium/sandbox/policy/sandbox_delegate.h
index 991eb065c7a..46913ae019d 100644
--- a/chromium/sandbox/policy/sandbox_delegate.h
+++ b/chromium/sandbox/policy/sandbox_delegate.h
@@ -27,7 +27,7 @@ class SandboxDelegate {
// Sandbox::kNoSandbox to run without a sandbox policy.
virtual sandbox::mojom::Sandbox GetSandboxType() = 0;
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
// Whether to disable the default policy specified in
// AddPolicyForSandboxedProcess.
virtual bool DisableDefaultPolicy() = 0;
@@ -48,7 +48,7 @@ class SandboxDelegate {
// Whether this process will be compatible with Control-flow Enforcement
// Technology (CET) / Hardware-enforced Stack Protection.
virtual bool CetCompatible() = 0;
-#endif // defined(OS_WIN)
+#endif // BUILDFLAG(IS_WIN)
};
} // namespace policy
diff --git a/chromium/sandbox/policy/sandbox_type.cc b/chromium/sandbox/policy/sandbox_type.cc
index 2a5385d07e8..944e9ba4fe4 100644
--- a/chromium/sandbox/policy/sandbox_type.cc
+++ b/chromium/sandbox/policy/sandbox_type.cc
@@ -26,7 +26,7 @@ bool IsUnsandboxedSandboxType(Sandbox sandbox_type) {
switch (sandbox_type) {
case Sandbox::kNoSandbox:
return true;
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
case Sandbox::kNoSandboxAndElevatedPrivileges:
return true;
case Sandbox::kXrCompositing:
@@ -39,7 +39,7 @@ bool IsUnsandboxedSandboxType(Sandbox sandbox_type) {
#endif
case Sandbox::kAudio:
return false;
-#if defined(OS_FUCHSIA)
+#if BUILDFLAG(IS_FUCHSIA)
case Sandbox::kVideoCapture:
return false;
#endif
@@ -47,6 +47,7 @@ bool IsUnsandboxedSandboxType(Sandbox sandbox_type) {
return false;
case Sandbox::kRenderer:
case Sandbox::kService:
+ case Sandbox::kServiceWithJit:
case Sandbox::kUtility:
case Sandbox::kGpu:
#if BUILDFLAG(ENABLE_PLUGINS)
@@ -57,7 +58,7 @@ bool IsUnsandboxedSandboxType(Sandbox sandbox_type) {
case Sandbox::kPrintBackend:
#endif
case Sandbox::kPrintCompositor:
-#if defined(OS_MAC)
+#if BUILDFLAG(IS_MAC)
case Sandbox::kMirroring:
case Sandbox::kNaClLoader:
#endif
@@ -69,7 +70,7 @@ bool IsUnsandboxedSandboxType(Sandbox sandbox_type) {
case Sandbox::kLibassistant:
#endif // BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
#endif // // BUILDFLAG(IS_CHROMEOS_ASH)
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
case Sandbox::kZygoteIntermediateSandbox:
#endif
case Sandbox::kSpeechRecognition:
@@ -112,6 +113,7 @@ void SetCommandLineFlagsForSandboxType(base::CommandLine* command_line,
break;
#endif
case Sandbox::kService:
+ case Sandbox::kServiceWithJit:
case Sandbox::kUtility:
case Sandbox::kNetwork:
case Sandbox::kCdm:
@@ -120,17 +122,17 @@ void SetCommandLineFlagsForSandboxType(base::CommandLine* command_line,
#endif
case Sandbox::kPrintCompositor:
case Sandbox::kAudio:
-#if defined(OS_FUCHSIA)
+#if BUILDFLAG(IS_FUCHSIA)
case Sandbox::kVideoCapture:
#endif
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
case Sandbox::kNoSandboxAndElevatedPrivileges:
case Sandbox::kXrCompositing:
case Sandbox::kPdfConversion:
case Sandbox::kIconReader:
case Sandbox::kMediaFoundationCdm:
case Sandbox::kWindowsSystemProxyResolver:
-#endif // defined(OS_WIN)
+#endif // BUILDFLAG(IS_WIN)
#if BUILDFLAG(IS_CHROMEOS_ASH)
case Sandbox::kHardwareVideoDecoding:
case Sandbox::kIme:
@@ -139,9 +141,9 @@ void SetCommandLineFlagsForSandboxType(base::CommandLine* command_line,
case Sandbox::kLibassistant:
#endif // BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
-#if defined(OS_MAC)
+#if BUILDFLAG(IS_MAC)
case Sandbox::kMirroring:
-#endif // defined(OS_MAC)
+#endif // BUILDFLAG(IS_MAC)
case Sandbox::kSpeechRecognition:
DCHECK(command_line->GetSwitchValueASCII(switches::kProcessType) ==
switches::kUtilityProcess);
@@ -150,11 +152,11 @@ void SetCommandLineFlagsForSandboxType(base::CommandLine* command_line,
switches::kServiceSandboxType,
StringFromUtilitySandboxType(sandbox_type));
break;
-#if defined(OS_MAC)
+#if BUILDFLAG(IS_MAC)
case Sandbox::kNaClLoader:
break;
-#endif // defined(OS_MAC)
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+#endif // BUILDFLAG(IS_MAC)
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
case Sandbox::kZygoteIntermediateSandbox:
break;
#endif
@@ -191,7 +193,7 @@ sandbox::mojom::Sandbox SandboxTypeFromCommandLine(
// NaCl tests on all platforms use the loader process.
if (process_type == switches::kNaClLoaderProcess) {
-#if defined(OS_MAC)
+#if BUILDFLAG(IS_MAC)
return Sandbox::kNaClLoader;
#else
return Sandbox::kUtility;
@@ -201,20 +203,17 @@ sandbox::mojom::Sandbox SandboxTypeFromCommandLine(
if (process_type == switches::kNaClBrokerProcess)
return Sandbox::kNoSandbox;
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
// Intermediate process gains a sandbox later.
if (process_type == switches::kZygoteProcessType)
return Sandbox::kZygoteIntermediateSandbox;
#endif
-#if defined(OS_MAC)
+#if BUILDFLAG(IS_MAC)
if (process_type == switches::kRelauncherProcessType)
return Sandbox::kNoSandbox;
#endif
- if (process_type == switches::kCloudPrintServiceProcess)
- return Sandbox::kNoSandbox;
-
CHECK(false)
<< "Command line does not provide a valid sandbox configuration: "
<< command_line.GetCommandLineString();
@@ -226,10 +225,10 @@ std::string StringFromUtilitySandboxType(Sandbox sandbox_type) {
switch (sandbox_type) {
case Sandbox::kNoSandbox:
return switches::kNoneSandbox;
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
case Sandbox::kNoSandboxAndElevatedPrivileges:
return switches::kNoneSandboxAndElevatedPrivileges;
-#endif // defined(OS_WIN)
+#endif // BUILDFLAG(IS_WIN)
case Sandbox::kNetwork:
return switches::kNetworkSandbox;
#if BUILDFLAG(ENABLE_PLUGINS)
@@ -248,15 +247,17 @@ std::string StringFromUtilitySandboxType(Sandbox sandbox_type) {
return switches::kUtilitySandbox;
case Sandbox::kAudio:
return switches::kAudioSandbox;
-#if defined(OS_FUCHSIA)
+#if BUILDFLAG(IS_FUCHSIA)
case Sandbox::kVideoCapture:
return switches::kVideoCaptureSandbox;
#endif
case Sandbox::kService:
return switches::kServiceSandbox;
+ case Sandbox::kServiceWithJit:
+ return switches::kServiceSandboxWithJit;
case Sandbox::kSpeechRecognition:
return switches::kSpeechRecognitionSandbox;
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
case Sandbox::kXrCompositing:
return switches::kXrCompositingSandbox;
case Sandbox::kPdfConversion:
@@ -267,8 +268,8 @@ std::string StringFromUtilitySandboxType(Sandbox sandbox_type) {
return switches::kMediaFoundationCdmSandbox;
case Sandbox::kWindowsSystemProxyResolver:
return switches::kWindowsSystemProxyResolverSandbox;
-#endif // defined(OS_WIN)
-#if defined(OS_MAC)
+#endif // BUILDFLAG(IS_WIN)
+#if BUILDFLAG(IS_MAC)
case Sandbox::kMirroring:
return switches::kMirroringSandbox;
#endif
@@ -287,10 +288,10 @@ std::string StringFromUtilitySandboxType(Sandbox sandbox_type) {
// The following are not utility processes so should not occur.
case Sandbox::kRenderer:
case Sandbox::kGpu:
-#if defined(OS_MAC)
+#if BUILDFLAG(IS_MAC)
case Sandbox::kNaClLoader:
-#endif // defined(OS_MAC)
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+#endif // BUILDFLAG(IS_MAC)
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
case Sandbox::kZygoteIntermediateSandbox:
#endif
NOTREACHED();
@@ -308,11 +309,13 @@ sandbox::mojom::Sandbox UtilitySandboxTypeFromString(
return Sandbox::kUtility;
if (sandbox_string == switches::kServiceSandbox)
return Sandbox::kService;
+ if (sandbox_string == switches::kServiceSandboxWithJit)
+ return Sandbox::kServiceWithJit;
if (sandbox_string == switches::kNoneSandbox)
return Sandbox::kNoSandbox;
if (sandbox_string == switches::kNoneSandboxAndElevatedPrivileges) {
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
return Sandbox::kNoSandboxAndElevatedPrivileges;
#else
return Sandbox::kNoSandbox;
@@ -332,7 +335,7 @@ sandbox::mojom::Sandbox UtilitySandboxTypeFromString(
#endif
if (sandbox_string == switches::kPrintCompositorSandbox)
return Sandbox::kPrintCompositor;
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
if (sandbox_string == switches::kXrCompositingSandbox)
return Sandbox::kXrCompositing;
if (sandbox_string == switches::kPdfConversionSandbox)
@@ -344,7 +347,7 @@ sandbox::mojom::Sandbox UtilitySandboxTypeFromString(
if (sandbox_string == switches::kWindowsSystemProxyResolverSandbox)
return Sandbox::kWindowsSystemProxyResolver;
#endif
-#if defined(OS_MAC)
+#if BUILDFLAG(IS_MAC)
if (sandbox_string == switches::kMirroringSandbox)
return Sandbox::kMirroring;
#endif
@@ -352,7 +355,7 @@ sandbox::mojom::Sandbox UtilitySandboxTypeFromString(
return Sandbox::kAudio;
if (sandbox_string == switches::kSpeechRecognitionSandbox)
return Sandbox::kSpeechRecognition;
-#if defined(OS_FUCHSIA)
+#if BUILDFLAG(IS_FUCHSIA)
if (sandbox_string == switches::kVideoCaptureSandbox)
return Sandbox::kVideoCapture;
#endif
diff --git a/chromium/sandbox/policy/sandbox_type_unittest.cc b/chromium/sandbox/policy/sandbox_type_unittest.cc
index 83da610d317..187043a5bda 100644
--- a/chromium/sandbox/policy/sandbox_type_unittest.cc
+++ b/chromium/sandbox/policy/sandbox_type_unittest.cc
@@ -86,7 +86,7 @@ TEST(SandboxTypeTest, Utility) {
EXPECT_EQ(Sandbox::kSpeechRecognition,
SandboxTypeFromCommandLine(command_line9));
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
base::CommandLine command_line10(command_line);
SetCommandLineFlagsForSandboxType(&command_line10, Sandbox::kXrCompositing);
EXPECT_EQ(Sandbox::kXrCompositing,
@@ -115,6 +115,11 @@ TEST(SandboxTypeTest, Utility) {
switches::kNoneSandbox);
EXPECT_EQ(Sandbox::kNoSandbox, SandboxTypeFromCommandLine(command_line14));
+ base::CommandLine command_line15(command_line);
+ SetCommandLineFlagsForSandboxType(&command_line15, Sandbox::kServiceWithJit);
+ EXPECT_EQ(Sandbox::kServiceWithJit,
+ SandboxTypeFromCommandLine(command_line15));
+
command_line.AppendSwitch(switches::kNoSandbox);
EXPECT_EQ(Sandbox::kNoSandbox, SandboxTypeFromCommandLine(command_line));
}
@@ -183,7 +188,7 @@ TEST(SandboxTypeTest, ElevatedPrivileges) {
// specific default to no sandbox on non Windows platforms.
Sandbox elevated_type =
UtilitySandboxTypeFromString(switches::kNoneSandboxAndElevatedPrivileges);
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
EXPECT_EQ(Sandbox::kNoSandboxAndElevatedPrivileges, elevated_type);
#else
EXPECT_EQ(Sandbox::kNoSandbox, elevated_type);
diff --git a/chromium/sandbox/policy/switches.cc b/chromium/sandbox/policy/switches.cc
index c7fa0112ebe..4ad0ff39cba 100644
--- a/chromium/sandbox/policy/switches.cc
+++ b/chromium/sandbox/policy/switches.cc
@@ -8,7 +8,7 @@
#include "build/chromeos_buildflags.h"
#include "printing/buildflags/buildflags.h"
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
#include "base/command_line.h"
#include "base/win/windows_version.h"
#endif
@@ -35,20 +35,21 @@ const char kPrintBackendSandbox[] = "print_backend";
const char kPrintCompositorSandbox[] = "print_compositor";
const char kAudioSandbox[] = "audio";
const char kServiceSandbox[] = "service";
+const char kServiceSandboxWithJit[] = "service_with_jit";
const char kSpeechRecognitionSandbox[] = "speech_recognition";
const char kVideoCaptureSandbox[] = "video_capture";
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
const char kPdfConversionSandbox[] = "pdf_conversion";
const char kXrCompositingSandbox[] = "xr_compositing";
const char kIconReaderSandbox[] = "icon_reader";
const char kMediaFoundationCdmSandbox[] = "mf_cdm";
const char kWindowsSystemProxyResolverSandbox[] = "proxy_resolver_win";
-#endif // OS_WIN
+#endif // BUILDFLAG(IS_WIN)
-#if defined(OS_MAC)
+#if BUILDFLAG(IS_MAC)
const char kMirroringSandbox[] = "mirroring";
-#endif // OS_MAC
+#endif // BUILDFLAG(IS_MAC)
#if BUILDFLAG(IS_CHROMEOS_ASH)
const char kHardwareVideoDecodingSandbox[] = "hardware_video_decoding";
@@ -94,13 +95,13 @@ const char kGpuSandboxFailuresFatal[] = "gpu-sandbox-failures-fatal";
// Meant to be used as a browser-level switch for testing purposes only.
const char kNoSandbox[] = "no-sandbox";
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
// Instructs the zygote to launch without a sandbox. Processes forked from this
// type of zygote will apply their own custom sandboxes later.
const char kNoZygoteSandbox[] = "no-zygote-sandbox";
#endif
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
// Allows third party modules to inject by disabling the BINARY_SIGNATURE
// mitigation policy on Win10+. Also has other effects in ELF.
const char kAllowThirdPartyModules[] = "allow-third-party-modules";
@@ -113,7 +114,7 @@ const char kAddGpuAppContainerCaps[] = "add-gpu-appcontainer-caps";
const char kAddXrAppContainerCaps[] = "add-xr-appcontainer-caps";
#endif
-#if defined(OS_MAC)
+#if BUILDFLAG(IS_MAC)
// Cause the OS X sandbox write to syslog every time an access to a resource
// is denied by the sandbox.
const char kEnableSandboxLogging[] = "enable-sandbox-logging";
@@ -130,7 +131,6 @@ const char kNaClLoaderProcess[] = "nacl-loader";
const char kPpapiPluginProcess[] = "ppapi";
const char kRendererProcess[] = "renderer";
const char kUtilityProcess[] = "utility";
-const char kCloudPrintServiceProcess[] = "service";
const char kZygoteProcessType[] = "zygote";
const char kRelauncherProcessType[] = "relauncher";
diff --git a/chromium/sandbox/policy/switches.h b/chromium/sandbox/policy/switches.h
index 5a4cb0afe91..d07e692c1b4 100644
--- a/chromium/sandbox/policy/switches.h
+++ b/chromium/sandbox/policy/switches.h
@@ -36,20 +36,21 @@ SANDBOX_POLICY_EXPORT extern const char kPrintBackendSandbox[];
SANDBOX_POLICY_EXPORT extern const char kPrintCompositorSandbox[];
SANDBOX_POLICY_EXPORT extern const char kAudioSandbox[];
SANDBOX_POLICY_EXPORT extern const char kServiceSandbox[];
+SANDBOX_POLICY_EXPORT extern const char kServiceSandboxWithJit[];
SANDBOX_POLICY_EXPORT extern const char kSpeechRecognitionSandbox[];
SANDBOX_POLICY_EXPORT extern const char kVideoCaptureSandbox[];
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
SANDBOX_POLICY_EXPORT extern const char kPdfConversionSandbox[];
SANDBOX_POLICY_EXPORT extern const char kXrCompositingSandbox[];
SANDBOX_POLICY_EXPORT extern const char kIconReaderSandbox[];
SANDBOX_POLICY_EXPORT extern const char kMediaFoundationCdmSandbox[];
SANDBOX_POLICY_EXPORT extern const char kWindowsSystemProxyResolverSandbox[];
-#endif // OS_WIN
+#endif // BUILDFLAG(IS_WIN)
-#if defined(OS_MAC)
+#if BUILDFLAG(IS_MAC)
SANDBOX_POLICY_EXPORT extern const char kMirroringSandbox[];
-#endif // OS_MAC
+#endif // BUILDFLAG(IS_MAC)
#if BUILDFLAG(IS_CHROMEOS_ASH)
SANDBOX_POLICY_EXPORT extern const char kHardwareVideoDecodingSandbox[];
@@ -70,15 +71,15 @@ SANDBOX_POLICY_EXPORT extern const char kDisableSetuidSandbox[];
SANDBOX_POLICY_EXPORT extern const char kGpuSandboxAllowSysVShm[];
SANDBOX_POLICY_EXPORT extern const char kGpuSandboxFailuresFatal[];
SANDBOX_POLICY_EXPORT extern const char kNoSandbox[];
-#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
SANDBOX_POLICY_EXPORT extern const char kNoZygoteSandbox[];
#endif
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
SANDBOX_POLICY_EXPORT extern const char kAllowThirdPartyModules[];
SANDBOX_POLICY_EXPORT extern const char kAddGpuAppContainerCaps[];
SANDBOX_POLICY_EXPORT extern const char kAddXrAppContainerCaps[];
#endif
-#if defined(OS_MAC)
+#if BUILDFLAG(IS_MAC)
SANDBOX_POLICY_EXPORT extern const char kEnableSandboxLogging[];
SANDBOX_POLICY_EXPORT extern const char kDisableMetalShaderCache[];
#endif
@@ -91,7 +92,6 @@ SANDBOX_POLICY_EXPORT extern const char kNaClLoaderProcess[];
SANDBOX_POLICY_EXPORT extern const char kPpapiPluginProcess[];
SANDBOX_POLICY_EXPORT extern const char kRendererProcess[];
SANDBOX_POLICY_EXPORT extern const char kUtilityProcess[];
-SANDBOX_POLICY_EXPORT extern const char kCloudPrintServiceProcess[];
SANDBOX_POLICY_EXPORT extern const char kZygoteProcessType[];
SANDBOX_POLICY_EXPORT extern const char kRelauncherProcessType[];
diff --git a/chromium/sandbox/policy/win/sandbox_policy_feature_test.cc b/chromium/sandbox/policy/win/sandbox_policy_feature_test.cc
index ee0e463aa2b..5cf590966dc 100644
--- a/chromium/sandbox/policy/win/sandbox_policy_feature_test.cc
+++ b/chromium/sandbox/policy/win/sandbox_policy_feature_test.cc
@@ -11,12 +11,12 @@ SandboxFeatureTest::SandboxFeatureTest() {
std::vector<base::Feature> enabled_features;
std::vector<base::Feature> disabled_features;
- if (::testing::get<0>(GetParam()))
+ if (::testing::get<TestParameter::kEnableRendererAppContainer>(GetParam()))
enabled_features.push_back(features::kRendererAppContainer);
else
disabled_features.push_back(features::kRendererAppContainer);
- if (::testing::get<1>(GetParam()))
+ if (::testing::get<TestParameter::kEnableKtmMitigation>(GetParam()))
enabled_features.push_back(features::kWinSboxDisableKtmComponent);
else
disabled_features.push_back(features::kWinSboxDisableKtmComponent);
@@ -24,8 +24,16 @@ SandboxFeatureTest::SandboxFeatureTest() {
feature_list_.InitWithFeatures(enabled_features, disabled_features);
}
-AppContainerType SandboxFeatureTest::GetExpectedAppContainerType() {
- return AppContainerType::kNone;
+IntegrityLevel SandboxFeatureTest::GetExpectedIntegrityLevel() {
+ return IntegrityLevel::INTEGRITY_LEVEL_LOW;
+}
+
+TokenLevel SandboxFeatureTest::GetExpectedLockdownTokenLevel() {
+ return TokenLevel::USER_LOCKDOWN;
+}
+
+TokenLevel SandboxFeatureTest::GetExpectedInitialTokenLevel() {
+ return TokenLevel::USER_RESTRICTED_SAME_ACCESS;
}
MitigationFlags SandboxFeatureTest::GetExpectedMitigationFlags() {
@@ -47,7 +55,7 @@ MitigationFlags SandboxFeatureTest::GetExpectedMitigationFlags() {
flags = flags | ::sandbox::MITIGATION_WIN32K_DISABLE;
#endif
- if (::testing::get<1>(GetParam()))
+ if (::testing::get<TestParameter::kEnableKtmMitigation>(GetParam()))
flags = flags | ::sandbox::MITIGATION_KTM_COMPONENT;
return flags;
@@ -58,5 +66,39 @@ MitigationFlags SandboxFeatureTest::GetExpectedDelayedMitigationFlags() {
::sandbox::MITIGATION_FORCE_MS_SIGNED_BINS;
}
+AppContainerType SandboxFeatureTest::GetExpectedAppContainerType() {
+ return AppContainerType::kNone;
+}
+
+std::vector<base::win::Sid> SandboxFeatureTest::GetExpectedCapabilities() {
+ return {};
+}
+
+void SandboxFeatureTest::ValidateSecurityLevels(
+ const scoped_refptr<TargetPolicy>& policy) {
+ EXPECT_EQ(policy->GetIntegrityLevel(), GetExpectedIntegrityLevel());
+ EXPECT_EQ(policy->GetLockdownTokenLevel(), GetExpectedLockdownTokenLevel());
+ EXPECT_EQ(policy->GetInitialTokenLevel(), GetExpectedInitialTokenLevel());
+}
+
+void SandboxFeatureTest::ValidatePolicyFlagSettings(
+ const scoped_refptr<TargetPolicy>& policy) {
+ EXPECT_EQ(policy->GetProcessMitigations(), GetExpectedMitigationFlags());
+ EXPECT_EQ(policy->GetDelayedProcessMitigations(),
+ GetExpectedDelayedMitigationFlags());
+}
+
+void SandboxFeatureTest::ValidateAppContainerSettings(
+ const scoped_refptr<TargetPolicy>& policy) {
+ if (GetExpectedAppContainerType() == ::sandbox::AppContainerType::kLowbox) {
+ EXPECT_EQ(GetExpectedAppContainerType(),
+ policy->GetAppContainer()->GetAppContainerType());
+
+ EqualSidList(policy->GetAppContainer()->GetCapabilities(),
+ GetExpectedCapabilities());
+ } else {
+ EXPECT_EQ(policy->GetAppContainer().get(), nullptr);
+ }
+}
} // namespace policy
} // namespace sandbox \ No newline at end of file
diff --git a/chromium/sandbox/policy/win/sandbox_policy_feature_test.h b/chromium/sandbox/policy/win/sandbox_policy_feature_test.h
index ca29735fdbf..8629153ba00 100644
--- a/chromium/sandbox/policy/win/sandbox_policy_feature_test.h
+++ b/chromium/sandbox/policy/win/sandbox_policy_feature_test.h
@@ -12,7 +12,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
#include "base/win/windows_version.h"
#include "sandbox/policy/win/sandbox_test_utils.h"
#include "sandbox/policy/win/sandbox_win.h"
@@ -31,15 +31,25 @@ class SandboxFeatureTest
::testing::tuple</* renderer app container feature */ bool,
/* ktm mitigation feature */ bool>> {
public:
+ enum TestParameter { kEnableRendererAppContainer, kEnableKtmMitigation };
+
SandboxFeatureTest();
- // App Containers are only available in Windows 8 and up
- virtual AppContainerType GetExpectedAppContainerType();
+ virtual IntegrityLevel GetExpectedIntegrityLevel();
+ virtual TokenLevel GetExpectedLockdownTokenLevel();
+ virtual TokenLevel GetExpectedInitialTokenLevel();
virtual MitigationFlags GetExpectedMitigationFlags();
-
virtual MitigationFlags GetExpectedDelayedMitigationFlags();
+ // App Containers are only available in Windows 8 and up
+ virtual AppContainerType GetExpectedAppContainerType();
+ virtual std::vector<base::win::Sid> GetExpectedCapabilities();
+
+ void ValidateSecurityLevels(const scoped_refptr<TargetPolicy>& policy);
+ void ValidatePolicyFlagSettings(const scoped_refptr<TargetPolicy>& policy);
+ void ValidateAppContainerSettings(const scoped_refptr<TargetPolicy>& policy);
+
base::test::ScopedFeatureList feature_list_;
};
} // namespace policy
diff --git a/chromium/sandbox/policy/win/sandbox_win.cc b/chromium/sandbox/policy/win/sandbox_win.cc
index 497d535f278..197e66eeb5b 100644
--- a/chromium/sandbox/policy/win/sandbox_win.cc
+++ b/chromium/sandbox/policy/win/sandbox_win.cc
@@ -25,6 +25,7 @@
#include "base/no_destructor.h"
#include "base/path_service.h"
#include "base/process/launch.h"
+#include "base/process/process.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
@@ -463,7 +464,7 @@ typedef BOOL(WINAPI* DuplicateHandleFunctionPtr)(HANDLE source_process_handle,
DuplicateHandleFunctionPtr g_iat_orig_duplicate_handle;
-NtQueryObject g_QueryObject = NULL;
+NtQueryObjectFunction g_QueryObject = NULL;
static const char* kDuplicateHandleWarning =
"You are attempting to duplicate a privileged handle into a sandboxed"
@@ -805,6 +806,8 @@ ResultCode LaunchWithoutSandbox(
}
*process = base::LaunchProcess(cmd_line, options);
+ if (!process->IsValid())
+ return SBOX_ERROR_CANNOT_LAUNCH_UNSANDBOXED_PROCESS;
return SBOX_ALL_OK;
}
@@ -1263,6 +1266,8 @@ std::string SandboxWin::GetSandboxTypeInEnglish(Sandbox sandbox_type) {
return "Media Foundation CDM";
case Sandbox::kService:
return "Service";
+ case Sandbox::kServiceWithJit:
+ return "Service With Jit";
case Sandbox::kIconReader:
return "Icon Reader";
case Sandbox::kWindowsSystemProxyResolver:
diff --git a/chromium/sandbox/win/BUILD.gn b/chromium/sandbox/win/BUILD.gn
index f33d9e8dde7..1eecd589044 100644
--- a/chromium/sandbox/win/BUILD.gn
+++ b/chromium/sandbox/win/BUILD.gn
@@ -146,15 +146,6 @@ static_library("sandbox") {
sources += [
"src/resolver_32.cc",
"src/service_resolver_32.cc",
- "src/sidestep/ia32_modrm_map.cpp",
- "src/sidestep/ia32_opcode_map.cpp",
- "src/sidestep/mini_disassembler.cpp",
- "src/sidestep/mini_disassembler.h",
- "src/sidestep/mini_disassembler_types.h",
- "src/sidestep/preamble_patcher.h",
- "src/sidestep/preamble_patcher_with_stub.cpp",
- "src/sidestep_resolver.cc",
- "src/sidestep_resolver.h",
]
}
@@ -193,7 +184,6 @@ test("sbox_integration_tests") {
"src/policy_target_test.cc",
"src/process_mitigations_dyncode_unittest.cc",
"src/process_mitigations_extensionpoints_unittest.cc",
- "src/process_mitigations_imageload_unittest.cc",
"src/process_mitigations_unittest.cc",
"src/process_mitigations_win32k_unittest.cc",
"src/process_policy_test.cc",
@@ -216,8 +206,6 @@ test("sbox_integration_tests") {
]
data_deps = [
- ":sbox_integration_test_hijack_dll",
- ":sbox_integration_test_hijack_shim_dll",
":sbox_integration_test_hooking_dll",
":sbox_integration_test_win_proc",
]
@@ -228,15 +216,6 @@ test("sbox_integration_tests") {
]
}
-shared_library("sbox_integration_test_hijack_dll") {
- sources = [
- "tests/integration_tests/hijack_dll.cc",
- "tests/integration_tests/hijack_dll.def",
- ]
-
- deps = [ ":maybe_set_appcontainer_acls" ]
-}
-
group("maybe_set_appcontainer_acls") {
# NACL on 32-bit builds this target twice, once for 64-bit and once for 32-bit
# so avoid this dep from running twice with the same output in that case.
@@ -260,20 +239,6 @@ if (current_cpu == target_cpu && host_os == "win") {
}
}
-shared_library("sbox_integration_test_hijack_shim_dll") {
- sources = [
- "tests/integration_tests/hijack_shim_dll.cc",
- "tests/integration_tests/hijack_shim_dll.def",
- ]
-
- # Implicitly linking hijack_dll as loader import resolution required.
- deps = [
- ":common",
- ":sbox_integration_test_hijack_dll",
- "//base",
- ]
-}
-
shared_library("sbox_integration_test_hooking_dll") {
sources = [ "tests/integration_tests/hooking_dll.cc" ]
@@ -353,7 +318,6 @@ source_set("common") {
"src/sandbox_types.h",
"src/security_level.h",
"tests/common/controller.h",
- "tests/integration_tests/hijack_shim_dll.h",
]
deps = [ "//base" ]
diff --git a/chromium/sandbox/win/src/app_container.h b/chromium/sandbox/win/src/app_container.h
index fc3f17fd618..1552a59e7f6 100644
--- a/chromium/sandbox/win/src/app_container.h
+++ b/chromium/sandbox/win/src/app_container.h
@@ -10,6 +10,7 @@
#include "base/win/sid.h"
#include "base/win/windows_types.h"
#include "sandbox/win/src/acl.h"
+#include "sandbox/win/src/security_capabilities.h"
namespace sandbox {
@@ -70,6 +71,16 @@ class AppContainer {
virtual bool GetEnableLowPrivilegeAppContainer() = 0;
virtual AppContainerType GetAppContainerType() = 0;
+
+ // Get a vector of capabilities.
+ virtual const std::vector<base::win::Sid>& GetCapabilities() = 0;
+
+ // Get a vector of impersonation only capabilities. Used if the process needs
+ // a more privileged token to start.
+ virtual const std::vector<base::win::Sid>& GetImpersonationCapabilities() = 0;
+
+ // Get an allocated SecurityCapabilities object for this App Container.
+ virtual std::unique_ptr<SecurityCapabilities> GetSecurityCapabilities() = 0;
};
} // namespace sandbox
diff --git a/chromium/sandbox/win/src/app_container_base.h b/chromium/sandbox/win/src/app_container_base.h
index 1215cf90f93..fabfe815059 100644
--- a/chromium/sandbox/win/src/app_container_base.h
+++ b/chromium/sandbox/win/src/app_container_base.h
@@ -15,7 +15,6 @@
#include "base/win/windows_types.h"
#include "sandbox/win/src/app_container.h"
#include "sandbox/win/src/sandbox_types.h"
-#include "sandbox/win/src/security_capabilities.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace sandbox {
@@ -47,20 +46,13 @@ class AppContainerBase final : public AppContainer {
void SetEnableLowPrivilegeAppContainer(bool enable) override;
bool GetEnableLowPrivilegeAppContainer() override;
AppContainerType GetAppContainerType() override;
+ const std::vector<base::win::Sid>& GetCapabilities() override;
+ const std::vector<base::win::Sid>& GetImpersonationCapabilities() override;
+ std::unique_ptr<SecurityCapabilities> GetSecurityCapabilities() override;
// Get the package SID for this AC.
const base::win::Sid& GetPackageSid() const;
- // Get an allocated SecurityCapabilities object for this App Container.
- std::unique_ptr<SecurityCapabilities> GetSecurityCapabilities();
-
- // Get a vector of capabilities.
- const std::vector<base::win::Sid>& GetCapabilities();
-
- // Get a vector of impersonation only capabilities. Used if the process needs
- // a more privileged token to start.
- const std::vector<base::win::Sid>& GetImpersonationCapabilities();
-
// Creates a new AppContainer object. This will create a new profile
// if it doesn't already exist. The profile must be deleted manually using
// the Delete method if it's no longer required.
diff --git a/chromium/sandbox/win/src/app_container_test.cc b/chromium/sandbox/win/src/app_container_test.cc
index d942eab35d6..73bb402eca2 100644
--- a/chromium/sandbox/win/src/app_container_test.cc
+++ b/chromium/sandbox/win/src/app_container_test.cc
@@ -491,7 +491,8 @@ TEST_F(AppContainerTest, DenyOpenEventForLowBox) {
::CreateEvent(nullptr, false, false, event_name.c_str()));
ASSERT_TRUE(event.IsValid());
- EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"AppContainerEvent_Open test"));
+ TestRunner runner2(JOB_UNPROTECTED, USER_UNPROTECTED, USER_UNPROTECTED);
+ EXPECT_EQ(SBOX_TEST_DENIED, runner2.RunTest(L"AppContainerEvent_Open test"));
}
TEST_F(AppContainerTest, CheckIncompatibleOptions) {
@@ -631,10 +632,10 @@ TEST_F(AppContainerTest, NoCapabilitiesLPAC) {
}
SBOX_TESTS_COMMAND int LoadDLL(int argc, wchar_t** argv) {
- // DLL here doesn't matter as long as it's in the output directory: re-use one
- // from another sbox test.
- base::ScopedNativeLibrary test_dll(base::FilePath(
- FILE_PATH_LITERAL("sbox_integration_test_hijack_dll.dll")));
+ // Library here doesn't matter as long as it's in the output directory: re-use
+ // one from another sbox test.
+ base::ScopedNativeLibrary test_dll(
+ base::FilePath(FILE_PATH_LITERAL("sbox_integration_test_win_proc.exe")));
if (test_dll.is_valid())
return SBOX_TEST_SUCCEEDED;
return SBOX_TEST_FAILED;
diff --git a/chromium/sandbox/win/src/broker_services.cc b/chromium/sandbox/win/src/broker_services.cc
index 99d04dfe938..6bce0cc3c35 100644
--- a/chromium/sandbox/win/src/broker_services.cc
+++ b/chromium/sandbox/win/src/broker_services.cc
@@ -520,8 +520,7 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
for (HANDLE handle : policy_handle_list)
startup_info->AddInheritedHandle(handle);
- scoped_refptr<AppContainerBase> container =
- policy_base->GetAppContainerBase();
+ scoped_refptr<AppContainer> container = policy_base->GetAppContainer();
if (container)
startup_info->SetAppContainer(container);
@@ -577,7 +576,7 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
// Now the policy is the owner of the target. TargetProcess will terminate
// the process if it has not completed when it is destroyed.
- result = policy_base->AddTarget(std::move(target));
+ result = policy_base->ApplyToTarget(std::move(target));
if (result != SBOX_ALL_OK) {
*last_error = ::GetLastError();
diff --git a/chromium/sandbox/win/src/broker_services.h b/chromium/sandbox/win/src/broker_services.h
index e63b0cb0eb4..a848198093e 100644
--- a/chromium/sandbox/win/src/broker_services.h
+++ b/chromium/sandbox/win/src/broker_services.h
@@ -5,7 +5,6 @@
#ifndef SANDBOX_WIN_SRC_BROKER_SERVICES_H_
#define SANDBOX_WIN_SRC_BROKER_SERVICES_H_
-#include <list>
#include <map>
#include <memory>
#include <set>
diff --git a/chromium/sandbox/win/src/file_policy_test.cc b/chromium/sandbox/win/src/file_policy_test.cc
index b061c049c89..dd02b5cf0ee 100644
--- a/chromium/sandbox/win/src/file_policy_test.cc
+++ b/chromium/sandbox/win/src/file_policy_test.cc
@@ -48,8 +48,9 @@ SBOX_TESTS_COMMAND int File_Create(int argc, wchar_t** argv) {
return file1.IsValid() ? SBOX_TEST_FIRST_ERROR : SBOX_TEST_SECOND_ERROR;
} else if (operation == L"Write") {
- base::win::ScopedHandle file1(CreateFile(
- argv[1], GENERIC_ALL, kSharing, nullptr, OPEN_EXISTING, 0, nullptr));
+ base::win::ScopedHandle file1(
+ CreateFile(argv[1], GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,
+ kSharing, nullptr, OPEN_EXISTING, 0, nullptr));
base::win::ScopedHandle file2(
CreateFile(argv[1], GENERIC_READ | FILE_WRITE_DATA, kSharing, nullptr,
OPEN_EXISTING, 0, nullptr));
@@ -273,54 +274,63 @@ SBOX_TESTS_COMMAND int File_CopyFile(int argc, wchar_t** argv) {
TEST(FilePolicyTest, DenyNtCreateCalc) {
TestRunner runner;
- EXPECT_TRUE(
- runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY, L"calc.exe"));
-
+ EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"calc.txt"));
EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_CreateSys32 calc.exe"));
- runner.SetTestState(BEFORE_REVERT);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_CreateSys32 calc.exe"));
+ TestRunner before_revert;
+ EXPECT_TRUE(
+ before_revert.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"calc.txt"));
+ before_revert.SetTestState(BEFORE_REVERT);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED,
+ before_revert.RunTest(L"File_CreateSys32 calc.exe"));
}
TEST(FilePolicyTest, AllowNtCreateCalc) {
TestRunner runner;
EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"calc.exe"));
-
EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_CreateSys32 calc.exe"));
- runner.SetTestState(BEFORE_REVERT);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_CreateSys32 calc.exe"));
+ TestRunner before_revert;
+ EXPECT_TRUE(
+ before_revert.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"calc.exe"));
+ before_revert.SetTestState(BEFORE_REVERT);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED,
+ before_revert.RunTest(L"File_CreateSys32 calc.exe"));
}
TEST(FilePolicyTest, AllowNtCreateWithNativePath) {
std::wstring calc = MakePathToSys(L"calc.exe", false);
std::wstring nt_path;
ASSERT_TRUE(GetNtPathFromWin32Path(calc, &nt_path));
+
TestRunner runner;
runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, nt_path.c_str());
-
wchar_t buff[MAX_PATH];
::wsprintfW(buff, L"File_CreateSys32 %s", nt_path.c_str());
EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(buff));
+ TestRunner runner2;
+ runner2.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, nt_path.c_str());
for (wchar_t& c : nt_path)
c = std::tolower(c);
::wsprintfW(buff, L"File_CreateSys32 %s", nt_path.c_str());
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(buff));
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(buff));
}
-TEST(FilePolicyTest, AllowReadOnly) {
- TestRunner runner;
+std::unique_ptr<TestRunner> AllowReadOnlyRunner(wchar_t* temp_file_name) {
+ auto runner = std::make_unique<TestRunner>();
+ EXPECT_TRUE(
+ runner->AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, temp_file_name));
+ return runner;
+}
+TEST(FilePolicyTest, AllowReadOnly) {
// Create a temp file because we need write access to it.
wchar_t temp_directory[MAX_PATH];
wchar_t temp_file_name[MAX_PATH];
ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name), 0u);
- EXPECT_TRUE(
- runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, temp_file_name));
-
wchar_t command_read[MAX_PATH + 20] = {};
wsprintf(command_read, L"File_Create Read \"%ls\"", temp_file_name);
wchar_t command_read_create[MAX_PATH + 20] = {};
@@ -330,25 +340,27 @@ TEST(FilePolicyTest, AllowReadOnly) {
wsprintf(command_write, L"File_Create Write \"%ls\"", temp_file_name);
// Verify that we cannot create the file after revert.
- EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command_read_create));
+ auto runner = AllowReadOnlyRunner(temp_file_name);
+ EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(command_read_create));
// Verify that we don't have write access after revert.
- EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command_write));
+ runner = AllowReadOnlyRunner(temp_file_name);
+ EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(command_write));
// Verify that we have read access after revert.
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_read));
+ runner = AllowReadOnlyRunner(temp_file_name);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(command_read));
// Verify that we really have write access to the file.
- runner.SetTestState(BEFORE_REVERT);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_write));
+ runner = AllowReadOnlyRunner(temp_file_name);
+ runner->SetTestState(BEFORE_REVERT);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(command_write));
DeleteFile(temp_file_name);
}
// Tests support of "\\\\.\\DeviceName" kind of paths.
TEST(FilePolicyTest, AllowImplicitDeviceName) {
- TestRunner runner;
-
wchar_t temp_directory[MAX_PATH];
wchar_t temp_file_name[MAX_PATH];
ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
@@ -363,9 +375,13 @@ TEST(FilePolicyTest, AllowImplicitDeviceName) {
wsprintf(command, L"File_Create Read \"\\\\.\\%ls\"", path.c_str());
path = std::wstring(kNTPrefix) + path;
+ TestRunner runner;
EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
- EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, path.c_str()));
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command));
+
+ TestRunner runner_with_rule;
+ EXPECT_TRUE(
+ runner_with_rule.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, path.c_str()));
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner_with_rule.RunTest(command));
DeleteFile(temp_file_name);
}
@@ -391,18 +407,28 @@ TEST(FilePolicyTest, AllowWildcard) {
DeleteFile(temp_file_name);
}
-TEST(FilePolicyTest, AllowNtCreatePatternRule) {
- TestRunner runner;
- EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"App*.dll"));
+std::unique_ptr<TestRunner> AllowNtCreatePatternRunner() {
+ auto runner = std::make_unique<TestRunner>();
+ EXPECT_TRUE(runner->AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"App*.dll"));
+ return runner;
+}
+TEST(FilePolicyTest, AllowNtCreatePatternRule) {
+ auto runner = AllowNtCreatePatternRunner();
EXPECT_EQ(SBOX_TEST_SUCCEEDED,
- runner.RunTest(L"File_OpenSys32 apphelp.dll"));
- EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_OpenSys32 appwiz.cpl"));
+ runner->RunTest(L"File_OpenSys32 apphelp.dll"));
+
+ runner = AllowNtCreatePatternRunner();
+ EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(L"File_OpenSys32 appwiz.cpl"));
- runner.SetTestState(BEFORE_REVERT);
+ runner = AllowNtCreatePatternRunner();
+ runner->SetTestState(BEFORE_REVERT);
EXPECT_EQ(SBOX_TEST_SUCCEEDED,
- runner.RunTest(L"File_OpenSys32 apphelp.dll"));
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_OpenSys32 appwiz.cpl"));
+ runner->RunTest(L"File_OpenSys32 apphelp.dll"));
+
+ runner = AllowNtCreatePatternRunner();
+ runner->SetTestState(BEFORE_REVERT);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"File_OpenSys32 appwiz.cpl"));
}
TEST(FilePolicyTest, CheckNotFound) {
@@ -418,30 +444,38 @@ TEST(FilePolicyTest, CheckNoLeak) {
EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_CreateSys32 notfound.exe"));
}
-TEST(FilePolicyTest, TestQueryAttributesFile) {
- TestRunner runner;
+std::unique_ptr<TestRunner> QueryAttributesFileRunner() {
+ auto runner = std::make_unique<TestRunner>();
EXPECT_TRUE(
- runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"apphelp.dll"));
+ runner->AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"apphelp.dll"));
EXPECT_TRUE(
- runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"notfound.exe"));
- EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"drivers"));
+ runner->AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"notfound.exe"));
+ EXPECT_TRUE(runner->AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"drivers"));
EXPECT_TRUE(
- runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_QUERY, L"ipconfig.exe"));
+ runner->AddRuleSys32(TargetPolicy::FILES_ALLOW_QUERY, L"ipconfig.exe"));
+ return runner;
+}
+TEST(FilePolicyTest, TestQueryAttributesFile) {
+ auto runner = QueryAttributesFileRunner();
EXPECT_EQ(SBOX_TEST_SUCCEEDED,
- runner.RunTest(L"File_QueryAttributes drivers d"));
+ runner->RunTest(L"File_QueryAttributes drivers d"));
+ runner = QueryAttributesFileRunner();
EXPECT_EQ(SBOX_TEST_SUCCEEDED,
- runner.RunTest(L"File_QueryAttributes apphelp.dll f"));
+ runner->RunTest(L"File_QueryAttributes apphelp.dll f"));
+ runner = QueryAttributesFileRunner();
EXPECT_EQ(SBOX_TEST_SUCCEEDED,
- runner.RunTest(L"File_QueryAttributes ipconfig.exe f"));
+ runner->RunTest(L"File_QueryAttributes ipconfig.exe f"));
+ runner = QueryAttributesFileRunner();
EXPECT_EQ(SBOX_TEST_DENIED,
- runner.RunTest(L"File_QueryAttributes ftp.exe f"));
+ runner->RunTest(L"File_QueryAttributes ftp.exe f"));
+ runner = QueryAttributesFileRunner();
EXPECT_EQ(SBOX_TEST_NOT_FOUND,
- runner.RunTest(L"File_QueryAttributes notfound.exe f"));
+ runner->RunTest(L"File_QueryAttributes notfound.exe f"));
}
// Makes sure that we don't leak information when there is not policy to allow
@@ -451,133 +485,139 @@ TEST(FilePolicyTest, TestQueryAttributesFileNoPolicy) {
EXPECT_EQ(SBOX_TEST_DENIED,
runner.RunTest(L"File_QueryAttributes ftp.exe f"));
+ TestRunner runner2;
EXPECT_EQ(SBOX_TEST_DENIED,
- runner.RunTest(L"File_QueryAttributes notfound.exe f"));
+ runner2.RunTest(L"File_QueryAttributes notfound.exe f"));
+}
+
+// Expects 8 file names. Attempts to copy even to odd files will happen.
+std::unique_ptr<TestRunner> RenameRunner(
+ std::vector<std::wstring>& temp_files) {
+ auto runner = std::make_unique<TestRunner>();
+ // Add rules to make file0->file1 succeed.
+ runner->AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_files[0].c_str());
+ runner->AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_files[1].c_str());
+
+ // Add rules to make file2->file3 fail.
+ runner->AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_files[2].c_str());
+ runner->AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, temp_files[3].c_str());
+
+ // Add rules to make file4->file5 fail.
+ runner->AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, temp_files[4].c_str());
+ runner->AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_files[5].c_str());
+
+ // Add rules to make file6->no_pol_file fail.
+ runner->AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_files[6].c_str());
+ return runner;
}
TEST(FilePolicyTest, TestRename) {
- TestRunner runner;
+ const size_t nFiles = 8;
// Give access to the temp directory.
wchar_t temp_directory[MAX_PATH];
- wchar_t temp_file_name1[MAX_PATH];
- wchar_t temp_file_name2[MAX_PATH];
- wchar_t temp_file_name3[MAX_PATH];
- wchar_t temp_file_name4[MAX_PATH];
- wchar_t temp_file_name5[MAX_PATH];
- wchar_t temp_file_name6[MAX_PATH];
- wchar_t temp_file_name7[MAX_PATH];
- wchar_t temp_file_name8[MAX_PATH];
+ std::vector<std::wstring> temp_files;
ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
- ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name1), 0u);
- ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name2), 0u);
- ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name3), 0u);
- ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name4), 0u);
- ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name5), 0u);
- ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name6), 0u);
- ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name7), 0u);
- ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file_name8), 0u);
-
- // Add rules to make file1->file2 succeed.
- ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name1));
- ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name2));
-
- // Add rules to make file3->file4 fail.
- ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name3));
- ASSERT_TRUE(
- runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, temp_file_name4));
-
- // Add rules to make file5->file6 fail.
- ASSERT_TRUE(
- runner.AddFsRule(TargetPolicy::FILES_ALLOW_READONLY, temp_file_name5));
- ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name6));
-
- // Add rules to make file7->no_pol_file fail.
- ASSERT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_file_name7));
+ for (size_t i = 0; i < nFiles; i++) {
+ wchar_t temp_file[MAX_PATH];
+ ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, temp_file), 0u);
+ temp_files.push_back(std::wstring(temp_file));
+ }
// Delete the files where the files are going to be renamed to.
- ::DeleteFile(temp_file_name2);
- ::DeleteFile(temp_file_name4);
- ::DeleteFile(temp_file_name6);
- ::DeleteFile(temp_file_name8);
+ ::DeleteFile(temp_files[1].c_str());
+ ::DeleteFile(temp_files[3].c_str());
+ ::DeleteFile(temp_files[5].c_str());
+ ::DeleteFile(temp_files[7].c_str());
+ auto runner = RenameRunner(temp_files);
wchar_t command[MAX_PATH * 2 + 20] = {};
- wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name1,
- temp_file_name2);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command));
+ wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_files[0].c_str(),
+ temp_files[1].c_str());
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(command));
- wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name3,
- temp_file_name4);
- EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
+ runner = RenameRunner(temp_files);
+ wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_files[2].c_str(),
+ temp_files[3].c_str());
+ EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(command));
- wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name5,
- temp_file_name6);
- EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
+ runner = RenameRunner(temp_files);
+ wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_files[4].c_str(),
+ temp_files[5].c_str());
+ EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(command));
- wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_file_name7,
- temp_file_name8);
- EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command));
+ runner = RenameRunner(temp_files);
+ wsprintf(command, L"File_Rename \"%ls\" \"%ls\"", temp_files[6].c_str(),
+ temp_files[7].c_str());
+ EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(command));
// Delete all the files in case they are still there.
- ::DeleteFile(temp_file_name1);
- ::DeleteFile(temp_file_name2);
- ::DeleteFile(temp_file_name3);
- ::DeleteFile(temp_file_name4);
- ::DeleteFile(temp_file_name5);
- ::DeleteFile(temp_file_name6);
- ::DeleteFile(temp_file_name7);
- ::DeleteFile(temp_file_name8);
+ for (auto& file : temp_files)
+ ::DeleteFile(file.c_str());
}
-TEST(FilePolicyTest, OpenSys32FilesDenyBecauseOfDir) {
- TestRunner runner;
- EXPECT_TRUE(
- runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY, L"notepad.exe"));
-
- EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_Win32Create notepad.exe"));
-
- runner.SetTestState(BEFORE_REVERT);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED,
- runner.RunTest(L"File_Win32Create notepad.exe"));
+std::unique_ptr<TestRunner> AllowNotepadRunner() {
+ auto runner = std::make_unique<TestRunner>();
+ runner->AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"notepad.exe");
+ return runner;
}
TEST(FilePolicyTest, OpenSys32FilesAllowNotepad) {
- TestRunner runner;
- EXPECT_TRUE(
- runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_ANY, L"notepad.exe"));
-
+ auto runner = AllowNotepadRunner();
EXPECT_EQ(SBOX_TEST_SUCCEEDED,
- runner.RunTest(L"File_Win32Create notepad.exe"));
+ runner->RunTest(L"File_Win32Create notepad.exe"));
- EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_Win32Create calc.exe"));
+ runner = AllowNotepadRunner();
+ EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(L"File_Win32Create calc.exe"));
- runner.SetTestState(BEFORE_REVERT);
+ runner = AllowNotepadRunner();
+ runner->SetTestState(BEFORE_REVERT);
EXPECT_EQ(SBOX_TEST_SUCCEEDED,
- runner.RunTest(L"File_Win32Create notepad.exe"));
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_Win32Create calc.exe"));
+ runner->RunTest(L"File_Win32Create notepad.exe"));
+
+ runner = AllowNotepadRunner();
+ runner->SetTestState(BEFORE_REVERT);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"File_Win32Create calc.exe"));
+}
+
+std::unique_ptr<TestRunner> FileGetDiskSpaceRunner() {
+ auto runner = std::make_unique<TestRunner>();
+ runner->AddRuleSys32(TargetPolicy::FILES_ALLOW_READONLY, L"");
+ return runner;
}
TEST(FilePolicyTest, FileGetDiskSpace) {
- TestRunner runner;
- EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_GetDiskSpace"));
- runner.SetTestState(BEFORE_REVERT);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_GetDiskSpace"));
+ auto runner = std::make_unique<TestRunner>();
+ EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(L"File_GetDiskSpace"));
+
+ runner = std::make_unique<TestRunner>();
+ runner->SetTestState(BEFORE_REVERT);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"File_GetDiskSpace"));
// Add an 'allow' rule in the windows\system32 such that GetDiskFreeSpaceEx
// succeeds (it does an NtOpenFile) but windows\system32\notepad.exe is
// denied since there is no wild card in the rule.
- EXPECT_TRUE(runner.AddRuleSys32(TargetPolicy::FILES_ALLOW_DIR_ANY, L""));
- runner.SetTestState(BEFORE_REVERT);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_GetDiskSpace"));
+ runner = FileGetDiskSpaceRunner();
+ runner->SetTestState(BEFORE_REVERT);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"File_GetDiskSpace"));
+
+ runner = FileGetDiskSpaceRunner();
+ runner->SetTestState(AFTER_REVERT);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"File_GetDiskSpace"));
- runner.SetTestState(AFTER_REVERT);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"File_GetDiskSpace"));
- EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"File_Win32Create notepad.exe"));
+ runner = FileGetDiskSpaceRunner();
+ runner->SetTestState(AFTER_REVERT);
+ EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(L"File_Win32Create notepad.exe"));
}
-TEST(FilePolicyTest, TestReparsePoint) {
- TestRunner runner;
+std::unique_ptr<TestRunner> ReparsePointRunner(
+ std::wstring& temp_dir_wildcard) {
+ auto runner = std::make_unique<TestRunner>();
+ runner->AddFsRule(TargetPolicy::FILES_ALLOW_ANY, temp_dir_wildcard.c_str());
+ return runner;
+}
+TEST(FilePolicyTest, TestReparsePoint) {
// Create a temp file because we need write access to it.
wchar_t temp_directory[MAX_PATH];
wchar_t temp_file_name[MAX_PATH];
@@ -593,7 +633,7 @@ TEST(FilePolicyTest, TestReparsePoint) {
std::wstring temp_file_title = subfolder.substr(subfolder.rfind(L"\\") + 1);
std::wstring temp_file = subfolder + L"\\file_" + temp_file_title;
- HANDLE file = ::CreateFile(temp_file.c_str(), FILE_ALL_ACCESS,
+ HANDLE file = ::CreateFile(temp_file.c_str(), FILE_WRITE_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
CREATE_ALWAYS, 0, nullptr);
ASSERT_TRUE(INVALID_HANDLE_VALUE != file);
@@ -602,7 +642,7 @@ TEST(FilePolicyTest, TestReparsePoint) {
// Create a temporary file in the temp directory.
std::wstring temp_dir = temp_directory;
std::wstring temp_file_in_temp = temp_dir + L"file_" + temp_file_title;
- file = ::CreateFile(temp_file_in_temp.c_str(), FILE_ALL_ACCESS,
+ file = ::CreateFile(temp_file_in_temp.c_str(), FILE_WRITE_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
CREATE_ALWAYS, 0, nullptr);
ASSERT_TRUE(INVALID_HANDLE_VALUE != file);
@@ -610,8 +650,7 @@ TEST(FilePolicyTest, TestReparsePoint) {
// Give write access to the temp directory.
std::wstring temp_dir_wildcard = temp_dir + L"*";
- EXPECT_TRUE(runner.AddFsRule(TargetPolicy::FILES_ALLOW_ANY,
- temp_dir_wildcard.c_str()));
+ auto runner = ReparsePointRunner(temp_dir_wildcard);
// Prepare the command to execute.
std::wstring command_write;
@@ -620,11 +659,11 @@ TEST(FilePolicyTest, TestReparsePoint) {
command_write += L"\"";
// Verify that we have write access to the original file
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_write.c_str()));
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(command_write.c_str()));
// Replace the subfolder by a reparse point to %temp%.
::DeleteFile(temp_file.c_str());
- HANDLE dir = ::CreateFile(subfolder.c_str(), FILE_ALL_ACCESS,
+ HANDLE dir = ::CreateFile(subfolder.c_str(), FILE_WRITE_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
EXPECT_TRUE(INVALID_HANDLE_VALUE != dir);
@@ -636,10 +675,11 @@ TEST(FilePolicyTest, TestReparsePoint) {
EXPECT_TRUE(::CloseHandle(dir));
// Try to open the file again.
- EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command_write.c_str()));
+ runner = ReparsePointRunner(temp_dir_wildcard);
+ EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(command_write.c_str()));
// Remove the reparse point.
- dir = ::CreateFile(subfolder.c_str(), FILE_ALL_ACCESS,
+ dir = ::CreateFile(subfolder.c_str(), FILE_WRITE_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
nullptr);
diff --git a/chromium/sandbox/win/src/filesystem_dispatcher.cc b/chromium/sandbox/win/src/filesystem_dispatcher.cc
index ea1c3314ba2..50dd777bf41 100644
--- a/chromium/sandbox/win/src/filesystem_dispatcher.cc
+++ b/chromium/sandbox/win/src/filesystem_dispatcher.cc
@@ -95,21 +95,8 @@ bool FilesystemDispatcher::NtCreateFile(IPCInfo* ipc,
return true;
}
- const wchar_t* filename = name->c_str();
-
- uint32_t broker = BROKER_TRUE;
- CountedParameterSet<OpenFile> params;
- params[OpenFile::NAME] = ParamPickerMake(filename);
- params[OpenFile::ACCESS] = ParamPickerMake(desired_access);
- params[OpenFile::DISPOSITION] = ParamPickerMake(create_disposition);
- params[OpenFile::OPTIONS] = ParamPickerMake(create_options);
- params[OpenFile::BROKER] = ParamPickerMake(broker);
-
- // To evaluate the policy we need to call back to the policy object. We
- // are just middlemen in the operation since is the FileSystemPolicy which
- // knows what to do.
- EvalResult result =
- policy_base_->EvalPolicy(IpcTag::NTCREATEFILE, params.GetBase());
+ EvalResult result = EvalPolicy(IpcTag::NTCREATEFILE, *name, desired_access,
+ create_disposition == FILE_OPEN);
HANDLE handle;
ULONG_PTR io_information = 0;
NTSTATUS nt_status;
@@ -139,22 +126,8 @@ bool FilesystemDispatcher::NtOpenFile(IPCInfo* ipc,
return true;
}
- const wchar_t* filename = name->c_str();
-
- uint32_t broker = BROKER_TRUE;
- uint32_t create_disposition = FILE_OPEN;
- CountedParameterSet<OpenFile> params;
- params[OpenFile::NAME] = ParamPickerMake(filename);
- params[OpenFile::ACCESS] = ParamPickerMake(desired_access);
- params[OpenFile::DISPOSITION] = ParamPickerMake(create_disposition);
- params[OpenFile::OPTIONS] = ParamPickerMake(open_options);
- params[OpenFile::BROKER] = ParamPickerMake(broker);
-
- // To evaluate the policy we need to call back to the policy object. We
- // are just middlemen in the operation since is the FileSystemPolicy which
- // knows what to do.
EvalResult result =
- policy_base_->EvalPolicy(IpcTag::NTOPENFILE, params.GetBase());
+ EvalPolicy(IpcTag::NTOPENFILE, *name, desired_access, true);
HANDLE handle;
ULONG_PTR io_information = 0;
NTSTATUS nt_status;
@@ -184,17 +157,7 @@ bool FilesystemDispatcher::NtQueryAttributesFile(IPCInfo* ipc,
return true;
}
- uint32_t broker = BROKER_TRUE;
- const wchar_t* filename = name->c_str();
- CountedParameterSet<FileName> params;
- params[FileName::NAME] = ParamPickerMake(filename);
- params[FileName::BROKER] = ParamPickerMake(broker);
-
- // To evaluate the policy we need to call back to the policy object. We
- // are just middlemen in the operation since is the FileSystemPolicy which
- // knows what to do.
- EvalResult result =
- policy_base_->EvalPolicy(IpcTag::NTQUERYATTRIBUTESFILE, params.GetBase());
+ EvalResult result = EvalPolicy(IpcTag::NTQUERYATTRIBUTESFILE, *name);
FILE_BASIC_INFORMATION* information =
reinterpret_cast<FILE_BASIC_INFORMATION*>(info->Buffer());
@@ -224,17 +187,7 @@ bool FilesystemDispatcher::NtQueryFullAttributesFile(IPCInfo* ipc,
return true;
}
- uint32_t broker = BROKER_TRUE;
- const wchar_t* filename = name->c_str();
- CountedParameterSet<FileName> params;
- params[FileName::NAME] = ParamPickerMake(filename);
- params[FileName::BROKER] = ParamPickerMake(broker);
-
- // To evaluate the policy we need to call back to the policy object. We
- // are just middlemen in the operation since is the FileSystemPolicy which
- // knows what to do.
- EvalResult result = policy_base_->EvalPolicy(
- IpcTag::NTQUERYFULLATTRIBUTESFILE, params.GetBase());
+ EvalResult result = EvalPolicy(IpcTag::NTQUERYFULLATTRIBUTESFILE, *name);
FILE_NETWORK_OPEN_INFORMATION* information =
reinterpret_cast<FILE_NETWORK_OPEN_INFORMATION*>(info->Buffer());
@@ -277,17 +230,7 @@ bool FilesystemDispatcher::NtSetInformationFile(IPCInfo* ipc,
return true;
}
- uint32_t broker = BROKER_TRUE;
- const wchar_t* filename = name.c_str();
- CountedParameterSet<FileName> params;
- params[FileName::NAME] = ParamPickerMake(filename);
- params[FileName::BROKER] = ParamPickerMake(broker);
-
- // To evaluate the policy we need to call back to the policy object. We
- // are just middlemen in the operation since is the FileSystemPolicy which
- // knows what to do.
- EvalResult result =
- policy_base_->EvalPolicy(IpcTag::NTSETINFO_RENAME, params.GetBase());
+ EvalResult result = EvalPolicy(IpcTag::NTSETINFO_RENAME, name);
IO_STATUS_BLOCK* io_status =
reinterpret_cast<IO_STATUS_BLOCK*>(status->Buffer());
@@ -304,4 +247,17 @@ bool FilesystemDispatcher::NtSetInformationFile(IPCInfo* ipc,
return true;
}
+EvalResult FilesystemDispatcher::EvalPolicy(IpcTag ipc_tag,
+ const std::wstring& name,
+ uint32_t desired_access,
+ bool open_only) {
+ CountedParameterSet<OpenFile> params;
+ const wchar_t* name_ptr = name.c_str();
+ params[OpenFile::NAME] = ParamPickerMake(name_ptr);
+ params[OpenFile::ACCESS] = ParamPickerMake(desired_access);
+ uint32_t open_only_int = open_only;
+ params[OpenFile::OPENONLY] = ParamPickerMake(open_only_int);
+ return policy_base_->EvalPolicy(ipc_tag, params.GetBase());
+}
+
} // namespace sandbox
diff --git a/chromium/sandbox/win/src/filesystem_dispatcher.h b/chromium/sandbox/win/src/filesystem_dispatcher.h
index 6bc5462a204..5b5b147e266 100644
--- a/chromium/sandbox/win/src/filesystem_dispatcher.h
+++ b/chromium/sandbox/win/src/filesystem_dispatcher.h
@@ -71,6 +71,12 @@ class FilesystemDispatcher : public Dispatcher {
uint32_t length,
uint32_t info_class);
+ // Evaluate the sandbox policy for the file system call.
+ EvalResult EvalPolicy(IpcTag ipc_tag,
+ const std::wstring& name,
+ uint32_t desired_access = 0,
+ bool open_only = true);
+
raw_ptr<PolicyBase> policy_base_;
};
diff --git a/chromium/sandbox/win/src/filesystem_interception.cc b/chromium/sandbox/win/src/filesystem_interception.cc
index 59934ebd59a..4210ba45574 100644
--- a/chromium/sandbox/win/src/filesystem_interception.cc
+++ b/chromium/sandbox/win/src/filesystem_interception.cc
@@ -18,6 +18,36 @@
namespace sandbox {
+namespace {
+// This checks for three conditions on whether to ask the broker.
+// - The path looks like a DOS device path (namely \??\something).
+// - The path looks like a short-name path.
+// - Whether the details match the policy.
+bool ShouldAskBroker(IpcTag ipc_tag,
+ const std::unique_ptr<wchar_t, NtAllocDeleter>& name,
+ size_t name_len,
+ uint32_t desired_access = 0,
+ bool open_only = true) {
+ const wchar_t* name_ptr = name.get();
+ if (name_len >= 4 && name_ptr[0] == L'\\' && name_ptr[1] == L'?' &&
+ name_ptr[2] == L'?' && name_ptr[3] == L'\\') {
+ return true;
+ }
+
+ for (size_t index = 0; index < name_len; ++index) {
+ if (name_ptr[index] == L'~')
+ return true;
+ }
+
+ CountedParameterSet<OpenFile> params;
+ params[OpenFile::NAME] = ParamPickerMake(name_ptr);
+ params[OpenFile::ACCESS] = ParamPickerMake(desired_access);
+ uint32_t open_only_int = open_only;
+ params[OpenFile::OPENONLY] = ParamPickerMake(open_only_int);
+ return QueryBroker(ipc_tag, params.GetBase());
+}
+} // namespace
+
NTSTATUS WINAPI TargetNtCreateFile(NtCreateFileFunction orig_CreateFile,
PHANDLE file,
ACCESS_MASK desired_access,
@@ -52,35 +82,24 @@ NTSTATUS WINAPI TargetNtCreateFile(NtCreateFileFunction orig_CreateFile,
break;
std::unique_ptr<wchar_t, NtAllocDeleter> name;
- uint32_t attributes = 0;
+ size_t name_len;
+ uint32_t attributes;
NTSTATUS ret =
- AllocAndCopyName(object_attributes, &name, &attributes, nullptr);
- if (!NT_SUCCESS(ret) || !name)
+ CopyNameAndAttributes(object_attributes, &name, &name_len, &attributes);
+ if (!NT_SUCCESS(ret) || !name || !name_len)
break;
-
- uint32_t desired_access_uint32 = desired_access;
- uint32_t options_uint32 = options;
- uint32_t disposition_uint32 = disposition;
- uint32_t broker = BROKER_FALSE;
- CountedParameterSet<OpenFile> params;
- const wchar_t* name_ptr = name.get();
- params[OpenFile::NAME] = ParamPickerMake(name_ptr);
- params[OpenFile::ACCESS] = ParamPickerMake(desired_access_uint32);
- params[OpenFile::DISPOSITION] = ParamPickerMake(disposition_uint32);
- params[OpenFile::OPTIONS] = ParamPickerMake(options_uint32);
- params[OpenFile::BROKER] = ParamPickerMake(broker);
-
- if (!QueryBroker(IpcTag::NTCREATEFILE, params.GetBase()))
+ if (!ShouldAskBroker(IpcTag::NTCREATEFILE, name, name_len, desired_access,
+ disposition == FILE_OPEN)) {
break;
+ }
SharedMemIPCClient ipc(memory);
CrossCallReturn answer = {0};
// The following call must match in the parameters with
// FilesystemDispatcher::ProcessNtCreateFile.
- ResultCode code =
- CrossCall(ipc, IpcTag::NTCREATEFILE, name.get(), attributes,
- desired_access_uint32, file_attributes, sharing, disposition,
- options_uint32, &answer);
+ ResultCode code = CrossCall(ipc, IpcTag::NTCREATEFILE, name.get(),
+ attributes, desired_access, file_attributes,
+ sharing, disposition, options, &answer);
if (SBOX_ALL_OK != code)
break;
@@ -129,32 +148,21 @@ NTSTATUS WINAPI TargetNtOpenFile(NtOpenFileFunction orig_OpenFile,
break;
std::unique_ptr<wchar_t, NtAllocDeleter> name;
+ size_t name_len;
uint32_t attributes;
NTSTATUS ret =
- AllocAndCopyName(object_attributes, &name, &attributes, nullptr);
- if (!NT_SUCCESS(ret) || !name)
+ CopyNameAndAttributes(object_attributes, &name, &name_len, &attributes);
+ if (!NT_SUCCESS(ret) || !name || !name_len)
break;
-
- uint32_t desired_access_uint32 = desired_access;
- uint32_t options_uint32 = options;
- uint32_t disposition_uint32 = FILE_OPEN;
- uint32_t broker = BROKER_FALSE;
- const wchar_t* name_ptr = name.get();
- CountedParameterSet<OpenFile> params;
- params[OpenFile::NAME] = ParamPickerMake(name_ptr);
- params[OpenFile::ACCESS] = ParamPickerMake(desired_access_uint32);
- params[OpenFile::DISPOSITION] = ParamPickerMake(disposition_uint32);
- params[OpenFile::OPTIONS] = ParamPickerMake(options_uint32);
- params[OpenFile::BROKER] = ParamPickerMake(broker);
-
- if (!QueryBroker(IpcTag::NTOPENFILE, params.GetBase()))
+ if (!ShouldAskBroker(IpcTag::NTOPENFILE, name, name_len, desired_access,
+ true)) {
break;
+ }
SharedMemIPCClient ipc(memory);
CrossCallReturn answer = {0};
- ResultCode code =
- CrossCall(ipc, IpcTag::NTOPENFILE, name.get(), attributes,
- desired_access_uint32, sharing, options_uint32, &answer);
+ ResultCode code = CrossCall(ipc, IpcTag::NTOPENFILE, name.get(), attributes,
+ desired_access, sharing, options, &answer);
if (SBOX_ALL_OK != code)
break;
@@ -197,24 +205,17 @@ TargetNtQueryAttributesFile(NtQueryAttributesFileFunction orig_QueryAttributes,
break;
std::unique_ptr<wchar_t, NtAllocDeleter> name;
- uint32_t attributes = 0;
+ size_t name_len;
+ uint32_t attributes;
NTSTATUS ret =
- AllocAndCopyName(object_attributes, &name, &attributes, nullptr);
- if (!NT_SUCCESS(ret) || !name)
+ CopyNameAndAttributes(object_attributes, &name, &name_len, &attributes);
+ if (!NT_SUCCESS(ret) || !name || !name_len)
+ break;
+ if (!ShouldAskBroker(IpcTag::NTQUERYATTRIBUTESFILE, name, name_len))
break;
InOutCountedBuffer file_info(file_attributes,
sizeof(FILE_BASIC_INFORMATION));
-
- uint32_t broker = BROKER_FALSE;
- CountedParameterSet<FileName> params;
- const wchar_t* name_ptr = name.get();
- params[FileName::NAME] = ParamPickerMake(name_ptr);
- params[FileName::BROKER] = ParamPickerMake(broker);
-
- if (!QueryBroker(IpcTag::NTQUERYATTRIBUTESFILE, params.GetBase()))
- break;
-
SharedMemIPCClient ipc(memory);
CrossCallReturn answer = {0};
ResultCode code = CrossCall(ipc, IpcTag::NTQUERYATTRIBUTESFILE, name.get(),
@@ -254,24 +255,17 @@ NTSTATUS WINAPI TargetNtQueryFullAttributesFile(
break;
std::unique_ptr<wchar_t, NtAllocDeleter> name;
- uint32_t attributes = 0;
+ size_t name_len;
+ uint32_t attributes;
NTSTATUS ret =
- AllocAndCopyName(object_attributes, &name, &attributes, nullptr);
- if (!NT_SUCCESS(ret) || !name)
+ CopyNameAndAttributes(object_attributes, &name, &name_len, &attributes);
+ if (!NT_SUCCESS(ret) || !name || !name_len)
+ break;
+ if (!ShouldAskBroker(IpcTag::NTQUERYFULLATTRIBUTESFILE, name, name_len))
break;
InOutCountedBuffer file_info(file_attributes,
sizeof(FILE_NETWORK_OPEN_INFORMATION));
-
- uint32_t broker = BROKER_FALSE;
- CountedParameterSet<FileName> params;
- const wchar_t* name_ptr = name.get();
- params[FileName::NAME] = ParamPickerMake(name_ptr);
- params[FileName::BROKER] = ParamPickerMake(broker);
-
- if (!QueryBroker(IpcTag::NTQUERYFULLATTRIBUTESFILE, params.GetBase()))
- break;
-
SharedMemIPCClient ipc(memory);
CrossCallReturn answer = {0};
ResultCode code = CrossCall(ipc, IpcTag::NTQUERYFULLATTRIBUTESFILE,
@@ -334,18 +328,11 @@ TargetNtSetInformationFile(NtSetInformationFileFunction orig_SetInformationFile,
}
std::unique_ptr<wchar_t, NtAllocDeleter> name;
- NTSTATUS ret =
- AllocAndCopyName(&object_attributes, &name, nullptr, nullptr);
- if (!NT_SUCCESS(ret) || !name)
+ size_t name_len;
+ NTSTATUS ret = CopyNameAndAttributes(&object_attributes, &name, &name_len);
+ if (!NT_SUCCESS(ret) || !name || !name_len)
break;
-
- uint32_t broker = BROKER_FALSE;
- CountedParameterSet<FileName> params;
- const wchar_t* name_ptr = name.get();
- params[FileName::NAME] = ParamPickerMake(name_ptr);
- params[FileName::BROKER] = ParamPickerMake(broker);
-
- if (!QueryBroker(IpcTag::NTSETINFO_RENAME, params.GetBase()))
+ if (!ShouldAskBroker(IpcTag::NTSETINFO_RENAME, name, name_len))
break;
InOutCountedBuffer io_status_buffer(io_status, sizeof(IO_STATUS_BLOCK));
diff --git a/chromium/sandbox/win/src/filesystem_policy.cc b/chromium/sandbox/win/src/filesystem_policy.cc
index fe995b7be70..0560ad31d62 100644
--- a/chromium/sandbox/win/src/filesystem_policy.cc
+++ b/chromium/sandbox/win/src/filesystem_policy.cc
@@ -15,6 +15,7 @@
#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_nt_util.h"
#include "sandbox/win/src/sandbox_types.h"
#include "sandbox/win/src/sandbox_utils.h"
#include "sandbox/win/src/win_utils.h"
@@ -32,14 +33,11 @@ NTSTATUS NtCreateFileInTarget(HANDLE* target_file_handle,
PVOID ea_buffer,
ULONG ea_length,
HANDLE target_process) {
- NtCreateFileFunction NtCreateFile = nullptr;
- ResolveNTFunctionPtr("NtCreateFile", &NtCreateFile);
-
HANDLE local_handle = INVALID_HANDLE_VALUE;
- NTSTATUS status =
- NtCreateFile(&local_handle, desired_access, obj_attributes,
- io_status_block, nullptr, file_attributes, share_access,
- create_disposition, create_options, ea_buffer, ea_length);
+ NTSTATUS status = sandbox::GetNtExports()->CreateFile(
+ &local_handle, desired_access, obj_attributes, io_status_block, nullptr,
+ file_attributes, share_access, create_disposition, create_options,
+ ea_buffer, ea_length);
if (!NT_SUCCESS(status)) {
return status;
}
@@ -82,6 +80,7 @@ bool FileSystemPolicy::GenerateRules(const wchar_t* name,
return false;
}
+ bool is_pipe = IsPipe(mod_name);
if (!PreProcessName(&mod_name)) {
// The path to be added might contain a reparse point.
NOTREACHED();
@@ -116,11 +115,6 @@ bool FileSystemPolicy::GenerateRules(const wchar_t* name,
PolicyRule rename(result);
switch (semantics) {
- case TargetPolicy::FILES_ALLOW_DIR_ANY: {
- open.AddNumberMatch(IF, OpenFile::OPTIONS, FILE_DIRECTORY_FILE, AND);
- create.AddNumberMatch(IF, OpenFile::OPTIONS, FILE_DIRECTORY_FILE, AND);
- break;
- }
case TargetPolicy::FILES_ALLOW_READONLY: {
// We consider all flags that are not known to be readonly as potentially
// used for write.
@@ -129,9 +123,9 @@ bool FileSystemPolicy::GenerateRules(const wchar_t* name,
GENERIC_READ | GENERIC_EXECUTE | READ_CONTROL;
DWORD restricted_flags = ~allowed_flags;
open.AddNumberMatch(IF_NOT, OpenFile::ACCESS, restricted_flags, AND);
- open.AddNumberMatch(IF, OpenFile::DISPOSITION, FILE_OPEN, EQUAL);
+ open.AddNumberMatch(IF, OpenFile::OPENONLY, true, EQUAL);
create.AddNumberMatch(IF_NOT, OpenFile::ACCESS, restricted_flags, AND);
- create.AddNumberMatch(IF, OpenFile::DISPOSITION, FILE_OPEN, EQUAL);
+ create.AddNumberMatch(IF, OpenFile::OPENONLY, true, EQUAL);
// Read only access don't work for rename.
rule_to_add &= ~kCallNtSetInfoRename;
@@ -165,19 +159,19 @@ bool FileSystemPolicy::GenerateRules(const wchar_t* name,
}
if ((rule_to_add & kCallNtQueryAttributesFile) &&
- (!query.AddStringMatch(IF, FileName::NAME, name, CASE_INSENSITIVE) ||
+ (!query.AddStringMatch(IF, OpenFile::NAME, name, CASE_INSENSITIVE) ||
!policy->AddRule(IpcTag::NTQUERYATTRIBUTESFILE, &query))) {
return false;
}
if ((rule_to_add & kCallNtQueryFullAttributesFile) &&
- (!query_full.AddStringMatch(IF, FileName::NAME, name, CASE_INSENSITIVE) ||
+ (!query_full.AddStringMatch(IF, OpenFile::NAME, name, CASE_INSENSITIVE) ||
!policy->AddRule(IpcTag::NTQUERYFULLATTRIBUTESFILE, &query_full))) {
return false;
}
- if ((rule_to_add & kCallNtSetInfoRename) &&
- (!rename.AddStringMatch(IF, FileName::NAME, name, CASE_INSENSITIVE) ||
+ if ((rule_to_add & kCallNtSetInfoRename) && !is_pipe &&
+ (!rename.AddStringMatch(IF, OpenFile::NAME, name, CASE_INSENSITIVE) ||
!policy->AddRule(IpcTag::NTSETINFO_RENAME, &rename))) {
return false;
}
@@ -185,60 +179,6 @@ bool FileSystemPolicy::GenerateRules(const wchar_t* name,
return true;
}
-// Right now we insert two rules, to be evaluated before any user supplied rule:
-// - go to the broker if the path doesn't look like the paths that we push on
-// the policy (namely \??\something).
-// - go to the broker if it looks like this is a short-name path.
-//
-// It is possible to add a rule to go to the broker in any case; it would look
-// something like:
-// rule = new PolicyRule(ASK_BROKER);
-// rule->AddNumberMatch(IF_NOT, FileName::BROKER, true, AND);
-// policy->AddRule(service, rule);
-bool FileSystemPolicy::SetInitialRules(LowLevelPolicy* policy) {
- PolicyRule format(ASK_BROKER);
- PolicyRule short_name(ASK_BROKER);
-
- bool rv = format.AddNumberMatch(IF_NOT, FileName::BROKER, BROKER_TRUE, AND);
- rv &= format.AddStringMatch(IF_NOT, FileName::NAME, L"\\/?/?\\*",
- CASE_SENSITIVE);
-
- rv &= short_name.AddNumberMatch(IF_NOT, FileName::BROKER, BROKER_TRUE, AND);
- rv &= short_name.AddStringMatch(IF, FileName::NAME, L"*~*", CASE_SENSITIVE);
-
- if (!rv || !policy->AddRule(IpcTag::NTCREATEFILE, &format))
- return false;
-
- if (!policy->AddRule(IpcTag::NTCREATEFILE, &short_name))
- return false;
-
- if (!policy->AddRule(IpcTag::NTOPENFILE, &format))
- return false;
-
- if (!policy->AddRule(IpcTag::NTOPENFILE, &short_name))
- return false;
-
- if (!policy->AddRule(IpcTag::NTQUERYATTRIBUTESFILE, &format))
- return false;
-
- if (!policy->AddRule(IpcTag::NTQUERYATTRIBUTESFILE, &short_name))
- return false;
-
- if (!policy->AddRule(IpcTag::NTQUERYFULLATTRIBUTESFILE, &format))
- return false;
-
- if (!policy->AddRule(IpcTag::NTQUERYFULLATTRIBUTESFILE, &short_name))
- return false;
-
- if (!policy->AddRule(IpcTag::NTSETINFO_RENAME, &format))
- return false;
-
- if (!policy->AddRule(IpcTag::NTSETINFO_RENAME, &short_name))
- return false;
-
- return true;
-}
-
bool FileSystemPolicy::CreateFileAction(EvalResult eval_result,
const ClientInfo& client_info,
const std::wstring& file,
@@ -322,16 +262,13 @@ bool FileSystemPolicy::QueryAttributesFileAction(
return false;
}
- NtQueryAttributesFileFunction NtQueryAttributesFile = nullptr;
- ResolveNTFunctionPtr("NtQueryAttributesFile", &NtQueryAttributesFile);
-
UNICODE_STRING uni_name = {0};
OBJECT_ATTRIBUTES obj_attributes = {0};
SECURITY_QUALITY_OF_SERVICE security_qos = GetAnonymousQOS();
InitObjectAttribs(file, attributes, nullptr, &obj_attributes, &uni_name,
IsPipe(file) ? &security_qos : nullptr);
- *nt_status = NtQueryAttributesFile(&obj_attributes, file_info);
+ *nt_status = GetNtExports()->QueryAttributesFile(&obj_attributes, file_info);
return true;
}
@@ -349,17 +286,14 @@ bool FileSystemPolicy::QueryFullAttributesFileAction(
*nt_status = STATUS_ACCESS_DENIED;
return false;
}
-
- NtQueryFullAttributesFileFunction NtQueryFullAttributesFile = nullptr;
- ResolveNTFunctionPtr("NtQueryFullAttributesFile", &NtQueryFullAttributesFile);
-
UNICODE_STRING uni_name = {0};
OBJECT_ATTRIBUTES obj_attributes = {0};
SECURITY_QUALITY_OF_SERVICE security_qos = GetAnonymousQOS();
InitObjectAttribs(file, attributes, nullptr, &obj_attributes, &uni_name,
IsPipe(file) ? &security_qos : nullptr);
- *nt_status = NtQueryFullAttributesFile(&obj_attributes, file_info);
+ *nt_status =
+ GetNtExports()->QueryFullAttributesFile(&obj_attributes, file_info);
return true;
}
@@ -379,9 +313,6 @@ bool FileSystemPolicy::SetInformationFileAction(EvalResult eval_result,
return false;
}
- NtSetInformationFileFunction NtSetInformationFile = nullptr;
- ResolveNTFunctionPtr("NtSetInformationFile", &NtSetInformationFile);
-
HANDLE local_handle = nullptr;
if (!::DuplicateHandle(client_info.process, target_file_handle,
::GetCurrentProcess(), &local_handle, 0, false,
@@ -394,8 +325,8 @@ bool FileSystemPolicy::SetInformationFileAction(EvalResult eval_result,
FILE_INFORMATION_CLASS file_info_class =
static_cast<FILE_INFORMATION_CLASS>(info_class);
- *nt_status = NtSetInformationFile(local_handle, io_block, file_info, length,
- file_info_class);
+ *nt_status = GetNtExports()->SetInformationFile(
+ local_handle, io_block, file_info, length, file_info_class);
return true;
}
diff --git a/chromium/sandbox/win/src/filesystem_policy.h b/chromium/sandbox/win/src/filesystem_policy.h
index 38d7484e269..e42b245f193 100644
--- a/chromium/sandbox/win/src/filesystem_policy.h
+++ b/chromium/sandbox/win/src/filesystem_policy.h
@@ -16,8 +16,6 @@
namespace sandbox {
-enum IsBroker { BROKER_FALSE, BROKER_TRUE };
-
// This class centralizes most of the knowledge related to file system policy
class FileSystemPolicy {
public:
@@ -30,9 +28,6 @@ class FileSystemPolicy {
TargetPolicy::Semantics semantics,
LowLevelPolicy* policy);
- // Add basic file system rules.
- static bool SetInitialRules(LowLevelPolicy* policy);
-
// Performs the desired policy action on a create request with an
// API that is compatible with the IPC-received parameters.
// 'client_info' : the target process that is making the request.
diff --git a/chromium/sandbox/win/src/handle_closer.cc b/chromium/sandbox/win/src/handle_closer.cc
index 841a81506b3..56e27d20826 100644
--- a/chromium/sandbox/win/src/handle_closer.cc
+++ b/chromium/sandbox/win/src/handle_closer.cc
@@ -11,10 +11,6 @@
#include "base/check_op.h"
#include "base/memory/free_deleter.h"
#include "base/win/windows_version.h"
-#include "sandbox/win/src/interceptors.h"
-#include "sandbox/win/src/internal_types.h"
-#include "sandbox/win/src/nt_internals.h"
-#include "sandbox/win/src/process_thread_interception.h"
#include "sandbox/win/src/win_utils.h"
namespace {
@@ -157,29 +153,4 @@ bool HandleCloser::SetupHandleList(void* buffer, size_t buffer_bytes) {
return output <= end;
}
-bool GetHandleName(HANDLE handle, std::wstring* handle_name) {
- static NtQueryObject QueryObject = nullptr;
- if (!QueryObject)
- ResolveNTFunctionPtr("NtQueryObject", &QueryObject);
-
- ULONG size = MAX_PATH;
- std::unique_ptr<UNICODE_STRING, base::FreeDeleter> name;
- NTSTATUS result;
-
- do {
- name.reset(static_cast<UNICODE_STRING*>(malloc(size)));
- DCHECK(name.get());
- result =
- QueryObject(handle, ObjectNameInformation, name.get(), size, &size);
- } while (result == STATUS_INFO_LENGTH_MISMATCH ||
- result == STATUS_BUFFER_OVERFLOW);
-
- if (NT_SUCCESS(result) && name->Buffer && name->Length)
- handle_name->assign(name->Buffer, name->Length / sizeof(wchar_t));
- else
- handle_name->clear();
-
- return NT_SUCCESS(result);
-}
-
} // namespace sandbox
diff --git a/chromium/sandbox/win/src/handle_closer.h b/chromium/sandbox/win/src/handle_closer.h
index 4bfab944178..ef885dc664e 100644
--- a/chromium/sandbox/win/src/handle_closer.h
+++ b/chromium/sandbox/win/src/handle_closer.h
@@ -72,9 +72,6 @@ class HandleCloser {
HandleMap handles_to_close_;
};
-// Returns the object manager's name associated with a handle
-bool GetHandleName(HANDLE handle, std::wstring* handle_name);
-
} // namespace sandbox
#endif // SANDBOX_WIN_SRC_HANDLE_CLOSER_H_
diff --git a/chromium/sandbox/win/src/handle_closer_agent.cc b/chromium/sandbox/win/src/handle_closer_agent.cc
index 045b17ac397..a0bb6569b31 100644
--- a/chromium/sandbox/win/src/handle_closer_agent.cc
+++ b/chromium/sandbox/win/src/handle_closer_agent.cc
@@ -4,36 +4,13 @@
#include "sandbox/win/src/handle_closer_agent.h"
-#include <limits.h>
#include <stddef.h>
#include "base/check.h"
#include "base/win/static_constants.h"
-#include "sandbox/win/src/nt_internals.h"
+#include "base/win/windows_version.h"
#include "sandbox/win/src/win_utils.h"
-
-namespace {
-
-// Returns type infomation for an NT object. This routine is expected to be
-// called for invalid handles so it catches STATUS_INVALID_HANDLE exceptions
-// that can be generated when handle tracing is enabled.
-NTSTATUS QueryObjectTypeInformation(HANDLE handle, void* buffer, ULONG* size) {
- static NtQueryObject QueryObject = nullptr;
- if (!QueryObject)
- ResolveNTFunctionPtr("NtQueryObject", &QueryObject);
-
- NTSTATUS status = STATUS_UNSUCCESSFUL;
- __try {
- status = QueryObject(handle, ObjectTypeInformation, buffer, *size, size);
- } __except (GetExceptionCode() == STATUS_INVALID_HANDLE
- ? EXCEPTION_EXECUTE_HANDLER
- : EXCEPTION_CONTINUE_SEARCH) {
- status = STATUS_INVALID_HANDLE;
- }
- return status;
-}
-
-} // namespace
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace sandbox {
@@ -165,69 +142,42 @@ void HandleCloserAgent::InitializeHandlesToClose(bool* is_csrss_connected) {
}
bool HandleCloserAgent::CloseHandles() {
- DWORD handle_count = UINT_MAX;
- const int kInvalidHandleThreshold = 100;
- const size_t kHandleOffset = 4; // Handles are always a multiple of 4.
-
- if (!::GetProcessHandleCount(::GetCurrentProcess(), &handle_count))
- return false;
-
// Skip closing these handles when Application Verifier is in use in order to
// avoid invalid-handle exceptions.
if (GetModuleHandleA(base::win::kApplicationVerifierDllName))
return true;
+ // If the accurate handle enumeration fails then fallback to the old brute
+ // force approach. This should only happen on Windows 7.
+ absl::optional<ProcessHandleMap> handle_map = GetCurrentProcessHandles();
+ if (!handle_map) {
+ DCHECK(base::win::GetVersion() < base::win::Version::WIN8);
+ handle_map = GetCurrentProcessHandlesWin7();
+ }
- // Set up buffers for the type info and the name.
- std::vector<BYTE> type_info_buffer(sizeof(OBJECT_TYPE_INFORMATION) +
- 32 * sizeof(wchar_t));
- OBJECT_TYPE_INFORMATION* type_info =
- reinterpret_cast<OBJECT_TYPE_INFORMATION*>(&(type_info_buffer[0]));
- std::wstring handle_name;
- HANDLE handle = nullptr;
- int invalid_count = 0;
-
- // Keep incrementing until we hit the number of handles reported by
- // GetProcessHandleCount(). If we hit a very long sequence of invalid
- // handles we assume that we've run past the end of the table.
- while (handle_count && invalid_count < kInvalidHandleThreshold) {
- reinterpret_cast<size_t&>(handle) += kHandleOffset;
- NTSTATUS rc;
-
- // Get the type name, reusing the buffer.
- ULONG size = static_cast<ULONG>(type_info_buffer.size());
- rc = QueryObjectTypeInformation(handle, type_info, &size);
- while (rc == STATUS_INFO_LENGTH_MISMATCH || rc == STATUS_BUFFER_OVERFLOW) {
- type_info_buffer.resize(size + sizeof(wchar_t));
- type_info =
- reinterpret_cast<OBJECT_TYPE_INFORMATION*>(&(type_info_buffer[0]));
- rc = QueryObjectTypeInformation(handle, type_info, &size);
- // Leave padding for the nul terminator.
- if (NT_SUCCESS(rc) && size == type_info_buffer.size())
- rc = STATUS_INFO_LENGTH_MISMATCH;
- }
- if (!NT_SUCCESS(rc) || !type_info->Name.Buffer) {
- ++invalid_count;
- continue;
- }
-
- --handle_count;
- type_info->Name.Buffer[type_info->Name.Length / sizeof(wchar_t)] = L'\0';
+ if (!handle_map)
+ return false;
- // Check if we're looking for this type of handle.
- HandleMap::iterator result = handles_to_close_.find(type_info->Name.Buffer);
- if (result != handles_to_close_.end()) {
- HandleMap::mapped_type& names = result->second;
+ for (const HandleMap::value_type& handle_to_close : handles_to_close_) {
+ ProcessHandleMap::iterator result = handle_map->find(handle_to_close.first);
+ if (result == handle_map->end())
+ continue;
+ const HandleMap::mapped_type& names = handle_to_close.second;
+ for (HANDLE handle : result->second) {
// Empty set means close all handles of this type; otherwise check name.
if (!names.empty()) {
+ std::wstring handle_name;
// Move on to the next handle if this name doesn't match.
- if (!GetHandleName(handle, &handle_name) || !names.count(handle_name))
+ if (!GetPathFromHandle(handle, &handle_name) ||
+ !names.count(handle_name)) {
continue;
+ }
}
+ // If we can't unprotect or close the handle we should keep going.
if (!::SetHandleInformation(handle, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0))
- return false;
+ continue;
if (!::CloseHandle(handle))
- return false;
+ continue;
// Attempt to stuff this handle with a new dummy Event.
AttemptToStuffHandleSlot(handle, result->first);
}
diff --git a/chromium/sandbox/win/src/handle_closer_test.cc b/chromium/sandbox/win/src/handle_closer_test.cc
index 7406f77592a..abfb21ca88f 100644
--- a/chromium/sandbox/win/src/handle_closer_test.cc
+++ b/chromium/sandbox/win/src/handle_closer_test.cc
@@ -5,6 +5,7 @@
#include <limits.h>
#include <stddef.h>
+#include "base/strings/string_util_win.h"
#include "base/strings/stringprintf.h"
#include "base/win/scoped_handle.h"
#include "sandbox/win/src/handle_closer_agent.h"
@@ -12,6 +13,7 @@
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_factory.h"
#include "sandbox/win/src/target_services.h"
+#include "sandbox/win/src/win_utils.h"
#include "sandbox/win/tests/common/controller.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -45,25 +47,6 @@ HANDLE GetMarkerFile(const wchar_t* extension) {
nullptr, OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, nullptr);
}
-// Returns type infomation for an NT object. This routine is expected to be
-// called for invalid handles so it catches STATUS_INVALID_HANDLE exceptions
-// that can be generated when handle tracing is enabled.
-NTSTATUS QueryObjectTypeInformation(HANDLE handle, void* buffer, ULONG* size) {
- static NtQueryObject QueryObject = nullptr;
- if (!QueryObject)
- ResolveNTFunctionPtr("NtQueryObject", &QueryObject);
-
- NTSTATUS status = STATUS_UNSUCCESSFUL;
- __try {
- status = QueryObject(handle, ObjectTypeInformation, buffer, *size, size);
- } __except (GetExceptionCode() == STATUS_INVALID_HANDLE
- ? EXCEPTION_EXECUTE_HANDLER
- : EXCEPTION_CONTINUE_SEARCH) {
- status = STATUS_INVALID_HANDLE;
- }
- return status;
-}
-
// Used by the thread pool tests.
HANDLE finish_event;
const int kWaitCount = 20;
@@ -105,7 +88,7 @@ SBOX_TESTS_COMMAND int CheckForFileHandles(int argc, wchar_t** argv) {
while (handle_count && invalid_count < kInvalidHandleThreshold) {
reinterpret_cast<size_t&>(handle) += kHandleOffset;
- if (GetHandleName(handle, &handle_name)) {
+ if (GetPathFromHandle(handle, &handle_name)) {
for (int i = 1; i < argc; ++i) {
if (handle_name == argv[i])
return should_find ? SBOX_TEST_SUCCEEDED : SBOX_TEST_FAILED;
@@ -144,36 +127,9 @@ SBOX_TESTS_COMMAND int CheckForEventHandles(int argc, wchar_t** argv) {
case AFTER_REVERT:
for (HANDLE handle : to_check) {
- // Set up buffers for the type info and the name.
- std::vector<BYTE> type_info_buffer(sizeof(OBJECT_TYPE_INFORMATION) +
- 32 * sizeof(wchar_t));
- OBJECT_TYPE_INFORMATION* type_info =
- reinterpret_cast<OBJECT_TYPE_INFORMATION*>(&(type_info_buffer[0]));
- NTSTATUS rc;
-
- // Get the type name, reusing the buffer.
- ULONG size = static_cast<ULONG>(type_info_buffer.size());
- rc = QueryObjectTypeInformation(handle, type_info, &size);
- while (rc == STATUS_INFO_LENGTH_MISMATCH ||
- rc == STATUS_BUFFER_OVERFLOW) {
- type_info_buffer.resize(size + sizeof(wchar_t));
- type_info = reinterpret_cast<OBJECT_TYPE_INFORMATION*>(
- &(type_info_buffer[0]));
- rc = QueryObjectTypeInformation(handle, type_info, &size);
- // Leave padding for the nul terminator.
- if (NT_SUCCESS(rc) && size == type_info_buffer.size())
- rc = STATUS_INFO_LENGTH_MISMATCH;
- }
-
- CHECK(NT_SUCCESS(rc));
- CHECK(type_info->Name.Buffer);
-
- type_info->Name.Buffer[type_info->Name.Length / sizeof(wchar_t)] =
- L'\0';
-
- // Should be an Event now.
- CHECK_EQ(wcslen(type_info->Name.Buffer), 5U);
- CHECK_EQ(wcscmp(L"Event", type_info->Name.Buffer), 0);
+ std::wstring type_name;
+ CHECK(GetTypeNameFromHandle(handle, &type_name));
+ CHECK(base::EqualsCaseInsensitiveASCII(type_name, L"Event"));
// Should not be able to wait.
CHECK_EQ(WaitForSingleObject(handle, INFINITE), WAIT_FAILED);
@@ -200,7 +156,7 @@ TEST(HandleCloserTest, CheckForMarkerFiles) {
std::wstring handle_name;
base::win::ScopedHandle marker(GetMarkerFile(kExtension));
CHECK(marker.IsValid());
- CHECK(sandbox::GetHandleName(marker.Get(), &handle_name));
+ CHECK(GetPathFromHandle(marker.Get(), &handle_name));
command += (L" ");
command += handle_name;
}
@@ -220,7 +176,7 @@ TEST(HandleCloserTest, CloseMarkerFiles) {
std::wstring handle_name;
base::win::ScopedHandle marker(GetMarkerFile(kExtension));
CHECK(marker.IsValid());
- CHECK(sandbox::GetHandleName(marker.Get(), &handle_name));
+ CHECK(GetPathFromHandle(marker.Get(), &handle_name));
CHECK_EQ(policy->AddKernelObjectToClose(L"File", handle_name.c_str()),
SBOX_ALL_OK);
command += (L" ");
@@ -241,7 +197,7 @@ TEST(HandleCloserTest, CheckStuffedHandle) {
std::wstring handle_name;
base::win::ScopedHandle marker(GetMarkerFile(kExtension));
CHECK(marker.IsValid());
- CHECK(sandbox::GetHandleName(marker.Get(), &handle_name));
+ CHECK(GetPathFromHandle(marker.Get(), &handle_name));
CHECK_EQ(policy->AddKernelObjectToClose(L"File", handle_name.c_str()),
SBOX_ALL_OK);
}
diff --git a/chromium/sandbox/win/src/integrity_level_test.cc b/chromium/sandbox/win/src/integrity_level_test.cc
index 0fa2627e897..b698cc1200f 100644
--- a/chromium/sandbox/win/src/integrity_level_test.cc
+++ b/chromium/sandbox/win/src/integrity_level_test.cc
@@ -42,31 +42,39 @@ SBOX_TESTS_COMMAND int CheckIntegrityLevel(int argc, wchar_t** argv) {
return SBOX_TEST_DENIED;
}
-TEST(IntegrityLevelTest, TestLowILReal) {
- TestRunner runner(JOB_LOCKDOWN, USER_INTERACTIVE, USER_INTERACTIVE);
-
- runner.SetTimeout(INFINITE);
+std::unique_ptr<TestRunner> LowILRealRunner() {
+ auto runner = std::make_unique<TestRunner>(JOB_LOCKDOWN, USER_INTERACTIVE,
+ USER_INTERACTIVE);
+ runner->SetTimeout(INFINITE);
+ runner->GetPolicy()->SetAlternateDesktop(true);
+ runner->GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
+ return runner;
+}
- runner.GetPolicy()->SetAlternateDesktop(true);
- runner.GetPolicy()->SetIntegrityLevel(INTEGRITY_LEVEL_LOW);
+TEST(IntegrityLevelTest, TestLowILReal) {
+ auto runner = LowILRealRunner();
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"CheckIntegrityLevel"));
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckIntegrityLevel"));
+ runner = LowILRealRunner();
+ runner->SetTestState(BEFORE_REVERT);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"CheckIntegrityLevel"));
+}
- runner.SetTestState(BEFORE_REVERT);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckIntegrityLevel"));
+std::unique_ptr<TestRunner> LowILDelayedRunner() {
+ auto runner = std::make_unique<TestRunner>(JOB_LOCKDOWN, USER_INTERACTIVE,
+ USER_INTERACTIVE);
+ runner->SetTimeout(INFINITE);
+ runner->GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_LOW);
+ return runner;
}
TEST(DelayedIntegrityLevelTest, TestLowILDelayed) {
- TestRunner runner(JOB_LOCKDOWN, USER_INTERACTIVE, USER_INTERACTIVE);
-
- runner.SetTimeout(INFINITE);
+ auto runner = LowILDelayedRunner();
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"CheckIntegrityLevel"));
- runner.GetPolicy()->SetDelayedIntegrityLevel(INTEGRITY_LEVEL_LOW);
-
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"CheckIntegrityLevel"));
-
- runner.SetTestState(BEFORE_REVERT);
- EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(L"CheckIntegrityLevel"));
+ runner = LowILDelayedRunner();
+ runner->SetTestState(BEFORE_REVERT);
+ EXPECT_EQ(SBOX_TEST_DENIED, runner->RunTest(L"CheckIntegrityLevel"));
}
TEST(IntegrityLevelTest, TestNoILChange) {
diff --git a/chromium/sandbox/win/src/interception_agent.cc b/chromium/sandbox/win/src/interception_agent.cc
index e095328a710..00d7c283e7a 100644
--- a/chromium/sandbox/win/src/interception_agent.cc
+++ b/chromium/sandbox/win/src/interception_agent.cc
@@ -15,7 +15,6 @@
#include "sandbox/win/src/interception_internal.h"
#include "sandbox/win/src/interceptors.h"
#include "sandbox/win/src/sandbox_nt_util.h"
-#include "sandbox/win/src/sidestep_resolver.h"
namespace {
@@ -29,9 +28,6 @@ bool IsWithinRange(const void* base, size_t range, const void* target) {
namespace sandbox {
-// This is the list of all imported symbols from ntdll.dll.
-SANDBOX_INTERCEPT NtExports g_nt;
-
// The list of intercepted functions back-pointers.
SANDBOX_INTERCEPT OriginalFunctions g_originals;
@@ -68,21 +64,18 @@ bool InterceptionAgent::DllMatch(const UNICODE_STRING* full_path,
const UNICODE_STRING* name,
const DllPatchInfo* dll_info) {
UNICODE_STRING current_name;
- current_name.Length =
- static_cast<USHORT>(g_nt.wcslen(dll_info->dll_name) * sizeof(wchar_t));
+ current_name.Length = static_cast<USHORT>(
+ GetNtExports()->wcslen(dll_info->dll_name) * sizeof(wchar_t));
current_name.MaximumLength = current_name.Length;
current_name.Buffer = const_cast<wchar_t*>(dll_info->dll_name);
BOOLEAN case_insensitive = TRUE;
- if (full_path &&
- !g_nt.RtlCompareUnicodeString(&current_name, full_path, case_insensitive))
- return true;
-
- if (name &&
- !g_nt.RtlCompareUnicodeString(&current_name, name, case_insensitive))
+ if (full_path && !GetNtExports()->RtlCompareUnicodeString(
+ &current_name, full_path, case_insensitive)) {
return true;
-
- return false;
+ }
+ return name && !GetNtExports()->RtlCompareUnicodeString(&current_name, name,
+ case_insensitive);
}
bool InterceptionAgent::OnDllLoad(const UNICODE_STRING* full_path,
@@ -129,9 +122,9 @@ bool InterceptionAgent::OnDllLoad(const UNICODE_STRING* full_path,
ULONG old_protect;
SIZE_T real_size = buffer_bytes;
void* to_protect = dlls_[i];
- VERIFY_SUCCESS(g_nt.ProtectVirtualMemory(NtCurrentProcess, &to_protect,
- &real_size, PAGE_EXECUTE_READ,
- &old_protect));
+ VERIFY_SUCCESS(GetNtExports()->ProtectVirtualMemory(
+ NtCurrentProcess, &to_protect, &real_size, PAGE_EXECUTE_READ,
+ &old_protect));
return true;
}
@@ -168,7 +161,7 @@ bool InterceptionAgent::PatchDll(const DllPatchInfo* dll_info,
return false;
const char* interceptor =
- function->function + g_nt.strlen(function->function) + 1;
+ function->function + GetNtExports()->strlen(function->function) + 1;
if (!IsWithinRange(function, function->record_bytes, interceptor) ||
!IsWithinRange(dll_info, dll_info->record_bytes, interceptor)) {
@@ -202,32 +195,12 @@ bool InterceptionAgent::PatchDll(const DllPatchInfo* dll_info,
// This method is called from within the loader lock
ResolverThunk* InterceptionAgent::GetResolver(InterceptionType type) {
static EatResolverThunk* eat_resolver = nullptr;
- static SidestepResolverThunk* sidestep_resolver = nullptr;
- static SmartSidestepResolverThunk* smart_sidestep_resolver = nullptr;
if (!eat_resolver)
eat_resolver = new (NT_ALLOC) EatResolverThunk;
-
-#if !defined(_WIN64)
- // Sidestep is not supported for x64.
- if (!sidestep_resolver)
- sidestep_resolver = new (NT_ALLOC) SidestepResolverThunk;
-
- if (!smart_sidestep_resolver)
- smart_sidestep_resolver = new (NT_ALLOC) SmartSidestepResolverThunk;
-#endif
-
- switch (type) {
- case INTERCEPTION_EAT:
- return eat_resolver;
- case INTERCEPTION_SIDESTEP:
- return sidestep_resolver;
- case INTERCEPTION_SMART_SIDESTEP:
- return smart_sidestep_resolver;
- default:
- NOTREACHED_NT();
- }
-
+ if (type == INTERCEPTION_EAT)
+ return eat_resolver;
+ NOTREACHED_NT();
return nullptr;
}
diff --git a/chromium/sandbox/win/src/interception_unittest.cc b/chromium/sandbox/win/src/interception_unittest.cc
index f898a2dda2b..1cbde5c5d10 100644
--- a/chromium/sandbox/win/src/interception_unittest.cc
+++ b/chromium/sandbox/win/src/interception_unittest.cc
@@ -146,9 +146,6 @@ TEST(InterceptionManagerTest, BufferLayout1) {
OPEN_KEY_ID);
interceptions.AddToPatchedFunctions(L"kernel32.dll", "CreateFileEx",
INTERCEPTION_EAT, function, OPEN_KEY_ID);
- interceptions.AddToPatchedFunctions(L"kernel32.dll", "SomeFileEx",
- INTERCEPTION_SMART_SIDESTEP, function,
- OPEN_KEY_ID);
interceptions.AddToPatchedFunctions(L"user32.dll", "FindWindow",
INTERCEPTION_EAT, function, OPEN_KEY_ID);
interceptions.AddToPatchedFunctions(L"kernel32.dll", "CreateMutex",
@@ -163,16 +160,11 @@ TEST(InterceptionManagerTest, BufferLayout1) {
interceptions.AddToPatchedFunctions(L"ntdll.dll", "NtClose",
INTERCEPTION_SERVICE_CALL, function,
OPEN_KEY_ID);
- interceptions.AddToPatchedFunctions(L"ntdll.dll", "NtOpenFile",
- INTERCEPTION_SIDESTEP, function,
- OPEN_KEY_ID);
interceptions.AddToPatchedFunctions(L"some.dll", "Superfn", INTERCEPTION_EAT,
function, OPEN_KEY_ID);
interceptions.AddToPatchedFunctions(L"comctl.dll", "SaveAsDlg",
INTERCEPTION_EAT, "a", OPEN_KEY_ID);
interceptions.AddToPatchedFunctions(L"comctl.dll", "SaveAsDlg",
- INTERCEPTION_SIDESTEP, "ab", OPEN_KEY_ID);
- interceptions.AddToPatchedFunctions(L"comctl.dll", "SaveAsDlg",
INTERCEPTION_EAT, "abc", OPEN_KEY_ID);
interceptions.AddToPatchedFunctions(L"a.dll", "p", INTERCEPTION_EAT, function,
OPEN_KEY_ID);
@@ -185,7 +177,7 @@ TEST(InterceptionManagerTest, BufferLayout1) {
function, OPEN_KEY_ID);
// Verify that all interceptions were added
- ASSERT_EQ(18u, interceptions.interceptions_.size());
+ ASSERT_EQ(15u, interceptions.interceptions_.size());
size_t buffer_size = interceptions.GetBufferSize();
std::unique_ptr<BYTE[]> local_buffer(new BYTE[buffer_size]);
@@ -198,20 +190,20 @@ TEST(InterceptionManagerTest, BufferLayout1) {
// another group with the interceptions belonging to dlls that will be "hot"
// patched on the client. The second group lives on local_buffer, and the
// first group remains on the list of interceptions (inside the object
- // "interceptions"). There are 3 local interceptions (of ntdll); the
- // other 15 have to be sent to the child to be performed "hot".
- EXPECT_EQ(3u, interceptions.interceptions_.size());
+ // "interceptions"). There are 2 local interceptions (of ntdll); the
+ // other 13 have to be sent to the child to be performed "hot".
+ EXPECT_EQ(2u, interceptions.interceptions_.size());
int num_dlls, num_functions, num_names;
WalkBuffer(local_buffer.get(), buffer_size, &num_dlls, &num_functions,
&num_names);
- // The 15 interceptions on the buffer (to the child) should be grouped on 6
+ // The 13 interceptions on the buffer (to the child) should be grouped on 6
// dlls. Only four interceptions are using an explicit name for the
// interceptor function.
EXPECT_EQ(6, num_dlls);
- EXPECT_EQ(15, num_functions);
- EXPECT_EQ(4, num_names);
+ EXPECT_EQ(13, num_functions);
+ EXPECT_EQ(3, num_names);
}
TEST(InterceptionManagerTest, BufferLayout2) {
@@ -233,11 +225,8 @@ TEST(InterceptionManagerTest, BufferLayout2) {
interceptions.AddToPatchedFunctions(L"kernel32.dll", "CreateFileEx",
INTERCEPTION_EAT, function, OPEN_FILE_ID);
interceptions.AddToUnloadModules(L"some02.dll");
- interceptions.AddToPatchedFunctions(L"kernel32.dll", "SomeFileEx",
- INTERCEPTION_SMART_SIDESTEP, function,
- OPEN_FILE_ID);
// Verify that all interceptions were added
- ASSERT_EQ(5u, interceptions.interceptions_.size());
+ ASSERT_EQ(4u, interceptions.interceptions_.size());
size_t buffer_size = interceptions.GetBufferSize();
std::unique_ptr<BYTE[]> local_buffer(new BYTE[buffer_size]);
@@ -256,7 +245,7 @@ TEST(InterceptionManagerTest, BufferLayout2) {
&num_names);
EXPECT_EQ(3, num_dlls);
- EXPECT_EQ(4, num_functions);
+ EXPECT_EQ(3, num_functions);
EXPECT_EQ(0, num_names);
}
diff --git a/chromium/sandbox/win/src/interceptors_64.cc b/chromium/sandbox/win/src/interceptors_64.cc
index ba1726bdc47..b355f0d69e1 100644
--- a/chromium/sandbox/win/src/interceptors_64.cc
+++ b/chromium/sandbox/win/src/interceptors_64.cc
@@ -17,7 +17,6 @@
namespace sandbox {
-SANDBOX_INTERCEPT NtExports g_nt;
SANDBOX_INTERCEPT OriginalFunctions g_originals;
NTSTATUS WINAPI TargetNtMapViewOfSection64(HANDLE section,
diff --git a/chromium/sandbox/win/src/ipc_ping_test.cc b/chromium/sandbox/win/src/ipc_ping_test.cc
index 44f6be433d0..39aa63226d1 100644
--- a/chromium/sandbox/win/src/ipc_ping_test.cc
+++ b/chromium/sandbox/win/src/ipc_ping_test.cc
@@ -48,11 +48,14 @@ TEST(IPCTest, IPCPingTestSimple) {
}
TEST(IPCTest, IPCPingTestWithOutput) {
- TestRunner runner;
- runner.SetTimeout(2000);
- runner.SetTestState(EVERY_STATE);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"IPC_Ping 2"));
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"IPC_Ping 2"));
+ TestRunner runner1;
+ runner1.SetTimeout(2000);
+ runner1.SetTestState(EVERY_STATE);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner1.RunTest(L"IPC_Ping 2"));
+ TestRunner runner2;
+ runner2.SetTimeout(2000);
+ runner2.SetTestState(EVERY_STATE);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(L"IPC_Ping 2"));
}
} // namespace sandbox
diff --git a/chromium/sandbox/win/src/job.cc b/chromium/sandbox/win/src/job.cc
index 7ef429d8291..d12a565f735 100644
--- a/chromium/sandbox/win/src/job.cc
+++ b/chromium/sandbox/win/src/job.cc
@@ -39,26 +39,26 @@ DWORD Job::Init(JobLevel security_level,
case JOB_LOCKDOWN: {
jeli.BasicLimitInformation.LimitFlags |=
JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION;
- FALLTHROUGH;
+ [[fallthrough]];
}
case JOB_RESTRICTED: {
jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_WRITECLIPBOARD;
jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_READCLIPBOARD;
jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES;
jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_GLOBALATOMS;
- FALLTHROUGH;
+ [[fallthrough]];
}
case JOB_LIMITED_USER: {
jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_DISPLAYSETTINGS;
jeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
jeli.BasicLimitInformation.ActiveProcessLimit = 1;
- FALLTHROUGH;
+ [[fallthrough]];
}
case JOB_INTERACTIVE: {
jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS;
jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_DESKTOP;
jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_EXITWINDOWS;
- FALLTHROUGH;
+ [[fallthrough]];
}
case JOB_UNPROTECTED: {
if (memory_limit) {
diff --git a/chromium/sandbox/win/src/named_pipe_policy_test.cc b/chromium/sandbox/win/src/named_pipe_policy_test.cc
index db532d618d6..817aa43580b 100644
--- a/chromium/sandbox/win/src/named_pipe_policy_test.cc
+++ b/chromium/sandbox/win/src/named_pipe_policy_test.cc
@@ -3,10 +3,10 @@
// found in the LICENSE file.
#include "base/win/windows_version.h"
-#include "sandbox/win/src/handle_closer.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_factory.h"
#include "sandbox/win/src/sandbox_policy.h"
+#include "sandbox/win/src/win_utils.h"
#include "sandbox/win/tests/common/controller.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -26,7 +26,7 @@ SBOX_TESTS_COMMAND int NamedPipe_Create(int argc, wchar_t** argv) {
// pipe should be in the object namespace after creation.
if (argc == 2) {
std::wstring handle_name;
- if (GetHandleName(pipe, &handle_name)) {
+ if (GetPathFromHandle(pipe, &handle_name)) {
if (handle_name.compare(0, wcslen(argv[1]), argv[1]) != 0)
return SBOX_TEST_FAILED;
} else {
@@ -52,39 +52,52 @@ SBOX_TESTS_COMMAND int NamedPipe_Create(int argc, wchar_t** argv) {
return SBOX_TEST_SUCCEEDED;
}
-// Tests if we can create a pipe in the sandbox.
-TEST(NamedPipePolicyTest, CreatePipe) {
- TestRunner runner;
+std::unique_ptr<TestRunner> CreatePipeRunner() {
+ auto runner = std::make_unique<TestRunner>();
// TODO(nsylvain): This policy is wrong because "*" is a valid char in a
// namedpipe name. Here we apply it like a wildcard. http://b/893603
- EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_NAMED_PIPES,
- TargetPolicy::NAMEDPIPES_ALLOW_ANY,
- L"\\\\.\\pipe\\test*"));
+ runner->AddRule(TargetPolicy::SUBSYS_NAMED_PIPES,
+ TargetPolicy::NAMEDPIPES_ALLOW_ANY, L"\\\\.\\pipe\\test*");
+ return runner;
+}
+// Tests if we can create a pipe in the sandbox.
+TEST(NamedPipePolicyTest, CreatePipe) {
+ auto runner = CreatePipeRunner();
EXPECT_EQ(SBOX_TEST_SUCCEEDED,
- runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\testbleh"));
+ runner->RunTest(L"NamedPipe_Create \\\\.\\pipe\\testbleh"));
+ runner = CreatePipeRunner();
EXPECT_EQ(SBOX_TEST_DENIED,
- runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\bleh"));
+ runner->RunTest(L"NamedPipe_Create \\\\.\\pipe\\bleh"));
}
-// Tests if we can create a pipe with a path traversal in the sandbox.
-TEST(NamedPipePolicyTest, CreatePipeTraversal) {
- TestRunner runner;
+std::unique_ptr<TestRunner> PipeTraversalRunner() {
+ auto runner = std::make_unique<TestRunner>();
// TODO(nsylvain): This policy is wrong because "*" is a valid char in a
// namedpipe name. Here we apply it like a wildcard. http://b/893603
- EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_NAMED_PIPES,
- TargetPolicy::NAMEDPIPES_ALLOW_ANY,
- L"\\\\.\\pipe\\test*"));
+ runner->AddRule(TargetPolicy::SUBSYS_NAMED_PIPES,
+ TargetPolicy::NAMEDPIPES_ALLOW_ANY, L"\\\\.\\pipe\\test*");
+ return runner;
+}
+// Tests if we can create a pipe with a path traversal in the sandbox.
+TEST(NamedPipePolicyTest, CreatePipeTraversal) {
+ auto runner = PipeTraversalRunner();
EXPECT_EQ(SBOX_TEST_DENIED,
- runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test\\..\\bleh"));
+ runner->RunTest(L"NamedPipe_Create \\\\.\\pipe\\test\\..\\bleh"));
+
+ runner = PipeTraversalRunner();
EXPECT_EQ(SBOX_TEST_DENIED,
- runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test/../bleh"));
+ runner->RunTest(L"NamedPipe_Create \\\\.\\pipe\\test/../bleh"));
+
+ runner = PipeTraversalRunner();
EXPECT_EQ(SBOX_TEST_DENIED,
- runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test\\../bleh"));
+ runner->RunTest(L"NamedPipe_Create \\\\.\\pipe\\test\\../bleh"));
+
+ runner = PipeTraversalRunner();
EXPECT_EQ(SBOX_TEST_DENIED,
- runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\test/..\\bleh"));
+ runner->RunTest(L"NamedPipe_Create \\\\.\\pipe\\test/..\\bleh"));
}
// This tests that path canonicalization is actually disabled if we use \\?\
@@ -100,22 +113,25 @@ TEST(NamedPipePolicyTest, CreatePipeCanonicalization) {
NamedPipe_Create(2, const_cast<wchar_t**>(argv)));
}
-// The same test as CreatePipe but this time using strict interceptions.
-TEST(NamedPipePolicyTest, CreatePipeStrictInterceptions) {
- TestRunner runner;
- runner.GetPolicy()->SetStrictInterceptions();
-
+std::unique_ptr<TestRunner> StrictInterceptionsRunner() {
+ auto runner = std::make_unique<TestRunner>();
+ runner->GetPolicy()->SetStrictInterceptions();
// TODO(nsylvain): This policy is wrong because "*" is a valid char in a
// namedpipe name. Here we apply it like a wildcard. http://b/893603
- EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_NAMED_PIPES,
- TargetPolicy::NAMEDPIPES_ALLOW_ANY,
- L"\\\\.\\pipe\\test*"));
+ runner->AddRule(TargetPolicy::SUBSYS_NAMED_PIPES,
+ TargetPolicy::NAMEDPIPES_ALLOW_ANY, L"\\\\.\\pipe\\test*");
+ return runner;
+}
+// The same test as CreatePipe but this time using strict interceptions.
+TEST(NamedPipePolicyTest, CreatePipeStrictInterceptions) {
+ auto runner = StrictInterceptionsRunner();
EXPECT_EQ(SBOX_TEST_SUCCEEDED,
- runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\testbleh"));
+ runner->RunTest(L"NamedPipe_Create \\\\.\\pipe\\testbleh"));
+ runner = StrictInterceptionsRunner();
EXPECT_EQ(SBOX_TEST_DENIED,
- runner.RunTest(L"NamedPipe_Create \\\\.\\pipe\\bleh"));
+ runner->RunTest(L"NamedPipe_Create \\\\.\\pipe\\bleh"));
}
} // namespace sandbox
diff --git a/chromium/sandbox/win/src/nt_internals.h b/chromium/sandbox/win/src/nt_internals.h
index 46d489fe2c5..f9847fc5b05 100644
--- a/chromium/sandbox/win/src/nt_internals.h
+++ b/chromium/sandbox/win/src/nt_internals.h
@@ -313,7 +313,8 @@ typedef NTSTATUS(WINAPI* NtSetInformationThreadFunction)(
// Partial definition only:
typedef enum _PROCESSINFOCLASS {
ProcessBasicInformation = 0,
- ProcessExecuteFlags = 0x22
+ ProcessExecuteFlags = 0x22,
+ ProcessHandleTable = 0x3A
} PROCESSINFOCLASS;
// For the structure documentation, see
@@ -723,13 +724,6 @@ typedef NTSTATUS(WINAPI* NtQuerySystemInformation)(
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength);
-typedef NTSTATUS(WINAPI* NtQueryObject)(IN HANDLE Handle,
- IN OBJECT_INFORMATION_CLASS
- ObjectInformationClass,
- OUT PVOID ObjectInformation,
- IN ULONG ObjectInformationLength,
- OUT PULONG ReturnLength);
-
// -----------------------------------------------------------------------
// Strings
diff --git a/chromium/sandbox/win/src/policy_broker.cc b/chromium/sandbox/win/src/policy_broker.cc
index 1f9fa6b613b..51e71a3b097 100644
--- a/chromium/sandbox/win/src/policy_broker.cc
+++ b/chromium/sandbox/win/src/policy_broker.cc
@@ -18,6 +18,7 @@
#include "sandbox/win/src/process_thread_interception.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_nt_types.h"
+#include "sandbox/win/src/sandbox_nt_util.h"
#include "sandbox/win/src/sandbox_types.h"
#include "sandbox/win/src/target_process.h"
@@ -26,65 +27,9 @@
namespace sandbox {
-// This is the list of all imported symbols from ntdll.dll.
-SANDBOX_INTERCEPT NtExports g_nt;
-
-#define INIT_GLOBAL_NT(member) \
- g_nt.member = reinterpret_cast<Nt##member##Function>( \
- ntdll_image.GetProcAddress("Nt" #member)); \
- if (!g_nt.member) \
- return false
-
-#define INIT_GLOBAL_RTL(member) \
- g_nt.member = \
- reinterpret_cast<member##Function>(ntdll_image.GetProcAddress(#member)); \
- if (!g_nt.member) \
- return false
-
-bool InitGlobalNt() {
- HMODULE ntdll = ::GetModuleHandle(kNtdllName);
- base::win::PEImage ntdll_image(ntdll);
-
- INIT_GLOBAL_NT(AllocateVirtualMemory);
- INIT_GLOBAL_NT(Close);
- INIT_GLOBAL_NT(DuplicateObject);
- INIT_GLOBAL_NT(FreeVirtualMemory);
- INIT_GLOBAL_NT(MapViewOfSection);
- INIT_GLOBAL_NT(ProtectVirtualMemory);
- INIT_GLOBAL_NT(QueryInformationProcess);
- INIT_GLOBAL_NT(QueryObject);
- INIT_GLOBAL_NT(QuerySection);
- INIT_GLOBAL_NT(QueryVirtualMemory);
- INIT_GLOBAL_NT(UnmapViewOfSection);
- INIT_GLOBAL_NT(SignalAndWaitForSingleObject);
- INIT_GLOBAL_NT(WaitForSingleObject);
-
- INIT_GLOBAL_RTL(RtlAllocateHeap);
- INIT_GLOBAL_RTL(RtlAnsiStringToUnicodeString);
- INIT_GLOBAL_RTL(RtlCompareUnicodeString);
- INIT_GLOBAL_RTL(RtlCreateHeap);
- INIT_GLOBAL_RTL(RtlCreateUserThread);
- INIT_GLOBAL_RTL(RtlDestroyHeap);
- INIT_GLOBAL_RTL(RtlFreeHeap);
- INIT_GLOBAL_RTL(_strnicmp);
- INIT_GLOBAL_RTL(strlen);
- INIT_GLOBAL_RTL(wcslen);
- INIT_GLOBAL_RTL(memcpy);
-
- return true;
-}
-
bool SetupNtdllImports(TargetProcess& child) {
- if (!InitGlobalNt()) {
- return false;
- }
-
-#ifndef NDEBUG
- // Verify that the structure is fully initialized.
- for (size_t i = 0; i < sizeof(g_nt) / sizeof(void*); i++)
- DCHECK(reinterpret_cast<char**>(&g_nt)[i]);
-#endif
- return (SBOX_ALL_OK == child.TransferVariable("g_nt", &g_nt, sizeof(g_nt)));
+ return (SBOX_ALL_OK ==
+ child.TransferVariable("g_nt", GetNtExports(), sizeof(NtExports)));
}
#undef INIT_GLOBAL_NT
diff --git a/chromium/sandbox/win/src/policy_broker.h b/chromium/sandbox/win/src/policy_broker.h
index 913a57a2c76..dbdac2cb3da 100644
--- a/chromium/sandbox/win/src/policy_broker.h
+++ b/chromium/sandbox/win/src/policy_broker.h
@@ -11,9 +11,6 @@ namespace sandbox {
class TargetProcess;
-// Initializes global imported symbols from ntdll.
-bool InitGlobalNt();
-
// Sets up interceptions not controlled by explicit policies.
bool SetupBasicInterceptions(InterceptionManager* manager,
bool is_csrss_connected);
diff --git a/chromium/sandbox/win/src/policy_engine_opcodes.cc b/chromium/sandbox/win/src/policy_engine_opcodes.cc
index d3ed12f3c57..931dad169be 100644
--- a/chromium/sandbox/win/src/policy_engine_opcodes.cc
+++ b/chromium/sandbox/win/src/policy_engine_opcodes.cc
@@ -9,6 +9,7 @@
#include "base/check_op.h"
#include "sandbox/win/src/sandbox_nt_types.h"
+#include "sandbox/win/src/sandbox_nt_util.h"
#include "sandbox/win/src/sandbox_types.h"
namespace {
@@ -30,8 +31,6 @@ bool InitStringUnicode(const wchar_t* source,
namespace sandbox {
-SANDBOX_INTERCEPT NtExports g_nt;
-
// Note: The opcodes are implemented as functions (as opposed to classes derived
// from PolicyOpcode) because you should not add more member variables to the
// PolicyOpcode class since it would cause object slicing on the target. So to
@@ -275,7 +274,7 @@ EvalResult OpcodeEval<OP_WSTRING_MATCH>(PolicyOpcode* opcode,
// Advance the source string to the last successfully evaluated position
// according to the match context.
source_str = &source_str[context->position];
- int source_len = static_cast<int>(g_nt.wcslen(source_str));
+ int source_len = static_cast<int>(GetNtExports()->wcslen(source_str));
if (0 == source_len) {
// If we reached the end of the source string there is nothing we can
@@ -320,8 +319,8 @@ EvalResult OpcodeEval<OP_WSTRING_MATCH>(PolicyOpcode* opcode,
!InitStringUnicode(source_str, match_len, &source_ustr))
return EVAL_ERROR;
- if (0 == g_nt.RtlCompareUnicodeString(&match_ustr, &source_ustr,
- case_sensitive)) {
+ if (0 == GetNtExports()->RtlCompareUnicodeString(&match_ustr, &source_ustr,
+ case_sensitive)) {
// Match! update the match context.
context->position += start_position + match_len;
return EVAL_TRUE;
@@ -336,8 +335,8 @@ EvalResult OpcodeEval<OP_WSTRING_MATCH>(PolicyOpcode* opcode,
return EVAL_ERROR;
do {
- if (0 == g_nt.RtlCompareUnicodeString(&match_ustr, &source_ustr,
- case_sensitive)) {
+ if (0 == GetNtExports()->RtlCompareUnicodeString(
+ &match_ustr, &source_ustr, case_sensitive)) {
// Match! update the match context.
context->position += (source_ustr.Buffer - source_str) + match_len;
return EVAL_TRUE;
diff --git a/chromium/sandbox/win/src/policy_engine_unittest.cc b/chromium/sandbox/win/src/policy_engine_unittest.cc
index b8b20021083..cd36c767602 100644
--- a/chromium/sandbox/win/src/policy_engine_unittest.cc
+++ b/chromium/sandbox/win/src/policy_engine_unittest.cc
@@ -15,11 +15,7 @@
namespace sandbox {
-bool SetupNtdllImports();
-
TEST(PolicyEngineTest, Rules1) {
- SetupNtdllImports();
-
// Construct two policy rules that say:
//
// #1
diff --git a/chromium/sandbox/win/src/policy_low_level.cc b/chromium/sandbox/win/src/policy_low_level.cc
index 79ef57cb43c..471d641c8d6 100644
--- a/chromium/sandbox/win/src/policy_low_level.cc
+++ b/chromium/sandbox/win/src/policy_low_level.cc
@@ -267,7 +267,7 @@ bool PolicyRule::AddStringMatch(RuleType rule_type,
if (L'?' == current_char[1]) {
++current_char;
}
- FALLTHROUGH;
+ [[fallthrough]];
default:
fragment += *current_char;
last_char = kLastCharIsAlpha;
diff --git a/chromium/sandbox/win/src/policy_low_level_unittest.cc b/chromium/sandbox/win/src/policy_low_level_unittest.cc
index 84846600961..53b7c10d291 100644
--- a/chromium/sandbox/win/src/policy_low_level_unittest.cc
+++ b/chromium/sandbox/win/src/policy_low_level_unittest.cc
@@ -17,11 +17,8 @@
namespace sandbox {
-bool SetupNtdllImports();
-
// Testing that we allow opcode generation on valid string patterns.
TEST(PolicyEngineTest, StringPatternsOK) {
- SetupNtdllImports();
PolicyRule pr(ASK_BROKER);
EXPECT_TRUE(pr.AddStringMatch(IF, 0, L"c:\\adobe\\ver??\\", CASE_SENSITIVE));
EXPECT_TRUE(pr.AddStringMatch(IF, 0, L"*.tmp", CASE_SENSITIVE));
@@ -33,7 +30,6 @@ TEST(PolicyEngineTest, StringPatternsOK) {
// Testing that we signal invalid string patterns.
TEST(PolicyEngineTest, StringPatternsBAD) {
- SetupNtdllImports();
PolicyRule pr(ASK_BROKER);
EXPECT_FALSE(pr.AddStringMatch(IF, 0, L"one**two", CASE_SENSITIVE));
EXPECT_FALSE(pr.AddStringMatch(IF, 0, L"**three", CASE_SENSITIVE));
@@ -54,7 +50,6 @@ PolicyGlobal* MakePolicyMemory() {
// The simplest test using LowLevelPolicy it should test a single opcode which
// does a exact string comparison.
TEST(PolicyEngineTest, SimpleStrMatch) {
- SetupNtdllImports();
PolicyRule pr(ASK_BROKER);
EXPECT_TRUE(
pr.AddStringMatch(IF, 0, L"z:\\Directory\\domo.txt", CASE_INSENSITIVE));
@@ -87,7 +82,6 @@ TEST(PolicyEngineTest, SimpleStrMatch) {
}
TEST(PolicyEngineTest, SimpleIfNotStrMatch) {
- SetupNtdllImports();
PolicyRule pr(ASK_BROKER);
EXPECT_TRUE(pr.AddStringMatch(IF_NOT, 0, L"c:\\Microsoft\\", CASE_SENSITIVE));
@@ -124,7 +118,6 @@ TEST(PolicyEngineTest, SimpleIfNotStrMatch) {
}
TEST(PolicyEngineTest, SimpleIfNotStrMatchWild1) {
- SetupNtdllImports();
PolicyRule pr(ASK_BROKER);
EXPECT_TRUE(
pr.AddStringMatch(IF_NOT, 0, L"c:\\Microsoft\\*", CASE_SENSITIVE));
@@ -157,7 +150,6 @@ TEST(PolicyEngineTest, SimpleIfNotStrMatchWild1) {
}
TEST(PolicyEngineTest, SimpleIfNotStrMatchWild2) {
- SetupNtdllImports();
PolicyRule pr(ASK_BROKER);
EXPECT_TRUE(
pr.AddStringMatch(IF_NOT, 0, L"c:\\Microsoft\\*.txt", CASE_SENSITIVE));
@@ -195,7 +187,6 @@ TEST(PolicyEngineTest, SimpleIfNotStrMatchWild2) {
}
TEST(PolicyEngineTest, IfNotStrMatchTwoRulesWild1) {
- SetupNtdllImports();
PolicyRule pr(ASK_BROKER);
EXPECT_TRUE(
pr.AddStringMatch(IF_NOT, 0, L"c:\\Microsoft\\*", CASE_SENSITIVE));
@@ -243,7 +234,6 @@ TEST(PolicyEngineTest, IfNotStrMatchTwoRulesWild1) {
}
TEST(PolicyEngineTest, IfNotStrMatchTwoRulesWild2) {
- SetupNtdllImports();
PolicyRule pr(ASK_BROKER);
EXPECT_TRUE(pr.AddNumberMatch(IF, 1, 24, EQUAL));
EXPECT_TRUE(
@@ -315,7 +305,6 @@ TEST(PolicyEngineTest, IfNotStrMatchTwoRulesWild2) {
// Testing one single rule in one single service. The service is made to
// resemble NtCreateFile.
TEST(PolicyEngineTest, OneRuleTest) {
- SetupNtdllImports();
PolicyRule pr(ASK_BROKER);
EXPECT_TRUE(
pr.AddStringMatch(IF, 0, L"c:\\*Microsoft*\\*.txt", CASE_SENSITIVE));
@@ -386,7 +375,6 @@ TEST(PolicyEngineTest, OneRuleTest) {
// Testing 3 rules in 3 services. Two of the services resemble File services.
TEST(PolicyEngineTest, ThreeRulesTest) {
- SetupNtdllImports();
PolicyRule pr_pipe(FAKE_SUCCESS);
EXPECT_TRUE(pr_pipe.AddStringMatch(IF, 0, L"\\\\/?/?\\Pipe\\Chrome.*",
CASE_INSENSITIVE));
@@ -590,7 +578,6 @@ TEST(PolicyEngineTest, ThreeRulesTest) {
}
TEST(PolicyEngineTest, PolicyRuleCopyConstructorTwoStrings) {
- SetupNtdllImports();
// Both pr_orig and pr_copy should allow hello.* but not *.txt files.
PolicyRule pr_orig(ASK_BROKER);
EXPECT_TRUE(pr_orig.AddStringMatch(IF, 0, L"hello.*", CASE_SENSITIVE));
@@ -633,7 +620,6 @@ TEST(PolicyEngineTest, PolicyRuleCopyConstructorTwoStrings) {
}
TEST(PolicyEngineTest, PolicyGenDoneCalledTwice) {
- SetupNtdllImports();
// The specific rules here are not important.
PolicyRule pr_orig(ASK_BROKER);
EXPECT_TRUE(pr_orig.AddStringMatch(IF, 0, L"hello.*", CASE_SENSITIVE));
diff --git a/chromium/sandbox/win/src/policy_opcodes_unittest.cc b/chromium/sandbox/win/src/policy_opcodes_unittest.cc
index c83efcba18a..4336c6a8afc 100644
--- a/chromium/sandbox/win/src/policy_opcodes_unittest.cc
+++ b/chromium/sandbox/win/src/policy_opcodes_unittest.cc
@@ -9,37 +9,14 @@
#include "sandbox/win/src/policy_engine_params.h"
#include "sandbox/win/src/sandbox_nt_types.h"
+#include "sandbox/win/src/sandbox_nt_util.h"
#include "sandbox/win/src/sandbox_types.h"
#include "testing/gtest/include/gtest/gtest.h"
-#define INIT_GLOBAL_RTL(member) \
- g_nt.member = \
- reinterpret_cast<member##Function>(::GetProcAddress(ntdll, #member)); \
- if (!g_nt.member) \
- return false
-
namespace sandbox {
const size_t kOpcodeMemory = 1024;
-SANDBOX_INTERCEPT NtExports g_nt;
-
-bool SetupNtdllImports() {
- HMODULE ntdll = ::GetModuleHandle(kNtdllName);
-
- INIT_GLOBAL_RTL(RtlAllocateHeap);
- INIT_GLOBAL_RTL(RtlAnsiStringToUnicodeString);
- INIT_GLOBAL_RTL(RtlCompareUnicodeString);
- INIT_GLOBAL_RTL(RtlCreateHeap);
- INIT_GLOBAL_RTL(RtlDestroyHeap);
- INIT_GLOBAL_RTL(RtlFreeHeap);
- INIT_GLOBAL_RTL(_strnicmp);
- INIT_GLOBAL_RTL(strlen);
- INIT_GLOBAL_RTL(wcslen);
-
- return true;
-}
-
TEST(PolicyEngineTest, ParameterSetTest) {
void* pv1 = reinterpret_cast<void*>(0x477EAA5);
const void* pv2 = reinterpret_cast<void*>(0x987654);
@@ -151,7 +128,6 @@ TEST(PolicyEngineTest, OpcodeMakerCase1) {
}
TEST(PolicyEngineTest, OpcodeMakerCase2) {
- SetupNtdllImports();
// Testing that the opcode maker does not overrun the
// supplied buffer. It should only be able to make 'count' opcodes.
// The difference with the previous test is that this opcodes allocate
@@ -236,8 +212,6 @@ TEST(PolicyEngineTest, LogicalOpcodes) {
}
TEST(PolicyEngineTest, WCharOpcodes1) {
- SetupNtdllImports();
-
const wchar_t* txt1 = L"the quick fox jumps over the lazy dog";
const wchar_t txt2[] = L"the quick";
const wchar_t txt3[] = L" fox jumps";
@@ -324,8 +298,6 @@ TEST(PolicyEngineTest, WCharOpcodes1) {
}
TEST(PolicyEngineTest, WCharOpcodes2) {
- SetupNtdllImports();
-
const wchar_t* path1 = L"c:\\documents and settings\\Microsoft\\BLAH.txt";
const wchar_t txt1[] = L"Settings\\microsoft";
ParameterSet pp_tc1 = ParamPickerMake(path1);
diff --git a/chromium/sandbox/win/src/policy_params.h b/chromium/sandbox/win/src/policy_params.h
index 485ecb14c80..ae48d57a162 100644
--- a/chromium/sandbox/win/src/policy_params.h
+++ b/chromium/sandbox/win/src/policy_params.h
@@ -18,27 +18,14 @@ class ParameterSet;
#define POLPARAMS_END(type) PolParamLast }; }; \
typedef sandbox::ParameterSet type##Array [type::PolParamLast];
-// Policy parameters for file open / create.
+// Policy parameters for file access.
POLPARAMS_BEGIN(OpenFile)
POLPARAM(NAME)
- POLPARAM(BROKER) // true if called from the broker.
POLPARAM(ACCESS)
- POLPARAM(DISPOSITION)
- POLPARAM(OPTIONS)
+ POLPARAM(OPENONLY)
POLPARAMS_END(OpenFile)
// Policy parameter for name-based policies.
-POLPARAMS_BEGIN(FileName)
- POLPARAM(NAME)
- POLPARAM(BROKER) // true if called from the broker.
-POLPARAMS_END(FileName)
-
-static_assert(OpenFile::NAME == static_cast<int>(FileName::NAME),
- "to simplify fs policies");
-static_assert(OpenFile::BROKER == static_cast<int>(FileName::BROKER),
- "to simplify fs policies");
-
-// Policy parameter for name-based policies.
POLPARAMS_BEGIN(NameBased)
POLPARAM(NAME)
POLPARAMS_END(NameBased)
diff --git a/chromium/sandbox/win/src/policy_target.cc b/chromium/sandbox/win/src/policy_target.cc
index 5cf894a4482..2be9bd0b7ba 100644
--- a/chromium/sandbox/win/src/policy_target.cc
+++ b/chromium/sandbox/win/src/policy_target.cc
@@ -18,12 +18,6 @@
namespace sandbox {
-// Handle for our private heap.
-extern void* g_heap;
-
-// This is the list of all imported symbols from ntdll.dll.
-SANDBOX_INTERCEPT NtExports g_nt;
-
// Policy data.
extern void* volatile g_shared_policy_memory;
SANDBOX_INTERCEPT size_t g_shared_policy_size;
diff --git a/chromium/sandbox/win/src/policy_target_test.cc b/chromium/sandbox/win/src/policy_target_test.cc
index b490cc40c73..1712142a4d6 100644
--- a/chromium/sandbox/win/src/policy_target_test.cc
+++ b/chromium/sandbox/win/src/policy_target_test.cc
@@ -9,6 +9,7 @@
#include "base/strings/string_util.h"
#include "base/win/scoped_process_information.h"
#include "base/win/windows_version.h"
+#include "build/build_config.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_factory.h"
#include "sandbox/win/src/sandbox_utils.h"
@@ -16,7 +17,7 @@
#include "sandbox/win/tests/common/controller.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if defined(OS_WIN)
+#if BUILDFLAG(IS_WIN)
#include "base/win/win_util.h"
#endif
@@ -179,11 +180,13 @@ TEST(PolicyTargetTest, SetInformationThread) {
runner.SetTestState(BEFORE_REVERT);
EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token"));
- runner.SetTestState(AFTER_REVERT);
- EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token"));
+ TestRunner runner1;
+ runner1.SetTestState(AFTER_REVERT);
+ EXPECT_EQ(ERROR_NO_TOKEN, runner1.RunTest(L"PolicyTargetTest_token"));
- runner.SetTestState(EVERY_STATE);
- EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(L"PolicyTargetTest_steal"));
+ TestRunner runner2;
+ runner2.SetTestState(EVERY_STATE);
+ EXPECT_EQ(SBOX_TEST_FAILED, runner2.RunTest(L"PolicyTargetTest_steal"));
}
TEST(PolicyTargetTest, OpenThreadToken) {
@@ -191,18 +194,19 @@ TEST(PolicyTargetTest, OpenThreadToken) {
runner.SetTestState(BEFORE_REVERT);
EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token2"));
- runner.SetTestState(AFTER_REVERT);
- EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token2"));
+ TestRunner runner2;
+ runner2.SetTestState(AFTER_REVERT);
+ EXPECT_EQ(ERROR_NO_TOKEN, runner2.RunTest(L"PolicyTargetTest_token2"));
}
TEST(PolicyTargetTest, OpenThreadTokenEx) {
TestRunner runner;
-
runner.SetTestState(BEFORE_REVERT);
EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_token3"));
- runner.SetTestState(AFTER_REVERT);
- EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token3"));
+ TestRunner runner2;
+ runner2.SetTestState(AFTER_REVERT);
+ EXPECT_EQ(ERROR_NO_TOKEN, runner2.RunTest(L"PolicyTargetTest_token3"));
}
TEST(PolicyTargetTest, OpenThread) {
@@ -210,7 +214,8 @@ TEST(PolicyTargetTest, OpenThread) {
EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_thread"))
<< "Opens the current thread";
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_thread2"))
+ TestRunner runner2;
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(L"PolicyTargetTest_thread2"))
<< "Creates a new thread and opens it";
}
diff --git a/chromium/sandbox/win/src/process_mitigations_dyncode_unittest.cc b/chromium/sandbox/win/src/process_mitigations_dyncode_unittest.cc
index 21d7021f343..b4dc8f2fd1a 100644
--- a/chromium/sandbox/win/src/process_mitigations_dyncode_unittest.cc
+++ b/chromium/sandbox/win/src/process_mitigations_dyncode_unittest.cc
@@ -244,6 +244,15 @@ class DynamicCodeOptOutThread {
int return_code_;
};
+// Helpers to set up rules for dynamic code tests, needed as policy
+// (from the TestRunner) can only be applied to a single process.
+std::unique_ptr<sandbox::TestRunner> RunnerWithMitigation(
+ sandbox::MitigationFlags mitigations) {
+ auto runner = std::make_unique<sandbox::TestRunner>();
+ runner->GetPolicy()->SetDelayedProcessMitigations(mitigations);
+ return runner;
+}
+
//------------------------------------------------------------------------------
// DisableDynamicCode test harness helper function. Tests numerous APIs.
// - APIs fail with ERROR_DYNAMIC_CODE_BLOCKED if this mitigation is
@@ -265,14 +274,6 @@ void DynamicCodeTestHarness(sandbox::MitigationFlags which_mitigation,
return;
}
- sandbox::TestRunner runner;
- sandbox::TargetPolicy* policy = runner.GetPolicy();
-
- if (enable_mitigation) {
- EXPECT_EQ(policy->SetDelayedProcessMitigations(which_mitigation),
- sandbox::SBOX_ALL_OK);
- }
-
std::wstring shared =
(which_mitigation == sandbox::MITIGATION_DYNAMIC_CODE_DISABLE)
? L"TestWin81DynamicCode "
@@ -283,32 +284,34 @@ void DynamicCodeTestHarness(sandbox::MitigationFlags which_mitigation,
}
// Test 1:
+ auto runner = enable_mitigation ? RunnerWithMitigation(which_mitigation)
+ : std::make_unique<sandbox::TestRunner>();
std::wstring test =
base::StringPrintf(L"%ls %u", shared.c_str(), VIRTUALALLOC);
EXPECT_EQ((expect_success ? sandbox::SBOX_TEST_SUCCEEDED
: ERROR_DYNAMIC_CODE_BLOCKED),
- runner.RunTest(test.c_str()));
+ runner->RunTest(test.c_str()));
// Test 2:
+ runner = enable_mitigation ? RunnerWithMitigation(which_mitigation)
+ : std::make_unique<sandbox::TestRunner>();
test = base::StringPrintf(L"%ls %u", shared.c_str(), VIRTUALPROTECT);
EXPECT_EQ((expect_success ? sandbox::SBOX_TEST_SUCCEEDED
: ERROR_DYNAMIC_CODE_BLOCKED),
- runner.RunTest(test.c_str()));
+ runner->RunTest(test.c_str()));
// Test 3:
// Need token level >= USER_LIMITED to be able to successfully run test 3.
- policy->SetTokenLevel(sandbox::TokenLevel::USER_RESTRICTED_SAME_ACCESS,
- sandbox::TokenLevel::USER_LIMITED);
+ runner = enable_mitigation ? RunnerWithMitigation(which_mitigation)
+ : std::make_unique<sandbox::TestRunner>();
+ runner->GetPolicy()->SetTokenLevel(
+ sandbox::TokenLevel::USER_RESTRICTED_SAME_ACCESS,
+ sandbox::TokenLevel::USER_LIMITED);
test = base::StringPrintf(L"%ls %u", shared.c_str(), MAPVIEWCUSTOM);
EXPECT_EQ((expect_success ? sandbox::SBOX_TEST_SUCCEEDED
: ERROR_DYNAMIC_CODE_BLOCKED),
- runner.RunTest(test.c_str()));
-
- // Test 4:
- // Set token levels back to default.
- policy->SetTokenLevel(sandbox::TokenLevel::USER_RESTRICTED_SAME_ACCESS,
- sandbox::TokenLevel::USER_LOCKDOWN);
+ runner->RunTest(test.c_str()));
// Ensure sandbox access to the file on disk.
base::FilePath dll_path;
@@ -322,14 +325,16 @@ void DynamicCodeTestHarness(sandbox::MitigationFlags which_mitigation,
temp_dir.GetPath().Append(hooking_dll::g_hook_dll_file);
ASSERT_TRUE(base::CopyFile(dll_path, temp_dll_path));
- EXPECT_TRUE(runner.AddFsRule(sandbox::TargetPolicy::FILES_ALLOW_ANY,
- temp_dll_path.value().c_str()));
+ runner = enable_mitigation ? RunnerWithMitigation(which_mitigation)
+ : std::make_unique<sandbox::TestRunner>();
+ EXPECT_TRUE(runner->AddFsRule(sandbox::TargetPolicy::FILES_ALLOW_ANY,
+ temp_dll_path.value().c_str()));
test = base::StringPrintf(L"%ls %u \"%ls\"", shared.c_str(), MAPVIEWFILE,
temp_dll_path.value().c_str());
EXPECT_EQ((expect_success ? sandbox::SBOX_TEST_SUCCEEDED
: ERROR_DYNAMIC_CODE_BLOCKED),
- runner.RunTest(test.c_str()));
+ runner->RunTest(test.c_str()));
}
} // namespace
diff --git a/chromium/sandbox/win/src/process_mitigations_imageload_unittest.cc b/chromium/sandbox/win/src/process_mitigations_imageload_unittest.cc
deleted file mode 100644
index f5094665a26..00000000000
--- a/chromium/sandbox/win/src/process_mitigations_imageload_unittest.cc
+++ /dev/null
@@ -1,462 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "sandbox/win/src/process_mitigations.h"
-
-#include <windows.h>
-
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/path_service.h"
-#include "base/scoped_native_library.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/test_timeouts.h"
-#include "base/win/windows_version.h"
-#include "sandbox/win/src/sandbox.h"
-#include "sandbox/win/src/target_services.h"
-#include "sandbox/win/tests/common/controller.h"
-#include "sandbox/win/tests/integration_tests/hijack_shim_dll.h"
-#include "sandbox/win/tests/integration_tests/integration_tests_common.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-//------------------------------------------------------------------------------
-// Internal Defines & Functions
-//------------------------------------------------------------------------------
-constexpr wchar_t g_hijack_dll_file[] = L"sbox_integration_test_hijack_dll.dll";
-constexpr wchar_t g_hijack_shim_dll_file[] =
- L"sbox_integration_test_hijack_shim_dll.dll";
-
-// System mutex to prevent conflicting tests from running at the same time.
-// This particular mutex is related to the use of the hijack dlls.
-constexpr wchar_t g_hijack_dlls_mutex[] = L"ChromeTestHijackDllsMutex";
-
-// API defined in hijack_shim_dll.h.
-using CheckHijackResultFunction = decltype(&CheckHijackResult);
-
-//------------------------------------------------------------------------------
-// ImageLoadRemote test helper function.
-//
-// Trigger test child process (with or without mitigation enabled).
-//------------------------------------------------------------------------------
-void TestWin10ImageLoadRemote(bool is_success_test) {
- // ***Insert a manual testing share UNC path here!
- // E.g.: \\\\hostname\\sharename\\calc.exe
- std::wstring unc = L"\"\\\\hostname\\sharename\\calc.exe\"";
-
- sandbox::TestRunner runner;
- sandbox::TargetPolicy* policy = runner.GetPolicy();
-
- // Set a policy that would normally allow for process creation.
- policy->SetJobLevel(sandbox::JOB_NONE, 0);
- policy->SetTokenLevel(sandbox::USER_UNPROTECTED, sandbox::USER_UNPROTECTED);
- runner.SetDisableCsrss(false);
-
- if (!is_success_test) {
- // Enable the NoRemote mitigation.
- EXPECT_EQ(policy->SetDelayedProcessMitigations(
- sandbox::MITIGATION_IMAGE_LOAD_NO_REMOTE),
- sandbox::SBOX_ALL_OK);
- }
-
- std::wstring test = L"TestChildProcess ";
- test += unc.c_str();
- EXPECT_EQ((is_success_test ? sandbox::SBOX_TEST_SUCCEEDED
- : sandbox::SBOX_TEST_FAILED),
- runner.RunTest(test.c_str()));
-}
-
-//------------------------------------------------------------------------------
-// ImageLoadLow test helper function.
-//
-// 1. Set up a copy of calc, using icacls to make it low integrity.
-// 2. Trigger test child process (with or without mitigation enabled).
-//------------------------------------------------------------------------------
-void TestWin10ImageLoadLowLabel(bool is_success_test) {
- // Setup a mandatory low executable for this test (calc.exe).
- // If anything fails during setup, ASSERT to end test.
- base::FilePath orig_path;
- ASSERT_TRUE(base::PathService::Get(base::DIR_SYSTEM, &orig_path));
- orig_path = orig_path.Append(L"calc.exe");
-
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- base::FilePath new_path = temp_dir.GetPath();
- new_path = new_path.Append(L"lowIL_calc.exe");
-
- // Test file will be cleaned up by the ScopedTempDir.
- ASSERT_TRUE(base::CopyFileW(orig_path, new_path));
-
- std::wstring cmd_line = L"icacls \"";
- cmd_line += new_path.value().c_str();
- cmd_line += L"\" /setintegritylevel Low";
-
- base::LaunchOptions options = base::LaunchOptionsForTest();
- base::Process setup_proc = base::LaunchProcess(cmd_line.c_str(), options);
- ASSERT_TRUE(setup_proc.IsValid());
-
- int exit_code = 1;
- if (!setup_proc.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
- &exit_code)) {
- // Might have timed out, or might have failed.
- // Terminate to make sure we clean up any mess.
- setup_proc.Terminate(0, false);
- ASSERT_TRUE(false);
- }
- // Make sure icacls was successful.
- ASSERT_EQ(0, exit_code);
-
- sandbox::TestRunner runner;
- sandbox::TargetPolicy* policy = runner.GetPolicy();
-
- // Set a policy that would normally allow for process creation.
- policy->SetJobLevel(sandbox::JOB_NONE, 0);
- policy->SetTokenLevel(sandbox::USER_UNPROTECTED, sandbox::USER_UNPROTECTED);
- runner.SetDisableCsrss(false);
-
- if (!is_success_test) {
- // Enable the NoLowLabel mitigation.
- EXPECT_EQ(policy->SetDelayedProcessMitigations(
- sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL),
- sandbox::SBOX_ALL_OK);
- }
-
- std::wstring test = L"TestChildProcess \"";
- test += new_path.value().c_str();
- test += L"\" false";
-
- EXPECT_EQ((is_success_test ? sandbox::SBOX_TEST_SUCCEEDED
- : sandbox::SBOX_TEST_FAILED),
- runner.RunTest(test.c_str()));
-}
-
-//------------------------------------------------------------------------------
-// ImageLoadPreferSystem32 test helper function.
-//
-// - Acquire the global g_hijack_dlls_mutex mutex before calling
-// (as we meddle with a shared system resource).
-// - Note: Do not use ASSERTs in this function, as a global mutex is held.
-// - If |baseline_test|, there is no attempted hijacking. Just test the
-// implicit import in the local directory.
-//
-// 1. Put a copy of the hijack DLL into system32.
-// 2. Trigger test child process (with or without mitigation enabled). When
-// the OS resolves the import table for the child process, it will either
-// choose the version in the local app directory, or the copy in system32.
-//------------------------------------------------------------------------------
-void TestWin10ImageLoadPreferSys32(bool baseline_test, bool expect_sys32_path) {
- base::FilePath app_path;
- EXPECT_TRUE(base::PathService::Get(base::DIR_EXE, &app_path));
-
- // Put a copy of the hijack dll into system32. So there's one in the
- // local dir, and one in system32.
- base::FilePath old_dll_path = app_path.Append(g_hijack_dll_file);
-
- base::FilePath sys_path;
- EXPECT_TRUE(base::PathService::Get(base::DIR_SYSTEM, &sys_path));
- base::FilePath new_dll_path = sys_path.Append(g_hijack_dll_file);
-
- // Note: test requires admin to copy/delete files in system32.
- EXPECT_TRUE(base::CopyFileW(old_dll_path, new_dll_path));
-
- // Get path for the test shim DLL to pass along to test child proc.
- base::FilePath shim_dll_path = app_path.Append(g_hijack_shim_dll_file);
-
- sandbox::TestRunner runner;
- sandbox::TargetPolicy* policy = runner.GetPolicy();
-
- // ACCESS_DENIED errors loading DLLs without a higher token - AddFsRule
- // alone doesn't cut it.
- policy->SetTokenLevel(sandbox::TokenLevel::USER_RESTRICTED_SAME_ACCESS,
- sandbox::TokenLevel::USER_LIMITED);
- runner.AddFsRule(sandbox::TargetPolicy::FILES_ALLOW_READONLY,
- shim_dll_path.value().c_str());
- runner.AddFsRule(sandbox::TargetPolicy::FILES_ALLOW_READONLY,
- old_dll_path.value().c_str());
- runner.AddFsRule(sandbox::TargetPolicy::FILES_ALLOW_READONLY,
- new_dll_path.value().c_str());
-
- if (!baseline_test && expect_sys32_path) {
- // Enable the PreferSystem32 mitigation.
- EXPECT_EQ(policy->SetDelayedProcessMitigations(
- sandbox::MITIGATION_IMAGE_LOAD_PREFER_SYS32),
- sandbox::SBOX_ALL_OK);
- }
-
- // For the baseline test, disable sandbox completely. Just trying to ensure
- // that the implicit link & import succeeds from local dir.
- if (baseline_test)
- runner.SetUnsandboxed(true);
-
- // If this is the "success" test, expect a return value of "false" - as the
- // hijack was successful so the hijack_dll is NOT in system32.
- // The failure case has the mitigation enabled, so expect the hijack_dll to be
- // in system32.
- std::wstring test = base::StringPrintf(
- L"%ls %ls \"%ls\"", L"TestImageLoadHijack",
- (!expect_sys32_path) ? L"true" : L"false", shim_dll_path.value().c_str());
-
- // NOTE: 1706098690 == SBOX_TEST_NOT_FOUND == LoadLibrary on the shim dll
- // failed, or the secondary import load of hijack.dll failed.
- EXPECT_EQ((expect_sys32_path ? sandbox::SBOX_TEST_SUCCEEDED
- : sandbox::SBOX_TEST_FAILED),
- runner.RunTest(test.c_str()));
-
- EXPECT_TRUE(base::DeleteFile(new_dll_path));
-}
-
-} // namespace
-
-namespace sandbox {
-
-//------------------------------------------------------------------------------
-// Exported functions called by child test processes.
-//------------------------------------------------------------------------------
-
-// This test loading and using the shim DLL is required.
-// The waterfall bots (test environment/harness) have unique resource
-// access failures if the main sbox_integration_tests executable
-// implicitely links against the hijack DLL (and implicit linking is required
-// to test this mitigation) - regardless of whether this test runs or is
-// disabled.
-//
-// - Arg1: "true" or "false", if the DLL path should be in system32.
-// - Arg2: the full path to the test shim DLL to load.
-SBOX_TESTS_COMMAND int TestImageLoadHijack(int argc, wchar_t** argv) {
- if (argc < 2 || !argv[0] || !argv[1])
- return SBOX_TEST_INVALID_PARAMETER;
-
- bool expect_system = false;
- if (::wcsicmp(argv[0], L"true") == 0)
- expect_system = true;
-
- // Ensure implicitely linked, secondary hijack DLL is not already
- // loaded in process.
- HMODULE check = ::GetModuleHandleW(g_hijack_dll_file);
- if (check)
- return SBOX_TEST_FAILED;
-
- // Load the shim DLL for this test.
- base::ScopedNativeLibrary shim_dll((base::FilePath(argv[1])));
- if (!shim_dll.is_valid())
- return SBOX_TEST_NOT_FOUND;
-
- CheckHijackResultFunction check_hijack_result =
- reinterpret_cast<CheckHijackResultFunction>(
- shim_dll.GetFunctionPointer(g_hijack_shim_func));
-
- if (!check_hijack_result)
- return SBOX_TEST_FAILED_TO_RUN_TEST;
-
- return check_hijack_result(expect_system);
-}
-
-//------------------------------------------------------------------------------
-// Exported Image Load Tests
-//------------------------------------------------------------------------------
-
-//------------------------------------------------------------------------------
-// Disable image load from remote devices (MITIGATION_IMAGE_LOAD_NO_REMOTE).
-// >= Win10_TH2
-//------------------------------------------------------------------------------
-
-// This test validates that setting the MITIGATION_IMAGE_LOAD_NO_REMOTE
-// mitigation enables the setting on a process.
-TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoRemotePolicySuccess) {
- if (base::win::GetVersion() < base::win::Version::WIN10_TH2)
- return;
-
- std::wstring test_command = L"CheckPolicy ";
- test_command += std::to_wstring(TESTPOLICY_LOADNOREMOTE);
-
- //---------------------------------
- // 1) Test setting pre-startup.
- //---------------------------------
- TestRunner runner;
- sandbox::TargetPolicy* policy = runner.GetPolicy();
-
- EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_IMAGE_LOAD_NO_REMOTE),
- SBOX_ALL_OK);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_command.c_str()));
-
- //---------------------------------
- // 2) Test setting post-startup.
- //---------------------------------
- TestRunner runner2;
- sandbox::TargetPolicy* policy2 = runner2.GetPolicy();
-
- EXPECT_EQ(
- policy2->SetDelayedProcessMitigations(MITIGATION_IMAGE_LOAD_NO_REMOTE),
- SBOX_ALL_OK);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(test_command.c_str()));
-}
-
-// This test validates that we CAN create a new process from
-// a remote UNC device, if the MITIGATION_IMAGE_LOAD_NO_REMOTE
-// mitigation is NOT set.
-//
-// MANUAL testing only.
-TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteSuccess) {
- if (base::win::GetVersion() < base::win::Version::WIN10_TH2)
- return;
-
- TestWin10ImageLoadRemote(true /* is_success_test */);
-}
-
-// This test validates that setting the MITIGATION_IMAGE_LOAD_NO_REMOTE
-// mitigation prevents creating a new process from a remote
-// UNC device.
-//
-// MANUAL testing only.
-TEST(ProcessMitigationsTest, DISABLED_CheckWin10ImageLoadNoRemoteFailure) {
- if (base::win::GetVersion() < base::win::Version::WIN10_TH2)
- return;
-
- TestWin10ImageLoadRemote(false /* is_success_test */);
-}
-
-//------------------------------------------------------------------------------
-// Disable image load when "mandatory low label" (integrity level).
-// (MITIGATION_IMAGE_LOAD_NO_LOW_LABEL)
-// >= Win10_TH2
-//------------------------------------------------------------------------------
-
-// This test validates that setting the MITIGATION_IMAGE_LOAD_NO_LOW_LABEL
-// mitigation enables the setting on a process.
-TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoLowLabelPolicySuccess) {
- if (base::win::GetVersion() < base::win::Version::WIN10_TH2)
- return;
-
- std::wstring test_command = L"CheckPolicy ";
- test_command += std::to_wstring(TESTPOLICY_LOADNOLOW);
-
- //---------------------------------
- // 1) Test setting pre-startup.
- //---------------------------------
- TestRunner runner;
- sandbox::TargetPolicy* policy = runner.GetPolicy();
-
- EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_IMAGE_LOAD_NO_LOW_LABEL),
- SBOX_ALL_OK);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_command.c_str()));
-
- //---------------------------------
- // 2) Test setting post-startup.
- //---------------------------------
- TestRunner runner2;
- sandbox::TargetPolicy* policy2 = runner2.GetPolicy();
-
- EXPECT_EQ(
- policy2->SetDelayedProcessMitigations(MITIGATION_IMAGE_LOAD_NO_LOW_LABEL),
- SBOX_ALL_OK);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(test_command.c_str()));
-}
-
-// This test validates that we CAN create a new process with
-// low mandatory label (IL), if the MITIGATION_IMAGE_LOAD_NO_LOW_LABEL
-// mitigation is NOT set.
-TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoLowLabelSuccess) {
- if (base::win::GetVersion() < base::win::Version::WIN10_TH2)
- return;
-
- TestWin10ImageLoadLowLabel(true /* is_success_test */);
-}
-
-// This test validates that setting the MITIGATION_IMAGE_LOAD_NO_LOW_LABEL
-// mitigation prevents creating a new process with low mandatory label (IL).
-TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoLowLabelFailure) {
- if (base::win::GetVersion() < base::win::Version::WIN10_TH2)
- return;
-
- TestWin10ImageLoadLowLabel(false /* is_success_test */);
-}
-
-//------------------------------------------------------------------------------
-// Prefer system32 directory on image load (MITIGATION_IMAGE_LOAD_PREFER_SYS32).
-// >= Win10_RS1 (Anniversary)
-//------------------------------------------------------------------------------
-
-// This test validates that setting the MITIGATION_IMAGE_LOAD_PREFER_SYS32
-// mitigation enables the setting on a process.
-TEST(ProcessMitigationsTest, CheckWin10ImageLoadPreferSys32PolicySuccess) {
- if (base::win::GetVersion() < base::win::Version::WIN10_RS1)
- return;
-
- std::wstring test_command = L"CheckPolicy ";
- test_command += std::to_wstring(TESTPOLICY_LOADPREFERSYS32);
-
- //---------------------------------
- // 1) Test setting pre-startup.
- // ** Currently disabled. All PreferSys32 tests start to explode on
- // >= Win10 1703/RS2 when this mitigation is set pre-startup.
- // Child process creation works fine, but when ::ResumeThread() is called,
- // there is a fatal error: "Entry point ucnv_convertEx_60 could not be
- // located in the DLL ... sbox_integration_tests.exe."
- // This is a character conversion function in a ucnv (unicode) DLL.
- // Potentially the loader is finding a different version of this DLL that
- // we have a dependency on in System32... but it doesn't match up with
- // what we build against???!
- //---------------------------------
-
- //---------------------------------
- // 2) Test setting post-startup.
- //---------------------------------
- TestRunner runner2;
- sandbox::TargetPolicy* policy2 = runner2.GetPolicy();
-
- EXPECT_EQ(
- policy2->SetDelayedProcessMitigations(MITIGATION_IMAGE_LOAD_PREFER_SYS32),
- SBOX_ALL_OK);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(test_command.c_str()));
-}
-
-// This baseline test validates that the implicit import works in the local
-// working directory.
-// MITIGATION_IMAGE_LOAD_PREFER_SYS32 mitigation is NOT set.
-//
-// Must run this test as admin/elevated.
-TEST(ProcessMitigationsTest, CheckWin10ImageLoadPreferSys32_Baseline) {
- if (base::win::GetVersion() < base::win::Version::WIN10_RS1)
- return;
-
- ScopedTestMutex mutex(g_hijack_dlls_mutex);
-
- // Baseline test, and expect the DLL to NOT be in system32.
- TestWin10ImageLoadPreferSys32(true /* baseline_test */,
- false /* expect_sys32_path */);
-}
-
-// This test validates that import hijacking succeeds, if the
-// MITIGATION_IMAGE_LOAD_PREFER_SYS32 mitigation is NOT set.
-// (Hijack success.)
-//
-// Must run this test as admin/elevated.
-TEST(ProcessMitigationsTest, CheckWin10ImageLoadPreferSys32_Success) {
- if (base::win::GetVersion() < base::win::Version::WIN10_RS1)
- return;
-
- ScopedTestMutex mutex(g_hijack_dlls_mutex);
-
- // Not a baseline test, and expect the DLL to be in system32.
- TestWin10ImageLoadPreferSys32(false /* baseline_test */,
- true /* expect_sys32_path */);
-}
-
-// This test validates that setting the MITIGATION_IMAGE_LOAD_PREFER_SYS32
-// mitigation prevents import hijacking. (Hijack failure.)
-//
-// Must run this test as admin/elevated.
-TEST(ProcessMitigationsTest, CheckWin10ImageLoadPreferSys32_Failure) {
- if (base::win::GetVersion() < base::win::Version::WIN10_RS1)
- return;
-
- ScopedTestMutex mutex(g_hijack_dlls_mutex);
-
- // Not a baseline test, and expect the DLL to NOT be in system32.
- TestWin10ImageLoadPreferSys32(false /* baseline_test */,
- false /* expect_sys32_path */);
-}
-
-} // namespace sandbox
diff --git a/chromium/sandbox/win/src/process_mitigations_unittest.cc b/chromium/sandbox/win/src/process_mitigations_unittest.cc
index 31138318dd2..551b07d0d6d 100644
--- a/chromium/sandbox/win/src/process_mitigations_unittest.cc
+++ b/chromium/sandbox/win/src/process_mitigations_unittest.cc
@@ -16,6 +16,7 @@
#include "base/win/scoped_handle.h"
#include "base/win/windows_version.h"
#include "sandbox/win/src/nt_internals.h"
+#include "sandbox/win/src/sandbox_nt_util.h"
#include "sandbox/win/src/target_services.h"
#include "sandbox/win/tests/common/controller.h"
#include "sandbox/win/tests/integration_tests/hooking_dll.h"
@@ -482,17 +483,11 @@ SBOX_TESTS_COMMAND int CheckDep(int argc, wchar_t** argv) {
return SBOX_TEST_SECOND_ERROR;
} else {
- NtQueryInformationProcessFunction query_information_process = nullptr;
- ResolveNTFunctionPtr("NtQueryInformationProcess",
- &query_information_process);
- if (!query_information_process)
- return SBOX_TEST_NOT_FOUND;
-
ULONG size = 0;
ULONG dep_flags = 0;
- if (!SUCCEEDED(query_information_process(::GetCurrentProcess(),
- ProcessExecuteFlags, &dep_flags,
- sizeof(dep_flags), &size))) {
+ if (!SUCCEEDED(GetNtExports()->QueryInformationProcess(
+ ::GetCurrentProcess(), ProcessExecuteFlags, &dep_flags,
+ sizeof(dep_flags), &size))) {
return SBOX_TEST_THIRD_ERROR;
}
@@ -925,13 +920,9 @@ TEST(ProcessMitigationsTest, CheckWin10MsSigned_Failure) {
// ASAN doesn't initialize early enough for the intercepts in NtCreateSection to
// be able to use std::unique_ptr, so disable pre-launch CIG on ASAN builds.
#if !defined(ADDRESS_SANITIZER)
-#define MAYBE_CheckWin10MsSignedWithIntercept_Success \
- CheckWin10MsSignedWithIntercept_Success
#define MAYBE_CheckWin10MsSigned_FailurePreSpawn \
CheckWin10MsSigned_FailurePreSpawn
#else
-#define MAYBE_CheckWin10MsSignedWithIntercept_Success \
- DISABLED_CheckWin10MsSignedWithIntercept_Success
#define MAYBE_CheckWin10MsSigned_FailurePreSpawn \
DISABLED_CheckWin10MsSigned_FailurePreSpawn
#endif
@@ -1298,4 +1289,99 @@ TEST(ProcessMitigationsTest, CheckWin10KernelTransactionManagerMitigation) {
EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_policy_command.c_str()));
}
+TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoRemotePolicySuccess) {
+ if (base::win::GetVersion() < base::win::Version::WIN10_TH2)
+ return;
+
+ std::wstring test_command = L"CheckPolicy ";
+ test_command += std::to_wstring(TESTPOLICY_LOADNOREMOTE);
+
+ //---------------------------------
+ // 1) Test setting pre-startup.
+ //---------------------------------
+ TestRunner runner;
+ sandbox::TargetPolicy* policy = runner.GetPolicy();
+
+ EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_IMAGE_LOAD_NO_REMOTE),
+ SBOX_ALL_OK);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_command.c_str()));
+
+ //---------------------------------
+ // 2) Test setting post-startup.
+ //---------------------------------
+ TestRunner runner2;
+ sandbox::TargetPolicy* policy2 = runner2.GetPolicy();
+
+ EXPECT_EQ(
+ policy2->SetDelayedProcessMitigations(MITIGATION_IMAGE_LOAD_NO_REMOTE),
+ SBOX_ALL_OK);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(test_command.c_str()));
+}
+
+//---------------
+// This test validates that setting the MITIGATION_IMAGE_LOAD_NO_LOW_LABEL
+// mitigation enables the setting on a process.
+TEST(ProcessMitigationsTest, CheckWin10ImageLoadNoLowLabelPolicySuccess) {
+ if (base::win::GetVersion() < base::win::Version::WIN10_TH2)
+ return;
+
+ std::wstring test_command = L"CheckPolicy ";
+ test_command += std::to_wstring(TESTPOLICY_LOADNOLOW);
+
+ //---------------------------------
+ // 1) Test setting pre-startup.
+ //---------------------------------
+ TestRunner runner;
+ sandbox::TargetPolicy* policy = runner.GetPolicy();
+
+ EXPECT_EQ(policy->SetProcessMitigations(MITIGATION_IMAGE_LOAD_NO_LOW_LABEL),
+ SBOX_ALL_OK);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_command.c_str()));
+
+ //---------------------------------
+ // 2) Test setting post-startup.
+ //---------------------------------
+ TestRunner runner2;
+ sandbox::TargetPolicy* policy2 = runner2.GetPolicy();
+
+ EXPECT_EQ(
+ policy2->SetDelayedProcessMitigations(MITIGATION_IMAGE_LOAD_NO_LOW_LABEL),
+ SBOX_ALL_OK);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(test_command.c_str()));
+}
+
+// This test validates that setting the MITIGATION_IMAGE_LOAD_PREFER_SYS32
+// mitigation enables the setting on a process.
+TEST(ProcessMitigationsTest, CheckWin10ImageLoadPreferSys32PolicySuccess) {
+ if (base::win::GetVersion() < base::win::Version::WIN10_RS1)
+ return;
+
+ std::wstring test_command = L"CheckPolicy ";
+ test_command += std::to_wstring(TESTPOLICY_LOADPREFERSYS32);
+
+ //---------------------------------
+ // 1) Test setting pre-startup.
+ // ** Currently disabled. All PreferSys32 tests start to explode on
+ // >= Win10 1703/RS2 when this mitigation is set pre-startup.
+ // Child process creation works fine, but when ::ResumeThread() is called,
+ // there is a fatal error: "Entry point ucnv_convertEx_60 could not be
+ // located in the DLL ... sbox_integration_tests.exe."
+ // This is a character conversion function in a ucnv (unicode) DLL.
+ // Potentially the loader is finding a different version of this DLL that
+ // we have a dependency on in System32... but it doesn't match up with
+ // what we build against???!
+ //---------------------------------
+
+ //---------------------------------
+ // 2) Test setting post-startup.
+ //---------------------------------
+ TestRunner runner2;
+ sandbox::TargetPolicy* policy2 = runner2.GetPolicy();
+
+ EXPECT_EQ(
+ policy2->SetDelayedProcessMitigations(MITIGATION_IMAGE_LOAD_PREFER_SYS32),
+ SBOX_ALL_OK);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner2.RunTest(test_command.c_str()));
+}
+
} // namespace sandbox
diff --git a/chromium/sandbox/win/src/process_thread_interception.cc b/chromium/sandbox/win/src/process_thread_interception.cc
index 4a9fff232aa..a0de6e68add 100644
--- a/chromium/sandbox/win/src/process_thread_interception.cc
+++ b/chromium/sandbox/win/src/process_thread_interception.cc
@@ -18,8 +18,6 @@
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,
diff --git a/chromium/sandbox/win/src/process_thread_policy.cc b/chromium/sandbox/win/src/process_thread_policy.cc
index 636f1ddf723..66b0a8a44e0 100644
--- a/chromium/sandbox/win/src/process_thread_policy.cc
+++ b/chromium/sandbox/win/src/process_thread_policy.cc
@@ -14,6 +14,7 @@
#include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/src/policy_engine_opcodes.h"
#include "sandbox/win/src/policy_params.h"
+#include "sandbox/win/src/sandbox_nt_util.h"
#include "sandbox/win/src/sandbox_types.h"
#include "sandbox/win/src/win_utils.h"
@@ -24,10 +25,6 @@ NTSTATUS ProcessPolicy::OpenThreadAction(const ClientInfo& client_info,
uint32_t thread_id,
HANDLE* handle) {
*handle = nullptr;
-
- NtOpenThreadFunction NtOpenThread = nullptr;
- ResolveNTFunctionPtr("NtOpenThread", &NtOpenThread);
-
OBJECT_ATTRIBUTES attributes = {0};
attributes.Length = sizeof(attributes);
CLIENT_ID client_id = {0};
@@ -37,8 +34,8 @@ NTSTATUS ProcessPolicy::OpenThreadAction(const ClientInfo& client_info,
reinterpret_cast<PVOID>(static_cast<ULONG_PTR>(thread_id));
HANDLE local_handle = nullptr;
- NTSTATUS status =
- NtOpenThread(&local_handle, desired_access, &attributes, &client_id);
+ NTSTATUS status = GetNtExports()->OpenThread(&local_handle, desired_access,
+ &attributes, &client_id);
if (NT_SUCCESS(status)) {
if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
client_info.process, handle, 0, false,
@@ -56,9 +53,6 @@ NTSTATUS ProcessPolicy::OpenProcessAction(const ClientInfo& client_info,
HANDLE* handle) {
*handle = nullptr;
- NtOpenProcessFunction NtOpenProcess = nullptr;
- ResolveNTFunctionPtr("NtOpenProcess", &NtOpenProcess);
-
if (client_info.process_id != process_id)
return STATUS_ACCESS_DENIED;
@@ -68,8 +62,8 @@ NTSTATUS ProcessPolicy::OpenProcessAction(const ClientInfo& client_info,
client_id.UniqueProcess =
reinterpret_cast<PVOID>(static_cast<ULONG_PTR>(client_info.process_id));
HANDLE local_handle = nullptr;
- NTSTATUS status =
- NtOpenProcess(&local_handle, desired_access, &attributes, &client_id);
+ NTSTATUS status = GetNtExports()->OpenProcess(&local_handle, desired_access,
+ &attributes, &client_id);
if (NT_SUCCESS(status)) {
if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
client_info.process, handle, 0, false,
@@ -86,15 +80,12 @@ NTSTATUS ProcessPolicy::OpenProcessTokenAction(const ClientInfo& client_info,
uint32_t desired_access,
HANDLE* handle) {
*handle = nullptr;
- NtOpenProcessTokenFunction NtOpenProcessToken = nullptr;
- ResolveNTFunctionPtr("NtOpenProcessToken", &NtOpenProcessToken);
-
if (CURRENT_PROCESS != process)
return STATUS_ACCESS_DENIED;
HANDLE local_handle = nullptr;
- NTSTATUS status =
- NtOpenProcessToken(client_info.process, desired_access, &local_handle);
+ NTSTATUS status = GetNtExports()->OpenProcessToken(
+ client_info.process, desired_access, &local_handle);
if (NT_SUCCESS(status)) {
if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
client_info.process, handle, 0, false,
@@ -111,15 +102,12 @@ NTSTATUS ProcessPolicy::OpenProcessTokenExAction(const ClientInfo& client_info,
uint32_t attributes,
HANDLE* handle) {
*handle = nullptr;
- NtOpenProcessTokenExFunction NtOpenProcessTokenEx = nullptr;
- ResolveNTFunctionPtr("NtOpenProcessTokenEx", &NtOpenProcessTokenEx);
-
if (CURRENT_PROCESS != process)
return STATUS_ACCESS_DENIED;
HANDLE local_handle = nullptr;
- NTSTATUS status = NtOpenProcessTokenEx(client_info.process, desired_access,
- attributes, &local_handle);
+ NTSTATUS status = GetNtExports()->OpenProcessTokenEx(
+ client_info.process, desired_access, attributes, &local_handle);
if (NT_SUCCESS(status)) {
if (!::DuplicateHandle(::GetCurrentProcess(), local_handle,
client_info.process, handle, 0, false,
diff --git a/chromium/sandbox/win/src/restricted_token_utils.cc b/chromium/sandbox/win/src/restricted_token_utils.cc
index f865c3e804c..3ca5062008f 100644
--- a/chromium/sandbox/win/src/restricted_token_utils.cc
+++ b/chromium/sandbox/win/src/restricted_token_utils.cc
@@ -17,6 +17,7 @@
#include "base/win/windows_version.h"
#include "sandbox/win/src/job.h"
#include "sandbox/win/src/restricted_token.h"
+#include "sandbox/win/src/sandbox_nt_util.h"
#include "sandbox/win/src/sandbox_utils.h"
#include "sandbox/win/src/security_level.h"
#include "sandbox/win/src/win_utils.h"
@@ -379,21 +380,18 @@ DWORD CreateLowBoxObjectDirectory(const base::win::Sid& lowbox_sid,
base::StringPrintf(L"\\Sessions\\%d\\AppContainerNamedObjects\\%ls",
session_id, sid_string->c_str());
- NtCreateDirectoryObjectFunction CreateObjectDirectory = nullptr;
- ResolveNTFunctionPtr("NtCreateDirectoryObject", &CreateObjectDirectory);
-
OBJECT_ATTRIBUTES obj_attr;
UNICODE_STRING obj_name;
DWORD attributes = OBJ_CASE_INSENSITIVE;
if (open_directory)
attributes |= OBJ_OPENIF;
- sandbox::InitObjectAttribs(directory_path, attributes, nullptr, &obj_attr,
- &obj_name, nullptr);
+ InitObjectAttribs(directory_path, attributes, nullptr, &obj_attr, &obj_name,
+ nullptr);
HANDLE handle = nullptr;
- NTSTATUS status =
- CreateObjectDirectory(&handle, DIRECTORY_ALL_ACCESS, &obj_attr);
+ NTSTATUS status = GetNtExports()->CreateDirectoryObject(
+ &handle, DIRECTORY_ALL_ACCESS, &obj_attr);
if (!NT_SUCCESS(status))
return GetLastErrorFromNtStatus(status);
diff --git a/chromium/sandbox/win/src/sandbox_nt_types.h b/chromium/sandbox/win/src/sandbox_nt_types.h
index 6700e5c51ac..58e033d7209 100644
--- a/chromium/sandbox/win/src/sandbox_nt_types.h
+++ b/chromium/sandbox/win/src/sandbox_nt_types.h
@@ -10,18 +10,31 @@
namespace sandbox {
struct NtExports {
+ bool Initialized;
NtAllocateVirtualMemoryFunction AllocateVirtualMemory;
+ NtCreateDirectoryObjectFunction CreateDirectoryObject;
+ NtCreateFileFunction CreateFile;
+ NtCreateSectionFunction CreateSection;
NtCloseFunction Close;
NtDuplicateObjectFunction DuplicateObject;
NtFreeVirtualMemoryFunction FreeVirtualMemory;
NtMapViewOfSectionFunction MapViewOfSection;
+ NtOpenFileFunction OpenFile;
+ NtOpenThreadFunction OpenThread;
+ NtOpenProcessFunction OpenProcess;
+ NtOpenProcessTokenFunction OpenProcessToken;
+ NtOpenProcessTokenExFunction OpenProcessTokenEx;
NtProtectVirtualMemoryFunction ProtectVirtualMemory;
+ NtQueryAttributesFileFunction QueryAttributesFile;
+ NtQueryFullAttributesFileFunction QueryFullAttributesFile;
NtQueryInformationProcessFunction QueryInformationProcess;
NtQueryObjectFunction QueryObject;
NtQuerySectionFunction QuerySection;
NtQueryVirtualMemoryFunction QueryVirtualMemory;
- NtUnmapViewOfSectionFunction UnmapViewOfSection;
+ NtSetInformationFileFunction SetInformationFile;
+ NtSetInformationProcessFunction SetInformationProcess;
NtSignalAndWaitForSingleObjectFunction SignalAndWaitForSingleObject;
+ NtUnmapViewOfSectionFunction UnmapViewOfSection;
NtWaitForSingleObjectFunction WaitForSingleObject;
RtlAllocateHeapFunction RtlAllocateHeap;
RtlAnsiStringToUnicodeStringFunction RtlAnsiStringToUnicodeString;
@@ -30,6 +43,7 @@ struct NtExports {
RtlCreateUserThreadFunction RtlCreateUserThread;
RtlDestroyHeapFunction RtlDestroyHeap;
RtlFreeHeapFunction RtlFreeHeap;
+ RtlNtStatusToDosErrorFunction RtlNtStatusToDosError;
_strnicmpFunction _strnicmp;
strlenFunction strlen;
wcslenFunction wcslen;
diff --git a/chromium/sandbox/win/src/sandbox_nt_util.cc b/chromium/sandbox/win/src/sandbox_nt_util.cc
index 8ba59ff7bf9..c17b311452d 100644
--- a/chromium/sandbox/win/src/sandbox_nt_util.cc
+++ b/chromium/sandbox/win/src/sandbox_nt_util.cc
@@ -11,6 +11,7 @@
#include "base/compiler_specific.h"
#include "base/win/pe_image.h"
+#include "sandbox/win/src/internal_types.h"
#include "sandbox/win/src/sandbox_factory.h"
#include "sandbox/win/src/target_services.h"
@@ -40,7 +41,6 @@ inline char* AlignToBoundary(void* ptr, size_t increment) {
// This is used for the DLL hooking code to get a valid trampoline location
// which must be within +/- 2GiB of the base. We only consider +2GiB for now.
void* AllocateNearTo(void* source, size_t size) {
- using sandbox::g_nt;
// 2GiB, maximum upper bound the allocation address must be within.
const size_t kMaxSize = 0x80000000ULL;
// We don't support null as a base as this would just pick an arbitrary
@@ -61,9 +61,9 @@ void* AllocateNearTo(void* source, size_t size) {
while (base < top_address) {
// Avoid memset inserted by -ftrivial-auto-var-init=pattern.
STACK_UNINITIALIZED MEMORY_BASIC_INFORMATION mem_info;
- NTSTATUS status =
- g_nt.QueryVirtualMemory(NtCurrentProcess, base, MemoryBasicInformation,
- &mem_info, sizeof(mem_info), nullptr);
+ NTSTATUS status = sandbox::GetNtExports()->QueryVirtualMemory(
+ NtCurrentProcess, base, MemoryBasicInformation, &mem_info,
+ sizeof(mem_info), nullptr);
if (!NT_SUCCESS(status))
break;
@@ -72,9 +72,9 @@ void* AllocateNearTo(void* source, size_t size) {
// Note that we need to both commit and reserve the block for the
// allocation to succeed as per Windows virtual memory requirements.
void* ret_base = mem_info.BaseAddress;
- status =
- g_nt.AllocateVirtualMemory(NtCurrentProcess, &ret_base, 0, &size,
- MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+ status = sandbox::GetNtExports()->AllocateVirtualMemory(
+ NtCurrentProcess, &ret_base, 0, &size, MEM_COMMIT | MEM_RESERVE,
+ PAGE_READWRITE);
// Shouldn't fail, but if it does we'll just continue and try next block.
if (NT_SUCCESS(status))
return ret_base;
@@ -89,8 +89,6 @@ void* AllocateNearTo(void* source, size_t size) {
}
#else // defined(_WIN64).
void* AllocateNearTo(void* source, size_t size) {
- using sandbox::g_nt;
-
// In 32-bit processes allocations below 512k are predictable, so mark
// anything in that range as reserved and retry until we get a good address.
const void* const kMinAddress = reinterpret_cast<void*>(512 * 1024);
@@ -100,21 +98,74 @@ void* AllocateNearTo(void* source, size_t size) {
do {
base = nullptr;
actual_size = 64 * 1024;
- ret = g_nt.AllocateVirtualMemory(NtCurrentProcess, &base, 0, &actual_size,
- MEM_RESERVE, PAGE_NOACCESS);
+ ret = sandbox::GetNtExports()->AllocateVirtualMemory(
+ NtCurrentProcess, &base, 0, &actual_size, MEM_RESERVE, PAGE_NOACCESS);
if (!NT_SUCCESS(ret))
return nullptr;
} while (base < kMinAddress);
actual_size = size;
- ret = g_nt.AllocateVirtualMemory(NtCurrentProcess, &base, 0, &actual_size,
- MEM_COMMIT, PAGE_READWRITE);
+ ret = sandbox::GetNtExports()->AllocateVirtualMemory(
+ NtCurrentProcess, &base, 0, &actual_size, MEM_COMMIT, PAGE_READWRITE);
if (!NT_SUCCESS(ret))
return nullptr;
return base;
}
#endif // defined(_WIN64).
+template <typename T>
+void InitFunc(const base::win::PEImage& image, T& member, const char* name) {
+ member = reinterpret_cast<T>(image.GetProcAddress(name));
+ DCHECK(member);
+}
+
+#define INIT_NT(member) InitFunc(image, sandbox::g_nt.member, "Nt" #member)
+#define INIT_RTL(member) InitFunc(image, sandbox::g_nt.member, #member)
+
+void InitGlobalNt() {
+ HMODULE ntdll = ::GetModuleHandle(sandbox::kNtdllName);
+ base::win::PEImage image(ntdll);
+ INIT_NT(AllocateVirtualMemory);
+ INIT_NT(CreateDirectoryObject);
+ INIT_NT(CreateFile);
+ INIT_NT(CreateSection);
+ INIT_NT(Close);
+ INIT_NT(DuplicateObject);
+ INIT_NT(FreeVirtualMemory);
+ INIT_NT(MapViewOfSection);
+ INIT_NT(OpenFile);
+ INIT_NT(OpenThread);
+ INIT_NT(OpenProcess);
+ INIT_NT(OpenProcessToken);
+ INIT_NT(OpenProcessTokenEx);
+ INIT_NT(ProtectVirtualMemory);
+ INIT_NT(QueryAttributesFile);
+ INIT_NT(QueryFullAttributesFile);
+ INIT_NT(QueryInformationProcess);
+ INIT_NT(QueryObject);
+ INIT_NT(QuerySection);
+ INIT_NT(QueryVirtualMemory);
+ INIT_NT(SetInformationFile);
+ INIT_NT(SetInformationProcess);
+ INIT_NT(SignalAndWaitForSingleObject);
+ INIT_NT(UnmapViewOfSection);
+ INIT_NT(WaitForSingleObject);
+
+ INIT_RTL(RtlAllocateHeap);
+ INIT_RTL(RtlAnsiStringToUnicodeString);
+ INIT_RTL(RtlCompareUnicodeString);
+ INIT_RTL(RtlCreateHeap);
+ INIT_RTL(RtlCreateUserThread);
+ INIT_RTL(RtlDestroyHeap);
+ INIT_RTL(RtlFreeHeap);
+ INIT_RTL(RtlNtStatusToDosError);
+ INIT_RTL(_strnicmp);
+ INIT_RTL(strlen);
+ INIT_RTL(wcslen);
+ INIT_RTL(memcpy);
+ sandbox::g_nt.Initialized = true;
+}
+
} // namespace.
namespace sandbox {
@@ -136,9 +187,9 @@ bool MapGlobalMemory() {
void* memory = nullptr;
SIZE_T size = 0;
// Map the entire shared section from the start.
- NTSTATUS ret =
- g_nt.MapViewOfSection(g_shared_section, NtCurrentProcess, &memory, 0, 0,
- nullptr, &size, ViewUnmap, 0, PAGE_READWRITE);
+ NTSTATUS ret = GetNtExports()->MapViewOfSection(
+ g_shared_section, NtCurrentProcess, &memory, 0, 0, nullptr, &size,
+ ViewUnmap, 0, PAGE_READWRITE);
if (!NT_SUCCESS(ret) || !memory) {
NOTREACHED_NT();
@@ -148,7 +199,8 @@ bool MapGlobalMemory() {
if (_InterlockedCompareExchangePointer(&g_shared_IPC_memory, memory,
nullptr)) {
// Somebody beat us to the memory setup.
- VERIFY_SUCCESS(g_nt.UnmapViewOfSection(NtCurrentProcess, memory));
+ VERIFY_SUCCESS(
+ GetNtExports()->UnmapViewOfSection(NtCurrentProcess, memory));
}
DCHECK_NT(g_shared_IPC_size > 0);
g_shared_policy_memory =
@@ -171,17 +223,24 @@ void* GetGlobalPolicyMemory() {
return g_shared_policy_memory;
}
+const NtExports* GetNtExports() {
+ if (!g_nt.Initialized)
+ InitGlobalNt();
+
+ return &g_nt;
+}
+
bool InitHeap() {
if (!g_heap) {
// Create a new heap using default values for everything.
- void* heap =
- g_nt.RtlCreateHeap(HEAP_GROWABLE, nullptr, 0, 0, nullptr, nullptr);
+ void* heap = GetNtExports()->RtlCreateHeap(HEAP_GROWABLE, nullptr, 0, 0,
+ nullptr, nullptr);
if (!heap)
return false;
if (_InterlockedCompareExchangePointer(&g_heap, heap, nullptr)) {
// Somebody beat us to the memory setup.
- g_nt.RtlDestroyHeap(heap);
+ GetNtExports()->RtlDestroyHeap(heap);
}
}
return !!g_heap;
@@ -223,113 +282,48 @@ bool ValidParameter(void* buffer, size_t size, RequiredAccess intent) {
NTSTATUS CopyData(void* destination, const void* source, size_t bytes) {
NTSTATUS ret = STATUS_SUCCESS;
__try {
- g_nt.memcpy(destination, source, bytes);
+ GetNtExports()->memcpy(destination, source, bytes);
} __except (EXCEPTION_EXECUTE_HANDLER) {
ret = GetExceptionCode();
}
return ret;
}
-NTSTATUS AllocAndGetFullPath(
- HANDLE root,
- const wchar_t* path,
- std::unique_ptr<wchar_t, NtAllocDeleter>* full_path) {
- if (!InitHeap())
- return STATUS_NO_MEMORY;
-
- DCHECK_NT(full_path);
- DCHECK_NT(path);
- NTSTATUS ret = STATUS_UNSUCCESSFUL;
- __try {
- do {
- static NtQueryObjectFunction NtQueryObject = nullptr;
- if (!NtQueryObject)
- ResolveNTFunctionPtr("NtQueryObject", &NtQueryObject);
-
- ULONG size = 0;
- // Query the name information a first time to get the size of the name.
- ret = NtQueryObject(root, ObjectNameInformation, nullptr, 0, &size);
-
- std::unique_ptr<OBJECT_NAME_INFORMATION, NtAllocDeleter> handle_name;
- if (size) {
- handle_name.reset(reinterpret_cast<OBJECT_NAME_INFORMATION*>(
- new (NT_ALLOC) BYTE[size]));
-
- // Query the name information a second time to get the name of the
- // object referenced by the handle.
- ret = NtQueryObject(root, ObjectNameInformation, handle_name.get(),
- size, &size);
- }
-
- if (STATUS_SUCCESS != ret)
- break;
-
- // Space for path + '\' + name + '\0'.
- size_t name_length =
- handle_name->ObjectName.Length + (wcslen(path) + 2) * sizeof(wchar_t);
- full_path->reset(new (NT_ALLOC) wchar_t[name_length / sizeof(wchar_t)]);
- if (!*full_path)
- break;
- wchar_t* off = full_path->get();
- ret = CopyData(off, handle_name->ObjectName.Buffer,
- handle_name->ObjectName.Length);
- if (!NT_SUCCESS(ret))
- break;
- off += handle_name->ObjectName.Length / sizeof(wchar_t);
- *off = L'\\';
- off += 1;
- ret = CopyData(off, path, wcslen(path) * sizeof(wchar_t));
- if (!NT_SUCCESS(ret))
- break;
- off += wcslen(path);
- *off = L'\0';
- } while (false);
- } __except (EXCEPTION_EXECUTE_HANDLER) {
- ret = GetExceptionCode();
- }
-
- if (!NT_SUCCESS(ret) && *full_path)
- full_path->reset(nullptr);
-
- return ret;
-}
-
-// Hacky code... replace with AllocAndCopyObjectAttributes.
-NTSTATUS AllocAndCopyName(const OBJECT_ATTRIBUTES* in_object,
- std::unique_ptr<wchar_t, NtAllocDeleter>* out_name,
- uint32_t* attributes,
- HANDLE* root) {
+NTSTATUS CopyNameAndAttributes(
+ const OBJECT_ATTRIBUTES* in_object,
+ std::unique_ptr<wchar_t, NtAllocDeleter>* out_name,
+ size_t* out_name_len,
+ uint32_t* attributes) {
if (!InitHeap())
return STATUS_NO_MEMORY;
DCHECK_NT(out_name);
+ DCHECK_NT(out_name_len);
NTSTATUS ret = STATUS_UNSUCCESSFUL;
__try {
do {
- if (in_object->RootDirectory != static_cast<HANDLE>(0) && !root)
+ if (in_object->RootDirectory != nullptr)
break;
if (!in_object->ObjectName)
break;
if (!in_object->ObjectName->Buffer)
break;
- size_t size = in_object->ObjectName->Length + sizeof(wchar_t);
- out_name->reset(new (NT_ALLOC) wchar_t[size / sizeof(wchar_t)]);
+ size_t size = in_object->ObjectName->Length / sizeof(wchar_t);
+ out_name->reset(new (NT_ALLOC) wchar_t[size + 1]);
if (!*out_name)
break;
ret = CopyData(out_name->get(), in_object->ObjectName->Buffer,
- size - sizeof(wchar_t));
+ size * sizeof(wchar_t));
if (!NT_SUCCESS(ret))
break;
- out_name->get()[size / sizeof(wchar_t) - 1] = L'\0';
-
+ *out_name_len = size;
+ out_name->get()[size] = L'\0';
if (attributes)
*attributes = in_object->Attributes;
- if (root)
- *root = in_object->RootDirectory;
ret = STATUS_SUCCESS;
} while (false);
} __except (EXCEPTION_EXECUTE_HANDLER) {
@@ -346,9 +340,9 @@ NTSTATUS GetProcessId(HANDLE process, DWORD* process_id) {
PROCESS_BASIC_INFORMATION proc_info;
ULONG bytes_returned;
- NTSTATUS ret =
- g_nt.QueryInformationProcess(process, ProcessBasicInformation, &proc_info,
- sizeof(proc_info), &bytes_returned);
+ NTSTATUS ret = GetNtExports()->QueryInformationProcess(
+ process, ProcessBasicInformation, &proc_info, sizeof(proc_info),
+ &bytes_returned);
if (!NT_SUCCESS(ret) || sizeof(proc_info) != bytes_returned)
return ret;
@@ -385,18 +379,19 @@ bool IsValidImageSection(HANDLE section,
HANDLE query_section;
- NTSTATUS ret =
- g_nt.DuplicateObject(NtCurrentProcess, section, NtCurrentProcess,
- &query_section, SECTION_QUERY, 0, 0);
+ NTSTATUS ret = GetNtExports()->DuplicateObject(
+ NtCurrentProcess, section, NtCurrentProcess, &query_section,
+ SECTION_QUERY, 0, 0);
if (!NT_SUCCESS(ret))
return false;
SECTION_BASIC_INFORMATION basic_info;
SIZE_T bytes_returned;
- ret = g_nt.QuerySection(query_section, SectionBasicInformation, &basic_info,
- sizeof(basic_info), &bytes_returned);
+ ret = GetNtExports()->QuerySection(query_section, SectionBasicInformation,
+ &basic_info, sizeof(basic_info),
+ &bytes_returned);
- VERIFY_SUCCESS(g_nt.Close(query_section));
+ VERIFY_SUCCESS(GetNtExports()->Close(query_section));
if (!NT_SUCCESS(ret) || sizeof(basic_info) != bytes_returned)
return false;
@@ -410,8 +405,8 @@ bool IsValidImageSection(HANDLE section,
// Avoid memset inserted by -ftrivial-auto-var-init=pattern.
STACK_UNINITIALIZED OBJECT_BASIC_INFORMATION obj_info;
ULONG obj_size_returned;
- ret = g_nt.QueryObject(section, ObjectBasicInformation, &obj_info,
- sizeof(obj_info), &obj_size_returned);
+ ret = GetNtExports()->QueryObject(section, ObjectBasicInformation, &obj_info,
+ sizeof(obj_info), &obj_size_returned);
if (!NT_SUCCESS(ret) || sizeof(obj_info) != obj_size_returned)
return false;
@@ -424,7 +419,7 @@ bool IsValidImageSection(HANDLE section,
UNICODE_STRING* AnsiToUnicode(const char* string) {
ANSI_STRING ansi_string;
- ansi_string.Length = static_cast<USHORT>(g_nt.strlen(string));
+ ansi_string.Length = static_cast<USHORT>(GetNtExports()->strlen(string));
ansi_string.MaximumLength = ansi_string.Length + 1;
ansi_string.Buffer = const_cast<char*>(string);
@@ -443,8 +438,8 @@ UNICODE_STRING* AnsiToUnicode(const char* string) {
out_string->Buffer = reinterpret_cast<wchar_t*>(&out_string[1]);
BOOLEAN alloc_destination = false;
- NTSTATUS ret = g_nt.RtlAnsiStringToUnicodeString(out_string, &ansi_string,
- alloc_destination);
+ NTSTATUS ret = GetNtExports()->RtlAnsiStringToUnicodeString(
+ out_string, &ansi_string, alloc_destination);
DCHECK_NT(STATUS_BUFFER_OVERFLOW != ret);
if (!NT_SUCCESS(ret)) {
operator delete(out_string, NT_ALLOC);
@@ -524,9 +519,9 @@ UNICODE_STRING* GetBackingFilePath(PVOID address) {
return nullptr;
SIZE_T returned_bytes;
- NTSTATUS ret =
- g_nt.QueryVirtualMemory(NtCurrentProcess, address, MemorySectionName,
- section_name, buffer_bytes, &returned_bytes);
+ NTSTATUS ret = GetNtExports()->QueryVirtualMemory(
+ NtCurrentProcess, address, MemorySectionName, section_name,
+ buffer_bytes, &returned_bytes);
if (STATUS_BUFFER_OVERFLOW == ret) {
// Retry the call with the given buffer size.
@@ -598,8 +593,8 @@ NTSTATUS AutoProtectMemory::ChangeProtection(void* address,
ULONG protect) {
DCHECK_NT(!changed_);
SIZE_T new_bytes = bytes;
- NTSTATUS ret = g_nt.ProtectVirtualMemory(NtCurrentProcess, &address,
- &new_bytes, protect, &old_protect_);
+ NTSTATUS ret = GetNtExports()->ProtectVirtualMemory(
+ NtCurrentProcess, &address, &new_bytes, protect, &old_protect_);
if (NT_SUCCESS(ret)) {
changed_ = true;
address_ = address;
@@ -617,7 +612,7 @@ NTSTATUS AutoProtectMemory::RevertProtection() {
DCHECK_NT(bytes_);
SIZE_T new_bytes = bytes_;
- NTSTATUS ret = g_nt.ProtectVirtualMemory(
+ NTSTATUS ret = GetNtExports()->ProtectVirtualMemory(
NtCurrentProcess, &address_, &new_bytes, old_protect_, &old_protect_);
DCHECK_NT(NT_SUCCESS(ret));
@@ -669,8 +664,8 @@ bool NtGetPathFromHandle(HANDLE handle,
OBJECT_NAME_INFORMATION* name;
ULONG size = 0;
// Query the name information a first time to get the size of the name.
- NTSTATUS status = g_nt.QueryObject(handle, ObjectNameInformation,
- &initial_buffer, size, &size);
+ NTSTATUS status = GetNtExports()->QueryObject(handle, ObjectNameInformation,
+ &initial_buffer, size, &size);
if (!NT_SUCCESS(status) && status != STATUS_INFO_LENGTH_MISMATCH)
return false;
@@ -683,7 +678,8 @@ bool NtGetPathFromHandle(HANDLE handle,
// Query the name information a second time to get the name of the
// object referenced by the handle.
- status = g_nt.QueryObject(handle, ObjectNameInformation, name, size, &size);
+ status = GetNtExports()->QueryObject(handle, ObjectNameInformation, name,
+ size, &size);
if (STATUS_SUCCESS != status)
return false;
@@ -704,7 +700,8 @@ void* operator new(size_t size, sandbox::AllocationType type, void* near_to) {
if (type == sandbox::NT_ALLOC) {
if (sandbox::InitHeap()) {
// Use default flags for the allocation.
- result = sandbox::g_nt.RtlAllocateHeap(sandbox::g_heap, 0, size);
+ result =
+ sandbox::GetNtExports()->RtlAllocateHeap(sandbox::g_heap, 0, size);
}
} else if (type == sandbox::NT_PAGE) {
result = AllocateNearTo(near_to, size);
@@ -722,12 +719,12 @@ void* operator new(size_t size, sandbox::AllocationType type, void* near_to) {
void operator delete(void* memory, sandbox::AllocationType type) {
if (type == sandbox::NT_ALLOC) {
// Use default flags.
- VERIFY(sandbox::g_nt.RtlFreeHeap(sandbox::g_heap, 0, memory));
+ VERIFY(sandbox::GetNtExports()->RtlFreeHeap(sandbox::g_heap, 0, memory));
} else if (type == sandbox::NT_PAGE) {
void* base = memory;
SIZE_T size = 0;
- VERIFY_SUCCESS(sandbox::g_nt.FreeVirtualMemory(NtCurrentProcess, &base,
- &size, MEM_RELEASE));
+ VERIFY_SUCCESS(sandbox::GetNtExports()->FreeVirtualMemory(
+ NtCurrentProcess, &base, &size, MEM_RELEASE));
} else {
NOTREACHED_NT();
}
diff --git a/chromium/sandbox/win/src/sandbox_nt_util.h b/chromium/sandbox/win/src/sandbox_nt_util.h
index f7a91d8eefa..cfe109aa2b7 100644
--- a/chromium/sandbox/win/src/sandbox_nt_util.h
+++ b/chromium/sandbox/win/src/sandbox_nt_util.h
@@ -101,6 +101,9 @@ void* GetGlobalIPCMemory();
// Returns a pointer to the Policy shared memory.
void* GetGlobalPolicyMemory();
+// Returns a reference to imported NT functions.
+const NtExports* GetNtExports();
+
enum RequiredAccess { READ, WRITE };
// Performs basic user mode buffer validation. In any case, buffers access must
@@ -111,17 +114,14 @@ bool ValidParameter(void* buffer, size_t size, RequiredAccess intent);
// Copies data from a user buffer to our buffer. Returns the operation status.
NTSTATUS CopyData(void* destination, const void* source, size_t bytes);
-// Copies the name from an object attributes.
-NTSTATUS AllocAndCopyName(const OBJECT_ATTRIBUTES* in_object,
- std::unique_ptr<wchar_t, NtAllocDeleter>* out_name,
- uint32_t* attributes,
- HANDLE* root);
-
-// Determine full path name from object root and path.
-NTSTATUS AllocAndGetFullPath(
- HANDLE root,
- const wchar_t* path,
- std::unique_ptr<wchar_t, NtAllocDeleter>* full_path);
+// Copies the name from an object attributes. |out_name| is a NUL terminated
+// string and |out_name_len| is the number of characters copied. |attributes|
+// is a copy of the attribute flags from |in_object|.
+NTSTATUS CopyNameAndAttributes(
+ const OBJECT_ATTRIBUTES* in_object,
+ std::unique_ptr<wchar_t, NtAllocDeleter>* out_name,
+ size_t* out_name_len,
+ uint32_t* attributes = nullptr);
// Initializes our ntdll level heap
bool InitHeap();
diff --git a/chromium/sandbox/win/src/sandbox_nt_util_unittest.cc b/chromium/sandbox/win/src/sandbox_nt_util_unittest.cc
index 011f1dbb326..6da41b2b159 100644
--- a/chromium/sandbox/win/src/sandbox_nt_util_unittest.cc
+++ b/chromium/sandbox/win/src/sandbox_nt_util_unittest.cc
@@ -9,6 +9,7 @@
#include <memory>
#include <vector>
+#include "base/cxx17_backports.h"
#include "base/files/file.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
@@ -22,15 +23,11 @@ namespace sandbox {
namespace {
TEST(SandboxNtUtil, IsSameProcessPseudoHandle) {
- InitGlobalNt();
-
HANDLE current_process_pseudo = GetCurrentProcess();
EXPECT_TRUE(IsSameProcess(current_process_pseudo));
}
TEST(SandboxNtUtil, IsSameProcessNonPseudoHandle) {
- InitGlobalNt();
-
base::win::ScopedHandle current_process(
OpenProcess(PROCESS_QUERY_INFORMATION, false, GetCurrentProcessId()));
ASSERT_TRUE(current_process.IsValid());
@@ -38,8 +35,6 @@ TEST(SandboxNtUtil, IsSameProcessNonPseudoHandle) {
}
TEST(SandboxNtUtil, IsSameProcessDifferentProcess) {
- InitGlobalNt();
-
STARTUPINFO si = {sizeof(si)};
PROCESS_INFORMATION pi = {};
wchar_t notepad[] = L"notepad";
@@ -183,7 +178,6 @@ void TestExtremes() {
// Test nearest allocator, only do this for 64 bit. We test through the exposed
// new operator as we can't call the AllocateNearTo function directly.
TEST(SandboxNtUtil, NearestAllocator) {
- InitGlobalNt();
std::vector<unique_ptr_vmem> mem_range;
AllocateTestRange(&mem_range);
ASSERT_LT(0U, mem_range.size());
@@ -242,8 +236,6 @@ TEST(SandboxNtUtil, ValidParameter) {
}
TEST(SandboxNtUtil, NtGetPathFromHandle) {
- InitGlobalNt();
-
base::FilePath exe;
ASSERT_TRUE(base::PathService::Get(base::FILE_EXE, &exe));
base::File exe_file(exe, base::File::FLAG_OPEN);
@@ -263,5 +255,50 @@ TEST(SandboxNtUtil, NtGetPathFromHandle) {
EXPECT_STREQ(path.get(), nt_path.c_str());
}
+TEST(SandboxNtUtil, CopyNameAndAttributes) {
+ OBJECT_ATTRIBUTES object_attributes;
+ InitializeObjectAttributes(&object_attributes, nullptr, 0, nullptr, nullptr);
+ std::unique_ptr<wchar_t, NtAllocDeleter> name;
+ size_t name_len;
+ uint32_t attributes;
+ EXPECT_EQ(STATUS_UNSUCCESSFUL,
+ sandbox::CopyNameAndAttributes(&object_attributes, &name, &name_len,
+ &attributes));
+ UNICODE_STRING object_name = {};
+ InitializeObjectAttributes(&object_attributes, &object_name, 0,
+ reinterpret_cast<HANDLE>(0x88), nullptr);
+ EXPECT_EQ(STATUS_UNSUCCESSFUL,
+ sandbox::CopyNameAndAttributes(&object_attributes, &name, &name_len,
+ &attributes));
+ wchar_t name_buffer[] = {L'A', L'B', L'C', L'D'};
+ object_name.Length = static_cast<USHORT>(sizeof(name_buffer));
+ object_name.MaximumLength = object_name.Length;
+ object_name.Buffer = name_buffer;
+
+ InitializeObjectAttributes(&object_attributes, &object_name, 0,
+ reinterpret_cast<HANDLE>(0x88), nullptr);
+ EXPECT_EQ(STATUS_UNSUCCESSFUL,
+ sandbox::CopyNameAndAttributes(&object_attributes, &name, &name_len,
+ &attributes));
+ InitializeObjectAttributes(&object_attributes, &object_name, 0x12345678,
+ nullptr, nullptr);
+ ASSERT_EQ(STATUS_SUCCESS,
+ sandbox::CopyNameAndAttributes(&object_attributes, &name, &name_len,
+ &attributes));
+ EXPECT_EQ(object_attributes.Attributes, attributes);
+ EXPECT_EQ(base::size(name_buffer), name_len);
+ EXPECT_EQ(0, wcsncmp(name.get(), name_buffer, base::size(name_buffer)));
+ EXPECT_EQ(L'\0', name.get()[name_len]);
+}
+
+TEST(SandboxNtUtil, GetNtExports) {
+ const NtExports* exports = GetNtExports();
+ ASSERT_TRUE(exports);
+ static_assert((sizeof(NtExports) % sizeof(void*)) == 0);
+ // Verify that the structure is fully initialized.
+ for (size_t i = 0; i < sizeof(NtExports) / sizeof(void*); i++)
+ EXPECT_TRUE(reinterpret_cast<void* const*>(exports)[i]);
+}
+
} // namespace
} // namespace sandbox
diff --git a/chromium/sandbox/win/src/sandbox_policy.h b/chromium/sandbox/win/src/sandbox_policy.h
index 5f3f1896060..2d7b1767149 100644
--- a/chromium/sandbox/win/src/sandbox_policy.h
+++ b/chromium/sandbox/win/src/sandbox_policy.h
@@ -40,8 +40,6 @@ class TargetPolicy {
// the file system supports.
FILES_ALLOW_READONLY, // Allows open or create with read access only.
FILES_ALLOW_QUERY, // Allows access to query the attributes of a file.
- FILES_ALLOW_DIR_ANY, // Allows open or create with directory semantics
- // only.
NAMEDPIPES_ALLOW_ANY, // Allows creation of a named pipe.
FAKE_USER_GDI_INIT, // Fakes user32 and gdi32 initialization. This can
// be used to allow the DLLs to load and initialize
diff --git a/chromium/sandbox/win/src/sandbox_policy_base.cc b/chromium/sandbox/win/src/sandbox_policy_base.cc
index 580968c1ef1..9e9de1b138a 100644
--- a/chromium/sandbox/win/src/sandbox_policy_base.cc
+++ b/chromium/sandbox/win/src/sandbox_policy_base.cc
@@ -96,7 +96,6 @@ PolicyBase::PolicyBase()
memory_limit_(0),
use_alternate_desktop_(false),
use_alternate_winstation_(false),
- file_system_init_(false),
relaxed_interceptions_(true),
stdout_handle_(INVALID_HANDLE_VALUE),
stderr_handle_(INVALID_HANDLE_VALUE),
@@ -488,7 +487,10 @@ ResultCode PolicyBase::MakeTokens(base::win::ScopedHandle* initial,
return SBOX_ALL_OK;
}
-ResultCode PolicyBase::AddTarget(std::unique_ptr<TargetProcess> target) {
+ResultCode PolicyBase::ApplyToTarget(std::unique_ptr<TargetProcess> target) {
+ if (target_)
+ return SBOX_ERROR_UNEXPECTED_CALL;
+
if (policy_) {
if (!policy_maker_->Done())
return SBOX_ERROR_NO_SPACE;
@@ -537,27 +539,19 @@ ResultCode PolicyBase::AddTarget(std::unique_ptr<TargetProcess> target) {
if (SBOX_ALL_OK != ret)
return ret;
- base::AutoLock lock(lock_);
- targets_.push_back(std::move(target));
+ target_ = std::move(target);
return SBOX_ALL_OK;
}
bool PolicyBase::OnJobEmpty(HANDLE job) {
- base::AutoLock lock(lock_);
- targets_.erase(
- std::remove_if(targets_.begin(), targets_.end(),
- [&](auto&& p) -> bool { return p->Job() == job; }),
- targets_.end());
+ if (target_->Job() == job)
+ target_.reset();
return true;
}
bool PolicyBase::OnProcessFinished(DWORD process_id) {
- base::AutoLock lock(lock_);
- targets_.erase(std::remove_if(targets_.begin(), targets_.end(),
- [&](auto&& p) -> bool {
- return p->ProcessId() == process_id;
- }),
- targets_.end());
+ if (target_->ProcessId() == process_id)
+ target_.reset();
return true;
}
@@ -644,7 +638,7 @@ ResultCode PolicyBase::AddAppContainerProfile(const wchar_t* package_name,
}
scoped_refptr<AppContainer> PolicyBase::GetAppContainer() {
- return GetAppContainerBase();
+ return app_container_;
}
void PolicyBase::SetEffectiveToken(HANDLE token) {
@@ -652,10 +646,6 @@ void PolicyBase::SetEffectiveToken(HANDLE token) {
effective_token_ = token;
}
-scoped_refptr<AppContainerBase> PolicyBase::GetAppContainerBase() {
- return app_container_;
-}
-
ResultCode PolicyBase::SetupAllInterceptions(TargetProcess& target) {
InterceptionManager manager(target, relaxed_interceptions_);
@@ -700,11 +690,6 @@ ResultCode PolicyBase::AddRuleInternal(SubSystem subsystem,
switch (subsystem) {
case SUBSYS_FILES: {
- if (!file_system_init_) {
- if (!FileSystemPolicy::SetInitialRules(policy_maker_))
- return SBOX_ERROR_BAD_PARAMS;
- file_system_init_ = true;
- }
if (!FileSystemPolicy::GenerateRules(pattern, semantics, policy_maker_)) {
NOTREACHED();
return SBOX_ERROR_BAD_PARAMS;
diff --git a/chromium/sandbox/win/src/sandbox_policy_base.h b/chromium/sandbox/win/src/sandbox_policy_base.h
index 695e942ff14..a88a95bb111 100644
--- a/chromium/sandbox/win/src/sandbox_policy_base.h
+++ b/chromium/sandbox/win/src/sandbox_policy_base.h
@@ -85,9 +85,6 @@ class PolicyBase final : public TargetPolicy {
void SetAllowNoSandboxJob() override;
bool GetAllowNoSandboxJob() override;
- // Get the AppContainer profile as its internal type.
- scoped_refptr<AppContainerBase> GetAppContainerBase();
-
// Creates a Job object with the level specified in a previous call to
// SetJobLevel().
ResultCode MakeJobObject(base::win::ScopedHandle* job);
@@ -103,9 +100,9 @@ class PolicyBase final : public TargetPolicy {
base::win::ScopedHandle* lockdown,
base::win::ScopedHandle* lowbox);
- // Adds a target process to the internal list of targets. Internally a
+ // Applies the sandbox to |target| and takes ownership. Internally a
// call to TargetProcess::Init() is issued.
- ResultCode AddTarget(std::unique_ptr<TargetProcess> target);
+ ResultCode ApplyToTarget(std::unique_ptr<TargetProcess> target);
// Called when there are no more active processes in a Job.
// Removes a Job object associated with this policy and the target associated
@@ -139,12 +136,8 @@ class PolicyBase final : public TargetPolicy {
Semantics semantics,
const wchar_t* pattern);
- // This lock synchronizes operations on the targets_ collection.
- base::Lock lock_;
- // Maintains the list of target process associated with this policy.
- // The policy takes ownership of them.
- typedef std::list<std::unique_ptr<TargetProcess>> TargetSet;
- TargetSet targets_;
+ // The policy takes ownership of a target as it is applied to it.
+ std::unique_ptr<TargetProcess> target_;
// Standard object-lifetime reference counter.
volatile LONG ref_count;
// The user-defined global policy settings.
@@ -155,8 +148,6 @@ class PolicyBase final : public TargetPolicy {
size_t memory_limit_;
bool use_alternate_desktop_;
bool use_alternate_winstation_;
- // Helps the file system policy initialization.
- bool file_system_init_;
bool relaxed_interceptions_;
HANDLE stdout_handle_;
HANDLE stderr_handle_;
diff --git a/chromium/sandbox/win/src/sandbox_policy_diagnostic.cc b/chromium/sandbox/win/src/sandbox_policy_diagnostic.cc
index 660fe487048..19ed93fbeac 100644
--- a/chromium/sandbox/win/src/sandbox_policy_diagnostic.cc
+++ b/chromium/sandbox/win/src/sandbox_policy_diagnostic.cc
@@ -4,6 +4,7 @@
#include "sandbox/win/src/sandbox_policy_diagnostic.h"
+#include <Windows.h>
#include <stddef.h>
#include <cinttypes>
@@ -34,6 +35,7 @@ const char kAppContainerCapabilities[] = "appContainerCapabilities";
const char kAppContainerInitialCapabilities[] =
"appContainerInitialCapabilities";
const char kAppContainerSid[] = "appContainerSid";
+const char kComponentFilters[] = "componentFilters";
const char kDesiredIntegrityLevel[] = "desiredIntegrityLevel";
const char kDesiredMitigations[] = "desiredMitigations";
const char kDisconnectCsrss[] = "disconnectCsrss";
@@ -43,20 +45,12 @@ const char kLockdownLevel[] = "lockdownLevel";
const char kLowboxSid[] = "lowboxSid";
const char kPlatformMitigations[] = "platformMitigations";
const char kPolicyRules[] = "policyRules";
-const char kProcessIds[] = "processIds";
+const char kProcessId[] = "processId";
// Values in snapshots of Policies.
const char kDisabled[] = "disabled";
const char kEnabled[] = "enabled";
-base::Value ProcessIdList(std::vector<uint32_t> process_ids) {
- base::Value results(base::Value::Type::LIST);
- for (const auto pid : process_ids) {
- results.Append(base::strict_cast<double>(pid));
- }
- return results;
-}
-
std::string GetTokenLevelInEnglish(TokenLevel token) {
switch (token) {
case USER_LOCKDOWN:
@@ -144,6 +138,12 @@ std::string GetPlatformMitigationsAsHex(MitigationFlags mitigations) {
return base::StringPrintf("%016" PRIx64, platform_flags[0]);
}
+std::string GetComponentFilterAsHex(MitigationFlags mitigations) {
+ COMPONENT_FILTER filter;
+ sandbox::ConvertProcessMitigationsToComponentFilter(mitigations, &filter);
+ return base::StringPrintf("%08lx", filter.ComponentFlags);
+}
+
std::string GetIpcTagAsString(IpcTag service) {
switch (service) {
case IpcTag::UNUSED:
@@ -371,13 +371,7 @@ base::Value GetHandlesToClose(const HandleMap& handle_map) {
PolicyDiagnostic::PolicyDiagnostic(PolicyBase* policy) {
DCHECK(policy);
// TODO(crbug/997273) Add more fields once webui plumbing is complete.
- {
- base::AutoLock lock(policy->lock_);
- for (auto&& target_process : policy->targets_) {
- process_ids_.push_back(
- base::strict_cast<uint32_t>(target_process->ProcessId()));
- }
- }
+ process_id_ = base::strict_cast<uint32_t>(policy->target_->ProcessId());
lockdown_level_ = policy->lockdown_level_;
job_level_ = policy->job_level_;
@@ -432,7 +426,7 @@ const char* PolicyDiagnostic::JsonString() {
return json_string_->c_str();
base::Value value(base::Value::Type::DICTIONARY);
- value.SetKey(kProcessIds, ProcessIdList(process_ids_));
+ value.SetKey(kProcessId, base::Value(base::strict_cast<double>(process_id_)));
value.SetKey(kLockdownLevel,
base::Value(GetTokenLevelInEnglish(lockdown_level_)));
value.SetKey(kJobLevel, base::Value(GetJobLevelInEnglish(job_level_)));
@@ -443,6 +437,8 @@ const char* PolicyDiagnostic::JsonString() {
base::Value(GetMitigationsAsHex(desired_mitigations_)));
value.SetKey(kPlatformMitigations,
base::Value(GetPlatformMitigationsAsHex(desired_mitigations_)));
+ value.SetKey(kComponentFilters,
+ base::Value(GetComponentFilterAsHex(desired_mitigations_)));
if (app_container_sid_) {
value.SetStringKey(
diff --git a/chromium/sandbox/win/src/sandbox_policy_diagnostic.h b/chromium/sandbox/win/src/sandbox_policy_diagnostic.h
index 31f3a52fc10..9cb74679bac 100644
--- a/chromium/sandbox/win/src/sandbox_policy_diagnostic.h
+++ b/chromium/sandbox/win/src/sandbox_policy_diagnostic.h
@@ -41,7 +41,7 @@ class PolicyDiagnostic final : public PolicyInfo {
private:
// |json_string_| is lazily constructed.
std::unique_ptr<std::string> json_string_;
- std::vector<uint32_t> process_ids_;
+ uint32_t process_id_;
TokenLevel lockdown_level_ = USER_LAST;
JobLevel job_level_ = JOB_NONE;
IntegrityLevel desired_integrity_level_ = INTEGRITY_LEVEL_LAST;
diff --git a/chromium/sandbox/win/src/sandbox_types.h b/chromium/sandbox/win/src/sandbox_types.h
index 40ae300a27a..bfbfc15dbed 100644
--- a/chromium/sandbox/win/src/sandbox_types.h
+++ b/chromium/sandbox/win/src/sandbox_types.h
@@ -15,7 +15,7 @@ namespace sandbox {
//
// Note: These codes are listed in a histogram and any new codes should be added
// at the end. If the underlying type is changed then the forward declaration in
-// sandbox_init.h must be updated.
+// sandbox_init_win.h must be updated.
//
enum ResultCode : int {
SBOX_ALL_OK = 0,
@@ -146,6 +146,9 @@ enum ResultCode : int {
SBOX_ERROR_CANNOT_CREATE_LOWBOX_IMPERSONATION_TOKEN = 61,
// Cannot create a sandbox policy for an unsandboxed process.
SBOX_ERROR_UNSANDBOXED_PROCESS = 62,
+ // Could not create the unsandboxed process. Extended error from
+ // base::LaunchProcess will be in GetLastError().
+ SBOX_ERROR_CANNOT_LAUNCH_UNSANDBOXED_PROCESS = 63,
// Placeholder for last item of the enum.
SBOX_ERROR_LAST
};
@@ -185,10 +188,8 @@ enum InterceptionType {
INTERCEPTION_INVALID = 0,
INTERCEPTION_SERVICE_CALL, // Trampoline of an NT native call
INTERCEPTION_EAT,
- INTERCEPTION_SIDESTEP, // Preamble patch
- INTERCEPTION_SMART_SIDESTEP, // Preamble patch but bypass internal calls
- INTERCEPTION_UNLOAD_MODULE, // Unload the module (don't patch)
- INTERCEPTION_LAST // Placeholder for last item in the enumeration
+ INTERCEPTION_UNLOAD_MODULE, // Unload the module (don't patch)
+ INTERCEPTION_LAST // Placeholder for last item in the enumeration
};
} // namespace sandbox
diff --git a/chromium/sandbox/win/src/sharedmem_ipc_client.cc b/chromium/sandbox/win/src/sharedmem_ipc_client.cc
index 9df60cf3671..93078c5c106 100644
--- a/chromium/sandbox/win/src/sharedmem_ipc_client.cc
+++ b/chromium/sandbox/win/src/sharedmem_ipc_client.cc
@@ -16,24 +16,15 @@
namespace sandbox {
-SANDBOX_INTERCEPT NtExports g_nt;
-
namespace {
DWORD SignalObjectAndWaitWrapper(HANDLE object_to_signal,
HANDLE object_to_wait_on,
- DWORD millis,
- BOOL alertable) {
- // Not running in a sandboxed process so can call directly.
- if (!g_nt.SignalAndWaitForSingleObject)
- return SignalObjectAndWait(object_to_signal, object_to_wait_on, millis,
- alertable);
- // Don't support alertable.
- CHECK_NT(!alertable);
+ DWORD millis) {
LARGE_INTEGER timeout;
timeout.QuadPart = millis * -10000LL;
- NTSTATUS status = g_nt.SignalAndWaitForSingleObject(
- object_to_signal, object_to_wait_on, alertable,
+ NTSTATUS status = GetNtExports()->SignalAndWaitForSingleObject(
+ object_to_signal, object_to_wait_on, FALSE,
millis == INFINITE ? nullptr : &timeout);
if (!NT_SUCCESS(status))
return WAIT_FAILED;
@@ -41,12 +32,9 @@ DWORD SignalObjectAndWaitWrapper(HANDLE object_to_signal,
}
DWORD WaitForSingleObjectWrapper(HANDLE handle, DWORD millis) {
- // Not running in a sandboxed process so can call directly.
- if (!g_nt.WaitForSingleObject)
- return WaitForSingleObject(handle, millis);
LARGE_INTEGER timeout;
timeout.QuadPart = millis * -10000LL;
- NTSTATUS status = g_nt.WaitForSingleObject(
+ NTSTATUS status = GetNtExports()->WaitForSingleObject(
handle, FALSE, millis == INFINITE ? nullptr : &timeout);
if (!NT_SUCCESS(status))
return WAIT_FAILED;
@@ -109,9 +97,8 @@ ResultCode SharedMemIPCClient::DoCall(CrossCallParams* params,
// While the atomic signaling and waiting is not a requirement, it
// is nice because we save a trip to kernel.
- DWORD wait = SignalObjectAndWaitWrapper(channel[num].ping_event,
- channel[num].pong_event,
- kIPCWaitTimeOut1, false);
+ DWORD wait = SignalObjectAndWaitWrapper(
+ channel[num].ping_event, channel[num].pong_event, kIPCWaitTimeOut1);
if (WAIT_TIMEOUT == wait) {
// The server is taking too long. Enter a loop were we check if the
// server_alive mutex has been abandoned which would signal a server crash
diff --git a/chromium/sandbox/win/src/sidestep/ia32_modrm_map.cpp b/chromium/sandbox/win/src/sidestep/ia32_modrm_map.cpp
deleted file mode 100644
index c66421f969e..00000000000
--- a/chromium/sandbox/win/src/sidestep/ia32_modrm_map.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Table of relevant information about how to decode the ModR/M byte.
-// Based on information in the IA-32 Intel Architecture
-// Software Developer's Manual Volume 2: Instruction Set Reference.
-
-#include "sandbox/win/src/sidestep/mini_disassembler.h"
-#include "sandbox/win/src/sidestep/mini_disassembler_types.h"
-
-namespace sidestep {
-
-const ModrmEntry MiniDisassembler::s_ia16_modrm_map_[] = {
-// mod == 00
- /* r/m == 000 */ { false, false, OS_ZERO },
- /* r/m == 001 */ { false, false, OS_ZERO },
- /* r/m == 010 */ { false, false, OS_ZERO },
- /* r/m == 011 */ { false, false, OS_ZERO },
- /* r/m == 100 */ { false, false, OS_ZERO },
- /* r/m == 101 */ { false, false, OS_ZERO },
- /* r/m == 110 */ { true, false, OS_WORD },
- /* r/m == 111 */ { false, false, OS_ZERO },
-// mod == 01
- /* r/m == 000 */ { true, false, OS_BYTE },
- /* r/m == 001 */ { true, false, OS_BYTE },
- /* r/m == 010 */ { true, false, OS_BYTE },
- /* r/m == 011 */ { true, false, OS_BYTE },
- /* r/m == 100 */ { true, false, OS_BYTE },
- /* r/m == 101 */ { true, false, OS_BYTE },
- /* r/m == 110 */ { true, false, OS_BYTE },
- /* r/m == 111 */ { true, false, OS_BYTE },
-// mod == 10
- /* r/m == 000 */ { true, false, OS_WORD },
- /* r/m == 001 */ { true, false, OS_WORD },
- /* r/m == 010 */ { true, false, OS_WORD },
- /* r/m == 011 */ { true, false, OS_WORD },
- /* r/m == 100 */ { true, false, OS_WORD },
- /* r/m == 101 */ { true, false, OS_WORD },
- /* r/m == 110 */ { true, false, OS_WORD },
- /* r/m == 111 */ { true, false, OS_WORD },
-// mod == 11
- /* r/m == 000 */ { false, false, OS_ZERO },
- /* r/m == 001 */ { false, false, OS_ZERO },
- /* r/m == 010 */ { false, false, OS_ZERO },
- /* r/m == 011 */ { false, false, OS_ZERO },
- /* r/m == 100 */ { false, false, OS_ZERO },
- /* r/m == 101 */ { false, false, OS_ZERO },
- /* r/m == 110 */ { false, false, OS_ZERO },
- /* r/m == 111 */ { false, false, OS_ZERO }
-};
-
-const ModrmEntry MiniDisassembler::s_ia32_modrm_map_[] = {
-// mod == 00
- /* r/m == 000 */ { false, false, OS_ZERO },
- /* r/m == 001 */ { false, false, OS_ZERO },
- /* r/m == 010 */ { false, false, OS_ZERO },
- /* r/m == 011 */ { false, false, OS_ZERO },
- /* r/m == 100 */ { false, true, OS_ZERO },
- /* r/m == 101 */ { true, false, OS_DOUBLE_WORD },
- /* r/m == 110 */ { false, false, OS_ZERO },
- /* r/m == 111 */ { false, false, OS_ZERO },
-// mod == 01
- /* r/m == 000 */ { true, false, OS_BYTE },
- /* r/m == 001 */ { true, false, OS_BYTE },
- /* r/m == 010 */ { true, false, OS_BYTE },
- /* r/m == 011 */ { true, false, OS_BYTE },
- /* r/m == 100 */ { true, true, OS_BYTE },
- /* r/m == 101 */ { true, false, OS_BYTE },
- /* r/m == 110 */ { true, false, OS_BYTE },
- /* r/m == 111 */ { true, false, OS_BYTE },
-// mod == 10
- /* r/m == 000 */ { true, false, OS_DOUBLE_WORD },
- /* r/m == 001 */ { true, false, OS_DOUBLE_WORD },
- /* r/m == 010 */ { true, false, OS_DOUBLE_WORD },
- /* r/m == 011 */ { true, false, OS_DOUBLE_WORD },
- /* r/m == 100 */ { true, true, OS_DOUBLE_WORD },
- /* r/m == 101 */ { true, false, OS_DOUBLE_WORD },
- /* r/m == 110 */ { true, false, OS_DOUBLE_WORD },
- /* r/m == 111 */ { true, false, OS_DOUBLE_WORD },
-// mod == 11
- /* r/m == 000 */ { false, false, OS_ZERO },
- /* r/m == 001 */ { false, false, OS_ZERO },
- /* r/m == 010 */ { false, false, OS_ZERO },
- /* r/m == 011 */ { false, false, OS_ZERO },
- /* r/m == 100 */ { false, false, OS_ZERO },
- /* r/m == 101 */ { false, false, OS_ZERO },
- /* r/m == 110 */ { false, false, OS_ZERO },
- /* r/m == 111 */ { false, false, OS_ZERO },
-};
-
-} // namespace sidestep
diff --git a/chromium/sandbox/win/src/sidestep/ia32_opcode_map.cpp b/chromium/sandbox/win/src/sidestep/ia32_opcode_map.cpp
deleted file mode 100644
index 6cd232c0598..00000000000
--- a/chromium/sandbox/win/src/sidestep/ia32_opcode_map.cpp
+++ /dev/null
@@ -1,1159 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Opcode decoding maps. Based on the IA-32 Intel Architecture
-// Software Developer's Manual Volume 2: Instruction Set Reference. Idea
-// for how to lay out the tables in memory taken from the implementation
-// in the Bastard disassembly environment.
-
-#include "sandbox/win/src/sidestep/mini_disassembler.h"
-
-namespace sidestep {
-
-/*
-* This is the first table to be searched; the first field of each
-* Opcode in the table is either 0 to indicate you're in the
-* right table, or an index to the correct table, in the global
-* map g_pentiumOpcodeMap
-*/
-const Opcode s_first_opcode_byte[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF */ { 1, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x10 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x11 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x12 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x13 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x14 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x15 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x16 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x17 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x18 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x19 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1C */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1E */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1F */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x20 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x21 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x22 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x23 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x24 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x25 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x26 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x27 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "daa", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x28 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x29 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2C */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2E */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2F */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "das", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x30 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x31 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x32 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x33 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x34 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x35 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x36 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x37 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "aaa", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x38 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x39 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3C */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3E */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3F */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "aas", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x40 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x41 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x42 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x43 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x44 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x45 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x46 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x47 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x48 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x49 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4A */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4B */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4C */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4E */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4F */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x50 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x51 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x52 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x53 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x54 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x55 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x56 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x57 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x58 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x59 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5A */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5B */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5C */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5E */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5F */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x60 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "pushad", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x61 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "popad", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x62 */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_A, AM_NOT_USED, "bound", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x63 */ { 0, IT_GENERIC, AM_E | OT_W, AM_G | OT_W, AM_NOT_USED, "arpl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x64 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x65 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x66 */ { 0, IT_PREFIX_OPERAND, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x67 */ { 0, IT_PREFIX_ADDRESS, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x68 */ { 0, IT_GENERIC, AM_I | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x69 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_I | OT_V, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6A */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_I | OT_B, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6C */ { 0, IT_GENERIC, AM_Y | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "insb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6D */ { 0, IT_GENERIC, AM_Y | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "insd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6E */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_X | OT_B, AM_NOT_USED, "outsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6F */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_X | OT_V, AM_NOT_USED, "outsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x70 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x71 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x72 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x73 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x74 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x75 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x76 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x77 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "ja", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x78 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "js", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x79 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7A */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7B */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7C */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7D */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7E */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7F */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x80 */ { 2, IT_REFERENCE, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x81 */ { 3, IT_REFERENCE, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x82 */ { 4, IT_REFERENCE, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x83 */ { 5, IT_REFERENCE, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x84 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x85 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x86 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x87 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x88 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x89 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8C */ { 0, IT_GENERIC, AM_E | OT_W, AM_S | OT_W, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8D */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_ADDRESS_MODE_M, AM_NOT_USED, "lea", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8E */ { 0, IT_GENERIC, AM_S | OT_W, AM_E | OT_W, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8F */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x90 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "nop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x91 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x92 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x93 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x94 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x95 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x96 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x97 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x98 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cwde", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x99 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cdq", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9A */ { 0, IT_JUMP, AM_A | OT_P, AM_NOT_USED, AM_NOT_USED, "callf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9B */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "wait", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9C */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "pushfd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9D */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "popfd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9E */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sahf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9F */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "lahf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA0 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_O | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA1 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_O | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA2 */ { 0, IT_GENERIC, AM_O | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA3 */ { 0, IT_GENERIC, AM_O | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA4 */ { 0, IT_GENERIC, AM_X | OT_B, AM_Y | OT_B, AM_NOT_USED, "movsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA5 */ { 0, IT_GENERIC, AM_X | OT_V, AM_Y | OT_V, AM_NOT_USED, "movsd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA6 */ { 0, IT_GENERIC, AM_X | OT_B, AM_Y | OT_B, AM_NOT_USED, "cmpsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA7 */ { 0, IT_GENERIC, AM_X | OT_V, AM_Y | OT_V, AM_NOT_USED, "cmpsd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA8 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA9 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAA */ { 0, IT_GENERIC, AM_Y | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "stosb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAB */ { 0, IT_GENERIC, AM_Y | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "stosd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAC */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_X| OT_B, AM_NOT_USED, "lodsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_X| OT_V, AM_NOT_USED, "lodsd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAE */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_Y | OT_B, AM_NOT_USED, "scasb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAF */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_Y | OT_V, AM_NOT_USED, "scasd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB0 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB1 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB2 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB3 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB4 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB5 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB6 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB7 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB8 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB9 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBA */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBB */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBC */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBE */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBF */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC0 */ { 6, IT_REFERENCE, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC1 */ { 7, IT_REFERENCE, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC2 */ { 0, IT_RETURN, AM_I | OT_W, AM_NOT_USED, AM_NOT_USED, "ret", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC3 */ { 0, IT_RETURN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ret", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC4 */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_P, AM_NOT_USED, "les", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC5 */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_P, AM_NOT_USED, "lds", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC8 */ { 0, IT_GENERIC, AM_I | OT_W, AM_I | OT_B, AM_NOT_USED, "enter", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC9 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "leave", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCA */ { 0, IT_RETURN, AM_I | OT_W, AM_NOT_USED, AM_NOT_USED, "retf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCB */ { 0, IT_RETURN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "retf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCC */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "int3", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCD */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "int", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCE */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "into", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCF */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "iret", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD0 */ { 8, IT_REFERENCE, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD1 */ { 9, IT_REFERENCE, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD2 */ { 10, IT_REFERENCE, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD3 */ { 11, IT_REFERENCE, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD4 */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "aam", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD5 */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "aad", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD6 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD7 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "xlat", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
-
- // The following 8 lines would be references to the FPU tables, but we currently
- // do not support the FPU instructions in this disassembler.
-
- /* 0xD8 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD9 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xDA */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xDB */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xDC */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xDD */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xDE */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xDF */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
-
-
- /* 0xE0 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "loopnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE1 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "loopz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE2 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "loop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE3 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jcxz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE4 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE5 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE6 */ { 0, IT_GENERIC, AM_I | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE7 */ { 0, IT_GENERIC, AM_I | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE8 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "call", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE9 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xEA */ { 0, IT_JUMP, AM_A | OT_P, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xEB */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xEC */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_REGISTER | OT_W, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xED */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_W, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xEE */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_REGISTER | OT_B, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xEF */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_REGISTER | OT_V, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF0 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "lock:", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF2 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "repne:", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF3 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rep:", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF4 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "hlt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF5 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cmc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF6 */ { 12, IT_REFERENCE, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF7 */ { 13, IT_REFERENCE, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF8 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "clc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF9 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "stc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xFA */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cli", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xFB */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sti", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xFC */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cld", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xFD */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "std", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xFE */ { 14, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xFF */ { 15, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_0f[] = {
- /* 0x0 */ { 16, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 17, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "lar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "lsl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "clts", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "invd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "wbinvd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ud2", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xE */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x10 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "movups", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "movsd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "movss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "movupd" } },
- /* 0x11 */ { 0, IT_GENERIC, AM_W | OT_PS, AM_V | OT_PS, AM_NOT_USED, "movups", true,
- /* F2h */ { 0, IT_GENERIC, AM_W | OT_SD, AM_V | OT_SD, AM_NOT_USED, "movsd" },
- /* F3h */ { 0, IT_GENERIC, AM_W | OT_SS, AM_V | OT_SS, AM_NOT_USED, "movss" },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_PD, AM_V | OT_PD, AM_NOT_USED, "movupd" } },
- /* 0x12 */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movlps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhlps" }, // only one of ...
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhlps" }, // ...these two is correct, Intel doesn't specify which
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_S, AM_NOT_USED, "movlpd" } },
- /* 0x13 */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movlps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movlpd" } },
- /* 0x14 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_Q, AM_NOT_USED, "unpcklps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_Q, AM_NOT_USED, "unpcklpd" } },
- /* 0x15 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_Q, AM_NOT_USED, "unpckhps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_Q, AM_NOT_USED, "unpckhpd" } },
- /* 0x16 */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movhps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movlhps" }, // only one of...
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movlhps" }, // ...these two is correct, Intel doesn't specify which
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movhpd" } },
- /* 0x17 */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhpd" } },
- /* 0x18 */ { 18, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x19 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1A */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1B */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1C */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1D */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1E */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1F */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x20 */ { 0, IT_GENERIC, AM_R | OT_D, AM_C | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x21 */ { 0, IT_GENERIC, AM_R | OT_D, AM_D | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x22 */ { 0, IT_GENERIC, AM_C | OT_D, AM_R | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x23 */ { 0, IT_GENERIC, AM_D | OT_D, AM_R | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x24 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x25 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x26 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x27 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x28 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "movaps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "movapd" } },
- /* 0x29 */ { 0, IT_GENERIC, AM_W | OT_PS, AM_V | OT_PS, AM_NOT_USED, "movaps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_PD, AM_V | OT_PD, AM_NOT_USED, "movapd" } },
- /* 0x2A */ { 0, IT_GENERIC, AM_V | OT_PS, AM_Q | OT_Q, AM_NOT_USED, "cvtpi2ps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_E | OT_D, AM_NOT_USED, "cvtsi2sd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_E | OT_D, AM_NOT_USED, "cvtsi2ss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_Q | OT_DQ, AM_NOT_USED, "cvtpi2pd" } },
- /* 0x2B */ { 0, IT_GENERIC, AM_W | OT_PS, AM_V | OT_PS, AM_NOT_USED, "movntps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_PD, AM_V | OT_PD, AM_NOT_USED, "movntpd" } },
- /* 0x2C */ { 0, IT_GENERIC, AM_Q | OT_Q, AM_W | OT_PS, AM_NOT_USED, "cvttps2pi", true,
- /* F2h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SD, AM_NOT_USED, "cvttsd2si" },
- /* F3h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SS, AM_NOT_USED, "cvttss2si" },
- /* 66h */ { 0, IT_GENERIC, AM_Q | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvttpd2pi" } },
- /* 0x2D */ { 0, IT_GENERIC, AM_Q | OT_Q, AM_W | OT_PS, AM_NOT_USED, "cvtps2pi", true,
- /* F2h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SD, AM_NOT_USED, "cvtsd2si" },
- /* F3h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SS, AM_NOT_USED, "cvtss2si" },
- /* 66h */ { 0, IT_GENERIC, AM_Q | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvtpd2pi" } },
- /* 0x2E */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "ucomiss", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "ucomisd" } },
- /* 0x2F */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_SS, AM_NOT_USED, "comiss", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "comisd" } },
- /* 0x30 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "wrmsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x31 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rdtsc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x32 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rdmsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x33 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rdpmc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x34 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sysenter", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x35 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sysexit", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x36 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x37 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x38 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x39 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3A */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3B */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3C */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "movnti", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3D */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3E */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3F */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x40 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x41 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x42 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x43 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x44 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x45 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x46 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x47 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmova", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x48 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovs", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x49 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4A */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4C */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4D */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4E */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4F */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x50 */ { 0, IT_GENERIC, AM_E | OT_D, AM_V | OT_PS, AM_NOT_USED, "movmskps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_E | OT_D, AM_V | OT_PD, AM_NOT_USED, "movmskpd" } },
- /* 0x51 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "sqrtps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "sqrtsd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "sqrtss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "sqrtpd" } },
- /* 0x52 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "rsqrtps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "rsqrtss" },
- /* 66h */ { 0 } },
- /* 0x53 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "rcpps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "rcpss" },
- /* 66h */ { 0 } },
- /* 0x54 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "andps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "andpd" } },
- /* 0x55 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "andnps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "andnpd" } },
- /* 0x56 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "orps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "orpd" } },
- /* 0x57 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "xorps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "xorpd" } },
- /* 0x58 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "addps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "addsd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "addss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "addpd" } },
- /* 0x59 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "mulps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "mulsd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "mulss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "mulpd" } },
- /* 0x5A */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PS, AM_NOT_USED, "cvtps2pd", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "cvtsd2ss" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "cvtss2sd" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PD, AM_NOT_USED, "cvtpd2ps" } },
- /* 0x5B */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_DQ, AM_NOT_USED, "cvtdq2ps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PS, AM_NOT_USED, "cvttps2dq" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PS, AM_NOT_USED, "cvtps2dq" } },
- /* 0x5C */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "subps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "subsd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "subss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "subpd" } },
- /* 0x5D */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "minps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "minsd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "minss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "minpd" } },
- /* 0x5E */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "divps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "divsd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "divss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "divpd" } },
- /* 0x5F */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "maxps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "maxsd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "maxss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "maxpd" } },
- /* 0x60 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpcklbw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklbw" } },
- /* 0x61 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpcklwd", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklwd" } },
- /* 0x62 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckldq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpckldq" } },
- /* 0x63 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "packsswb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "packsswb" } },
- /* 0x64 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "pcmpgtb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpgtb" } },
- /* 0x65 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "pcmpgtw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpgtw" } },
- /* 0x66 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "pcmpgtd", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpgtd" } },
- /* 0x67 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "packuswb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "packuswb" } },
- /* 0x68 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckhbw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "punpckhbw" } },
- /* 0x69 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckhwd", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "punpckhwd" } },
- /* 0x6A */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckhdq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "punpckhdq" } },
- /* 0x6B */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "packssdw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "packssdw" } },
- /* 0x6C */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "not used without prefix", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklqdq" } },
- /* 0x6D */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "not used without prefix", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklqdq" } },
- /* 0x6E */ { 0, IT_GENERIC, AM_P | OT_D, AM_E | OT_D, AM_NOT_USED, "movd", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_E | OT_D, AM_NOT_USED, "movd" } },
- /* 0x6F */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "movq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "movdqu" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "movdqa" } },
- /* 0x70 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_I | OT_B, "pshuf", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_I | OT_B, "pshuflw" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_I | OT_B, "pshufhw" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_I | OT_B, "pshufd" } },
- /* 0x71 */ { 19, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x72 */ { 20, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x73 */ { 21, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x74 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pcmpeqb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpeqb" } },
- /* 0x75 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pcmpeqw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpeqw" } },
- /* 0x76 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pcmpeqd", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpeqd" } },
- /* 0x77 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "emms", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
-
- // The following six opcodes are escapes into the MMX stuff, which this disassembler does not support.
- /* 0x78 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x79 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7A */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7B */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7C */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7D */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
-
- /* 0x7E */ { 0, IT_GENERIC, AM_E | OT_D, AM_P | OT_D, AM_NOT_USED, "movd", true,
- /* F2h */ { 0 },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movq" },
- /* 66h */ { 0, IT_GENERIC, AM_E | OT_D, AM_V | OT_DQ, AM_NOT_USED, "movd" } },
- /* 0x7F */ { 0, IT_GENERIC, AM_Q | OT_Q, AM_P | OT_Q, AM_NOT_USED, "movq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_V | OT_DQ, AM_NOT_USED, "movdqu" },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_V | OT_DQ, AM_NOT_USED, "movdqa" } },
- /* 0x80 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x81 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x82 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x83 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x84 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x85 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x86 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x87 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "ja", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x88 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "js", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x89 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8A */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8B */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8C */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8D */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8E */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x8F */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x90 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "seto", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x91 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x92 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x93 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x94 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x95 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x96 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x97 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "seta", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x98 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "sets", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x99 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9A */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9B */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9C */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9D */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9E */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x9F */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA0 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA1 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA2 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cpuid", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "bt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B, "shld", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B | AM_REGISTER, "shld", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA6 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA7 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA8 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xA9 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAA */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rsm", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAB */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "bts", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAC */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B, "shrd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAD */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B | AM_REGISTER, "shrd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAE */ { 22, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xAF */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "cmpxchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "cmpxchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB2 */ { 0, IT_GENERIC, AM_M | OT_P, AM_NOT_USED, AM_NOT_USED, "lss", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "btr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB4 */ { 0, IT_GENERIC, AM_M | OT_P, AM_NOT_USED, AM_NOT_USED, "lfs", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB5 */ { 0, IT_GENERIC, AM_M | OT_P, AM_NOT_USED, AM_NOT_USED, "lgs", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB6 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_B, AM_NOT_USED, "movzx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB7 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "movzx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB8 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xB9 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ud1", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBA */ { 23, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBB */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "btc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBC */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "bsf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBD */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "bsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBE */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_B, AM_NOT_USED, "movsx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xBF */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "movsx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "xadd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "xadd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC2 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_I | OT_B, "cmpps", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_I | OT_B, "cmpsd" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_I | OT_B, "cmpss" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_I | OT_B, "cmppd" } },
- /* 0xC3 */ { 0, IT_GENERIC, AM_E | OT_D, AM_G | OT_D, AM_NOT_USED, "movnti", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_E | OT_D, AM_I | OT_B, "pinsrw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_E | OT_D, AM_I | OT_B, "pinsrw" } },
- /* 0xC5 */ { 0, IT_GENERIC, AM_G | OT_D, AM_P | OT_Q, AM_I | OT_B, "pextrw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_G | OT_D, AM_V | OT_DQ, AM_I | OT_B, "pextrw" } },
- /* 0xC6 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_I | OT_B, "shufps", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_I | OT_B, "shufpd" } },
- /* 0xC7 */ { 24, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC8 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xC9 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCA */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCB */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCC */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCD */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCE */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xCF */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xD1 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrlw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrlw" } },
- /* 0xD2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrld", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrld" } },
- /* 0xD3 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrlq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrlq" } },
- /* 0xD4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddq" } },
- /* 0xD5 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmullw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmullw" } },
- /* 0xD6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "unused without prefix", true,
- /* F2h */ { 0, IT_GENERIC, AM_P | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movdq2q" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_Q | OT_Q, AM_NOT_USED, "movq2dq" },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movq" } },
- /* 0xD7 */ { 0, IT_GENERIC, AM_G | OT_D, AM_P | OT_Q, AM_NOT_USED, "pmovmskb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_G | OT_D, AM_V | OT_DQ, AM_NOT_USED, "pmovmskb" } },
- /* 0xD8 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubusb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubusb" } },
- /* 0xD9 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubusw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubusw" } },
- /* 0xDA */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pminub", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pminub" } },
- /* 0xDB */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pand", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pand" } },
- /* 0xDC */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddusb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddusb" } },
- /* 0xDD */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddusw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddusw" } },
- /* 0xDE */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmaxub", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmaxub" } },
- /* 0xDF */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pandn", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pandn" } },
- /* 0xE0 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pavgb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pavgb" } },
- /* 0xE1 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psraw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrqw" } },
- /* 0xE2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrad", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrad" } },
- /* 0xE3 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pavgw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pavgw" } },
- /* 0xE4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmulhuw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmulhuw" } },
- /* 0xE5 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmulhuw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmulhw" } },
- /* 0xE6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "not used without prefix", true,
- /* F2h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvtpd2dq" },
- /* F3h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_DQ, AM_NOT_USED, "cvtdq2pd" },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvttpd2dq" } },
- /* 0xE7 */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movntq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_V | OT_DQ, AM_NOT_USED, "movntdq" } },
- /* 0xE8 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubsb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubsb" } },
- /* 0xE9 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubsw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubsw" } },
- /* 0xEA */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pminsw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pminsw" } },
- /* 0xEB */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "por", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "por" } },
- /* 0xEC */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddsb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddsb" } },
- /* 0xED */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddsw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddsw" } },
- /* 0xEE */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmaxsw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmaxsw" } },
- /* 0xEF */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pxor", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pxor" } },
- /* 0xF0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0xF1 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psllw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psllw" } },
- /* 0xF2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pslld", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pslld" } },
- /* 0xF3 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psllq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psllq" } },
- /* 0xF4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmuludq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmuludq" } },
- /* 0xF5 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmaddwd", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmaddwd" } },
- /* 0xF6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psadbw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psadbw" } },
- /* 0xF7 */ { 0, IT_GENERIC, AM_P | OT_PI, AM_Q | OT_PI, AM_NOT_USED, "maskmovq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "maskmovdqu" } },
- /* 0xF8 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubb" } },
- /* 0xF9 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubw" } },
- /* 0xFA */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubd", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubd" } },
- /* 0xFB */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubq" } },
- /* 0xFC */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddb", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddb" } },
- /* 0xFD */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddw" } },
- /* 0xFE */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddd", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddd" } },
- /* 0xFF */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_0f00[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "sldt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "str", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "lldt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "ltr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "verr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "verw", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_0f01[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "sgdt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "sidt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "lgdt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "lidt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "smsw", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "lmsw", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_M | OT_B, AM_NOT_USED, AM_NOT_USED, "invlpg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_0f18[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_M | OT_ADDRESS_MODE_M, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_0f71[] = {
- /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrlw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrlw" } },
- /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psraw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psraw" } },
- /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psllw", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psllw" } },
- /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_0f72[] = {
- /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrld", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrld" } },
- /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrad", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrad" } },
- /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "pslld", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "pslld" } },
- /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_0f73[] = {
- /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrlq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrlq" } },
- /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psllq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psllq" } },
- /* 0x7 */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "pslldq", true,
- /* F2h */ { 0 },
- /* F3h */ { 0 },
- /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "pslldq" } },
-};
-
-const Opcode s_opcode_byte_after_0fae[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "fxsave", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "fxrstor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ldmxcsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "stmxcsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "lfence", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "mfence", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "clflush/sfence", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
-};
-
-const Opcode s_opcode_byte_after_0fba[] = {
- /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "bt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "bts", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "btr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "btc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_0fc7[] = {
- /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_M | OT_Q, AM_NOT_USED, AM_NOT_USED, "cmpxch8b", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_80[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_81[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_82[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_83[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_c0[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_c1[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_d0[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_d1[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_d2[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_d3[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_f6[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "not", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "neg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, OT_B | AM_REGISTER, AM_E | OT_B, AM_NOT_USED, "mul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, OT_B | AM_REGISTER, AM_E | OT_B, AM_NOT_USED, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_E | OT_B, AM_NOT_USED, "div", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_E | OT_B, AM_NOT_USED, "idiv", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_f7[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "not", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "neg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "mul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "div", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "idiv", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_fe[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-const Opcode s_opcode_byte_after_ff[] = {
- /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x2 */ { 0, IT_JUMP, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "call", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x3 */ { 0, IT_JUMP, AM_E | OT_P, AM_NOT_USED, AM_NOT_USED, "call", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x4 */ { 0, IT_JUMP, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x5 */ { 0, IT_JUMP, AM_E | OT_P, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
- /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
-};
-
-/*
-* A table of all the other tables, containing some extra information, e.g.
-* how to mask out the byte we're looking at.
-*/
-const OpcodeTable MiniDisassembler::s_ia32_opcode_map_[]={
- // One-byte opcodes and jumps to larger
- /* 0 */ {s_first_opcode_byte, 0, 0xff, 0, 0xff},
- // Two-byte opcodes (second byte)
- /* 1 */ {s_opcode_byte_after_0f, 0, 0xff, 0, 0xff},
- // Start of tables for opcodes using ModR/M bits as extension
- /* 2 */ {s_opcode_byte_after_80, 3, 0x07, 0, 0x07},
- /* 3 */ {s_opcode_byte_after_81, 3, 0x07, 0, 0x07},
- /* 4 */ {s_opcode_byte_after_82, 3, 0x07, 0, 0x07},
- /* 5 */ {s_opcode_byte_after_83, 3, 0x07, 0, 0x07},
- /* 6 */ {s_opcode_byte_after_c0, 3, 0x07, 0, 0x07},
- /* 7 */ {s_opcode_byte_after_c1, 3, 0x07, 0, 0x07},
- /* 8 */ {s_opcode_byte_after_d0, 3, 0x07, 0, 0x07},
- /* 9 */ {s_opcode_byte_after_d1, 3, 0x07, 0, 0x07},
- /* 10 */ {s_opcode_byte_after_d2, 3, 0x07, 0, 0x07},
- /* 11 */ {s_opcode_byte_after_d3, 3, 0x07, 0, 0x07},
- /* 12 */ {s_opcode_byte_after_f6, 3, 0x07, 0, 0x07},
- /* 13 */ {s_opcode_byte_after_f7, 3, 0x07, 0, 0x07},
- /* 14 */ {s_opcode_byte_after_fe, 3, 0x07, 0, 0x01},
- /* 15 */ {s_opcode_byte_after_ff, 3, 0x07, 0, 0x07},
- /* 16 */ {s_opcode_byte_after_0f00, 3, 0x07, 0, 0x07},
- /* 17 */ {s_opcode_byte_after_0f01, 3, 0x07, 0, 0x07},
- /* 18 */ {s_opcode_byte_after_0f18, 3, 0x07, 0, 0x07},
- /* 19 */ {s_opcode_byte_after_0f71, 3, 0x07, 0, 0x07},
- /* 20 */ {s_opcode_byte_after_0f72, 3, 0x07, 0, 0x07},
- /* 21 */ {s_opcode_byte_after_0f73, 3, 0x07, 0, 0x07},
- /* 22 */ {s_opcode_byte_after_0fae, 3, 0x07, 0, 0x07},
- /* 23 */ {s_opcode_byte_after_0fba, 3, 0x07, 0, 0x07},
- /* 24 */ {s_opcode_byte_after_0fc7, 3, 0x07, 0, 0x01}
-};
-
-} // namespace sidestep
diff --git a/chromium/sandbox/win/src/sidestep/mini_disassembler.cpp b/chromium/sandbox/win/src/sidestep/mini_disassembler.cpp
deleted file mode 100644
index b2648bbf02b..00000000000
--- a/chromium/sandbox/win/src/sidestep/mini_disassembler.cpp
+++ /dev/null
@@ -1,396 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Implementation of MiniDisassembler.
-
-#ifdef _WIN64
-#error The code in this file should not be used on 64-bit Windows.
-#endif
-
-#include "sandbox/win/src/sidestep/mini_disassembler.h"
-
-namespace sidestep {
-
-MiniDisassembler::MiniDisassembler(bool operand_default_is_32_bits,
- bool address_default_is_32_bits)
- : operand_default_is_32_bits_(operand_default_is_32_bits),
- address_default_is_32_bits_(address_default_is_32_bits) {
- Initialize();
-}
-
-MiniDisassembler::MiniDisassembler()
- : operand_default_is_32_bits_(true),
- address_default_is_32_bits_(true) {
- Initialize();
-}
-
-InstructionType MiniDisassembler::Disassemble(
- unsigned char* start_byte,
- unsigned int* instruction_bytes) {
- // Clean up any state from previous invocations.
- Initialize();
-
- // Start by processing any prefixes.
- unsigned char* current_byte = start_byte;
- unsigned int size = 0;
- InstructionType instruction_type = ProcessPrefixes(current_byte, &size);
-
- if (IT_UNKNOWN == instruction_type)
- return instruction_type;
-
- current_byte += size;
- size = 0;
-
- // Invariant: We have stripped all prefixes, and the operand_is_32_bits_
- // and address_is_32_bits_ flags are correctly set.
-
- instruction_type = ProcessOpcode(current_byte, 0, &size);
-
- // Check for error processing instruction
- if ((IT_UNKNOWN == instruction_type_) || (IT_UNUSED == instruction_type_)) {
- return IT_UNKNOWN;
- }
-
- current_byte += size;
-
- // Invariant: operand_bytes_ indicates the total size of operands
- // specified by the opcode and/or ModR/M byte and/or SIB byte.
- // pCurrentByte points to the first byte after the ModR/M byte, or after
- // the SIB byte if it is present (i.e. the first byte of any operands
- // encoded in the instruction).
-
- // We get the total length of any prefixes, the opcode, and the ModR/M and
- // SIB bytes if present, by taking the difference of the original starting
- // address and the current byte (which points to the first byte of the
- // operands if present, or to the first byte of the next instruction if
- // they are not). Adding the count of bytes in the operands encoded in
- // the instruction gives us the full length of the instruction in bytes.
- *instruction_bytes += operand_bytes_ + (current_byte - start_byte);
-
- // Return the instruction type, which was set by ProcessOpcode().
- return instruction_type_;
-}
-
-void MiniDisassembler::Initialize() {
- operand_is_32_bits_ = operand_default_is_32_bits_;
- address_is_32_bits_ = address_default_is_32_bits_;
- operand_bytes_ = 0;
- have_modrm_ = false;
- should_decode_modrm_ = false;
- instruction_type_ = IT_UNKNOWN;
- got_f2_prefix_ = false;
- got_f3_prefix_ = false;
- got_66_prefix_ = false;
-}
-
-InstructionType MiniDisassembler::ProcessPrefixes(unsigned char* start_byte,
- unsigned int* size) {
- InstructionType instruction_type = IT_GENERIC;
- const Opcode& opcode = s_ia32_opcode_map_[0].table_[*start_byte];
-
- switch (opcode.type_) {
- case IT_PREFIX_ADDRESS:
- address_is_32_bits_ = !address_default_is_32_bits_;
- goto nochangeoperand;
- case IT_PREFIX_OPERAND:
- operand_is_32_bits_ = !operand_default_is_32_bits_;
- nochangeoperand:
- case IT_PREFIX:
-
- if (0xF2 == (*start_byte))
- got_f2_prefix_ = true;
- else if (0xF3 == (*start_byte))
- got_f3_prefix_ = true;
- else if (0x66 == (*start_byte))
- got_66_prefix_ = true;
-
- instruction_type = opcode.type_;
- (*size)++;
- // we got a prefix, so add one and check next byte
- ProcessPrefixes(start_byte + 1, size);
- break;
- default:
- break; // not a prefix byte
- }
-
- return instruction_type;
-}
-
-InstructionType MiniDisassembler::ProcessOpcode(unsigned char* start_byte,
- unsigned int table_index,
- unsigned int* size) {
- const OpcodeTable& table = s_ia32_opcode_map_[table_index]; // Get our table
- unsigned char current_byte = (*start_byte) >> table.shift_;
- current_byte = current_byte & table.mask_; // Mask out the bits we will use
-
- // Check whether the byte we have is inside the table we have.
- if (current_byte < table.min_lim_ || current_byte > table.max_lim_) {
- instruction_type_ = IT_UNKNOWN;
- return instruction_type_;
- }
-
- const Opcode& opcode = table.table_[current_byte];
- if (IT_UNUSED == opcode.type_) {
- // This instruction is not used by the IA-32 ISA, so we indicate
- // this to the user. Probably means that we were pointed to
- // a byte in memory that was not the start of an instruction.
- instruction_type_ = IT_UNUSED;
- return instruction_type_;
- } else if (IT_REFERENCE == opcode.type_) {
- // We are looking at an opcode that has more bytes (or is continued
- // in the ModR/M byte). Recursively find the opcode definition in
- // the table for the opcode's next byte.
- (*size)++;
- ProcessOpcode(start_byte + 1, opcode.table_index_, size);
- return instruction_type_;
- }
-
- const SpecificOpcode* specific_opcode = reinterpret_cast<
- const SpecificOpcode*>(&opcode);
- if (opcode.is_prefix_dependent_) {
- if (got_f2_prefix_ && opcode.opcode_if_f2_prefix_.mnemonic_ != 0) {
- specific_opcode = &opcode.opcode_if_f2_prefix_;
- } else if (got_f3_prefix_ && opcode.opcode_if_f3_prefix_.mnemonic_ != 0) {
- specific_opcode = &opcode.opcode_if_f3_prefix_;
- } else if (got_66_prefix_ && opcode.opcode_if_66_prefix_.mnemonic_ != 0) {
- specific_opcode = &opcode.opcode_if_66_prefix_;
- }
- }
-
- // Inv: The opcode type is known.
- instruction_type_ = specific_opcode->type_;
-
- // Let's process the operand types to see if we have any immediate
- // operands, and/or a ModR/M byte.
-
- ProcessOperand(specific_opcode->flag_dest_);
- ProcessOperand(specific_opcode->flag_source_);
- ProcessOperand(specific_opcode->flag_aux_);
-
- // Inv: We have processed the opcode and incremented operand_bytes_
- // by the number of bytes of any operands specified by the opcode
- // that are stored in the instruction (not registers etc.). Now
- // we need to return the total number of bytes for the opcode and
- // for the ModR/M or SIB bytes if they are present.
-
- if (table.mask_ != 0xff) {
- if (have_modrm_) {
- // we're looking at a ModR/M byte so we're not going to
- // count that into the opcode size
- ProcessModrm(start_byte, size);
- return IT_GENERIC;
- } else {
- // need to count the ModR/M byte even if it's just being
- // used for opcode extension
- (*size)++;
- return IT_GENERIC;
- }
- } else {
- if (have_modrm_) {
- // The ModR/M byte is the next byte.
- (*size)++;
- ProcessModrm(start_byte + 1, size);
- return IT_GENERIC;
- } else {
- (*size)++;
- return IT_GENERIC;
- }
- }
-}
-
-bool MiniDisassembler::ProcessOperand(int flag_operand) {
- bool succeeded = true;
- if (AM_NOT_USED == flag_operand)
- return succeeded;
-
- // Decide what to do based on the addressing mode.
- switch (flag_operand & AM_MASK) {
- // No ModR/M byte indicated by these addressing modes, and no
- // additional (e.g. immediate) parameters.
- case AM_A: // Direct address
- case AM_F: // EFLAGS register
- case AM_X: // Memory addressed by the DS:SI register pair
- case AM_Y: // Memory addressed by the ES:DI register pair
- case AM_IMPLICIT: // Parameter is implicit, occupies no space in
- // instruction
- break;
-
- // There is a ModR/M byte but it does not necessarily need
- // to be decoded.
- case AM_C: // reg field of ModR/M selects a control register
- case AM_D: // reg field of ModR/M selects a debug register
- case AM_G: // reg field of ModR/M selects a general register
- case AM_P: // reg field of ModR/M selects an MMX register
- case AM_R: // mod field of ModR/M may refer only to a general register
- case AM_S: // reg field of ModR/M selects a segment register
- case AM_T: // reg field of ModR/M selects a test register
- case AM_V: // reg field of ModR/M selects a 128-bit XMM register
- have_modrm_ = true;
- break;
-
- // In these addressing modes, there is a ModR/M byte and it needs to be
- // decoded. No other (e.g. immediate) params than indicated in ModR/M.
- case AM_E: // Operand is either a general-purpose register or memory,
- // specified by ModR/M byte
- case AM_M: // ModR/M byte will refer only to memory
- case AM_Q: // Operand is either an MMX register or memory (complex
- // evaluation), specified by ModR/M byte
- case AM_W: // Operand is either a 128-bit XMM register or memory (complex
- // eval), specified by ModR/M byte
- have_modrm_ = true;
- should_decode_modrm_ = true;
- break;
-
- // These addressing modes specify an immediate or an offset value
- // directly, so we need to look at the operand type to see how many
- // bytes.
- case AM_I: // Immediate data.
- case AM_J: // Jump to offset.
- case AM_O: // Operand is at offset.
- switch (flag_operand & OT_MASK) {
- case OT_B: // Byte regardless of operand-size attribute.
- operand_bytes_ += OS_BYTE;
- break;
- case OT_C: // Byte or word, depending on operand-size attribute.
- if (operand_is_32_bits_)
- operand_bytes_ += OS_WORD;
- else
- operand_bytes_ += OS_BYTE;
- break;
- case OT_D: // Doubleword, regardless of operand-size attribute.
- operand_bytes_ += OS_DOUBLE_WORD;
- break;
- case OT_DQ: // Double-quadword, regardless of operand-size attribute.
- operand_bytes_ += OS_DOUBLE_QUAD_WORD;
- break;
- case OT_P: // 32-bit or 48-bit pointer, depending on operand-size
- // attribute.
- if (operand_is_32_bits_)
- operand_bytes_ += OS_48_BIT_POINTER;
- else
- operand_bytes_ += OS_32_BIT_POINTER;
- break;
- case OT_PS: // 128-bit packed single-precision floating-point data.
- operand_bytes_ += OS_128_BIT_PACKED_SINGLE_PRECISION_FLOATING;
- break;
- case OT_Q: // Quadword, regardless of operand-size attribute.
- operand_bytes_ += OS_QUAD_WORD;
- break;
- case OT_S: // 6-byte pseudo-descriptor.
- operand_bytes_ += OS_PSEUDO_DESCRIPTOR;
- break;
- case OT_SD: // Scalar Double-Precision Floating-Point Value
- case OT_PD: // Unaligned packed double-precision floating point value
- operand_bytes_ += OS_DOUBLE_PRECISION_FLOATING;
- break;
- case OT_SS:
- // Scalar element of a 128-bit packed single-precision
- // floating data.
- // We simply return enItUnknown since we don't have to support
- // floating point
- succeeded = false;
- break;
- case OT_V: // Word or doubleword, depending on operand-size attribute.
- if (operand_is_32_bits_)
- operand_bytes_ += OS_DOUBLE_WORD;
- else
- operand_bytes_ += OS_WORD;
- break;
- case OT_W: // Word, regardless of operand-size attribute.
- operand_bytes_ += OS_WORD;
- break;
-
- // Can safely ignore these.
- case OT_A: // Two one-word operands in memory or two double-word
- // operands in memory
- case OT_PI: // Quadword MMX technology register (e.g. mm0)
- case OT_SI: // Doubleword integer register (e.g., eax)
- break;
-
- default:
- break;
- }
- break;
-
- default:
- break;
- }
-
- return succeeded;
-}
-
-bool MiniDisassembler::ProcessModrm(unsigned char* start_byte,
- unsigned int* size) {
- // If we don't need to decode, we just return the size of the ModR/M
- // byte (there is never a SIB byte in this case).
- if (!should_decode_modrm_) {
- (*size)++;
- return true;
- }
-
- // We never care about the reg field, only the combination of the mod
- // and r/m fields, so let's start by packing those fields together into
- // 5 bits.
- unsigned char modrm = (*start_byte);
- unsigned char mod = modrm & 0xC0; // mask out top two bits to get mod field
- modrm = modrm & 0x07; // mask out bottom 3 bits to get r/m field
- mod = mod >> 3; // shift the mod field to the right place
- modrm = mod | modrm; // combine the r/m and mod fields as discussed
- mod = mod >> 3; // shift the mod field to bits 2..0
-
- // Invariant: modrm contains the mod field in bits 4..3 and the r/m field
- // in bits 2..0, and mod contains the mod field in bits 2..0
-
- const ModrmEntry* modrm_entry = 0;
- if (address_is_32_bits_)
- modrm_entry = &s_ia32_modrm_map_[modrm];
- else
- modrm_entry = &s_ia16_modrm_map_[modrm];
-
- // Invariant: modrm_entry points to information that we need to decode
- // the ModR/M byte.
-
- // Add to the count of operand bytes, if the ModR/M byte indicates
- // that some operands are encoded in the instruction.
- if (modrm_entry->is_encoded_in_instruction_)
- operand_bytes_ += modrm_entry->operand_size_;
-
- // Process the SIB byte if necessary, and return the count
- // of ModR/M and SIB bytes.
- if (modrm_entry->use_sib_byte_) {
- (*size)++;
- return ProcessSib(start_byte + 1, mod, size);
- } else {
- (*size)++;
- return true;
- }
-}
-
-bool MiniDisassembler::ProcessSib(unsigned char* start_byte,
- unsigned char mod,
- unsigned int* size) {
- // get the mod field from the 2..0 bits of the SIB byte
- unsigned char sib_base = (*start_byte) & 0x07;
- if (0x05 == sib_base) {
- switch (mod) {
- case 0x00: // mod == 00
- case 0x02: // mod == 10
- operand_bytes_ += OS_DOUBLE_WORD;
- break;
- case 0x01: // mod == 01
- operand_bytes_ += OS_BYTE;
- break;
- case 0x03: // mod == 11
- // According to the IA-32 docs, there does not seem to be a disp
- // value for this value of mod
- default:
- break;
- }
- }
-
- (*size)++;
- return true;
-}
-
-} // namespace sidestep
diff --git a/chromium/sandbox/win/src/sidestep/mini_disassembler.h b/chromium/sandbox/win/src/sidestep/mini_disassembler.h
deleted file mode 100644
index 501ab638296..00000000000
--- a/chromium/sandbox/win/src/sidestep/mini_disassembler.h
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Definition of MiniDisassembler.
-
-#ifndef SANDBOX_WIN_SRC_SIDESTEP_MINI_DISASSEMBLER_H_
-#define SANDBOX_WIN_SRC_SIDESTEP_MINI_DISASSEMBLER_H_
-
-#include "sandbox/win/src/sidestep/mini_disassembler_types.h"
-
-namespace sidestep {
-
-// This small disassembler is very limited
-// in its functionality, and in fact does only the bare minimum required by the
-// preamble patching utility. It may be useful for other purposes, however.
-//
-// The limitations include at least the following:
-// -# No support for coprocessor opcodes, MMX, etc.
-// -# No machine-readable identification of opcodes or decoding of
-// assembly parameters. The name of the opcode (as a string) is given,
-// however, to aid debugging.
-//
-// You may ask what this little disassembler actually does, then? The answer is
-// that it does the following, which is exactly what the patching utility needs:
-// -# Indicates if opcode is a jump (any kind) or a return (any kind)
-// because this is important for the patching utility to determine if
-// a function is too short or there are jumps too early in it for it
-// to be preamble patched.
-// -# The opcode length is always calculated, so that the patching utility
-// can figure out where the next instruction starts, and whether it
-// already has enough instructions to replace with the absolute jump
-// to the patching code.
-//
-// The usage is quite simple; just create a MiniDisassembler and use its
-// Disassemble() method.
-//
-// If you would like to extend this disassembler, please refer to the
-// IA-32 Intel Architecture Software Developer's Manual Volume 2:
-// Instruction Set Reference for information about operand decoding
-// etc.
-class MiniDisassembler {
- public:
- // Creates a new instance and sets defaults.
- //
- // operand_default_32_bits: If true, the default operand size is
- // set to 32 bits, which is the default under Win32. Otherwise it is 16 bits.
- // address_default_32_bits: If true, the default address size is
- // set to 32 bits, which is the default under Win32. Otherwise it is 16 bits.
- MiniDisassembler(bool operand_default_32_bits, bool address_default_32_bits);
-
- // Equivalent to MiniDisassembler(true, true);
- MiniDisassembler();
-
- // Attempts to disassemble a single instruction starting from the
- // address in memory it is pointed to.
- //
- // start: Address where disassembly should start.
- // instruction_bytes: Variable that will be incremented by
- // the length in bytes of the instruction.
- // Returns enItJump, enItReturn or enItGeneric on success. enItUnknown
- // if unable to disassemble, enItUnused if this seems to be an unused
- // opcode. In the last two (error) cases, cbInstruction will be set
- // to 0xffffffff.
- //
- // Postcondition: This instance of the disassembler is ready to be used again,
- // with unchanged defaults from creation time.
- InstructionType Disassemble(unsigned char* start,
- unsigned int* instruction_bytes);
-
- private:
- // Makes the disassembler ready for reuse.
- void Initialize();
-
- // Sets the flags for address and operand sizes.
- // Returns Number of prefix bytes.
- InstructionType ProcessPrefixes(unsigned char* start, unsigned int* size);
-
- // Sets the flag for whether we have ModR/M, and increments
- // operand_bytes_ if any are specifies by the opcode directly.
- // Returns Number of opcode bytes.
- InstructionType ProcessOpcode(unsigned char* start,
- unsigned int table,
- unsigned int* size);
-
- // Checks the type of the supplied operand. Increments
- // operand_bytes_ if it directly indicates an immediate etc.
- // operand. Asserts have_modrm_ if the operand specifies
- // a ModR/M byte.
- bool ProcessOperand(int flag_operand);
-
- // Increments operand_bytes_ by size specified by ModR/M and
- // by SIB if present.
- // Returns 0 in case of error, 1 if there is just a ModR/M byte,
- // 2 if there is a ModR/M byte and a SIB byte.
- bool ProcessModrm(unsigned char* start, unsigned int* size);
-
- // Processes the SIB byte that it is pointed to.
- // start: Pointer to the SIB byte.
- // mod: The mod field from the ModR/M byte.
- // Returns 1 to indicate success (indicates 1 SIB byte)
- bool ProcessSib(unsigned char* start, unsigned char mod, unsigned int* size);
-
- // The instruction type we have decoded from the opcode.
- InstructionType instruction_type_;
-
- // Counts the number of bytes that is occupied by operands in
- // the current instruction (note: we don't care about how large
- // operands stored in registers etc. are).
- unsigned int operand_bytes_;
-
- // True iff there is a ModR/M byte in this instruction.
- bool have_modrm_;
-
- // True iff we need to decode the ModR/M byte (sometimes it just
- // points to a register, we can tell by the addressing mode).
- bool should_decode_modrm_;
-
- // Current operand size is 32 bits if true, 16 bits if false.
- bool operand_is_32_bits_;
-
- // Default operand size is 32 bits if true, 16 bits if false.
- bool operand_default_is_32_bits_;
-
- // Current address size is 32 bits if true, 16 bits if false.
- bool address_is_32_bits_;
-
- // Default address size is 32 bits if true, 16 bits if false.
- bool address_default_is_32_bits_;
-
- // Huge big opcode table based on the IA-32 manual, defined
- // in Ia32OpcodeMap.cpp
- static const OpcodeTable s_ia32_opcode_map_[];
-
- // Somewhat smaller table to help with decoding ModR/M bytes
- // when 16-bit addressing mode is being used. Defined in
- // Ia32ModrmMap.cpp
- static const ModrmEntry s_ia16_modrm_map_[];
-
- // Somewhat smaller table to help with decoding ModR/M bytes
- // when 32-bit addressing mode is being used. Defined in
- // Ia32ModrmMap.cpp
- static const ModrmEntry s_ia32_modrm_map_[];
-
- // Indicators of whether we got certain prefixes that certain
- // silly Intel instructions depend on in nonstandard ways for
- // their behaviors.
- bool got_f2_prefix_, got_f3_prefix_, got_66_prefix_;
-};
-
-} // namespace sidestep
-
-#endif // SANDBOX_WIN_SRC_SIDESTEP_MINI_DISASSEMBLER_H_
diff --git a/chromium/sandbox/win/src/sidestep/mini_disassembler_types.h b/chromium/sandbox/win/src/sidestep/mini_disassembler_types.h
deleted file mode 100644
index 394d8d8d61b..00000000000
--- a/chromium/sandbox/win/src/sidestep/mini_disassembler_types.h
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Several simple types used by the disassembler and some of the patching
-// mechanisms.
-
-#ifndef SANDBOX_WIN_SRC_SIDESTEP_MINI_DISASSEMBLER_TYPES_H_
-#define SANDBOX_WIN_SRC_SIDESTEP_MINI_DISASSEMBLER_TYPES_H_
-
-namespace sidestep {
-
-// Categories of instructions that we care about
-enum InstructionType {
- // This opcode is not used
- IT_UNUSED,
- // This disassembler does not recognize this opcode (error)
- IT_UNKNOWN,
- // This is not an instruction but a reference to another table
- IT_REFERENCE,
- // This byte is a prefix byte that we can ignore
- IT_PREFIX,
- // This is a prefix byte that switches to the nondefault address size
- IT_PREFIX_ADDRESS,
- // This is a prefix byte that switches to the nondefault operand size
- IT_PREFIX_OPERAND,
- // A jump or call instruction
- IT_JUMP,
- // A return instruction
- IT_RETURN,
- // Any other type of instruction (in this case we don't care what it is)
- IT_GENERIC,
-};
-
-// Lists IA-32 operand sizes in multiples of 8 bits
-enum OperandSize {
- OS_ZERO = 0,
- OS_BYTE = 1,
- OS_WORD = 2,
- OS_DOUBLE_WORD = 4,
- OS_QUAD_WORD = 8,
- OS_DOUBLE_QUAD_WORD = 16,
- OS_32_BIT_POINTER = 32 / 8,
- OS_48_BIT_POINTER = 48 / 8,
- OS_SINGLE_PRECISION_FLOATING = 32 / 8,
- OS_DOUBLE_PRECISION_FLOATING = 64 / 8,
- OS_DOUBLE_EXTENDED_PRECISION_FLOATING = 80 / 8,
- OS_128_BIT_PACKED_SINGLE_PRECISION_FLOATING = 128 / 8,
- OS_PSEUDO_DESCRIPTOR = 6
-};
-
-// Operand addressing methods from the IA-32 manual. The enAmMask value
-// is a mask for the rest. The other enumeration values are named for the
-// names given to the addressing methods in the manual, e.g. enAm_D is for
-// the D addressing method.
-//
-// The reason we use a full 4 bytes and a mask, is that we need to combine
-// these flags with the enOperandType to store the details
-// on the operand in a single integer.
-enum AddressingMethod {
- AM_NOT_USED = 0, // This operand is not used for this instruction
- AM_MASK = 0x00FF0000, // Mask for the rest of the values in this enumeration
- AM_A = 0x00010000, // A addressing type
- AM_C = 0x00020000, // C addressing type
- AM_D = 0x00030000, // D addressing type
- AM_E = 0x00040000, // E addressing type
- AM_F = 0x00050000, // F addressing type
- AM_G = 0x00060000, // G addressing type
- AM_I = 0x00070000, // I addressing type
- AM_J = 0x00080000, // J addressing type
- AM_M = 0x00090000, // M addressing type
- AM_O = 0x000A0000, // O addressing type
- AM_P = 0x000B0000, // P addressing type
- AM_Q = 0x000C0000, // Q addressing type
- AM_R = 0x000D0000, // R addressing type
- AM_S = 0x000E0000, // S addressing type
- AM_T = 0x000F0000, // T addressing type
- AM_V = 0x00100000, // V addressing type
- AM_W = 0x00110000, // W addressing type
- AM_X = 0x00120000, // X addressing type
- AM_Y = 0x00130000, // Y addressing type
- AM_REGISTER = 0x00140000, // Specific register is always used as this op
- AM_IMPLICIT = 0x00150000, // An implicit, fixed value is used
-};
-
-// Operand types from the IA-32 manual. The enOtMask value is
-// a mask for the rest. The rest of the values are named for the
-// names given to these operand types in the manual, e.g. enOt_ps
-// is for the ps operand type in the manual.
-//
-// The reason we use a full 4 bytes and a mask, is that we need
-// to combine these flags with the enAddressingMethod to store the details
-// on the operand in a single integer.
-enum OperandType {
- OT_MASK = 0xFF000000,
- OT_A = 0x01000000,
- OT_B = 0x02000000,
- OT_C = 0x03000000,
- OT_D = 0x04000000,
- OT_DQ = 0x05000000,
- OT_P = 0x06000000,
- OT_PI = 0x07000000,
- OT_PS = 0x08000000, // actually unsupported for (we don't know its size)
- OT_Q = 0x09000000,
- OT_S = 0x0A000000,
- OT_SS = 0x0B000000,
- OT_SI = 0x0C000000,
- OT_V = 0x0D000000,
- OT_W = 0x0E000000,
- OT_SD = 0x0F000000, // scalar double-precision floating-point value
- OT_PD = 0x10000000, // double-precision floating point
- // dummy "operand type" for address mode M - which doesn't specify
- // operand type
- OT_ADDRESS_MODE_M = 0x80000000
-};
-
-// Everything that's in an Opcode (see below) except the three
-// alternative opcode structs for different prefixes.
-struct SpecificOpcode {
- // Index to continuation table, or 0 if this is the last
- // byte in the opcode.
- int table_index_;
-
- // The opcode type
- InstructionType type_;
-
- // Description of the type of the dest, src and aux operands,
- // put together from an enOperandType flag and an enAddressingMethod
- // flag.
- int flag_dest_;
- int flag_source_;
- int flag_aux_;
-
- // We indicate the mnemonic for debugging purposes
- const char* mnemonic_;
-};
-
-// The information we keep in our tables about each of the different
-// valid instructions recognized by the IA-32 architecture.
-struct Opcode {
- // Index to continuation table, or 0 if this is the last
- // byte in the opcode.
- int table_index_;
-
- // The opcode type
- InstructionType type_;
-
- // Description of the type of the dest, src and aux operands,
- // put together from an enOperandType flag and an enAddressingMethod
- // flag.
- int flag_dest_;
- int flag_source_;
- int flag_aux_;
-
- // We indicate the mnemonic for debugging purposes
- const char* mnemonic_;
-
- // Alternative opcode info if certain prefixes are specified.
- // In most cases, all of these are zeroed-out. Only used if
- // bPrefixDependent is true.
- bool is_prefix_dependent_;
- SpecificOpcode opcode_if_f2_prefix_;
- SpecificOpcode opcode_if_f3_prefix_;
- SpecificOpcode opcode_if_66_prefix_;
-};
-
-// Information about each table entry.
-struct OpcodeTable {
- // Table of instruction entries
- const Opcode* table_;
- // How many bytes left to shift ModR/M byte <b>before</b> applying mask
- unsigned char shift_;
- // Mask to apply to byte being looked at before comparing to table
- unsigned char mask_;
- // Minimum/maximum indexes in table.
- unsigned char min_lim_;
- unsigned char max_lim_;
-};
-
-// Information about each entry in table used to decode ModR/M byte.
-struct ModrmEntry {
- // Is the operand encoded as bytes in the instruction (rather than
- // if it's e.g. a register in which case it's just encoded in the
- // ModR/M byte)
- bool is_encoded_in_instruction_;
-
- // Is there a SIB byte? In this case we always need to decode it.
- bool use_sib_byte_;
-
- // What is the size of the operand (only important if it's encoded
- // in the instruction)?
- OperandSize operand_size_;
-};
-
-} // namespace sidestep
-
-#endif // SANDBOX_WIN_SRC_SIDESTEP_MINI_DISASSEMBLER_TYPES_H_
diff --git a/chromium/sandbox/win/src/sidestep/preamble_patcher.h b/chromium/sandbox/win/src/sidestep/preamble_patcher.h
deleted file mode 100644
index 1083e89f44e..00000000000
--- a/chromium/sandbox/win/src/sidestep/preamble_patcher.h
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Definition of PreamblePatcher
-
-#ifndef SANDBOX_WIN_SRC_SIDESTEP_PREAMBLE_PATCHER_H_
-#define SANDBOX_WIN_SRC_SIDESTEP_PREAMBLE_PATCHER_H_
-
-#include <stddef.h>
-
-namespace sidestep {
-
-// Maximum size of the preamble stub. We overwrite at least the first 5
-// bytes of the function. Considering the worst case scenario, we need 4
-// bytes + the max instruction size + 5 more bytes for our jump back to
-// the original code. With that in mind, 32 is a good number :)
-const size_t kMaxPreambleStubSize = 32;
-
-// Possible results of patching/unpatching
-enum SideStepError {
- SIDESTEP_SUCCESS = 0,
- SIDESTEP_INVALID_PARAMETER,
- SIDESTEP_INSUFFICIENT_BUFFER,
- SIDESTEP_JUMP_INSTRUCTION,
- SIDESTEP_FUNCTION_TOO_SMALL,
- SIDESTEP_UNSUPPORTED_INSTRUCTION,
- SIDESTEP_NO_SUCH_MODULE,
- SIDESTEP_NO_SUCH_FUNCTION,
- SIDESTEP_ACCESS_DENIED,
- SIDESTEP_UNEXPECTED,
-};
-
-// Implements a patching mechanism that overwrites the first few bytes of
-// a function preamble with a jump to our hook function, which is then
-// able to call the original function via a specially-made preamble-stub
-// that imitates the action of the original preamble.
-//
-// Note that there are a number of ways that this method of patching can
-// fail. The most common are:
-// - If there is a jump (jxx) instruction in the first 5 bytes of
-// the function being patched, we cannot patch it because in the
-// current implementation we do not know how to rewrite relative
-// jumps after relocating them to the preamble-stub. Note that
-// if you really really need to patch a function like this, it
-// would be possible to add this functionality (but at some cost).
-// - If there is a return (ret) instruction in the first 5 bytes
-// we cannot patch the function because it may not be long enough
-// for the jmp instruction we use to inject our patch.
-// - If there is another thread currently executing within the bytes
-// that are copied to the preamble stub, it will crash in an undefined
-// way.
-//
-// If you get any other error than the above, you're either pointing the
-// patcher at an invalid instruction (e.g. into the middle of a multi-
-// byte instruction, or not at memory containing executable instructions)
-// or, there may be a bug in the disassembler we use to find
-// instruction boundaries.
-class PreamblePatcher {
- public:
- // Patches target_function to point to replacement_function using a provided
- // preamble_stub of stub_size bytes.
- // Returns An error code indicating the result of patching.
- template <class T>
- static SideStepError Patch(T target_function,
- T replacement_function,
- void* preamble_stub,
- size_t stub_size) {
- return RawPatchWithStub(target_function, replacement_function,
- reinterpret_cast<unsigned char*>(preamble_stub),
- stub_size, nullptr);
- }
-
- private:
- // Patches a function by overwriting its first few bytes with
- // a jump to a different function. This is similar to the RawPatch
- // function except that it uses the stub allocated by the caller
- // instead of allocating it.
- //
- // To use this function, you first have to call VirtualProtect to make the
- // target function writable at least for the duration of the call.
- //
- // target_function: A pointer to the function that should be
- // patched.
- //
- // replacement_function: A pointer to the function that should
- // replace the target function. The replacement function must have
- // exactly the same calling convention and parameters as the original
- // function.
- //
- // preamble_stub: A pointer to a buffer where the preamble stub
- // should be copied. The size of the buffer should be sufficient to
- // hold the preamble bytes.
- //
- // stub_size: Size in bytes of the buffer allocated for the
- // preamble_stub
- //
- // bytes_needed: Pointer to a variable that receives the minimum
- // number of bytes required for the stub. Can be set to nullptr if you're
- // not interested.
- //
- // Returns An error code indicating the result of patching.
- static SideStepError RawPatchWithStub(void* target_function,
- void* replacement_function,
- unsigned char* preamble_stub,
- size_t stub_size,
- size_t* bytes_needed);
-};
-
-} // namespace sidestep
-
-#endif // SANDBOX_WIN_SRC_SIDESTEP_PREAMBLE_PATCHER_H_
diff --git a/chromium/sandbox/win/src/sidestep/preamble_patcher_with_stub.cpp b/chromium/sandbox/win/src/sidestep/preamble_patcher_with_stub.cpp
deleted file mode 100644
index cbe98d05783..00000000000
--- a/chromium/sandbox/win/src/sidestep/preamble_patcher_with_stub.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Implementation of PreamblePatcher
-
-#include "sandbox/win/src/sidestep/preamble_patcher.h"
-
-#include <stddef.h>
-
-#include "sandbox/win/src/sandbox_nt_util.h"
-#include "sandbox/win/src/sidestep/mini_disassembler.h"
-
-// Definitions of assembly statements we need
-#define ASM_JMP32REL 0xE9
-#define ASM_INT3 0xCC
-
-namespace {
-
-// Very basic memcpy. We are copying 4 to 12 bytes most of the time, so there
-// is no attempt to optimize this code or have a general purpose function.
-// We don't want to call the crt from this code.
-inline void* RawMemcpy(void* destination, const void* source, size_t bytes) {
- const char* from = reinterpret_cast<const char*>(source);
- char* to = reinterpret_cast<char*>(destination);
-
- for (size_t i = 0; i < bytes ; i++)
- to[i] = from[i];
-
- return destination;
-}
-
-// Very basic memset. We are filling 1 to 7 bytes most of the time, so there
-// is no attempt to optimize this code or have a general purpose function.
-// We don't want to call the crt from this code.
-inline void* RawMemset(void* destination, int value, size_t bytes) {
- char* to = reinterpret_cast<char*>(destination);
-
- for (size_t i = 0; i < bytes ; i++)
- to[i] = static_cast<char>(value);
-
- return destination;
-}
-
-} // namespace
-
-#define ASSERT(a, b) DCHECK_NT(a)
-
-namespace sidestep {
-
-SideStepError PreamblePatcher::RawPatchWithStub(
- void* target_function,
- void* replacement_function,
- unsigned char* preamble_stub,
- size_t stub_size,
- size_t* bytes_needed) {
- if ((NULL == target_function) ||
- (NULL == replacement_function) ||
- (NULL == preamble_stub)) {
- ASSERT(false, (L"Invalid parameters - either pTargetFunction or "
- L"pReplacementFunction or pPreambleStub were NULL."));
- return SIDESTEP_INVALID_PARAMETER;
- }
-
- // TODO(V7:joi) Siggi and I just had a discussion and decided that both
- // patching and unpatching are actually unsafe. We also discussed a
- // method of making it safe, which is to freeze all other threads in the
- // process, check their thread context to see if their eip is currently
- // inside the block of instructions we need to copy to the stub, and if so
- // wait a bit and try again, then unfreeze all threads once we've patched.
- // Not implementing this for now since we're only using SideStep for unit
- // testing, but if we ever use it for production code this is what we
- // should do.
- //
- // NOTE: Stoyan suggests we can write 8 or even 10 bytes atomically using
- // FPU instructions, and on newer processors we could use cmpxchg8b or
- // cmpxchg16b. So it might be possible to do the patching/unpatching
- // atomically and avoid having to freeze other threads. Note though, that
- // doing it atomically does not help if one of the other threads happens
- // to have its eip in the middle of the bytes you change while you change
- // them.
- unsigned char* target = reinterpret_cast<unsigned char*>(target_function);
-
- // Let's disassemble the preamble of the target function to see if we can
- // patch, and to see how much of the preamble we need to take. We need 5
- // bytes for our jmp instruction, so let's find the minimum number of
- // instructions to get 5 bytes.
- MiniDisassembler disassembler;
- unsigned int preamble_bytes = 0;
- while (preamble_bytes < 5) {
- InstructionType instruction_type =
- disassembler.Disassemble(target + preamble_bytes, &preamble_bytes);
- if (IT_JUMP == instruction_type) {
- ASSERT(false, (L"Unable to patch because there is a jump instruction "
- L"in the first 5 bytes."));
- return SIDESTEP_JUMP_INSTRUCTION;
- } else if (IT_RETURN == instruction_type) {
- ASSERT(false, (L"Unable to patch because function is too short"));
- return SIDESTEP_FUNCTION_TOO_SMALL;
- } else if (IT_GENERIC != instruction_type) {
- ASSERT(false, (L"Disassembler encountered unsupported instruction "
- L"(either unused or unknown"));
- return SIDESTEP_UNSUPPORTED_INSTRUCTION;
- }
- }
-
- if (NULL != bytes_needed)
- *bytes_needed = preamble_bytes + 5;
-
- // Inv: preamble_bytes is the number of bytes (at least 5) that we need to
- // take from the preamble to have whole instructions that are 5 bytes or more
- // in size total. The size of the stub required is cbPreamble + size of
- // jmp (5)
- if (preamble_bytes + 5 > stub_size) {
- NOTREACHED_NT();
- return SIDESTEP_INSUFFICIENT_BUFFER;
- }
-
- // First, copy the preamble that we will overwrite.
- RawMemcpy(reinterpret_cast<void*>(preamble_stub),
- reinterpret_cast<void*>(target), preamble_bytes);
-
- // Now, make a jmp instruction to the rest of the target function (minus the
- // preamble bytes we moved into the stub) and copy it into our preamble-stub.
- // find address to jump to, relative to next address after jmp instruction
-#pragma warning(push)
-#pragma warning(disable:4244)
- // This assignment generates a warning because it is 32 bit specific.
- int relative_offset_to_target_rest
- = ((reinterpret_cast<unsigned char*>(target) + preamble_bytes) -
- (preamble_stub + preamble_bytes + 5));
-#pragma warning(pop)
- // jmp (Jump near, relative, displacement relative to next instruction)
- preamble_stub[preamble_bytes] = ASM_JMP32REL;
- // copy the address
- RawMemcpy(reinterpret_cast<void*>(preamble_stub + preamble_bytes + 1),
- reinterpret_cast<void*>(&relative_offset_to_target_rest), 4);
-
- // Inv: preamble_stub points to assembly code that will execute the
- // original function by first executing the first cbPreamble bytes of the
- // preamble, then jumping to the rest of the function.
-
- // Overwrite the first 5 bytes of the target function with a jump to our
- // replacement function.
- // (Jump near, relative, displacement relative to next instruction)
- target[0] = ASM_JMP32REL;
-
- // Find offset from instruction after jmp, to the replacement function.
-#pragma warning(push)
-#pragma warning(disable:4244)
- int offset_to_replacement_function =
- reinterpret_cast<unsigned char*>(replacement_function) -
- reinterpret_cast<unsigned char*>(target) - 5;
-#pragma warning(pop)
- // complete the jmp instruction
- RawMemcpy(reinterpret_cast<void*>(target + 1),
- reinterpret_cast<void*>(&offset_to_replacement_function), 4);
- // Set any remaining bytes that were moved to the preamble-stub to INT3 so
- // as not to cause confusion (otherwise you might see some strange
- // instructions if you look at the disassembly, or even invalid
- // instructions). Also, by doing this, we will break into the debugger if
- // some code calls into this portion of the code. If this happens, it
- // means that this function cannot be patched using this patcher without
- // further thought.
- if (preamble_bytes > 5) {
- RawMemset(reinterpret_cast<void*>(target + 5), ASM_INT3,
- preamble_bytes - 5);
- }
-
- // Inv: The memory pointed to by target_function now points to a relative
- // jump instruction that jumps over to the preamble_stub. The preamble
- // stub contains the first stub_size bytes of the original target
- // function's preamble code, followed by a relative jump back to the next
- // instruction after the first cbPreamble bytes.
-
- return SIDESTEP_SUCCESS;
-}
-
-} // namespace sidestep
-
-#undef ASSERT
diff --git a/chromium/sandbox/win/src/sidestep_resolver.cc b/chromium/sandbox/win/src/sidestep_resolver.cc
deleted file mode 100644
index 59274893b8e..00000000000
--- a/chromium/sandbox/win/src/sidestep_resolver.cc
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "sandbox/win/src/sidestep_resolver.h"
-
-#include <stddef.h>
-
-#include "base/win/pe_image.h"
-#include "sandbox/win/src/sandbox_nt_util.h"
-#include "sandbox/win/src/sidestep/preamble_patcher.h"
-
-namespace {
-
-const size_t kSizeOfSidestepStub = sidestep::kMaxPreambleStubSize;
-
-struct SidestepThunk {
- char sidestep[kSizeOfSidestepStub]; // Storage for the sidestep stub.
- int internal_thunk; // Dummy member to the beginning of the internal thunk.
-};
-
-struct SmartThunk {
- const void* module_base; // Target module's base.
- const void* interceptor; // Real interceptor.
- SidestepThunk sidestep; // Standard sidestep thunk.
-};
-
-} // namespace
-
-namespace sandbox {
-
-NTSTATUS SidestepResolverThunk::Setup(const void* target_module,
- const void* interceptor_module,
- const char* target_name,
- const char* interceptor_name,
- const void* interceptor_entry_point,
- void* thunk_storage,
- size_t storage_bytes,
- size_t* storage_used) {
- NTSTATUS ret =
- Init(target_module, interceptor_module, target_name, interceptor_name,
- interceptor_entry_point, thunk_storage, storage_bytes);
- if (!NT_SUCCESS(ret))
- return ret;
-
- SidestepThunk* thunk = reinterpret_cast<SidestepThunk*>(thunk_storage);
-
- size_t internal_bytes = storage_bytes - kSizeOfSidestepStub;
- if (!SetInternalThunk(&thunk->internal_thunk, internal_bytes, thunk_storage,
- interceptor_))
- return STATUS_BUFFER_TOO_SMALL;
-
- AutoProtectMemory memory;
- ret = memory.ChangeProtection(target_, kSizeOfSidestepStub, PAGE_READWRITE);
- if (!NT_SUCCESS(ret))
- return ret;
-
- sidestep::SideStepError rv = sidestep::PreamblePatcher::Patch(
- target_, reinterpret_cast<void*>(&thunk->internal_thunk), thunk_storage,
- kSizeOfSidestepStub);
-
- if (sidestep::SIDESTEP_INSUFFICIENT_BUFFER == rv)
- return STATUS_BUFFER_TOO_SMALL;
-
- if (sidestep::SIDESTEP_SUCCESS != rv)
- return STATUS_UNSUCCESSFUL;
-
- if (storage_used)
- *storage_used = GetThunkSize();
-
- return ret;
-}
-
-size_t SidestepResolverThunk::GetThunkSize() const {
- return GetInternalThunkSize() + kSizeOfSidestepStub;
-}
-
-// This is basically a wrapper around the normal sidestep patch that extends
-// the thunk to use a chained interceptor. It uses the fact that
-// SetInternalThunk generates the code to pass as the first parameter whatever
-// it receives as original_function; we let SidestepResolverThunk set this value
-// to its saved code, and then we change it to our thunk data.
-NTSTATUS SmartSidestepResolverThunk::Setup(const void* target_module,
- const void* interceptor_module,
- const char* target_name,
- const char* interceptor_name,
- const void* interceptor_entry_point,
- void* thunk_storage,
- size_t storage_bytes,
- size_t* storage_used) {
- if (storage_bytes < GetThunkSize())
- return STATUS_BUFFER_TOO_SMALL;
-
- SmartThunk* thunk = reinterpret_cast<SmartThunk*>(thunk_storage);
- thunk->module_base = target_module;
-
- NTSTATUS ret;
- if (interceptor_entry_point) {
- thunk->interceptor = interceptor_entry_point;
- } else {
- ret = ResolveInterceptor(interceptor_module, interceptor_name,
- &thunk->interceptor);
- if (!NT_SUCCESS(ret))
- return ret;
- }
-
- // Perform a standard sidestep patch on the last part of the thunk, but point
- // to our internal smart interceptor.
- size_t standard_bytes = storage_bytes - offsetof(SmartThunk, sidestep);
- ret = SidestepResolverThunk::Setup(target_module, interceptor_module,
- target_name, nullptr,
- reinterpret_cast<void*>(&SmartStub),
- &thunk->sidestep, standard_bytes, nullptr);
- if (!NT_SUCCESS(ret))
- return ret;
-
- // Fix the internal thunk to pass the whole buffer to the interceptor.
- SetInternalThunk(&thunk->sidestep.internal_thunk, GetInternalThunkSize(),
- thunk_storage, reinterpret_cast<void*>(&SmartStub));
-
- if (storage_used)
- *storage_used = GetThunkSize();
-
- return ret;
-}
-
-size_t SmartSidestepResolverThunk::GetThunkSize() const {
- return GetInternalThunkSize() + kSizeOfSidestepStub +
- offsetof(SmartThunk, sidestep);
-}
-
-// This code must basically either call the intended interceptor or skip the
-// call and invoke instead the original function. In any case, we are saving
-// the registers that may be trashed by our c++ code.
-//
-// This function is called with a first parameter inserted by us, that points
-// to our SmartThunk. When we call the interceptor we have to replace this
-// parameter with the one expected by that function (stored inside our
-// structure); on the other hand, when we skip the interceptor we have to remove
-// that extra argument before calling the original function.
-//
-// When we skip the interceptor, the transformation of the stack looks like:
-// On Entry: On Use: On Exit:
-// [param 2] = first real argument [param 2] (esp+1c) [param 2]
-// [param 1] = our SmartThunk [param 1] (esp+18) [ret address]
-// [ret address] = real caller [ret address] (esp+14) [xxx]
-// [xxx] [addr to jump to] (esp+10) [xxx]
-// [xxx] [saved eax] [xxx]
-// [xxx] [saved ebx] [xxx]
-// [xxx] [saved ecx] [xxx]
-// [xxx] [saved edx] [xxx]
-__declspec(naked)
-void SmartSidestepResolverThunk::SmartStub() {
- __asm {
- push eax // Space for the jump.
- push eax // Save registers.
- push ebx
- push ecx
- push edx
- mov ebx, [esp + 0x18] // First parameter = SmartThunk.
- mov edx, [esp + 0x14] // Get the return address.
- mov eax, [ebx]SmartThunk.module_base
- push edx
- push eax
- call SmartSidestepResolverThunk::IsInternalCall
- add esp, 8
-
- test eax, eax
- lea edx, [ebx]SmartThunk.sidestep // The original function.
- jz call_interceptor
-
- // Skip this call
- mov ecx, [esp + 0x14] // Return address.
- mov [esp + 0x18], ecx // Remove first parameter.
- mov [esp + 0x10], edx
- pop edx // Restore registers.
- pop ecx
- pop ebx
- pop eax
- ret 4 // Jump to original function.
-
- call_interceptor:
- mov ecx, [ebx]SmartThunk.interceptor
- mov [esp + 0x18], edx // Replace first parameter.
- mov [esp + 0x10], ecx
- pop edx // Restore registers.
- pop ecx
- pop ebx
- pop eax
- ret // Jump to original function.
- }
-}
-
-bool SmartSidestepResolverThunk::IsInternalCall(const void* base,
- void* return_address) {
- DCHECK_NT(base);
- DCHECK_NT(return_address);
-
- base::win::PEImage pe(base);
- if (pe.GetImageSectionFromAddr(return_address))
- return true;
- return false;
-}
-
-} // namespace sandbox
diff --git a/chromium/sandbox/win/src/sidestep_resolver.h b/chromium/sandbox/win/src/sidestep_resolver.h
deleted file mode 100644
index d06655031d6..00000000000
--- a/chromium/sandbox/win/src/sidestep_resolver.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SANDBOX_WIN_SRC_SIDESTEP_RESOLVER_H_
-#define SANDBOX_WIN_SRC_SIDESTEP_RESOLVER_H_
-
-#include <stddef.h>
-
-#include "sandbox/win/src/nt_internals.h"
-#include "sandbox/win/src/resolver.h"
-
-namespace sandbox {
-
-// This is the concrete resolver used to perform sidestep interceptions.
-class SidestepResolverThunk : public ResolverThunk {
- public:
- SidestepResolverThunk() {}
-
- SidestepResolverThunk(const SidestepResolverThunk&) = delete;
- SidestepResolverThunk& operator=(const SidestepResolverThunk&) = delete;
-
- ~SidestepResolverThunk() override {}
-
- // Implementation of Resolver::Setup.
- NTSTATUS Setup(const void* target_module,
- const void* interceptor_module,
- const char* target_name,
- const char* interceptor_name,
- const void* interceptor_entry_point,
- void* thunk_storage,
- size_t storage_bytes,
- size_t* storage_used) override;
-
- // Implementation of Resolver::GetThunkSize.
- size_t GetThunkSize() const override;
-};
-
-// This is the concrete resolver used to perform smart sidestep interceptions.
-// This means basically a sidestep interception that skips the interceptor when
-// the caller resides on the same dll being intercepted. It is intended as
-// a helper only, because that determination is not infallible.
-class SmartSidestepResolverThunk : public SidestepResolverThunk {
- public:
- SmartSidestepResolverThunk() {}
-
- SmartSidestepResolverThunk(const SmartSidestepResolverThunk&) = delete;
- SmartSidestepResolverThunk& operator=(const SmartSidestepResolverThunk&) =
- delete;
-
- ~SmartSidestepResolverThunk() override {}
-
- // Implementation of Resolver::Setup.
- NTSTATUS Setup(const void* target_module,
- const void* interceptor_module,
- const char* target_name,
- const char* interceptor_name,
- const void* interceptor_entry_point,
- void* thunk_storage,
- size_t storage_bytes,
- size_t* storage_used) override;
-
- // Implementation of Resolver::GetThunkSize.
- size_t GetThunkSize() const override;
-
- private:
- // Performs the actual call to the interceptor if the conditions are correct
- // (as determined by IsInternalCall).
- static void SmartStub();
-
- // Returns true if return_address is inside the module loaded at base.
- static bool IsInternalCall(const void* base, void* return_address);
-};
-
-} // namespace sandbox
-
-#endif // SANDBOX_WIN_SRC_SIDESTEP_RESOLVER_H_
diff --git a/chromium/sandbox/win/src/signed_policy.cc b/chromium/sandbox/win/src/signed_policy.cc
index f446fa668be..eb32734abec 100644
--- a/chromium/sandbox/win/src/signed_policy.cc
+++ b/chromium/sandbox/win/src/signed_policy.cc
@@ -11,6 +11,7 @@
#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_nt_util.h"
#include "sandbox/win/src/sandbox_policy.h"
#include "sandbox/win/src/win_utils.h"
@@ -49,20 +50,17 @@ NTSTATUS SignedPolicy::CreateSectionAction(
const ClientInfo& client_info,
const base::win::ScopedHandle& local_file_handle,
HANDLE* target_section_handle) {
- NtCreateSectionFunction NtCreateSection = nullptr;
- ResolveNTFunctionPtr("NtCreateSection", &NtCreateSection);
-
// The only action supported is ASK_BROKER which means create the requested
// section as specified.
if (ASK_BROKER != eval_result)
return false;
HANDLE local_section_handle = nullptr;
- NTSTATUS status = NtCreateSection(&local_section_handle,
- SECTION_QUERY | SECTION_MAP_WRITE |
- SECTION_MAP_READ | SECTION_MAP_EXECUTE,
- nullptr, 0, PAGE_EXECUTE, SEC_IMAGE,
- local_file_handle.Get());
+ NTSTATUS status = GetNtExports()->CreateSection(
+ &local_section_handle,
+ SECTION_QUERY | SECTION_MAP_WRITE | SECTION_MAP_READ |
+ SECTION_MAP_EXECUTE,
+ nullptr, 0, PAGE_EXECUTE, SEC_IMAGE, local_file_handle.Get());
if (!local_section_handle)
return status;
diff --git a/chromium/sandbox/win/src/startup_information_helper.cc b/chromium/sandbox/win/src/startup_information_helper.cc
index 7251205d8b3..d85c1ff65a3 100644
--- a/chromium/sandbox/win/src/startup_information_helper.cc
+++ b/chromium/sandbox/win/src/startup_information_helper.cc
@@ -68,7 +68,7 @@ void StartupInformationHelper::AddInheritedHandle(HANDLE handle) {
}
void StartupInformationHelper::SetAppContainer(
- scoped_refptr<AppContainerBase> container) {
+ scoped_refptr<AppContainer> container) {
// Only supported for Windows 8+.
DCHECK(base::win::GetVersion() >= base::win::Version::WIN8);
// LowPrivilegeAppContainer only supported for Windows 10+
diff --git a/chromium/sandbox/win/src/startup_information_helper.h b/chromium/sandbox/win/src/startup_information_helper.h
index 87034d2ec0d..166f2fc4238 100644
--- a/chromium/sandbox/win/src/startup_information_helper.h
+++ b/chromium/sandbox/win/src/startup_information_helper.h
@@ -43,7 +43,7 @@ class StartupInformationHelper {
// Create PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES and
// PROC_THREAD_ATTRIBUTE_ALL_APPLICATION_PACKAGES_POLICY
// based on |container|. |container| should be valid.
- void SetAppContainer(scoped_refptr<AppContainerBase> container);
+ void SetAppContainer(scoped_refptr<AppContainer> container);
// Creates PROC_THREAD_ATTRIBUTE_JOB_LIST with |job_handle|. Not valid before
// Windows 10.
void AddJobToAssociate(HANDLE job_handle);
@@ -69,7 +69,7 @@ class StartupInformationHelper {
int CountAttributes();
// Fields that are not passed into CreateProcessAsUserW().
- scoped_refptr<AppContainerBase> app_container_;
+ scoped_refptr<AppContainer> app_container_;
bool restrict_child_process_creation_ = false;
HANDLE stdout_handle_ = INVALID_HANDLE_VALUE;
HANDLE stderr_handle_ = INVALID_HANDLE_VALUE;
diff --git a/chromium/sandbox/win/src/target_interceptions.cc b/chromium/sandbox/win/src/target_interceptions.cc
index 1b467814c6c..d44a2651369 100644
--- a/chromium/sandbox/win/src/target_interceptions.cc
+++ b/chromium/sandbox/win/src/target_interceptions.cc
@@ -11,8 +11,6 @@
namespace sandbox {
-SANDBOX_INTERCEPT NtExports g_nt;
-
const char KERNEL32_DLL_NAME[] = "kernel32.dll";
enum SectionLoadState {
@@ -60,14 +58,16 @@ TargetNtMapViewOfSection(NtMapViewOfSectionFunction orig_MapViewOfSection,
// indicates Application Verifier is enabled and we should wait until
// the next module is loaded.
if (ansi_module_name &&
- (g_nt._strnicmp(
+ (GetNtExports()->_strnicmp(
ansi_module_name, base::win::kApplicationVerifierDllName,
- g_nt.strlen(base::win::kApplicationVerifierDllName) + 1) == 0))
+ GetNtExports()->strlen(
+ base::win::kApplicationVerifierDllName) +
+ 1) == 0)) {
break;
-
+ }
if (ansi_module_name &&
- (g_nt._strnicmp(ansi_module_name, KERNEL32_DLL_NAME,
- sizeof(KERNEL32_DLL_NAME)) == 0)) {
+ (GetNtExports()->_strnicmp(ansi_module_name, KERNEL32_DLL_NAME,
+ sizeof(KERNEL32_DLL_NAME)) == 0)) {
s_state = kAfterKernel32;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
@@ -96,7 +96,7 @@ TargetNtMapViewOfSection(NtMapViewOfSectionFunction orig_MapViewOfSection,
if (agent) {
if (!agent->OnDllLoad(file_name, module_name, *base)) {
// Interception agent is demanding to un-map the module.
- g_nt.UnmapViewOfSection(process, *base);
+ GetNtExports()->UnmapViewOfSection(process, *base);
*base = nullptr;
ret = STATUS_UNSUCCESSFUL;
}
diff --git a/chromium/sandbox/win/src/target_process.cc b/chromium/sandbox/win/src/target_process.cc
index d8fb75899d9..7a7aaf013c2 100644
--- a/chromium/sandbox/win/src/target_process.cc
+++ b/chromium/sandbox/win/src/target_process.cc
@@ -23,6 +23,7 @@
#include "sandbox/win/src/crosscall_server.h"
#include "sandbox/win/src/policy_low_level.h"
#include "sandbox/win/src/restricted_token_utils.h"
+#include "sandbox/win/src/sandbox_nt_util.h"
#include "sandbox/win/src/sandbox_types.h"
#include "sandbox/win/src/security_capabilities.h"
#include "sandbox/win/src/sharedmem_ipc_server.h"
@@ -205,16 +206,17 @@ ResultCode TargetProcess::Create(
}
ResultCode TargetProcess::TransferVariable(const char* name,
- void* address,
+ const void* address,
size_t size) {
if (!sandbox_process_info_.IsValid())
return SBOX_ERROR_UNEXPECTED_CALL;
SIZE_T written;
- if (!::WriteProcessMemory(sandbox_process_info_.process_handle(), address,
- address, size, &written))
+ if (!::WriteProcessMemory(sandbox_process_info_.process_handle(),
+ const_cast<void*>(address), address, size,
+ &written)) {
return SBOX_ERROR_CANNOT_WRITE_VARIABLE_VALUE;
-
+ }
if (written != size)
return SBOX_ERROR_INVALID_WRITE_VARIABLE_SIZE;
@@ -319,12 +321,9 @@ ResultCode TargetProcess::AssignLowBoxToken(
PROCESS_ACCESS_TOKEN process_access_token = {};
process_access_token.token = token.Get();
- NtSetInformationProcess SetInformationProcess = nullptr;
- ResolveNTFunctionPtr("NtSetInformationProcess", &SetInformationProcess);
-
- NTSTATUS status = SetInformationProcess(
+ NTSTATUS status = GetNtExports()->SetInformationProcess(
sandbox_process_info_.process_handle(),
- static_cast<PROCESS_INFORMATION_CLASS>(NtProcessInformationAccessToken),
+ static_cast<PROCESSINFOCLASS>(NtProcessInformationAccessToken),
&process_access_token, sizeof(process_access_token));
if (!NT_SUCCESS(status)) {
::SetLastError(GetLastErrorFromNtStatus(status));
diff --git a/chromium/sandbox/win/src/target_process.h b/chromium/sandbox/win/src/target_process.h
index 082d92e3ec2..060016e4543 100644
--- a/chromium/sandbox/win/src/target_process.h
+++ b/chromium/sandbox/win/src/target_process.h
@@ -90,7 +90,9 @@ class TargetProcess {
HANDLE MainThread() const { return sandbox_process_info_.thread_handle(); }
// Transfers variable at |address| of |size| bytes from broker to target.
- ResultCode TransferVariable(const char* name, void* address, size_t size);
+ ResultCode TransferVariable(const char* name,
+ const void* address,
+ size_t size);
private:
// Details of the target process.
diff --git a/chromium/sandbox/win/src/unload_dll_test.cc b/chromium/sandbox/win/src/unload_dll_test.cc
index fc85c0cd179..2067f777ebb 100644
--- a/chromium/sandbox/win/src/unload_dll_test.cc
+++ b/chromium/sandbox/win/src/unload_dll_test.cc
@@ -42,6 +42,17 @@ SBOX_TESTS_COMMAND int OpenExecutablePath(int argc, wchar_t** argv) {
return SBOX_TEST_SUCCEEDED;
}
+std::unique_ptr<TestRunner> BaselineAvicapRunner() {
+ auto runner = std::make_unique<TestRunner>();
+ runner->SetTestState(BEFORE_REVERT);
+ runner->SetTimeout(2000);
+ // Add a registry rule, because that ensures that the interception agent has
+ // more than one item in its internal table.
+ runner->AddRule(TargetPolicy::SUBSYS_FILES, TargetPolicy::FILES_ALLOW_QUERY,
+ L"\\??\\*.exe");
+ return runner;
+}
+
// Fails on Windows ARM64: https://crbug.com/905526
#if defined(ARCH_CPU_ARM64)
#define MAYBE_BaselineAvicapDll DISABLED_BaselineAvicapDll
@@ -49,49 +60,51 @@ SBOX_TESTS_COMMAND int OpenExecutablePath(int argc, wchar_t** argv) {
#define MAYBE_BaselineAvicapDll BaselineAvicapDll
#endif
TEST(UnloadDllTest, MAYBE_BaselineAvicapDll) {
- TestRunner runner;
- runner.SetTestState(BEFORE_REVERT);
- runner.SetTimeout(2000);
- // Add a registry rule, because that ensures that the interception agent has
- // more than one item in its internal table.
- EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_FILES,
- TargetPolicy::FILES_ALLOW_QUERY, L"\\??\\*.exe"));
-
+ auto runner = BaselineAvicapRunner();
// Note for the puzzled: avicap32.dll is a 64-bit dll in 64-bit versions of
// windows so this test and the others just work.
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"UseOneDLL L avicap32.dll"));
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"UseOneDLL B avicap32.dll"));
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"UseOneDLL L avicap32.dll"));
+ runner = BaselineAvicapRunner();
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"UseOneDLL B avicap32.dll"));
}
-TEST(UnloadDllTest, UnloadAviCapDllNoPatching) {
- TestRunner runner;
- runner.SetTestState(BEFORE_REVERT);
- runner.SetTimeout(2000);
- sandbox::TargetPolicy* policy = runner.GetPolicy();
- policy->AddDllToUnload(L"avicap32.dll");
- EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(L"UseOneDLL L avicap32.dll"));
- EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(L"UseOneDLL B avicap32.dll"));
+std::unique_ptr<TestRunner> UnloadAvicapNoPatchingRunner() {
+ auto runner = std::make_unique<TestRunner>();
+ runner->SetTestState(BEFORE_REVERT);
+ runner->SetTimeout(2000);
+ runner->GetPolicy()->AddDllToUnload(L"avicap32.dll");
+ return runner;
}
-TEST(UnloadDllTest, UnloadAviCapDllWithPatching) {
- TestRunner runner;
- runner.SetTimeout(2000);
- runner.SetTestState(BEFORE_REVERT);
- sandbox::TargetPolicy* policy = runner.GetPolicy();
- policy->AddDllToUnload(L"avicap32.dll");
+TEST(UnloadDllTest, UnloadAviCapDllNoPatching) {
+ auto runner = UnloadAvicapNoPatchingRunner();
+ EXPECT_EQ(SBOX_TEST_FAILED, runner->RunTest(L"UseOneDLL L avicap32.dll"));
+ runner = UnloadAvicapNoPatchingRunner();
+ EXPECT_EQ(SBOX_TEST_FAILED, runner->RunTest(L"UseOneDLL B avicap32.dll"));
+}
+std::unique_ptr<TestRunner> UnloadAvicapWithPatchingRunner() {
+ auto runner = std::make_unique<TestRunner>();
+ runner->SetTestState(BEFORE_REVERT);
+ runner->SetTimeout(2000);
+ runner->GetPolicy()->AddDllToUnload(L"avicap32.dll");
// Add a couple of rules that ensures that the interception agent add EAT
// patching on the client which makes sure that the unload dll record does
// not interact badly with them.
- EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_FILES,
- TargetPolicy::FILES_ALLOW_QUERY, L"\\??\\*.exe"));
- EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_FILES,
- TargetPolicy::FILES_ALLOW_QUERY, L"\\??\\*.log"));
+ runner->AddRule(TargetPolicy::SUBSYS_FILES, TargetPolicy::FILES_ALLOW_QUERY,
+ L"\\??\\*.exe");
+ runner->AddRule(TargetPolicy::SUBSYS_FILES, TargetPolicy::FILES_ALLOW_QUERY,
+ L"\\??\\*.log");
+ return runner;
+}
- EXPECT_EQ(SBOX_TEST_FAILED, runner.RunTest(L"UseOneDLL L avicap32.dll"));
+TEST(UnloadDllTest, UnloadAviCapDllWithPatching) {
+ auto runner = UnloadAvicapWithPatchingRunner();
+ EXPECT_EQ(SBOX_TEST_FAILED, runner->RunTest(L"UseOneDLL L avicap32.dll"));
- runner.SetTestState(AFTER_REVERT);
- EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"OpenExecutablePath"));
+ runner = UnloadAvicapWithPatchingRunner();
+ runner->SetTestState(AFTER_REVERT);
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner->RunTest(L"OpenExecutablePath"));
}
} // namespace sandbox
diff --git a/chromium/sandbox/win/src/win_utils.cc b/chromium/sandbox/win/src/win_utils.cc
index c8d0702652e..0769fd82376 100644
--- a/chromium/sandbox/win/src/win_utils.cc
+++ b/chromium/sandbox/win/src/win_utils.cc
@@ -10,6 +10,7 @@
#include <stddef.h>
#include <stdint.h>
+#include <limits>
#include <map>
#include <memory>
#include <string>
@@ -19,6 +20,8 @@
#include "base/numerics/safe_math.h"
#include "base/strings/string_util.h"
#include "base/win/pe_image.h"
+#include "base/win/scoped_handle.h"
+#include "base/win/win_util.h"
#include "sandbox/win/src/internal_types.h"
#include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/src/sandbox_nt_util.h"
@@ -147,6 +150,21 @@ void RemoveImpliedDevice(std::wstring* path) {
*path = path->substr(kNTDotPrefixLen);
}
+bool QueryObjectInformation(HANDLE handle,
+ OBJECT_INFORMATION_CLASS info_class,
+ std::vector<char>& buffer) {
+ NtQueryObjectFunction NtQueryObject = sandbox::GetNtExports()->QueryObject;
+ ULONG size = static_cast<ULONG>(buffer.size());
+ __try {
+ return NT_SUCCESS(
+ NtQueryObject(handle, info_class, buffer.data(), size, &size));
+ } __except (GetExceptionCode() == STATUS_INVALID_HANDLE
+ ? EXCEPTION_EXECUTE_HANDLER
+ : EXCEPTION_CONTINUE_SEARCH) {
+ return false;
+ }
+}
+
} // namespace
namespace sandbox {
@@ -411,44 +429,39 @@ bool ConvertToLongPath(std::wstring* native_path,
}
bool GetPathFromHandle(HANDLE handle, std::wstring* path) {
- NtQueryObjectFunction NtQueryObject = nullptr;
- ResolveNTFunctionPtr("NtQueryObject", &NtQueryObject);
-
- OBJECT_NAME_INFORMATION initial_buffer;
- OBJECT_NAME_INFORMATION* name = &initial_buffer;
- ULONG size = sizeof(initial_buffer);
- // Query the name information a first time to get the size of the name.
- // Windows XP requires that the size of the buffer passed in here be != 0.
- NTSTATUS status =
- NtQueryObject(handle, ObjectNameInformation, name, size, &size);
-
- std::unique_ptr<BYTE[]> name_ptr;
- if (size) {
- name_ptr.reset(new BYTE[size]);
- name = reinterpret_cast<OBJECT_NAME_INFORMATION*>(name_ptr.get());
-
- // Query the name information a second time to get the name of the
- // object referenced by the handle.
- status = NtQueryObject(handle, ObjectNameInformation, name, size, &size);
- }
-
- if (STATUS_SUCCESS != status)
+ using LengthType = decltype(OBJECT_NAME_INFORMATION::ObjectName.Length);
+ std::vector<char> buffer(sizeof(OBJECT_NAME_INFORMATION) +
+ std::numeric_limits<LengthType>::max());
+ if (!QueryObjectInformation(handle, ObjectNameInformation, buffer))
return false;
-
+ OBJECT_NAME_INFORMATION* name =
+ reinterpret_cast<OBJECT_NAME_INFORMATION*>(buffer.data());
path->assign(name->ObjectName.Buffer,
name->ObjectName.Length / sizeof(name->ObjectName.Buffer[0]));
return true;
}
bool GetNtPathFromWin32Path(const std::wstring& path, std::wstring* nt_path) {
- HANDLE file = ::CreateFileW(
+ base::win::ScopedHandle file(::CreateFileW(
path.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
- if (file == INVALID_HANDLE_VALUE)
+ nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr));
+ if (!file.IsValid())
+ return false;
+ return GetPathFromHandle(file.Get(), nt_path);
+}
+
+bool GetTypeNameFromHandle(HANDLE handle, std::wstring* type_name) {
+ // No typename is currently longer than 32 characters on Windows 11, so use an
+ // upper bound of 128 characters.
+ std::vector<char> buffer(sizeof(OBJECT_TYPE_INFORMATION) +
+ 128 * sizeof(WCHAR));
+ if (!QueryObjectInformation(handle, ObjectTypeInformation, buffer))
return false;
- bool rv = GetPathFromHandle(file, nt_path);
- ::CloseHandle(file);
- return rv;
+ OBJECT_TYPE_INFORMATION* name =
+ reinterpret_cast<OBJECT_TYPE_INFORMATION*>(buffer.data());
+ type_name->assign(name->Name.Buffer,
+ name->Name.Length / sizeof(name->Name.Buffer[0]));
+ return true;
}
bool WriteProtectedChildMemory(HANDLE child_process,
@@ -504,20 +517,14 @@ bool CopyToChildMemory(HANDLE child,
}
DWORD GetLastErrorFromNtStatus(NTSTATUS status) {
- RtlNtStatusToDosErrorFunction NtStatusToDosError = nullptr;
- ResolveNTFunctionPtr("RtlNtStatusToDosError", &NtStatusToDosError);
- return NtStatusToDosError(status);
+ return GetNtExports()->RtlNtStatusToDosError(status);
}
// This function uses the undocumented PEB ImageBaseAddress field to extract
// the base address of the new process.
void* GetProcessBaseAddress(HANDLE process) {
- NtQueryInformationProcessFunction query_information_process = nullptr;
- ResolveNTFunctionPtr("NtQueryInformationProcess", &query_information_process);
- if (!query_information_process)
- return nullptr;
PROCESS_BASIC_INFORMATION process_basic_info = {};
- NTSTATUS status = query_information_process(
+ NTSTATUS status = GetNtExports()->QueryInformationProcess(
process, ProcessBasicInformation, &process_basic_info,
sizeof(process_basic_info), nullptr);
if (STATUS_SUCCESS != status)
@@ -545,6 +552,67 @@ void* GetProcessBaseAddress(HANDLE process) {
return base_address;
}
+absl::optional<ProcessHandleMap> GetCurrentProcessHandles() {
+ DWORD handle_count;
+ if (!::GetProcessHandleCount(::GetCurrentProcess(), &handle_count))
+ return absl::nullopt;
+
+ // The system call will return only handles up to the buffer size so add a
+ // margin of error of an additional 1000 handles.
+ std::vector<char> buffer((handle_count + 1000) * sizeof(uint32_t));
+ DWORD return_length;
+ NTSTATUS status = GetNtExports()->QueryInformationProcess(
+ ::GetCurrentProcess(), ProcessHandleTable, buffer.data(),
+ static_cast<ULONG>(buffer.size()), &return_length);
+
+ if (!NT_SUCCESS(status)) {
+ ::SetLastError(GetLastErrorFromNtStatus(status));
+ return absl::nullopt;
+ }
+ DCHECK(buffer.size() >= return_length);
+ DCHECK((buffer.size() % sizeof(uint32_t)) == 0);
+ ProcessHandleMap handle_map;
+ const uint32_t* handle_values = reinterpret_cast<uint32_t*>(buffer.data());
+ size_t count = return_length / sizeof(uint32_t);
+ for (size_t index = 0; index < count; ++index) {
+ HANDLE handle = base::win::Uint32ToHandle(handle_values[index]);
+ std::wstring type_name;
+ if (GetTypeNameFromHandle(handle, &type_name))
+ handle_map[type_name].push_back(handle);
+ }
+ return handle_map;
+}
+
+absl::optional<ProcessHandleMap> GetCurrentProcessHandlesWin7() {
+ DWORD handle_count = UINT_MAX;
+ const int kInvalidHandleThreshold = 100;
+ const size_t kHandleOffset = 4; // Handles are always a multiple of 4.
+
+ if (!::GetProcessHandleCount(::GetCurrentProcess(), &handle_count))
+ return absl::nullopt;
+ ProcessHandleMap handle_map;
+
+ uint32_t handle_value = 0;
+ int invalid_count = 0;
+
+ // Keep incrementing until we hit the number of handles reported by
+ // GetProcessHandleCount(). If we hit a very long sequence of invalid
+ // handles we assume that we've run past the end of the table.
+ while (handle_count && invalid_count < kInvalidHandleThreshold) {
+ handle_value += kHandleOffset;
+ HANDLE handle = base::win::Uint32ToHandle(handle_value);
+ std::wstring type_name;
+ if (!GetTypeNameFromHandle(handle, &type_name)) {
+ ++invalid_count;
+ continue;
+ }
+
+ --handle_count;
+ handle_map[type_name].push_back(handle);
+ }
+ return handle_map;
+}
+
} // namespace sandbox
void ResolveNTFunctionPtr(const char* name, void* ptr) {
diff --git a/chromium/sandbox/win/src/win_utils.h b/chromium/sandbox/win/src/win_utils.h
index 6f54d200499..2acbe034b24 100644
--- a/chromium/sandbox/win/src/win_utils.h
+++ b/chromium/sandbox/win/src/win_utils.h
@@ -7,11 +7,14 @@
#include <stdlib.h>
+#include <map>
#include <memory>
#include <string>
+#include <vector>
#include "base/cxx17_backports.h"
#include "base/win/windows_types.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace sandbox {
@@ -22,6 +25,9 @@ const size_t kNTPrefixLen = base::size(kNTPrefix) - 1;
const wchar_t kNTDevicePrefix[] = L"\\Device\\";
const size_t kNTDevicePrefixLen = base::size(kNTDevicePrefix) - 1;
+// List of handles mapped to their kernel object type name.
+using ProcessHandleMap = std::map<std::wstring, std::vector<HANDLE>>;
+
// Basic implementation of a singleton which calls the destructor
// when the exe is shutting down or the DLL is being unloaded.
template <typename Derived>
@@ -69,9 +75,12 @@ bool SameObject(HANDLE handle, const wchar_t* full_path);
bool GetPathFromHandle(HANDLE handle, std::wstring* path);
// Resolves a win32 path to an nt path using GetPathFromHandle. The path must
-// exist. Returs true if the translation was succesful.
+// exist. Returns true if the translation was successful.
bool GetNtPathFromWin32Path(const std::wstring& path, std::wstring* nt_path);
+// Resolves a handle to its type name. Returns true if successful.
+bool GetTypeNameFromHandle(HANDLE handle, std::wstring* type_name);
+
// Translates a reserved key name to its handle.
// For example "HKEY_LOCAL_MACHINE" returns HKEY_LOCAL_MACHINE.
// Returns nullptr if the name does not represent any reserved key name.
@@ -113,6 +122,18 @@ DWORD GetLastErrorFromNtStatus(NTSTATUS status);
// the base address. This should only be called on new, suspended processes.
void* GetProcessBaseAddress(HANDLE process);
+// Returns a map of handles open in the current process. The call will only
+// works on Windows 8+. The map is keyed by the kernel object type name. If
+// querying the handles fails an empty optional value is returned. Note that
+// unless all threads are suspended in the process the valid handles could
+// change between the return of the list and when you use them.
+absl::optional<ProcessHandleMap> GetCurrentProcessHandles();
+
+// Fallback function for GetCurrentProcessHandles. Should only be needed on
+// Windows 7 which doesn't support the API to query all process handles. This
+// uses a brute force method to get the process handles.
+absl::optional<ProcessHandleMap> GetCurrentProcessHandlesWin7();
+
} // namespace sandbox
// Resolves a function name in NTDLL to a function pointer. The second parameter
diff --git a/chromium/sandbox/win/src/win_utils_unittest.cc b/chromium/sandbox/win/src/win_utils_unittest.cc
index da82ec17949..4469da4c18c 100644
--- a/chromium/sandbox/win/src/win_utils_unittest.cc
+++ b/chromium/sandbox/win/src/win_utils_unittest.cc
@@ -8,14 +8,20 @@
#include <psapi.h>
+#include <algorithm>
#include <vector>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
#include "base/numerics/safe_conversions.h"
#include "base/path_service.h"
+#include "base/rand_util.h"
+#include "base/strings/string_util_win.h"
+#include "base/strings/stringprintf.h"
#include "base/win/scoped_handle.h"
#include "base/win/scoped_process_information.h"
+#include "base/win/windows_version.h"
#include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/tests/common/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -57,11 +63,58 @@ bool GetModuleList(HANDLE process, std::vector<HMODULE>* result) {
return false;
}
+std::wstring GetRandomName() {
+ return base::StringPrintf(L"chrome_%08X%08X", base::RandUint64(),
+ base::RandUint64());
+}
+
+void CompareHandlePath(const base::win::ScopedHandle& handle,
+ const std::wstring& expected_path) {
+ std::wstring path;
+ ASSERT_TRUE(GetPathFromHandle(handle.Get(), &path));
+ EXPECT_TRUE(base::EqualsCaseInsensitiveASCII(path, expected_path));
+}
+
+void CompareHandleType(const base::win::ScopedHandle& handle,
+ const std::wstring& expected_type) {
+ std::wstring type_name;
+ ASSERT_TRUE(GetTypeNameFromHandle(handle.Get(), &type_name));
+ EXPECT_TRUE(base::EqualsCaseInsensitiveASCII(type_name, expected_type));
+}
+
+void FindHandle(const ProcessHandleMap& handle_map,
+ const wchar_t* type_name,
+ const base::win::ScopedHandle& handle) {
+ ProcessHandleMap::const_iterator entry = handle_map.find(type_name);
+ ASSERT_NE(handle_map.end(), entry);
+ const std::vector<HANDLE>& handles = entry->second;
+ EXPECT_NE(handles.cend(),
+ std::find(handles.cbegin(), handles.cend(), handle.Get()));
+}
+
+void TestCurrentProcessHandles(absl::optional<ProcessHandleMap> (*func)()) {
+ std::wstring random_name = GetRandomName();
+ ASSERT_FALSE(random_name.empty());
+ base::win::ScopedHandle event_handle(
+ ::CreateEvent(nullptr, FALSE, FALSE, random_name.c_str()));
+ ASSERT_TRUE(event_handle.IsValid());
+ std::wstring pipe_name = L"\\\\.\\pipe\\" + random_name;
+ base::win::ScopedHandle pipe_handle(::CreateNamedPipe(
+ pipe_name.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE,
+ PIPE_UNLIMITED_INSTANCES, 0, 0, NMPWAIT_USE_DEFAULT_WAIT, nullptr));
+ ASSERT_TRUE(pipe_handle.IsValid());
+
+ absl::optional<ProcessHandleMap> handle_map = func();
+ ASSERT_TRUE(handle_map);
+ EXPECT_LE(2U, handle_map->size());
+ FindHandle(*handle_map, L"Event", event_handle);
+ FindHandle(*handle_map, L"File", pipe_handle);
+}
+
} // namespace
TEST(WinUtils, IsReparsePoint) {
using sandbox::IsReparsePoint;
-
// Create a temp file because we need write access to it.
wchar_t temp_directory[MAX_PATH];
wchar_t my_folder[MAX_PATH];
@@ -84,7 +137,7 @@ TEST(WinUtils, IsReparsePoint) {
IsReparsePoint(new_file));
// Replace the directory with a reparse point to %temp%.
- HANDLE dir = ::CreateFile(my_folder, FILE_ALL_ACCESS,
+ HANDLE dir = ::CreateFile(my_folder, FILE_WRITE_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
EXPECT_NE(INVALID_HANDLE_VALUE, dir);
@@ -207,19 +260,20 @@ TEST(WinUtils, ConvertToLongPath) {
ASSERT_TRUE(base::PathService::Get(base::DIR_SYSTEM, &orig_path));
orig_path = orig_path.Append(L"calc.exe");
- base::FilePath temp_path;
- ASSERT_TRUE(base::PathService::Get(base::DIR_PROGRAM_FILES, &temp_path));
- temp_path = temp_path.Append(L"test_calc.exe");
+ base::ScopedTempDir temp_dir;
+ base::FilePath base_path;
+ ASSERT_TRUE(base::PathService::Get(base::DIR_COMMON_APP_DATA, &base_path));
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDirUnderPath(base_path));
+ base::FilePath temp_path = temp_dir.GetPath().Append(L"test_calc.exe");
ASSERT_TRUE(base::CopyFile(orig_path, temp_path));
- // No more asserts until cleanup.
- // WIN32 long path: "c:\Program Files\test_calc.exe"
+ // WIN32 long path: "C:\ProgramData\%TEMP%\test_calc.exe"
wchar_t short_path[MAX_PATH] = {};
DWORD size =
::GetShortPathNameW(temp_path.value().c_str(), short_path, MAX_PATH);
EXPECT_TRUE(size > 0 && size < MAX_PATH);
- // WIN32 short path: "C:\PROGRA~1\TEST_C~1.exe"
+ // WIN32 short path: "C:\PROGRA~3\%TEMP%\TEST_C~1.exe"
// Sanity check that we actually got a short path above! Small chance
// it was disabled in the filesystem setup.
@@ -228,13 +282,13 @@ TEST(WinUtils, ConvertToLongPath) {
std::wstring short_form_native_path;
EXPECT_TRUE(sandbox::GetNtPathFromWin32Path(std::wstring(short_path),
&short_form_native_path));
- // NT short path: "\Device\HarddiskVolume4\PROGRA~1\TEST_C~1.EXE"
+ // NT short path: "\Device\HarddiskVolume4\PROGRA~3\%TEMP%\TEST_C~1.EXE"
// Test 1: convert win32 short path to long:
std::wstring test1(short_path);
EXPECT_TRUE(sandbox::ConvertToLongPath(&test1));
EXPECT_TRUE(::wcsicmp(temp_path.value().c_str(), test1.c_str()) == 0);
- // Expected result: "c:\Program Files\test_calc.exe"
+ // Expected result: "C:\ProgramData\%TEMP%\test_calc.exe"
// Test 2: convert native short path to long:
std::wstring drive_letter = temp_path.value().substr(0, 3);
@@ -247,10 +301,40 @@ TEST(WinUtils, ConvertToLongPath) {
std::wstring expected_result = short_form_native_path.substr(0, index + 1);
expected_result.append(temp_path.value().substr(3));
EXPECT_TRUE(::wcsicmp(expected_result.c_str(), test2.c_str()) == 0);
- // Expected result: "\Device\HarddiskVolumeX\Program Files\test_calc.exe"
+ // Expected result: "\Device\HarddiskVolumeX\ProgramData\%TEMP%\test_calc.exe"
+}
- // clean up
- EXPECT_TRUE(base::DeleteFile(temp_path));
+TEST(WinUtils, GetPathAndTypeFromHandle) {
+ std::wstring invalid_handle;
+ EXPECT_FALSE(GetPathFromHandle(nullptr, &invalid_handle));
+ EXPECT_TRUE(invalid_handle.empty());
+ EXPECT_FALSE(GetTypeNameFromHandle(nullptr, &invalid_handle));
+ EXPECT_TRUE(invalid_handle.empty());
+ std::wstring random_name = GetRandomName();
+ ASSERT_FALSE(random_name.empty());
+ std::wstring event_name = L"Global\\" + random_name;
+ base::win::ScopedHandle event_handle(
+ ::CreateEvent(nullptr, FALSE, FALSE, event_name.c_str()));
+ ASSERT_TRUE(event_handle.IsValid());
+ CompareHandlePath(event_handle, L"\\BaseNamedObjects\\" + random_name);
+ CompareHandleType(event_handle, L"Event");
+ std::wstring pipe_name = L"\\\\.\\pipe\\" + random_name;
+ base::win::ScopedHandle pipe_handle(::CreateNamedPipe(
+ pipe_name.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE,
+ PIPE_UNLIMITED_INSTANCES, 0, 0, NMPWAIT_USE_DEFAULT_WAIT, nullptr));
+ ASSERT_TRUE(pipe_handle.IsValid());
+ CompareHandlePath(pipe_handle, L"\\Device\\NamedPipe\\" + random_name);
+ CompareHandleType(pipe_handle, L"File");
+}
+
+TEST(WinUtils, GetCurrentProcessHandles) {
+ if (base::win::GetVersion() < base::win::Version::WIN8) {
+ ASSERT_FALSE(GetCurrentProcessHandles());
+ EXPECT_EQ(DWORD{ERROR_INVALID_PARAMETER}, ::GetLastError());
+ } else {
+ TestCurrentProcessHandles(GetCurrentProcessHandles);
+ }
+ TestCurrentProcessHandles(GetCurrentProcessHandlesWin7);
}
} // namespace sandbox