1 /* 2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. 3 * Portions Copyright (c) 2000 Ulrich Drepper 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 * 13 * Further, this software is distributed without any warranty that it is 14 * free of the rightful claim of any third person regarding infringement 15 * or the like. Any license provided herein, whether implied or 16 * otherwise, applies only to this software file. Patent licenses, if 17 * any, provided herein do not apply to combinations of this program with 18 * other software, or any other product whatsoever. 19 * 20 * You should have received a copy of the GNU General Public License along 21 * with this program; if not, write the Free Software Foundation, Inc., 22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23 * 24 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 25 * Mountain View, CA 94043, or: 26 * 27 * http://www.sgi.com$ 28 * 29 * For further information regarding this notice, see:$ 30 * 31 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ 32 * 33 * 34 * Linux Test Project - Silicon Graphics, Inc. 35 * TEST IDENTIFIER : fork05 36 * EXECUTED BY : anyone 37 * TEST TITLE : Make sure LDT is propagated correctly 38 * TEST CASE TOTAL : 1 39 * CPU TYPES : i386 40 * AUTHORS : Ulrich Drepper 41 * Nate Straz 42 * 43 *On Friday, May 2, 2003 at 09:47:00AM MST, Ulrich Drepper wrote: 44 *>Robert Williamson wrote: 45 *> 46 *>> I'm getting a SIGSEGV with one of our tests, fork05.c, that apparently 47 *>> you wrote (attached below). The test passes on my 2.5.68 machine running 48 *>> SuSE 8.0 (glibc 2.2.5 and Linuxthreads), however it segmentation faults on 49 *>> RedHat 9 running 2.5.68. The test seems to "break" when it attempts to run 50 *>> the assembly code....could you take a look at it? 51 *> 52 *>There is no need to look at it, I know it cannot work anymore on recent 53 *>systems. Either change all uses of %gs to %fs or skip the entire patch 54 *>if %gs has a nonzero value. 55 *> 56 *>- -- 57 *>- --------------. ,-. 444 Castro Street 58 *>Ulrich Drepper \ ,-----------------' \ Mountain View, CA 94041 USA 59 *>Red Hat `--' drepper at redhat.com `--------------------------- 60 * 61 * 62 * 63 *On Sat, Aug 12, 2000 at 12:47:31PM -0700, Ulrich Drepper wrote: 64 *> Ever since the %gs handling was fixed in the 2.3.99 series the 65 *> appended test program worked. Now with 2.4.0-test6 it's not working 66 *> again. Looking briefly over the patch from test5 to test6 I haven't 67 *> seen an immediate candidate for the breakage. It could be missing 68 *> propagation of the LDT to the new process (and therefore an invalid 69 *> segment descriptor) or simply clearing %gs. 70 *> 71 *> Anyway, this is what you should see and what you get with test5: 72 *> 73 *> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 74 *> a = 42 75 *> %gs = 0x0007 76 *> %gs = 0x0007 77 *> a = 99 78 *> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 79 *> 80 *> This is what you get with test6: 81 *> 82 *> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 83 *> a = 42 84 *> %gs = 0x0007 85 *> %gs = 0x0000 86 *> <SEGFAULT> 87 *> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 88 *> 89 *> If somebody is actually creating a test suite for the kernel, please 90 *> add this program. It's mostly self-contained. The correct handling 91 *> of %gs is really important since glibc 2.2 will make heavy use of it. 92 *> 93 *> - -- 94 *> - ---------------. ,-. 1325 Chesapeake Terrace 95 *> Ulrich Drepper \ ,-------------------' \ Sunnyvale, CA 94089 USA 96 *> Red Hat `--' drepper at redhat.com `------------------------ 97 *> 98 *> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 99 * 100 */ 101 102 #include <stdio.h> 103 #include <fcntl.h> 104 #include <unistd.h> 105 #include <stdlib.h> 106 #include <sys/wait.h> 107 #include "test.h" 108 109 char *TCID = "fork05"; 110 111 static char *environ_list[] = { "TERM", "NoTSetzWq", "TESTPROG" }; 112 113 #define NUMBER_OF_ENVIRON (sizeof(environ_list)/sizeof(char *)) 114 int TST_TOTAL = NUMBER_OF_ENVIRON; 115 116 #if defined(linux) && defined(__i386__) 117 118 struct modify_ldt_ldt_s { 119 unsigned int entry_number; 120 unsigned long int base_addr; 121 unsigned int limit; 122 unsigned int seg_32bit:1; 123 unsigned int contents:2; 124 unsigned int read_exec_only:1; 125 unsigned int limit_in_pages:1; 126 unsigned int seg_not_present:1; 127 unsigned int useable:1; 128 unsigned int empty:25; 129 }; 130 131 static int a = 42; 132 133 static void modify_ldt(int, struct modify_ldt_ldt_s *, int); 134 asm(" .text\n\ 135 .type modify_ldt,@function \n\ 136 modify_ldt: \n\ 137 push %ebx \n\ 138 mov 0x10(%esp,1),%edx \n\ 139 mov 0xc(%esp,1),%ecx \n\ 140 mov 0x8(%esp,1),%ebx \n\ 141 mov $0x7b,%eax \n\ 142 int $0x80 \n\ 143 pop %ebx \n\ 144 ret"); 145 146 int main(void) 147 { 148 struct modify_ldt_ldt_s ldt0; 149 int lo; 150 pid_t pid; 151 int res; 152 153 ldt0.entry_number = 0; 154 ldt0.base_addr = (long)&a; 155 ldt0.limit = 4; 156 ldt0.seg_32bit = 1; 157 ldt0.contents = 0; 158 ldt0.read_exec_only = 0; 159 ldt0.limit_in_pages = 0; 160 ldt0.seg_not_present = 0; 161 ldt0.useable = 1; 162 ldt0.empty = 0; 163 164 modify_ldt(1, &ldt0, sizeof(ldt0)); 165 166 asm volatile ("movw %w0, %%fs"::"q" (7)); 167 168 asm volatile ("movl %%fs:0, %0":"=r" (lo)); 169 tst_resm(TINFO, "a = %d", lo); 170 171 asm volatile ("pushl %%fs; popl %0":"=q" (lo)); 172 tst_resm(TINFO, "%%fs = %#06hx", lo); 173 174 asm volatile ("movl %0, %%fs:0"::"r" (99)); 175 176 pid = fork(); 177 178 if (pid == 0) { 179 asm volatile ("pushl %%fs; popl %0":"=q" (lo)); 180 tst_resm(TINFO, "%%fs = %#06hx", lo); 181 182 asm volatile ("movl %%fs:0, %0":"=r" (lo)); 183 tst_resm(TINFO, "a = %d", lo); 184 185 if (lo != 99) 186 tst_resm(TFAIL, "Test failed"); 187 else 188 tst_resm(TPASS, "Test passed"); 189 exit(lo != 99); 190 } else { 191 waitpid(pid, &res, 0); 192 } 193 194 return WIFSIGNALED(res); 195 } 196 197 #else /* if defined(linux) && defined(__i386__) */ 198 199 int main(void) 200 { 201 tst_resm(TINFO, "%%fs test only for ix86"); 202 203 /* 204 * should be successful on all non-ix86 platforms. 205 */ 206 tst_exit(); 207 } 208 209 #endif /* if defined(linux) && defined(__i386__) */ 210