[PATCH 1/2] i386: Generate lfence with load/indirect branch/ret [CVE-2020-0551]

Hongtao Liu crazylht@gmail.com
Thu Apr 16 05:34:27 GMT 2020


On Thu, Mar 26, 2020 at 5:12 PM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 26.03.2020 03:23, Hongtao Liu wrote:
> > On Wed, Mar 25, 2020 at 6:03 PM Jan Beulich <jbeulich@suse.com> wrote:
> >> On 25.03.2020 10:27, Hongtao Liu wrote:
> >>> On Thu, Mar 12, 2020 at 12:17 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >>>> On Wed, Mar 11, 2020 at 3:55 AM Jan Beulich <jbeulich@suse.com> wrote:
> >>>>> On 10.03.2020 17:05, H.J. Lu wrote:
> >>>>>> +  if (lfence_before_ret != lfence_before_ret_none
> >>>>>> +      && (i.tm.base_opcode == 0xc2
> >>>>>> +       || i.tm.base_opcode == 0xc3
> >>>>>> +       || i.tm.base_opcode == 0xca
> >>>>>> +       || i.tm.base_opcode == 0xcb))
> >>>>>> +    {
> >>>>>> +      if (last_insn.kind != last_insn_other
> >>>>>> +       && last_insn.seg == now_seg)
> >>>>>> +     {
> >>>>>> +       as_warn_where (last_insn.file, last_insn.line,
> >>>>>> +                      _("`%s` skips -mlfence-before-ret on `%s`"),
> >>>>>> +                      last_insn.name, i.tm.name);
> >>>>>> +       return;
> >>>>>> +     }
> >>>>>> +      if (lfence_before_ret == lfence_before_ret_or)
> >>>>>> +     {
> >>>>>> +       /* orl: 0x830c2400.  */
> >>>>>> +       p = frag_more ((flag_code == CODE_64BIT ? 1 : 0) + 4 + 3);
> >>>>>> +       if (flag_code == CODE_64BIT)
> >>>>>> +         *p++ = 0x48;
> >>>>>
> >>>>> Shouldn't this depend on RET's operand size? Likewise wouldn't you
> >>>>> also need to insert 0x66/0x67 in certain cases?
> >>>>
> >>>> Hongtao, can you look into it?
> >>>
> >>> I suppose you mean OR's operand size?
> >>
> >> Not exactly - I mean RET's operand size ought to affect the one
> >> chosen for OR.
> >>
> >> Jan
> >
> >>> I wonder whether this shouldn't also enable a safe lfence_before_ret
> >>> mode (i.e. not the OR one), for RET also being an indirect branch. Of
> >>> course care would need to be taken to avoid clobbering an already set
> >>> lfence_before_ret mode.
> >
> > Also for this part, maybe i'll add some comments to indicate
> > -mlfence-before-indirect-branch doesn't include ret. Orelse it would
> > be weird for user when clobber happens, Is it ok for you?
>
> Well, extending the description / comments to be more precise is one
> solution, but only the the 2nd best one. I continue to think that
> there would better be an implication as the one suggested.
>
> Jan

Apologies for the delayed response.
I tried to re-arranged to use a common pattern (memory operand is
destination) and only exclude those which don't also read this
operand. But it turn out there still a lot of such instructions
include all mov instruction, store instruction for i387 and cet,
extract instructions, vgather instructions, vscatter instrcutions,
convert instrcutions and so on, so i didn't re-arrange them.
Other requests are done by the updated patch, also plus handling REP
CMP/SCAS specially since they would set EFLAGS which affects control
flow behavior.

  1. No load for INVPCID, Implict load for POPS/POPF/POPA/XLATB
  2. Add -mlfence-before-ret=shl, adjust operand size of or/not/shl to
  ret's.
  3. Ajust -mlfence-after-load=[yes/no] to
  -mlfence-after-load=[none|general|all]. -mlfence-after-load=[none/all]
  equal original -mlfence-after-load=[no/yes],
  -mlfence-after-load=general won't add lfence after REP CMPS/SCAS
  since they would affect control flow behavior.
  -mlfence-after-load=all will issue an warning when adding lfence
  after REP CMPS/SCAS.
  4. Adjust testcases and documents.

gas/Changelog:
        * config/tc-i386.c (lfence_after_load_kine): New.
        (lfence_before_ret_shl): Change from lfence_before_ret_not.
        (load_insn_p): No load for INVPCID, implict load for
        POPS/POPA/POPF/XLATB.
        (insert_after_load): Insert lfence under
        -mlfence-after-load=[general|all],issue an warning when encounter
        REP CMPS/SCAS.
        (insert_before_before): Replace -mlfence-before-ret=not to
        -mlfence-before-ret=shl.
        (md_parse_option): Adjust -mlfence-after-load=[yes|no] to
        -mlfence-after-load=[none|general|all], Replace
        -mlfence-before-ret=not to -mlfence-before-ret=shl. Enable
        -mlfence-before-ret=shl when
        -mlfence-beofre-indirect-branch=all.
        (md_show_usage): Ditto.
        * doc/c-i386.texi: Ditto.
        * testsuite/gas/i386/i386.exp: Add new testcases.
        * gas/testsuite/gas/i386/lfence-load-b.d: New.
        * gas/testsuite/gas/i386/lfence-load-b.e: New.
        * gas/testsuite/gas/i386/lfence-load.d: Modified.
        * gas/testsuite/gas/i386/lfence-load.e: New.
        * gas/testsuite/gas/i386/lfence-load.s: Modified.
        * gas/testsuite/gas/i386/lfence-ret-a.d: Modified.
        * gas/testsuite/gas/i386/lfence-ret-b.d: Modified.
        * gas/testsuite/gas/i386/lfence-ret-c.d: New.
        * gas/testsuite/gas/i386/lfence-ret-d.d: New.
        * gas/testsuite/gas/i386/lfence-ret.s: Modified
        * gas/testsuite/gas/i386/x86-64-lfence-load-b.d: New.
        * gas/testsuite/gas/i386/x86-64-lfence-load.d: Modified.
        * gas/testsuite/gas/i386/x86-64-lfence-load.s: Modified.
        * gas/testsuite/gas/i386/x86-64-lfence-ret-a.d: Modified.
        * gas/testsuite/gas/i386/x86-64-lfence-ret-b.d: Modified.
        * gas/testsuite/gas/i386/x86-64-lfence-ret-c.d: New.
        * gas/testsuite/gas/i386/x86-64-lfence-ret-d.d: New.


-- 
BR,
Hongtao
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Improve-mlfence-after-load.patch
Type: text/x-patch
Size: 41016 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/binutils/attachments/20200416/2e80deb4/attachment-0001.bin>


More information about the Binutils mailing list