This is an archive of the discontinued LLVM Phabricator instance.

[COFF] Mark images with no exception handlers for /safeseh
ClosedPublic

Authored by rnk on Apr 18 2018, 10:39 AM.

Details

Summary

DLLs and executables with no exception handlers need to be marked with
IMAGE_DLL_CHARACTERISTICS_NO_SEH, even if they have a load config.

Discovered here when building Chromium with LLD on Windows:
https://crbug.com/833951

Diff Detail

Repository
rL LLVM

Event Timeline

rnk created this revision.Apr 18 2018, 10:39 AM
rnk added a comment.Apr 18 2018, 10:51 AM

@mstorsjo will this be a problem for mingw? Does the mingw CRT provide a load config for each image? This could be an undesirable behavior change if mingw does not provide a load config, and the user links in a 32-bit object file that has exception handlers that they don't actually need for program correctness, but now the DLL is marked as not using safe SEH.

In D45778#1071192, @rnk wrote:

@mstorsjo will this be a problem for mingw? Does the mingw CRT provide a load config for each image?

I have no idea what a load config is - what should I look for and where?

This could be an undesirable behavior change if mingw does not provide a load config, and the user links in a 32-bit object file that has exception handlers that they don't actually need for program correctness, but now the DLL is marked as not using safe SEH.

Fwiw, no mingw setups use SEH for exceptions on i386 so far - it's only used on x86_64. On i386, it's either dwarf or sjlj.

What effect does it have if a DLL is marked as not using safe SEH?

rnk updated this revision to Diff 142984.Apr 18 2018, 1:04 PM
  • Set the flag if there are handlers but no load config
rnk added a comment.Apr 18 2018, 1:05 PM

What effect does it have if a DLL is marked as not using safe SEH?

If it also lacks a load config, it is more easily expoitable. If a DLL doesn't have a IMAGE_LOAD_CONFIG_DIRECTORY64 and it doesn't have the "no SEH" flag set, then any address in that DLL can be used as an exception handler. For 32-bit, exception handler function pointers are stored on the stack, so only a stack buffer overrun followed by an exception is needed to start an exploit chain.

After thinking that through, I think we should adjust the check to always add the "no SEH" flag if there is no load config. That's the safe thing to do.

rnk updated this revision to Diff 142986.Apr 18 2018, 1:06 PM
  • remove tab
ruiu added inline comments.Apr 18 2018, 1:39 PM
lld/COFF/Writer.cpp
833–834 ↗(On Diff #142986)

Maybe we should move these conditions to createSEHTable and make it a Config member (such as Config->SEH?)

rnk added inline comments.Apr 18 2018, 2:42 PM
lld/COFF/Writer.cpp
833–834 ↗(On Diff #142986)

That makes sense, but I wouldn't want to put mutable state on Config. We can just put it on Writer.

rnk updated this revision to Diff 143002.Apr 18 2018, 2:44 PM
  • move logic to createSEHTable
ruiu accepted this revision.Apr 18 2018, 2:47 PM

LGTM

lld/COFF/Writer.cpp
830 ↗(On Diff #143002)

Maybe you should move I386 to createSEHTable as well?

This revision is now accepted and ready to land.Apr 18 2018, 2:47 PM
rnk updated this revision to Diff 143004.Apr 18 2018, 2:54 PM
  • fix hello32.test: default to marking image as "no seh", then remove it if we record handlers
rnk updated this revision to Diff 143006.Apr 18 2018, 2:56 PM
  • fix boolean logic thinko
rnk added inline comments.Apr 18 2018, 3:40 PM
lld/COFF/Writer.cpp
830 ↗(On Diff #143002)

I found a way to do this that I like.

This revision was automatically updated to reflect the committed changes.