Rebase against 0abb419016e3a38e36ba0bdfe9c0497a29a86fcf.

This commit is contained in:
Elizabeth Figura
2025-09-18 17:22:54 -05:00
parent 04570cc4c7
commit 0e9c421030
2 changed files with 1 additions and 144 deletions

View File

@@ -1,143 +0,0 @@
From fdc7661206f824bcf796ee6b59a222fd28c5437b Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Thu, 28 Apr 2016 18:14:36 +0800
Subject: [PATCH] ntdll/tests: Add some tests for NtSetLdtEntries.
1. Some copy protections call NtSetLdtEntries(0x000f) and then with 'retf'
instruction jump to that selector expecting that it works (the tests show that
NtSetLdtEntries(0x000f,0x001f) should succeed). In order to make this work a
limitation to set only selectors > LDT_FIRST_ENTRY (512) in wine_ldt_set_entry()
was removed.
2. wine_ldt_set_entry() was made to always mark modified selector entries as
WINE_LDT_FLAGS_ALLOCATED, otherwise get_selector_entry() server call returns
entries without that flag set and NtQueryInformationThread(ThreadDescriptorTableEntry)
fails.
---
dlls/kernel32/tests/thread.c | 75 +++++++++++++++++++++++++++++++++++
dlls/ntdll/unix/signal_i386.c | 2 +-
2 files changed, 76 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/thread.c b/dlls/kernel32/tests/thread.c
index c0303b471e8..64b62fefd0d 100644
--- a/dlls/kernel32/tests/thread.c
+++ b/dlls/kernel32/tests/thread.c
@@ -103,6 +103,7 @@ static HRESULT (WINAPI *pSetThreadDescription)(HANDLE,const WCHAR *);
static HRESULT (WINAPI *pGetThreadDescription)(HANDLE,WCHAR **);
static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG,PVECTORED_EXCEPTION_HANDLER);
static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID);
+static NTSTATUS (WINAPI *pNtSetLdtEntries)(ULONG,ULONG,ULONG,ULONG,ULONG,ULONG);
static HANDLE create_target_process(const char *arg)
{
@@ -1319,6 +1320,78 @@ static void test_GetThreadSelectorEntry(void)
ok(entry.HighWord.Bits.Granularity == 1, "expected 1, got %u\n", entry.HighWord.Bits.Granularity);
}
+static void test_NtSetLdtEntries(void)
+{
+ THREAD_DESCRIPTOR_INFORMATION tdi;
+ LDT_ENTRY ds_entry;
+ CONTEXT ctx;
+ DWORD ret;
+ union
+ {
+ LDT_ENTRY entry;
+ DWORD dw[2];
+ } sel;
+
+ if (!pNtSetLdtEntries)
+ {
+ win_skip("NtSetLdtEntries is not available on this platform\n");
+ return;
+ }
+
+ if (pNtSetLdtEntries(0, 0, 0, 0, 0, 0) == STATUS_NOT_IMPLEMENTED) /* WoW64 */
+ {
+ win_skip("NtSetLdtEntries is not implemented on this platform\n");
+ return;
+ }
+
+ ret = pNtSetLdtEntries(0, 0, 0, 0, 0, 0);
+ ok(!ret, "NtSetLdtEntries failed: %08x\n", ret);
+
+ ctx.ContextFlags = CONTEXT_SEGMENTS;
+ ret = GetThreadContext(GetCurrentThread(), &ctx);
+ ok(ret, "GetThreadContext failed\n");
+
+ tdi.Selector = ctx.SegDs;
+ ret = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, &tdi, sizeof(tdi), &ret);
+ ok(!ret, "NtQueryInformationThread failed: %08x\n", ret);
+ ds_entry = tdi.Entry;
+
+ tdi.Selector = 0x000f;
+ ret = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, &tdi, sizeof(tdi), &ret);
+ ok(ret == STATUS_ACCESS_VIOLATION, "got %08x\n", ret);
+
+ tdi.Selector = 0x001f;
+ ret = pNtQueryInformationThread(GetCurrentThread(), ThreadDescriptorTableEntry, &tdi, sizeof(tdi), &ret);
+ ok(ret == STATUS_ACCESS_VIOLATION, "NtQueryInformationThread returned %08x\n", ret);
+
+ ret = GetThreadSelectorEntry(GetCurrentThread(), 0x000f, &sel.entry);
+ ok(!ret, "GetThreadSelectorEntry should fail\n");
+
+ ret = GetThreadSelectorEntry(GetCurrentThread(), 0x001f, &sel.entry);
+ ok(!ret, "GetThreadSelectorEntry should fail\n");
+
+ memset(&sel.entry, 0x9a, sizeof(sel.entry));
+ ret = GetThreadSelectorEntry(GetCurrentThread(), ctx.SegDs, &sel.entry);
+ ok(ret, "GetThreadSelectorEntry failed\n");
+ ok(!memcmp(&ds_entry, &sel.entry, sizeof(ds_entry)), "entries do not match\n");
+
+ ret = pNtSetLdtEntries(0x000f, sel.dw[0], sel.dw[1], 0x001f, sel.dw[0], sel.dw[1]);
+ ok(!ret || broken(ret == STATUS_INVALID_LDT_DESCRIPTOR) /*XP*/, "NtSetLdtEntries failed: %08x\n", ret);
+
+ if (!ret)
+ {
+ memset(&sel.entry, 0x9a, sizeof(sel.entry));
+ ret = GetThreadSelectorEntry(GetCurrentThread(), 0x000f, &sel.entry);
+ ok(ret, "GetThreadSelectorEntry failed\n");
+ ok(!memcmp(&ds_entry, &sel.entry, sizeof(ds_entry)), "entries do not match\n");
+
+ memset(&sel.entry, 0x9a, sizeof(sel.entry));
+ ret = GetThreadSelectorEntry(GetCurrentThread(), 0x001f, &sel.entry);
+ ok(ret, "GetThreadSelectorEntry failed\n");
+ ok(!memcmp(&ds_entry, &sel.entry, sizeof(ds_entry)), "entries do not match\n");
+ }
+}
+
#endif /* __i386__ */
static HANDLE finish_event;
@@ -2644,6 +2717,7 @@ static void init_funcs(void)
X(NtSetInformationThread);
X(RtlAddVectoredExceptionHandler);
X(RtlRemoveVectoredExceptionHandler);
+ X(NtSetLdtEntries);
}
#undef X
}
@@ -2700,6 +2774,7 @@ START_TEST(thread)
test_SetThreadContext();
test_GetThreadSelectorEntry();
test_GetThreadContext();
+ test_NtSetLdtEntries();
#endif
test_QueueUserWorkItem();
test_RegisterWaitForSingleObject();
diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c
index 59069f92b43..505e0b652b5 100644
--- a/dlls/ntdll/unix/signal_i386.c
+++ b/dlls/ntdll/unix/signal_i386.c
@@ -2300,7 +2300,7 @@ NTSTATUS get_thread_ldt_entry( HANDLE handle, void *data, ULONG len, ULONG *ret_
if (base || bits.limit || bits.type)
info->Entry = ldt_make_entry( base, bits );
else
- status = STATUS_UNSUCCESSFUL;
+ status = STATUS_ACCESS_VIOLATION;
}
if (status == STATUS_SUCCESS && ret_len)
--
2.50.1

View File

@@ -1 +1 @@
915a1e6fc76943913a77b71446c72dc13eadc1a0
0abb419016e3a38e36ba0bdfe9c0497a29a86fcf