taviso / 123elf

A native port of Lotus 1-2-3 to Linux.
1.16k stars 59 forks source link

OpenBSD port #87

Open vrza opened 2 years ago

vrza commented 2 years ago

Project now builds using the feature branch from https://github.com/taviso/123elf/pull/86

It segfaults at runtime in init_terminal_settings in wrappers.c, when ioctl(2) (called by tcgetattr(3)) attempts to write to this memory location:

static struct termios original;

ioctl(2) fails with errno == 14 (EFAULT, "Bad address").

Is it possible that there is some unsafe programming practice at play here that OpenBSD catches?

vrza commented 2 years ago

Passing a pointer to heap memory to ioctl instead works around the problem:

void __attribute__((constructor)) init_terminal_settings()
{
    // Make a backup of the terminal state to restore to later.
    int attr;
    struct termios *t;
    t = malloc(sizeof(struct termios));
    if (isatty(STDIN_FILENO)) {
        attr = tcgetattr(STDIN_FILENO, t);
        memmove(t, &original, sizeof(struct termios));
        if (attr != 0) err(EXIT_FAILURE, "Failed to query terminal attributes.");
    }

}

but I still don't understand why it can't write directly to the data segment.

taviso commented 2 years ago

wow, cool that it works!

I'm not really sure why it's failing, the code seems okay to me... I think there's no guarantee about what order constructors are run in, so maybe they're being run too early, and OpenBSD expects some other constructor to run first?

These might not really be necessary anymore though... I might be able to refactor them out. I think now terminal settings are better handled, so less cleanup is necessary.

(Sorry for the slow response to PRs, I'll get to them!)

vrza commented 2 years ago

Although it passes the workaround, it proceeds to segfault here:

Program received signal SIGSEGV, Segmentation fault.
0x0804adb8 in ?? ()
(gdb) bt
#0  0x0804adb8 in ?? ()
#1  0x0804a53b in __init ()
#2  0x0804ad67 in _start ()
(gdb) disas __init
Dump of assembler code for function __init:
   0x0804a530 <+0>: push   %ebp
   0x0804a531 <+1>: mov    %esp,%ebp
   0x0804a533 <+3>: and    $0xfffffff0,%esp
   0x0804a536 <+6>: call   0x804ad90
   0x0804a53b <+11>:    nop
   0x0804a53c <+12>:    leave  
   0x0804a53d <+13>:    ret    
End of assembler dump.
vrza commented 2 years ago

After rebuilding the symbol undefine list for OpenBSD (using the Linux list as the starting point), the "Bad address" ioctl issue is gone. I reverted the workaround.

Program still segfaults in __init, though.