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

Fix illegal instructions on x86 CPU that have MMX but not SSE #6828

Closed
wants to merge 1 commit into from

Conversation

manu0401
Copy link

On x86, CRYPTO_gcm128_init() uses a MMX-enabled version if the CPU has
the MMX flag. Unfortunately, the code contains the pinsrw instruction,
which is only available when the CPU has the SSE flag.

A CPU such as Geode GX1 has MMX but not SSE. Since it only checks MMX
flag OpenSSL uses the unimplemented pinsrw instruction and the program
crashes.

This change makes sure the offending code is only used when the CPU
has both MMX and SSE.

Checklist
  • documentation is added or updated
  • tests are added or updated

…not SSE

On x86, CRYPTO_gcm128_init() uses a MMX-enabled version if the CPU has
the MMX flag. Unfortunately, the code contains the pinsrw instruction,
which is only available when the CPU has the SSE flag.

A CPU such as Geode GX1 has MMX but not SSE. Since it only checks MMX
flag OpenSSL uses the unimplemented pinsrw instruction and the program
crashes.

This change makes sure the offending code is only used when the CPU
has both MMX and SSE.
@openssl-machine openssl-machine added the hold: cla required The contributor needs to submit a license agreement label Jul 31, 2018
if (OPENSSL_ia32cap_P[0] & (1 << 23)) { /* check MMX bit */
# endif
if (OPENSSL_ia32cap_P[0] & (1 << 25) && /* check SSE bit */
OPENSSL_ia32cap_P[0] & (1 << 23)) { /* check MMX bit */
Copy link
Contributor

@dot-asm dot-asm Jul 31, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seem to be misunderstanding. The [original] conditions above basically mean that if you configure without no-sse2 (which is the default), then it will check for SSE flag alone. At the same time code generated by ghash-x86.pl will indeed contain pinsrw, but it won't be executed on Geode, because SSE flag is checked. But[!] if you configure with no-sse2, then mmx code generated by ghash-x86.pl will not contain pinsrw, and check for MMX flag would be correct. If you in fact experience crash, then something went wrong somewhere. One possibility can be that you first configured without no-sse2, executed make, then re-configured with no-sse, but didn't execute make clean...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So close this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I just figure that reporter deserves a chance to do so... Or maybe there is something more to it... Otherwise I'll close it after some grace period...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This happens with NetBSD-8.0/i386 release, where some build operations (such as running configure and ghash-x86.pl) are done when an OpenSSL release is imported in the NetBSD tree, and not at build time. You answer suggest the import operation has been done badly.

The source tree is there: http://cvsweb.netbsd.org/bsdweb.cgi/src/crypto/external/bsd/openssl/

import-time generated ghash-x86.S contains pinsrw:
http://cvsweb.netbsd.org/bsdweb.cgi/src/crypto/external/bsd/openssl/lib/libcrypto/arch/i386/ghash-x86.S?rev=1.7

If I understand correctly, it is only compatible with code built with OPENSSL_IA32_SSE2. It seems a -DOPENSSL_IA32_SSE2 is missing in http://cvsweb.netbsd.org/bsdweb.cgi/src/crypto/external/bsd/openssl/lib/libcrypto/Makefile?rev=1.16

Is that the problem root?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should not import a configured build tree. You should run config on the target system.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import-time generated ghash-x86.S contains pinsrw: ... If I understand correctly, it is only compatible with code built with OPENSSL_IA32_SSE2.

Correct. To summarize, it's problem with NetBSD, not OpenSSL.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But what if I don't know what the target system is (I am creating x86 release binaries to be used on any IA32 system) and I want the best performance to be determined at runtime? I.e. should I be compiling with the minimal set of features for IA32?

Copy link
Contributor

@dot-asm dot-asm Aug 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want the best performance to be determined at runtime

Irregardless on what one does, if ghash-x86.S was generated with -DOPENSSL_IA32_SSE2, then gcm128.c has to be compiled with same option. It's just the way things are. Whether or not it's optimal choice [for specific corner case] is actually a different question. Currently ghash-x86.pl generates either vanilla+sse+pcmulqdq or vanilla+mmx(*). The rationale is that vast majority will use sse or pclmuldq, so that vanilla and mmx are kind of dead code. I wish we could omit both, but one can't and has to choose. Choice is obvious, keep vanilla as absolutely least common denominator. And vanilla+mmx option is kept for tailored builds, when you actually know that sse+pclmulqdq would be dead code, and just has have to score on mmx processor.

(*) Actually there is 3rd option, vanilla without bswap, so that code would be executable on pre-486.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, one can probably argue that mmx omission is kind of cheap. Because mmx code size is not larger than 200 bytes... [To give perspective vanilla code is >700 bytes large.]

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation; I added the extra defines.

@dot-asm dot-asm closed this Aug 1, 2018
netbsd-srcmastr pushed a commit to NetBSD/src that referenced this pull request Aug 1, 2018
openssl/openssl#6828
When ghash-x86.S is generated with -DOPENSSL_IA32_SSE2 we need to compile
gcm128.c with the same flags.
Reported by manu@
ryo pushed a commit to IIJ-NetBSD/netbsd-src that referenced this pull request Aug 1, 2018
openssl/openssl#6828
When ghash-x86.S is generated with -DOPENSSL_IA32_SSE2 we need to compile
gcm128.c with the same flags.
Reported by manu@
ryo pushed a commit to IIJ-NetBSD/netbsd-src that referenced this pull request Aug 26, 2018
	crypto/external/bsd/openssl/lib/libcrypto/arch/i386/modes.inc: revision 1.2
	crypto/external/bsd/openssl/lib/libcrypto/arch/i386/modes.inc: revision 1.3

Add missing defines:
openssl/openssl#6828

When ghash-x86.S is generated with -DOPENSSL_IA32_SSE2 we need to
compile
gcm128.c with the same flags.

Reported by manu@

remove -DGHASH_ASM_X86; it is already defined.
netbsd-srcmastr pushed a commit to NetBSD/src that referenced this pull request Sep 3, 2018
	crypto/external/bsd/openssl/lib/libcrypto/arch/i386/modes.inc: revision 1.2
	crypto/external/bsd/openssl/lib/libcrypto/arch/i386/modes.inc: revision 1.3

Add missing defines:
openssl/openssl#6828

When ghash-x86.S is generated with -DOPENSSL_IA32_SSE2 we need to
compile
gcm128.c with the same flags.

Reported by manu@

remove -DGHASH_ASM_X86; it is already defined.
netbsd-srcmastr pushed a commit to NetBSD/src that referenced this pull request Sep 6, 2018
	crypto/external/bsd/openssl/lib/libcrypto/arch/i386/modes.inc: revision 1.2
	crypto/external/bsd/openssl/lib/libcrypto/arch/i386/modes.inc: revision 1.3

Add missing defines:
openssl/openssl#6828

When ghash-x86.S is generated with -DOPENSSL_IA32_SSE2 we need to
compile
gcm128.c with the same flags.

Reported by manu@

remove -DGHASH_ASM_X86; it is already defined.
netbsd-srcmastr pushed a commit to NetBSD/src that referenced this pull request Apr 8, 2020
	crypto/external/bsd/openssl/lib/libcrypto/arch/i386/modes.inc: revision 1.2
	crypto/external/bsd/openssl/lib/libcrypto/arch/i386/modes.inc: revision 1.3

Add missing defines:
openssl/openssl#6828

When ghash-x86.S is generated with -DOPENSSL_IA32_SSE2 we need to
compile
gcm128.c with the same flags.

Reported by manu@

remove -DGHASH_ASM_X86; it is already defined.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hold: cla required The contributor needs to submit a license agreement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants