gramineproject / gramine

A library OS for Linux multi-process applications, with Intel SGX support
GNU Lesser General Public License v3.0
588 stars 193 forks source link

in and out instruction causes SIGILL instead of SIGSEGV #1191

Closed NirjharRoyiitk closed 2 months ago

NirjharRoyiitk commented 1 year ago

Description of the problem

in and out instruction causes SIGILL instead of SIGSEGV. in and out instructions aren't allowed inside SGX enclaves and hence throws SIGILL but native behavior of user applications is that in / out instructions throws SIGSEGV.

Some relevant links

https://stackoverflow.com/questions/3215878/what-are-in-out-instructions-in-x86-used-for (please read all answers)

https://stackoverflow.com/questions/46642384/how-to-run-code-that-uses-x86-in-and-out-i-o-instructions

https://c9x.me/x86/html/file_module_x86_id_139.html

This bug prevents lscpu to run.

Steps to reproduce

asm("in %dx, %al;");/ AT & T style /

The above code snippet run on any unit test .c file throws SIGSEGV natively but in gramine (SGX) it throws SIGILL

Expected results

expects SIGSEGV

Actual results

getting SIGILL

Gramine commit hash

da7ea3f0f4e72033ccbea877e5599ee65564a516

kailun-qin commented 1 year ago

Yes, according to Intel SGX programming reference, executing I/O instructions (e.g., IN/OUT) inside an enclave will generate a #UD fault. Gramine (PAL) will then try to handle the exception and will propogate #UD to LibOS/app (eventually SIGILL) if not (properly) handled (which is the case for IN/OUT). However natively, Linux maps all #GP exceptions to SIGSEGV signal. I guess this is the reason of the observed discrepancy.

Technically it's possible to remap the #UD caused by in-enclave IN/OUT to SIGSEGV, but I'm not sure if it's desired.

dimakuv commented 1 year ago

Thanks @NirjharRoyiitk for the bug report!

I think this is a valid issue, and we can remap this #UD to a SIGSEGV signal. As mentioned in the issue, the SIGILL signal generated by Gramine confuses the lscpu application, and remapping it to SIGSEGV makes lscpu work again. So we have at least one application that would benefit from it (though I admit, I don't know why would anyone want to run lscpu inside of the enclave, but people/language runtimes do weird things).

TLDR: I think it doesn't hurt to emulate in/out instructions (family of these instructions) as though they throw #GP, and deliver SIGSEGV to the app.

@NirjharRoyiitk Is this something you wanted to implement in Gramine, or you expect us (Gramine maintainers) to work on this?