summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/binutils/binutils/CVE-2020-0551.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/binutils/binutils/CVE-2020-0551.patch')
-rw-r--r--meta/recipes-devtools/binutils/binutils/CVE-2020-0551.patch549
1 files changed, 0 insertions, 549 deletions
diff --git a/meta/recipes-devtools/binutils/binutils/CVE-2020-0551.patch b/meta/recipes-devtools/binutils/binutils/CVE-2020-0551.patch
deleted file mode 100644
index 53e3caf445..0000000000
--- a/meta/recipes-devtools/binutils/binutils/CVE-2020-0551.patch
+++ /dev/null
@@ -1,549 +0,0 @@
-From ae531041c7c5956672342f89c486a011c84f027f Mon Sep 17 00:00:00 2001
-From: "H.J. Lu" <hjl.tools@gmail.com>
-Date: Wed, 11 Mar 2020 09:46:19 -0700
-Subject: [PATCH 1/1] i386: Generate lfence with load/indirect branch/ret
- [CVE-2020-0551]
-
-Add 3 command-line options to generate lfence for load, indirect near
-branch and ret to help mitigate:
-
-https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00334.html
-http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-0551
-
-1. -mlfence-after-load=[no|yes]:
- -mlfence-after-load=yes generates lfence after load instructions.
-2. -mlfence-before-indirect-branch=[none|all|memory|register]:
- a. -mlfence-before-indirect-branch=all generates lfence before indirect
- near branches via register and a warning before indirect near branches
- via memory.
- b. -mlfence-before-indirect-branch=memory issue a warning before
- indirect near branches via memory.
- c. -mlfence-before-indirect-branch=register generates lfence before
- indirect near branches via register.
-Note that lfence won't be generated before indirect near branches via
-register with -mlfence-after-load=yes since lfence will be generated
-after loading branch target register.
-3. -mlfence-before-ret=[none|or|not]
- a. -mlfence-before-ret=or generates or with lfence before ret.
- b. -mlfence-before-ret=not generates not with lfence before ret.
-
-A warning will be issued and lfence won't be generated before indirect
-near branch and ret if the previous item is a prefix or a constant
-directive, which may be used to hardcode an instruction, since there
-is no clear instruction boundary.
-
- * config/tc-i386.c (lfence_after_load): New.
- (lfence_before_indirect_branch_kind): New.
- (lfence_before_indirect_branch): New.
- (lfence_before_ret_kind): New.
- (lfence_before_ret): New.
- (last_insn): New.
- (load_insn_p): New.
- (insert_lfence_after): New.
- (insert_lfence_before): New.
- (md_assemble): Call insert_lfence_before and insert_lfence_after.
- Set last_insn.
- (OPTION_MLFENCE_AFTER_LOAD): New.
- (OPTION_MLFENCE_BEFORE_INDIRECT_BRANCH): New.
- (OPTION_MLFENCE_BEFORE_RET): New.
- (md_longopts): Add -mlfence-after-load=,
- -mlfence-before-indirect-branch= and -mlfence-before-ret=.
- (md_parse_option): Handle -mlfence-after-load=,
- -mlfence-before-indirect-branch= and -mlfence-before-ret=.
- (md_show_usage): Display -mlfence-after-load=,
- -mlfence-before-indirect-branch= and -mlfence-before-ret=.
- (i386_cons_align): New.
- * config/tc-i386.h (i386_cons_align): New.
- (md_cons_align): New.
- * doc/c-i386.texi: Document -mlfence-after-load=,
- -mlfence-before-indirect-branch= and -mlfence-before-ret=.
-
-Signed-off-by: Anuj Mittal <anuj.mittal@intel.com>
-Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=ae531041c7c5956672342f89c486a011c84f027f]
-CVE: CVE-2020-0551
----
-diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
-index b020f39c863..09063f784b7 100644
---- a/gas/config/tc-i386.c
-+++ b/gas/config/tc-i386.c
-@@ -629,7 +629,29 @@ static int omit_lock_prefix = 0;
- "lock addl $0, (%{re}sp)". */
- static int avoid_fence = 0;
-
--/* Type of the previous instruction. */
-+/* 1 if lfence should be inserted after every load. */
-+static int lfence_after_load = 0;
-+
-+/* Non-zero if lfence should be inserted before indirect branch. */
-+static enum lfence_before_indirect_branch_kind
-+ {
-+ lfence_branch_none = 0,
-+ lfence_branch_register,
-+ lfence_branch_memory,
-+ lfence_branch_all
-+ }
-+lfence_before_indirect_branch;
-+
-+/* Non-zero if lfence should be inserted before ret. */
-+static enum lfence_before_ret_kind
-+ {
-+ lfence_before_ret_none = 0,
-+ lfence_before_ret_not,
-+ lfence_before_ret_or
-+ }
-+lfence_before_ret;
-+
-+/* Types of previous instruction is .byte or prefix. */
- static struct
- {
- segT seg;
-@@ -4311,6 +4333,283 @@ optimize_encoding (void)
- }
- }
-
-+/* Return non-zero for load instruction. */
-+
-+static int
-+load_insn_p (void)
-+{
-+ unsigned int dest;
-+ int any_vex_p = is_any_vex_encoding (&i.tm);
-+ unsigned int base_opcode = i.tm.base_opcode | 1;
-+
-+ if (!any_vex_p)
-+ {
-+ /* lea */
-+ if (i.tm.base_opcode == 0x8d)
-+ return 0;
-+
-+ /* pop */
-+ if ((i.tm.base_opcode & ~7) == 0x58
-+ || (i.tm.base_opcode == 0x8f && i.tm.extension_opcode == 0))
-+ return 1;
-+
-+ /* movs, cmps, lods, scas. */
-+ if ((i.tm.base_opcode | 0xb) == 0xaf)
-+ return 1;
-+
-+ /* outs */
-+ if (base_opcode == 0x6f)
-+ return 1;
-+ }
-+
-+ /* No memory operand. */
-+ if (!i.mem_operands)
-+ return 0;
-+
-+ if (any_vex_p)
-+ {
-+ /* vldmxcsr. */
-+ if (i.tm.base_opcode == 0xae
-+ && i.tm.opcode_modifier.vex
-+ && i.tm.opcode_modifier.vexopcode == VEX0F
-+ && i.tm.extension_opcode == 2)
-+ return 1;
-+ }
-+ else
-+ {
-+ /* test, not, neg, mul, imul, div, idiv. */
-+ if ((i.tm.base_opcode == 0xf6 || i.tm.base_opcode == 0xf7)
-+ && i.tm.extension_opcode != 1)
-+ return 1;
-+
-+ /* inc, dec. */
-+ if (base_opcode == 0xff && i.tm.extension_opcode <= 1)
-+ return 1;
-+
-+ /* add, or, adc, sbb, and, sub, xor, cmp. */
-+ if (i.tm.base_opcode >= 0x80 && i.tm.base_opcode <= 0x83)
-+ return 1;
-+
-+ /* bt, bts, btr, btc. */
-+ if (i.tm.base_opcode == 0xfba
-+ && (i.tm.extension_opcode >= 4 && i.tm.extension_opcode <= 7))
-+ return 1;
-+
-+ /* rol, ror, rcl, rcr, shl/sal, shr, sar. */
-+ if ((base_opcode == 0xc1
-+ || (i.tm.base_opcode >= 0xd0 && i.tm.base_opcode <= 0xd3))
-+ && i.tm.extension_opcode != 6)
-+ return 1;
-+
-+ /* cmpxchg8b, cmpxchg16b, xrstors. */
-+ if (i.tm.base_opcode == 0xfc7
-+ && (i.tm.extension_opcode == 1 || i.tm.extension_opcode == 3))
-+ return 1;
-+
-+ /* fxrstor, ldmxcsr, xrstor. */
-+ if (i.tm.base_opcode == 0xfae
-+ && (i.tm.extension_opcode == 1
-+ || i.tm.extension_opcode == 2
-+ || i.tm.extension_opcode == 5))
-+ return 1;
-+
-+ /* lgdt, lidt, lmsw. */
-+ if (i.tm.base_opcode == 0xf01
-+ && (i.tm.extension_opcode == 2
-+ || i.tm.extension_opcode == 3
-+ || i.tm.extension_opcode == 6))
-+ return 1;
-+
-+ /* vmptrld */
-+ if (i.tm.base_opcode == 0xfc7
-+ && i.tm.extension_opcode == 6)
-+ return 1;
-+
-+ /* Check for x87 instructions. */
-+ if (i.tm.base_opcode >= 0xd8 && i.tm.base_opcode <= 0xdf)
-+ {
-+ /* Skip fst, fstp, fstenv, fstcw. */
-+ if (i.tm.base_opcode == 0xd9
-+ && (i.tm.extension_opcode == 2
-+ || i.tm.extension_opcode == 3
-+ || i.tm.extension_opcode == 6
-+ || i.tm.extension_opcode == 7))
-+ return 0;
-+
-+ /* Skip fisttp, fist, fistp, fstp. */
-+ if (i.tm.base_opcode == 0xdb
-+ && (i.tm.extension_opcode == 1
-+ || i.tm.extension_opcode == 2
-+ || i.tm.extension_opcode == 3
-+ || i.tm.extension_opcode == 7))
-+ return 0;
-+
-+ /* Skip fisttp, fst, fstp, fsave, fstsw. */
-+ if (i.tm.base_opcode == 0xdd
-+ && (i.tm.extension_opcode == 1
-+ || i.tm.extension_opcode == 2
-+ || i.tm.extension_opcode == 3
-+ || i.tm.extension_opcode == 6
-+ || i.tm.extension_opcode == 7))
-+ return 0;
-+
-+ /* Skip fisttp, fist, fistp, fbstp, fistp. */
-+ if (i.tm.base_opcode == 0xdf
-+ && (i.tm.extension_opcode == 1
-+ || i.tm.extension_opcode == 2
-+ || i.tm.extension_opcode == 3
-+ || i.tm.extension_opcode == 6
-+ || i.tm.extension_opcode == 7))
-+ return 0;
-+
-+ return 1;
-+ }
-+ }
-+
-+ dest = i.operands - 1;
-+
-+ /* Check fake imm8 operand and 3 source operands. */
-+ if ((i.tm.opcode_modifier.immext
-+ || i.tm.opcode_modifier.vexsources == VEX3SOURCES)
-+ && i.types[dest].bitfield.imm8)
-+ dest--;
-+
-+ /* add, or, adc, sbb, and, sub, xor, cmp, test, xchg, xadd */
-+ if (!any_vex_p
-+ && (base_opcode == 0x1
-+ || base_opcode == 0x9
-+ || base_opcode == 0x11
-+ || base_opcode == 0x19
-+ || base_opcode == 0x21
-+ || base_opcode == 0x29
-+ || base_opcode == 0x31
-+ || base_opcode == 0x39
-+ || (i.tm.base_opcode >= 0x84 && i.tm.base_opcode <= 0x87)
-+ || base_opcode == 0xfc1))
-+ return 1;
-+
-+ /* Check for load instruction. */
-+ return (i.types[dest].bitfield.class != ClassNone
-+ || i.types[dest].bitfield.instance == Accum);
-+}
-+
-+/* Output lfence, 0xfaee8, after instruction. */
-+
-+static void
-+insert_lfence_after (void)
-+{
-+ if (lfence_after_load && load_insn_p ())
-+ {
-+ char *p = frag_more (3);
-+ *p++ = 0xf;
-+ *p++ = 0xae;
-+ *p = 0xe8;
-+ }
-+}
-+
-+/* Output lfence, 0xfaee8, before instruction. */
-+
-+static void
-+insert_lfence_before (void)
-+{
-+ char *p;
-+
-+ if (is_any_vex_encoding (&i.tm))
-+ return;
-+
-+ if (i.tm.base_opcode == 0xff
-+ && (i.tm.extension_opcode == 2 || i.tm.extension_opcode == 4))
-+ {
-+ /* Insert lfence before indirect branch if needed. */
-+
-+ if (lfence_before_indirect_branch == lfence_branch_none)
-+ return;
-+
-+ if (i.operands != 1)
-+ abort ();
-+
-+ if (i.reg_operands == 1)
-+ {
-+ /* Indirect branch via register. Don't insert lfence with
-+ -mlfence-after-load=yes. */
-+ if (lfence_after_load
-+ || lfence_before_indirect_branch == lfence_branch_memory)
-+ return;
-+ }
-+ else if (i.mem_operands == 1
-+ && lfence_before_indirect_branch != lfence_branch_register)
-+ {
-+ as_warn (_("indirect `%s` with memory operand should be avoided"),
-+ i.tm.name);
-+ return;
-+ }
-+ else
-+ return;
-+
-+ 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-indirect-branch on `%s`"),
-+ last_insn.name, i.tm.name);
-+ return;
-+ }
-+
-+ p = frag_more (3);
-+ *p++ = 0xf;
-+ *p++ = 0xae;
-+ *p = 0xe8;
-+ return;
-+ }
-+
-+ /* Output or/not and lfence before ret. */
-+ 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;
-+ *p++ = 0x83;
-+ *p++ = 0xc;
-+ *p++ = 0x24;
-+ *p++ = 0x0;
-+ }
-+ else
-+ {
-+ p = frag_more ((flag_code == CODE_64BIT ? 2 : 0) + 6 + 3);
-+ /* notl: 0xf71424. */
-+ if (flag_code == CODE_64BIT)
-+ *p++ = 0x48;
-+ *p++ = 0xf7;
-+ *p++ = 0x14;
-+ *p++ = 0x24;
-+ /* notl: 0xf71424. */
-+ if (flag_code == CODE_64BIT)
-+ *p++ = 0x48;
-+ *p++ = 0xf7;
-+ *p++ = 0x14;
-+ *p++ = 0x24;
-+ }
-+ *p++ = 0xf;
-+ *p++ = 0xae;
-+ *p = 0xe8;
-+ }
-+}
-+
- /* This is the guts of the machine-dependent assembler. LINE points to a
- machine dependent instruction. This function is supposed to emit
- the frags/bytes it assembles to. */
-@@ -4628,9 +4927,13 @@ md_assemble (char *line)
- if (i.rex != 0)
- add_prefix (REX_OPCODE | i.rex);
-
-+ insert_lfence_before ();
-+
- /* We are ready to output the insn. */
- output_insn ();
-
-+ insert_lfence_after ();
-+
- last_insn.seg = now_seg;
-
- if (i.tm.opcode_modifier.isprefix)
-@@ -12250,6 +12553,9 @@ const char *md_shortopts = "qnO::";
- #define OPTION_MALIGN_BRANCH_PREFIX_SIZE (OPTION_MD_BASE + 28)
- #define OPTION_MALIGN_BRANCH (OPTION_MD_BASE + 29)
- #define OPTION_MBRANCHES_WITH_32B_BOUNDARIES (OPTION_MD_BASE + 30)
-+#define OPTION_MLFENCE_AFTER_LOAD (OPTION_MD_BASE + 31)
-+#define OPTION_MLFENCE_BEFORE_INDIRECT_BRANCH (OPTION_MD_BASE + 32)
-+#define OPTION_MLFENCE_BEFORE_RET (OPTION_MD_BASE + 33)
-
- struct option md_longopts[] =
- {
-@@ -12289,6 +12595,10 @@ struct option md_longopts[] =
- {"malign-branch-prefix-size", required_argument, NULL, OPTION_MALIGN_BRANCH_PREFIX_SIZE},
- {"malign-branch", required_argument, NULL, OPTION_MALIGN_BRANCH},
- {"mbranches-within-32B-boundaries", no_argument, NULL, OPTION_MBRANCHES_WITH_32B_BOUNDARIES},
-+ {"mlfence-after-load", required_argument, NULL, OPTION_MLFENCE_AFTER_LOAD},
-+ {"mlfence-before-indirect-branch", required_argument, NULL,
-+ OPTION_MLFENCE_BEFORE_INDIRECT_BRANCH},
-+ {"mlfence-before-ret", required_argument, NULL, OPTION_MLFENCE_BEFORE_RET},
- {"mamd64", no_argument, NULL, OPTION_MAMD64},
- {"mintel64", no_argument, NULL, OPTION_MINTEL64},
- {NULL, no_argument, NULL, 0}
-@@ -12668,6 +12978,41 @@ md_parse_option (int c, const char *arg)
- as_fatal (_("invalid -mfence-as-lock-add= option: `%s'"), arg);
- break;
-
-+ case OPTION_MLFENCE_AFTER_LOAD:
-+ if (strcasecmp (arg, "yes") == 0)
-+ lfence_after_load = 1;
-+ else if (strcasecmp (arg, "no") == 0)
-+ lfence_after_load = 0;
-+ else
-+ as_fatal (_("invalid -mlfence-after-load= option: `%s'"), arg);
-+ break;
-+
-+ case OPTION_MLFENCE_BEFORE_INDIRECT_BRANCH:
-+ if (strcasecmp (arg, "all") == 0)
-+ lfence_before_indirect_branch = lfence_branch_all;
-+ else if (strcasecmp (arg, "memory") == 0)
-+ lfence_before_indirect_branch = lfence_branch_memory;
-+ else if (strcasecmp (arg, "register") == 0)
-+ lfence_before_indirect_branch = lfence_branch_register;
-+ else if (strcasecmp (arg, "none") == 0)
-+ lfence_before_indirect_branch = lfence_branch_none;
-+ else
-+ as_fatal (_("invalid -mlfence-before-indirect-branch= option: `%s'"),
-+ arg);
-+ break;
-+
-+ case OPTION_MLFENCE_BEFORE_RET:
-+ if (strcasecmp (arg, "or") == 0)
-+ lfence_before_ret = lfence_before_ret_or;
-+ else if (strcasecmp (arg, "not") == 0)
-+ lfence_before_ret = lfence_before_ret_not;
-+ else if (strcasecmp (arg, "none") == 0)
-+ lfence_before_ret = lfence_before_ret_none;
-+ else
-+ as_fatal (_("invalid -mlfence-before-ret= option: `%s'"),
-+ arg);
-+ break;
-+
- case OPTION_MRELAX_RELOCATIONS:
- if (strcasecmp (arg, "yes") == 0)
- generate_relax_relocations = 1;
-@@ -13025,6 +13370,15 @@ md_show_usage (FILE *stream)
- -mbranches-within-32B-boundaries\n\
- align branches within 32 byte boundary\n"));
- fprintf (stream, _("\
-+ -mlfence-after-load=[no|yes] (default: no)\n\
-+ generate lfence after load\n"));
-+ fprintf (stream, _("\
-+ -mlfence-before-indirect-branch=[none|all|register|memory] (default: none)\n\
-+ generate lfence before indirect near branch\n"));
-+ fprintf (stream, _("\
-+ -mlfence-before-ret=[none|or|not] (default: none)\n\
-+ generate lfence before ret\n"));
-+ fprintf (stream, _("\
- -mamd64 accept only AMD64 ISA [default]\n"));
- fprintf (stream, _("\
- -mintel64 accept only Intel64 ISA\n"));
-@@ -13254,6 +13608,16 @@ i386_cons_align (int ignore ATTRIBUTE_UNUSED)
- last_insn.kind = last_insn_directive;
- last_insn.name = "constant directive";
- last_insn.file = as_where (&last_insn.line);
-+ if (lfence_before_ret != lfence_before_ret_none)
-+ {
-+ if (lfence_before_indirect_branch != lfence_branch_none)
-+ as_warn (_("constant directive skips -mlfence-before-ret "
-+ "and -mlfence-before-indirect-branch"));
-+ else
-+ as_warn (_("constant directive skips -mlfence-before-ret"));
-+ }
-+ else if (lfence_before_indirect_branch != lfence_branch_none)
-+ as_warn (_("constant directive skips -mlfence-before-indirect-branch"));
- }
- }
-
-diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi
-index c536759cb38..1dd99f91bb0 100644
---- a/gas/doc/c-i386.texi
-+++ b/gas/doc/c-i386.texi
-@@ -464,6 +464,49 @@ on an instruction. It is equivalent to
- @option{-malign-branch-prefix-size=5}.
- The default doesn't align branches.
-
-+@cindex @samp{-mlfence-after-load=} option, i386
-+@cindex @samp{-mlfence-after-load=} option, x86-64
-+@item -mlfence-after-load=@var{no}
-+@itemx -mlfence-after-load=@var{yes}
-+These options control whether the assembler should generate lfence
-+after load instructions. @option{-mlfence-after-load=@var{yes}} will
-+generate lfence. @option{-mlfence-after-load=@var{no}} will not generate
-+lfence, which is the default.
-+
-+@cindex @samp{-mlfence-before-indirect-branch=} option, i386
-+@cindex @samp{-mlfence-before-indirect-branch=} option, x86-64
-+@item -mlfence-before-indirect-branch=@var{none}
-+@item -mlfence-before-indirect-branch=@var{all}
-+@item -mlfence-before-indirect-branch=@var{register}
-+@itemx -mlfence-before-indirect-branch=@var{memory}
-+These options control whether the assembler should generate lfence
-+after indirect near branch instructions.
-+@option{-mlfence-before-indirect-branch=@var{all}} will generate lfence
-+after indirect near branch via register and issue a warning before
-+indirect near branch via memory.
-+@option{-mlfence-before-indirect-branch=@var{register}} will generate
-+lfence after indirect near branch via register.
-+@option{-mlfence-before-indirect-branch=@var{memory}} will issue a
-+warning before indirect near branch via memory.
-+@option{-mlfence-before-indirect-branch=@var{none}} will not generate
-+lfence nor issue warning, which is the default. Note that lfence won't
-+be generated before indirect near branch via register with
-+@option{-mlfence-after-load=@var{yes}} since lfence will be generated
-+after loading branch target register.
-+
-+@cindex @samp{-mlfence-before-ret=} option, i386
-+@cindex @samp{-mlfence-before-ret=} option, x86-64
-+@item -mlfence-before-ret=@var{none}
-+@item -mlfence-before-ret=@var{or}
-+@itemx -mlfence-before-ret=@var{not}
-+These options control whether the assembler should generate lfence
-+before ret. @option{-mlfence-before-ret=@var{or}} will generate
-+generate or instruction with lfence.
-+@option{-mlfence-before-ret=@var{not}} will generate not instruction
-+with lfence.
-+@option{-mlfence-before-ret=@var{none}} will not generate lfence,
-+which is the default.
-+
- @cindex @samp{-mx86-used-note=} option, i386
- @cindex @samp{-mx86-used-note=} option, x86-64
- @item -mx86-used-note=@var{no}
---
-2.18.2