Subject: port-i386/16842: setjmp()/longjmp() don't recover %fs register
To: None <gnats-bugs@gnats.netbsd.org>
From: None <kent@netbsd.org>
List: netbsd-bugs
Date: 05/16/2002 01:30:34
>Number: 16842
>Category: port-i386
>Synopsis: setjmp()/longjmp() don't recover %fs register
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: port-i386-maintainer
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Thu May 16 01:31:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator: TAMURA Kent
>Release: -current
>Organization:
>Environment:
NetBSD gabi-n.hauN.org 1.5ZC NetBSD 1.5ZC (GABI-N) #1: Fri Apr 12 12:22:33 JST 2002 kent@gabi-n.hauN.org:/home1/n/src/sys/arch/i386/compile/GABI-N i386
>Description:
The function setjmp() does not save %fs register and longjump() does
not restore %fs register.
If the kernl has "options USER_LDT", userland programs can handle LDT
by setting %fs register. The current behavior of setjmp()/longjmp()
is not suitable for such programs.
>How-To-Repeat:
Run the following code. The result in -current is:
1: fs = 31
2: fs = 0
3: fs = 0
3: should be 31.
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
static void inline set_fs(int fs) {
__asm__ volatile ("
movl %0,%%eax
movw %%ax,%%fs"
: /* no ret */
: "r"(fs) /* input */
: "%eax");
}
static int inline get_fs() {
int fs = 0;
__asm__ volatile ("movl %%fs,%0" : "=r"(fs));
return fs;
}
int main() {
int saved_fs;
jmp_buf env;
saved_fs = get_fs();
printf("1: fs = %d\n", get_fs());
if (0 == setjmp(env)) {
set_fs(0);
printf("2: fs = %d\n", get_fs());
longjmp(env, 1);
}
printf("3: fs = %d\n", get_fs());
return saved_fs != get_fs() ? EXIT_FAILURE : EXIT_SUCCESS;
}
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted: