[systemd-devel] rdrand generated with march=winchip-c6 in systemd-241

tedheadster tedheadster at gmail.com
Tue May 7 14:45:27 UTC 2019


On Tue, May 7, 2019 at 10:27 AM Segher Boessenkool
<segher at kernel.crashing.org> wrote:
> But it should not execute it, it is guarded by some cpuid things.
>
> If the assembler does not like the insn, first do (in the same asm) an
> assembler pseudo-instruction to select a CPU that does have that insn,
> then the rdrand, and then the original CPU again.  Or write the bytes
> of the instruction encoding directly.

Segher,
  you are correct that the code should avoid executing the rdrand
instruction by doing some cpuid queries. The problem is that does not
work: systemd _does_ execute the rdrand instruction and the system
crashes.

So there is something wrong with the cpuid logic or results. This
system _does_ support cpuid. Here is the raw data from it:

# cpuid -r
CPU 0:
   0x00000000 0x00: eax=0x00000001 ebx=0x746e6543 ecx=0x736c7561 edx=0x48727561
   0x00000001 0x00: eax=0x00000585 ebx=0x00000000 ecx=0x00000000
edx=0x008001b5  <--- look at %ecx
   0x80000000 0x00: eax=0x80000005 ebx=0x00000001 ecx=0x00000000 edx=0x00000050
   0x80000001 0x00: eax=0x00000585 ebx=0x00000001 ecx=0x00000000 edx=0x808001b5
   0x80000002 0x00: eax=0x20544449 ebx=0x436e6957 ecx=0x20706968 edx=0x44332d32
   0x80000003 0x00: eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000
   0x80000004 0x00: eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000
   0x80000005 0x00: eax=0x80000005 ebx=0x08800880 ecx=0x20040120 edx=0x20020120
   0x80860000 0x00: eax=0x80860000 ebx=0x08800880 ecx=0x00000000 edx=0x00000050
   0xc0000000 0x00: eax=0xc0000005 ebx=0x08800880 ecx=0x00000000 edx=0x00000050
   0xc0000001 0x00: eax=0x00000585 ebx=0x08800880 ecx=0x00000000 edx=0x808001b5
   0xc0000002 0x00: eax=0x20544449 ebx=0x436e6957 ecx=0x20706968 edx=0x44332d32
   0xc0000003 0x00: eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000
   0xc0000004 0x00: eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000
   0xc0000005 0x00: eax=0xc0000005 ebx=0x08800880 ecx=0x20040120 edx=0x20020120

So cpuid query 0x1 returns 0x0 in the %ecx register. I believe this
means that rdrand is not supported (bit 30 is not set). Yet the code
executes it anyhow.

Here is the full disassembly with a few comments:

(gdb) disassemble
Dump of assembler code for function rdrand:
   0xb7e21440 <+0>:     push   %esi
   0xb7e21441 <+1>:     push   %ebx
   0xb7e21442 <+2>:     call   0xb7e0af5d <__x86.get_pc_thunk.si>
   0xb7e21447 <+7>:     add    $0x1acb39,%esi
   0xb7e2144d <+13>:    mov    0x2870(%esi),%ecx
   0xb7e21453 <+19>:    test   %ecx,%ecx
   0xb7e21455 <+21>:    js     0xb7e21480 <rdrand+64>
   0xb7e21457 <+23>:    test   %ecx,%ecx
   0xb7e21459 <+25>:    je     0xb7e214e0 <rdrand+160>
   0xb7e2145f <+31>:    rdrand %ecx  <---- illegal instruction was
attempted here
   0xb7e21462 <+34>:    setb   %al
   0xb7e21465 <+37>:    mov    0xc(%esp),%edx
   0xb7e21469 <+41>:    mov    %ecx,(%edx)
   0xb7e2146b <+43>:    cmp    $0x1,%al
   0xb7e2146d <+45>:    sbb    %eax,%eax
   0xb7e2146f <+47>:    and    $0xfffffff5,%eax
   0xb7e21472 <+50>:    pop    %ebx
   0xb7e21473 <+51>:    pop    %esi
   0xb7e21474 <+52>:    ret
   0xb7e21475 <+53>:    lea    0x0(%esi,%eiz,1),%esi
   0xb7e21479 <+57>:    lea    0x0(%edi,%eiz,1),%edi
   0xb7e21480 <+64>:    pushf
   0xb7e21481 <+65>:    pushf
   0xb7e21482 <+66>:    pop    %eax
   0xb7e21483 <+67>:    mov    %eax,%edx
   0xb7e21485 <+69>:    xor    $0x200000,%eax
   0xb7e2148a <+74>:    push   %eax
   0xb7e2148b <+75>:    popf
   0xb7e2148c <+76>:    pushf
   0xb7e2148d <+77>:    pop    %eax
   0xb7e2148e <+78>:    popf
   0xb7e2148f <+79>:    xor    %edx,%eax
   0xb7e21491 <+81>:    test   $0x200000,%eax  <--- checks if cpuid is supported
   0xb7e21496 <+86>:    je     0xb7e214c0 <rdrand+128>
   0xb7e21498 <+88>:    xor    %eax,%eax
   0xb7e2149a <+90>:    cpuid
   0xb7e2149c <+92>:    test   %eax,%eax
   0xb7e2149e <+94>:    je     0xb7e214c0 <rdrand+128>
   0xb7e214a0 <+96>:    mov    $0x1,%eax  <--- checks if cpuid query
0x1 is supported
   0xb7e214a5 <+101>:   cpuid
   0xb7e214a7 <+103>:   shr    $0x1e,%ecx  <---- shifts right 30 bits
to rdrand position
   0xb7e214aa <+106>:   and    $0x1,%ecx  <--- checks if rdrand is supported
   0xb7e214ad <+109>:   mov    %ecx,0x2870(%esi)
   0xb7e214b3 <+115>:   jmp    0xb7e21457 <rdrand+23>
   0xb7e214b5 <+117>:   lea    0x0(%esi,%eiz,1),%esi
   0xb7e214b9 <+121>:   lea    0x0(%edi,%eiz,1),%edi
   0xb7e214c0 <+128>:   movl   $0x0,0x2870(%esi)
   0xb7e214ca <+138>:   mov    $0xffffffa1,%eax
   0xb7e214cf <+143>:   jmp    0xb7e21472 <rdrand+50>
   0xb7e214d1 <+145>:   jmp    0xb7e214e0 <rdrand+160>
   0xb7e214d3 <+147>:   nop
   0xb7e214d4 <+148>:   nop
   0xb7e214d5 <+149>:   nop
   0xb7e214d6 <+150>:   nop
   0xb7e214d7 <+151>:   nop
   0xb7e214d8 <+152>:   nop
   0xb7e214d9 <+153>:   nop
   0xb7e214da <+154>:   nop
   0xb7e214db <+155>:   nop
   0xb7e214dc <+156>:   nop
   0xb7e214dd <+157>:   nop
   0xb7e214de <+158>:   nop
   0xb7e214df <+159>:   nop
   0xb7e214e0 <+160>:   mov    $0xffffffa1,%eax
   0xb7e214e5 <+165>:   jmp    0xb7e21472 <rdrand+5

- Matthew Whitehead


More information about the systemd-devel mailing list