Home | History | Annotate | Download | only in fork
      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