Bug 865124

Summary: openssl libcrypto using 64-bit Category instruction incorrectly
Product: [Fedora] Fedora Reporter: Maynard Johnson <maynardj>
Component: opensslAssignee: Tomas Mraz <tmraz>
Status: CLOSED NOTABUG QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: unspecified    
Version: 18CC: tmraz
Target Milestone: ---   
Target Release: ---   
Hardware: powerpc   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2012-10-17 19:39:31 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Maynard Johnson 2012-10-10 21:15:08 UTC
Description of problem:
While investigating a different bug (bug # 810992), we discoverd that openssl's 32-bit libcrypto library is apparently using certain instructions on the ppc64 platform incorrectly.  In the following file:

http://ftp.netbsd.org/pub/NetBSD/NetBSD-current/src/crypto/external/bsd/openssl/lib/libcrypto/arch/powerpc/ppccpuid.S

there is the following procedure:
------------------------------------
.globl	OPENSSL_ppc64_probe
.type	OPENSSL_ppc64_probe,@function
.align	4
OPENSSL_ppc64_probe:
	fcfid	1,1
	rldicl	0,0,32,32
	blr	
.long	0
.byte	0,12,0x14,0,0,0,0,0
------------------------------------

Further, this procedure is called from the following piece of code:
   if (sigsetjmp(ill_jmp,1) == 0)
    {
    OPENSSL_ppc64_probe();
    OPENSSL_ppccap_P |= PPC_FPU64;
    }
   }

This code incorrectly assumes that either the fcfid or rldicl instruction in the OPENSSL_ppc64_probe procedure may generate a SIGILL under certain situations. This is not the case in current POWER7 implementation. The rldicl instruction is of the 64-bit Category in the Power ISA, but neverthless, it is implemented and can be executed even in a 32-bit program, even though the ISA states that instructions in the 64-bit Category "may" result in an unsupported operation exception when run in 32-bit mode.  It's our belief that the libcrypto library made the assumption that executing this instruction in 32-bit mode would cause a SIGILL.  But since it does not, the behavior of OR'ing PPC_FPU64 to the OPENSSL_ppccap_P variable appears to be erroneous.

Version-Release number of selected component (if applicable):
1.0.1c.7.fc18

How reproducible:

See bug #810992, comment 5.

Steps to Reproduce:
1.
2.
3.
  
Actual results:


Expected results:


Additional info:

Comment 1 Tomas Mraz 2012-10-11 06:22:22 UTC
Please report the issue to the openssl upstream bug tracker: rt

What do you propose as a fix? Just removing the whole if() block above?

Comment 2 Maynard Johnson 2012-10-12 21:48:48 UTC
An email has been sent to rt explaining the situation.  They should inspect the aux vector to ascertain h/w capabilities rather than trying to pick certain instructions that they hope will give them a SIGILL.  Since the rldicl instruction is officially not supported in 32-bit mode (according to the ISA), we will probably change Valgrind to fail with an "unhandled instruction" error.  So (as described in bug # 810992) the "ppc-koji build --scratch f18 curl-7.25.0-1.fc18.src.rpm" will still bomb until libcrypto stops using unsupported instructions.

Comment 3 Maynard Johnson 2012-10-17 19:00:52 UTC
The response below was received from openssl contact, Andy Polyakov.  The upshot is that openssl's use of rldicl in 32-bit mode is intentional.  But as a workaround for the valgrind issue that is choking on the rldicl (see bug # 810992), try setting OPENSSL_ppccap environment variable to 0 prior running the application under valgrind's control.

This bug should be closed as NOTABUG.

On Mon, 2012-10-15 at 17:22 +0200, Andy Polyakov via RT wrote:
> > The OpenSSL library on Fedora 18 appears to use the routine
> > 
> > .globl		 OPENSSL_ppc64_probe
> > .type		 OPENSSL_ppc64_probe,@function
> > .align		 4
> > OPENSSL_ppc64_probe:
> > 		 fcfid		 1,1
> > 		 rldicl		 0,0,32,32
> > 		 blr		 
> > .long		 0
> > .byte		 0,12,0x14,0,0,0,0,0
> > 
> > to try and determine if the hardware is 32-bit or 64-bit.  The rldicl is
> > a 64-bit class instruction.  On a 32-bit power processor it will
> > generate a SIGILL when the instruction is executed.  The belief is that
> > the error handler then catches this and thus the OpenSSL package knows
> > it is running on a 32-bit platform.  However, when the library is
> > compiled as a 32-bit library running on a 64-bit system the instruction
> > will execute without generating a SIGILL exception.  Thus the library
> > might think it is running on a 64-bit system in 64-bit mode when it is
> > actually running in 32-bit mode.
> 
> Yes, and this is totally intentional. As long as a) CPU is 64-bit and b)
> kernel is 64-bit, even 32-bit processes can use 64-bit instructions such
>  as rldicl. Yes, they actually *can* do so, but *only* as long as they
> are not hit by asynchronous signal. The thing is that 64-bit kernel
> preserves full 64-bit registers even for 32-bit processes upon context
> switch, but *not* upon signal delivery. Which is why you can observe
> sigprocmask in bn_mul_mont in the beginning of crypto/ppccap.c. See even
> "December 2009" comment in crypto/bn/asm/ppc64-mont.pl for why it's
> interesting to do that.
> 
> > The concern is that the probe test may
> > not work as expected for a 32-bit binary running on a 64-bit system and
> > thus may give erroneous results.
> 
> It shouldn't. What would be appropriate for Linux kernel to do is to
> arrange so that upper halves of 64-bit GP registers even upon signal
> delivery [which would allow to get rid of expensive setprocmask calls].
> It's done on s390x platforms and one can do same even on PPC. For
> backward compatibility you'd have to save upper halves separately, but
> it can be done without having to recompile all the applications.
> 
> > Note, this issue was seen on a Fedora release 18 (Spherical Cow).  It
> > does not occur on the RedHat 6.3 release.
> 
> 6.3 has 1.0.0, which doesn't perform the probe in question.
> 
> > The issue was found when
> > running a test program using valgrind as valgrind detected a type
> > conflict.
> > 
> > Maynard Johnson on the cc list can provide additional details if needed.
> 
> You should be able to avoid this by setting OPENSSL_ppccap environment
> variable to 0 prior running the application under valgrid's control.
> This way you'll avoid the trouble with rldilc and have valgrind catch
> eventual problems.
>