summary refs log tree commit diff stats
path: root/results/classifier/118/virtual/1405
diff options
context:
space:
mode:
Diffstat (limited to 'results/classifier/118/virtual/1405')
-rw-r--r--results/classifier/118/virtual/1405151
1 files changed, 151 insertions, 0 deletions
diff --git a/results/classifier/118/virtual/1405 b/results/classifier/118/virtual/1405
new file mode 100644
index 00000000..d58227d7
--- /dev/null
+++ b/results/classifier/118/virtual/1405
@@ -0,0 +1,151 @@
+register: 0.931
+virtual: 0.929
+semantic: 0.917
+device: 0.914
+arm: 0.914
+PID: 0.910
+assembly: 0.910
+graphic: 0.903
+i386: 0.901
+debug: 0.899
+kernel: 0.893
+permissions: 0.884
+risc-v: 0.878
+socket: 0.878
+architecture: 0.873
+performance: 0.869
+vnc: 0.868
+files: 0.863
+boot: 0.847
+TCG: 0.834
+x86: 0.833
+user-level: 0.832
+network: 0.821
+VMM: 0.816
+ppc: 0.796
+KVM: 0.792
+peripherals: 0.792
+hypervisor: 0.778
+mistranslation: 0.643
+
+linux-user: calling SYS_get_thread_area and SYS_get_thread_area has incorrent result on multithread environment
+Description of problem:
+
+Steps to reproduce:
+1. Compile test.out by Command and source code: 
+```
+gcc -m32 -g test.c -lpthread -o test.out
+```
+```
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <asm/ldt.h>
+
+static inline int set_thread_area( struct user_desc *ptr )
+{
+    return syscall( SYS_set_thread_area, ptr );
+}
+
+static inline int get_thread_area( struct user_desc *ptr )
+{
+    return syscall( SYS_get_thread_area, ptr );
+}
+
+static unsigned int entry_number;
+
+static void* start_routine(void* ptr) 
+{
+    struct user_desc user_desc0 = { entry_number };
+    struct user_desc user_desc1 = { entry_number };
+    struct user_desc user_desc2 = { entry_number };
+    get_thread_area(&user_desc0);
+    printf("child thread: %u\n", user_desc0.base_addr);
+
+    user_desc1.base_addr = 2;
+    user_desc1.limit     = 0xFFF;
+    user_desc1.seg_32bit = 1;
+    set_thread_area( &user_desc1 );
+
+    get_thread_area(&user_desc2);
+    printf("child thread: %u\n", user_desc2.base_addr);
+    return NULL;
+}
+
+int main(void) {
+    struct user_desc user_desc0 = { -1 }, user_desc1 = { 0 }, user_desc2 = { 0 };
+    user_desc0.seg_32bit = 1;
+    user_desc0.useable = 1;
+    set_thread_area( &user_desc0 );
+
+    entry_number = user_desc0.entry_number;
+
+    user_desc1.entry_number = entry_number;
+    user_desc1.base_addr = 1;
+    user_desc1.limit     = 0xFFF;
+    user_desc1.seg_32bit = 1;
+    set_thread_area( &user_desc1 );
+
+    pthread_t thread_id;
+    pthread_create(&thread_id, NULL, &start_routine, NULL);
+    pthread_join(thread_id, NULL);
+
+    user_desc2.entry_number = entry_number;
+    get_thread_area(&user_desc2);
+    printf("main  thread: %u\n", user_desc2.base_addr); // main  thread: 1
+    return 0;
+}
+ ```
+2. Correct Result:
+```
+child thread: 1
+child thread: 2
+main  thread: 1
+```
+qemu-i386 Print Result:
+```
+child thread: 1
+child thread: 2
+main  thread: 2
+```
+Additional information:
+patch for fix the bug: 
+
+https://lists.nongnu.org/archive/html/qemu-devel/2023-02/msg02203.html
+
+CPUX86State::gdt::base on differect threads must have different vaules, but it points to same memory.
+value of CPUX86State::gdt::base must be copied when clone thread.
+
+https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/tls.c
+
+SYS_set_thread_area call do_set_thread_area in kernel, it set user_desc to different memroy area on differernt threads. tls_array is in thread local memory.
+
+```
+static void set_tls_desc(struct task_struct *p, int idx,
+			 const struct user_desc *info, int n)
+{
+	struct thread_struct *t = &p->thread;
+	struct desc_struct *desc = &t->tls_array[idx - GDT_ENTRY_TLS_MIN];
+	int cpu;
+
+	/*
+	 * We must not get preempted while modifying the TLS.
+	 */
+	cpu = get_cpu();
+
+	while (n-- > 0) {
+		if (LDT_empty(info) || LDT_zero(info))
+			memset(desc, 0, sizeof(*desc));
+		else
+			fill_ldt(desc, info);
+		++info;
+		++desc;
+	}
+
+	if (t == &current->thread)
+		load_TLS(t, cpu);
+
+	put_cpu();
+}
+```