• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
4  *     Author: Ulrich Drepper / Nate Straz , Red Hat
5  * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
6  */
7 
8 /*\
9  * [Description]
10  *
11  * This test verifies that LDT is propagated correctly from parent process to
12  * the child process.
13  *
14  * On Friday, May 2, 2003 at 09:47:00AM MST, Ulrich Drepper wrote:
15  *
16  *  Robert Williamson wrote:
17  *
18  *  I'm getting a SIGSEGV with one of our tests, fork05.c, that apparently
19  *  you wrote (attached below).  The test passes on my 2.5.68 machine running
20  *  SuSE 8.0 (glibc 2.2.5 and Linuxthreads), however it segmentation faults on
21  *  RedHat 9 running 2.5.68.  The test seems to "break" when it attempts to run
22  *  the assembly code....could you take a look at it?
23  *
24  *  There is no need to look at it, I know it cannot work anymore on recent
25  *  systems.  Either change all uses of %gs to %fs or skip the entire patch
26  *  if %gs has a nonzero value.
27  *
28  * On Sat, Aug 12, 2000 at 12:47:31PM -0700, Ulrich Drepper wrote:
29  *
30  *  Ever since the %gs handling was fixed in the 2.3.99 series the
31  *  appended test program worked.  Now with 2.4.0-test6 it's not working
32  *  again.  Looking briefly over the patch from test5 to test6 I haven't
33  *  seen an immediate candidate for the breakage.  It could be missing
34  *  propagation of the LDT to the new process (and therefore an invalid
35  *  segment descriptor) or simply clearing %gs.
36  *
37  *  Anyway, this is what you should see and what you get with test5:
38  *
39  *  a = 42
40  *  %gs = 0x0007
41  *  %gs = 0x0007
42  *  a = 99
43  *
44  *  This is what you get with test6:
45  *
46  *  a = 42
47  *  %gs = 0x0007
48  *  %gs = 0x0000
49  *  <SEGFAULT>
50  *
51  *  If somebody is actually creating a test suite for the kernel, please
52  *  add this program.  It's mostly self-contained.  The correct handling
53  *  of %gs is really important since glibc 2.2 will make heavy use of it.
54  */
55 
56 #include "tst_test.h"
57 
58 #if defined(__i386__)
59 
60 #include "lapi/syscalls.h"
61 #include <asm/ldt.h>
62 
run(void)63 static void run(void)
64 {
65 	struct user_desc ldt0;
66 	int base_addr = 42;
67 	int status;
68 	pid_t pid;
69 	int lo;
70 
71 	ldt0.entry_number = 0;
72 	ldt0.base_addr = (long)&base_addr;
73 	ldt0.limit = 4;
74 	ldt0.seg_32bit = 1;
75 	ldt0.contents = 0;
76 	ldt0.read_exec_only = 0;
77 	ldt0.limit_in_pages = 0;
78 	ldt0.seg_not_present = 0;
79 	ldt0.useable = 1;
80 
81 	tst_syscall(__NR_modify_ldt, 1, &ldt0, sizeof(ldt0));
82 
83 	asm volatile ("movw %w0, %%fs"::"q" (7));
84 	asm volatile ("movl %%fs:0, %0":"=r" (lo));
85 	tst_res(TINFO, "a = %d", lo);
86 
87 	asm volatile ("pushl %%fs; popl %0":"=q" (lo));
88 	tst_res(TINFO, "%%fs = %#06hx", lo);
89 
90 	asm volatile ("movl %0, %%fs:0"::"r" (99));
91 
92 	pid = SAFE_FORK();
93 	if (!pid) {
94 		asm volatile ("pushl %%fs; popl %0":"=q" (lo));
95 		tst_res(TINFO, "%%fs = %#06hx", lo);
96 
97 		asm volatile ("movl %%fs:0, %0":"=r" (lo));
98 		tst_res(TINFO, "a = %d", lo);
99 
100 		TST_EXP_EQ_LI(lo, 99);
101 
102 		exit(0);
103 	}
104 
105 	SAFE_WAITPID(pid, &status, 0);
106 
107 	if (WIFEXITED(status) && !WEXITSTATUS(status))
108 		tst_res(TPASS, "Child did exit with 0");
109 	else
110 		tst_res(TFAIL, "Child %s", tst_strstatus(status));
111 }
112 
113 static struct tst_test test = {
114 	.test_all = run,
115 	.forks_child = 1,
116 };
117 
118 #else
119 	TST_TEST_TCONF("Test only supports Intel 32 bits");
120 #endif
121