Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected hw exceptions causes exit(1) instead of segfault #1655

Closed
poizan42 opened this issue Feb 1, 2017 · 2 comments
Closed

Unexpected hw exceptions causes exit(1) instead of segfault #1655

poizan42 opened this issue Feb 1, 2017 · 2 comments

Comments

@poizan42
Copy link

poizan42 commented Feb 1, 2017

  • A brief description

If I execute certain instructions with invalid operands / values on stack then the process immediately exists with exitcode 1. This includes far calls / returns with invalid segment selector and unmapped software interrupts.

  • Expected results

These conditions produces a SIGSEGV on linux.

  • Actual results (with terminal output if applicable)
poizan@poiR61:~/wsl32/exitcode1bug$ ./farcall; echo $?
1
poizan@poiR61:~/wsl32/exitcode1bug$ ./int21; echo $?
1
  • Your Windows build number

15019

  • Steps / All commands required to reproduce the error from a brand new installation
  1. (Install Bash on Windows and install package build-essential)
  2. Build the following programs with gcc:
poizan@poiR61:~/wsl32/exitcode1bug$ cat farcall.c
int main(int argc, char* argv[])
{
    __asm__("pushq  $0x2a\n\t"
            "pushq  $0x2a\n\t"
            "lretq");
    return 42;
}
poizan@poiR61:~/wsl32/exitcode1bug$ cat int21.c
int main(int argc, char* argv[])
{
    __asm__("int $0x21");
    return 42;
}
  1. Try running the programs. They just exits with errorcode 1 instead of generating a segmentation fault.
  • Strace of the failing command
poizan@poiR61:~/wsl32/exitcode1bug$ strace ./farcall
execve("./farcall", ["./farcall"], [/* 16 vars */]) = 0
brk(NULL)                               = 0x190c000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f69781c0000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=24473, ...}) = 0
mmap(NULL, 24473, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f69781ca000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\t\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1864888, ...}) = 0
mmap(NULL, 3967392, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f6977a30000
mprotect(0x7f6977bef000, 2097152, PROT_NONE) = 0
mmap(0x7f6977def000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bf000) = 0x7f6977def000
mmap(0x7f6977df5000, 14752, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f6977df5000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f69781b0000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f69781a0000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6978190000
arch_prctl(ARCH_SET_FS, 0x7f69781a0700) = 0
mprotect(0x7f6977def000, 16384, PROT_READ) = 0
mprotect(0x600000, 4096, PROT_READ)     = 0
mprotect(0x7f6978025000, 4096, PROT_READ) = 0
munmap(0x7f69781ca000, 24473)           = 0
+++ exited with 1 +++
poizan@poiR61:~/wsl32/exitcode1bug$ strace ./int21
execve("./int21", ["./int21"], [/* 16 vars */]) = 0
brk(NULL)                               = 0xc71000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f43e15d0000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=24473, ...}) = 0
mmap(NULL, 24473, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f43e15db000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\t\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1864888, ...}) = 0
mmap(NULL, 3967392, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f43e0e30000
mprotect(0x7f43e0fef000, 2097152, PROT_NONE) = 0
mmap(0x7f43e11ef000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bf000) = 0x7f43e11ef000
mmap(0x7f43e11f5000, 14752, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f43e11f5000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f43e15c0000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f43e15b0000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f43e15a0000
arch_prctl(ARCH_SET_FS, 0x7f43e15b0700) = 0
mprotect(0x7f43e11ef000, 16384, PROT_READ) = 0
mprotect(0x600000, 4096, PROT_READ)     = 0
mprotect(0x7f43e1425000, 4096, PROT_READ) = 0
munmap(0x7f43e15db000, 24473)           = 0
+++ exited with 1 +++
  • Required packages and commands to install

gcc (build-essential)

@stehufntdev
Copy link
Collaborator

Thanks for reporting the issue. Is this blocking a particular scenario or just something you noticed during tests?

Currently WSL does not translate all traps\exceptions to Linux signals. #513 has a few more details if you are interested.

@poizan42
Copy link
Author

poizan42 commented Feb 2, 2017

Actually I was investigating the possibility of implementing 32-bit support in userspace. Probably not surprisingly, codesegment 0x23 is set up for compatibility mode, so we can in fact execute 32-bit code. The biggest problem here is if code makes direct syscalls with int 80h. Then I need some way to trap that. If we got a SIGSEGV then we could just forward the syscall attempted to a syscall from 64-bit code. However this isn't possible now since the process just exits immediately without any signals involved.

Btw. note that syscalls from 32-bit land are normally done through the vDSO, which we of course get to define for ourselves if we make a custom loader for 32-bit binaries

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants