[LLD][COFF] Zero linker-version header field breaks Authenticode on Windows 7

Hello llvm-dev,

I've recently been using clang-cl and lld-link to build Windows PE executables, which I then code-sign with Authenticode. I've found that although the resulting signed executables seem to validate successfully on Windows 10, they don't on Windows 7: right-clicking on one and bringing up the Windows Properties dialog shows either no 'Digital Signatures' tab at all (for a 32-bit binary), or one in which Windows says the signature doesn't validate.

After some experimentation, it appears that this is a consequence of the 'linker version' field in the PE header being zero! lld-link sets both the MajorLinkerVersion and MinorLinkerVersion bytes to zero; Visual Studio's linker (as of VS2015) sets MajorLinkerVersion to 14. And if I patch lld to set MajorLinkerVersion to 14, the problem goes away, and my signed lld-linked executables validate just fine on Windows 7 as well as 10.

I have no idea why this happens, though I speculate that if Windows is depending on the linker-version field at all then it's probably using it as a trigger to enable or disable particular bug workarounds (and making the unwarranted assumption that only one linker exists). But regardless of the reason, I think it would be more useful if lld-link wrote a value into that field that makes this use case do the right thing.

Does that sound reasonable? If so, I'll prepare a patch. (Though I'm not sure whether I should do the trivial thing of just writing a value I know to work, or whether I should invent a command-line option to tell lld which version of Visual Studio's linker it should claim to be. The latter would be consistent with clang-cl's configurable compiler-version emulation, I suppose.)

Cheers,
Simon

Hi,

lld-link already has an option to specify version. Please try to add “/version:14.0” to your command line.

As to whether we should set it to 14.0 (or some other version number) by default or not, we probably should. The reason why I didn’t do that until now is just because I didn’t see a need for that, but if a Microsoft tool expects some value there, there’s no reason to not do that.

From: Rui Ueyama [mailto:ruiu@google.com]
Sent: 21 June 2017 15:23

lld-link already has an option to specify version. Please try to add
"/version:14.0" to your command line.

That doesn't affect the same version field. The number I put in there goes into the MajorImageVersion and MinorImageVersion fields, whereas to solve this signature issue I need to control MajorLinkerVersion and MinorLinkerVersion.

Cheers,
Simon

Ah, OK. Then I think we should just hard-code the linker so that it sets MajorLinkerVersion to 14. We can make it configurable, but hard-coding should suffice.

Do you want to write a patch? I mean it’s going to be just a single-line patch, so if you are not familiar with LLVM development process, I can do that for you.

From: Rui Ueyama [mailto:ruiu@google.com]
Sent: 21 June 2017 16:05

Ah, OK. Then I think we should just hard-code the linker so that it sets
MajorLinkerVersion to 14.

Fair enough.

Do you want to write a patch? I mean it's going to be just a single-line patch,
so if you are not familiar with LLVM development process, I can do that for
you.

I haven't interacted with the LLVM development process before, but submitting a nice easy one-line patch seems like an excellent way to start, so I'm happy to do it myself :slight_smile:

Cheers,
SImon

Sure! Then please go ahead and send me a patch.

Thank you for reporting the issue!