[PATCH v5] x86: Disallow GOT memory access beyond its GOT slot
H.J. Lu
hjl.tools@gmail.com
Tue Feb 11 21:47:38 GMT 2025
GOT slot contains the symbol run-time address, whose size is 32 bits for
i386 and 64 bits for x86-64. Memory beyond GOT slot is undefined, which
can be anything, including unmapped or unreadable memory. Disallow GOT
memory access beyond its GOT slot.
PR gas/32624
* config/tc-i386.c (_i386_insn): Add memsize.
(check_VecOperands): Set i.memsize when setting i.memshift.
(check_GOT_memory): New function.
(output_disp): Call check_GOT_memory to check valid GOT memory
access.
* testsuite/gas/i386/got.s: Add vector instructions with
byte/word/dword GOT memory.
* testsuite/gas/i386/got-no-relax.d: Updated.
* testsuite/gas/i386/got.d: Likewise.
* testsuite/gas/i386/x86-64-gotpcrel-2.d: Likewise.
* testsuite/gas/i386/i386.exp: Run inval-got.
* testsuite/gas/i386/inval-got.l: New file.
* testsuite/gas/i386/inval-got.s: Likewise.
* testsuite/gas/i386/x86-64-inval-got.l: Likewise.
* testsuite/gas/i386/x86-64-inval-got.l: Likewise.
* testsuite/gas/i386/x86-64-gotpcrel-2.s: Add vector instructions
with byte/word/dword/qword GOT memory.
* testsuite/gas/i386/x86-64.exp: Run x86-64-inval-got.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
gas/config/tc-i386.c | 70 +++++++++++++++++++++-
gas/testsuite/gas/i386/got-no-relax.d | 3 +
gas/testsuite/gas/i386/got.d | 3 +
gas/testsuite/gas/i386/got.s | 5 ++
gas/testsuite/gas/i386/i386.exp | 1 +
gas/testsuite/gas/i386/inval-got.l | 34 +++++++++++
gas/testsuite/gas/i386/inval-got.s | 8 +++
gas/testsuite/gas/i386/x86-64-gotpcrel-2.d | 7 +++
gas/testsuite/gas/i386/x86-64-gotpcrel-2.s | 7 +++
gas/testsuite/gas/i386/x86-64-inval-got.l | 34 +++++++++++
gas/testsuite/gas/i386/x86-64-inval-got.s | 8 +++
gas/testsuite/gas/i386/x86-64.exp | 1 +
12 files changed, 179 insertions(+), 2 deletions(-)
create mode 100644 gas/testsuite/gas/i386/inval-got.l
create mode 100644 gas/testsuite/gas/i386/inval-got.s
create mode 100644 gas/testsuite/gas/i386/x86-64-inval-got.l
create mode 100644 gas/testsuite/gas/i386/x86-64-inval-got.s
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 99c0b5de615..038d66ab0d6 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -453,6 +453,9 @@ struct _i386_insn
/* Compressed disp8*N attribute. */
unsigned int memshift;
+ /* Memory size for instructions with compressed disp8. */
+ unsigned int memsize;
+
/* SCC = EVEX.[SC3,SC2,SC1,SC0]. */
unsigned int scc;
@@ -8811,9 +8814,17 @@ check_VecOperands (const insn_template *t)
&& pp.disp_encoding <= disp_encoding_8bit)
{
if (i.broadcast.type || i.broadcast.bytes)
- i.memshift = t->opcode_modifier.broadcast - 1;
+ {
+ i.memshift = t->opcode_modifier.broadcast - 1;
+ /* Remember memory size. */
+ i.memsize = 1 << i.memshift;
+ }
else if (t->opcode_modifier.disp8memshift != DISP8_SHIFT_VL)
- i.memshift = t->opcode_modifier.disp8memshift;
+ {
+ i.memshift = t->opcode_modifier.disp8memshift;
+ /* Remember memory size. */
+ i.memsize = 1 << i.memshift;
+ }
else
{
const i386_operand_type *type = NULL, *fallback = NULL;
@@ -8856,6 +8867,9 @@ check_VecOperands (const insn_template *t)
i.memshift = 4;
}
+ /* Remember memory size. */
+ i.memsize = 1 << i.memshift;
+
/* For the check in fits_in_disp8(). */
if (i.memshift == 0)
i.memshift = -1;
@@ -12725,6 +12739,51 @@ imm_size (unsigned int n)
return size;
}
+/* Since GOT slot size is 32 bits for i386 and 64 bits for x86-64,
+ disallow GOT memory access beyond its GOT slot. */
+
+static bool
+check_GOT_memory (enum bfd_reloc_code_real reloc_type, unsigned int n)
+{
+ bool qword;
+
+ qword = false;
+ if (reloc_type == BFD_RELOC_32_PCREL)
+ {
+ if (!GOT_symbol || GOT_symbol != i.op[n].disps->X_op_symbol)
+ return true;
+ qword = true;
+ }
+ else if (reloc_type != BFD_RELOC_386_GOT32)
+ return true;
+
+ /* Disallow AMX TILE configuration load and store instructions. */
+ if (is_cpu (&i.tm, CpuAMX_TILE))
+ return false;
+
+ /* Disallow instructions with 6-byte and 10-byte memory access. */
+ if (i.tm.operand_types[n].bitfield.fword
+ || i.tm.operand_types[n].bitfield.tbyte)
+ return false;
+
+ if (i.tm.operand_types[n].bitfield.xmmword
+ || i.tm.operand_types[n].bitfield.ymmword
+ || i.tm.operand_types[n].bitfield.zmmword)
+ {
+ /* Allow memory access within GOT slot. */
+ if (i.memsize != 0)
+ return i.memsize <= (qword ? 8 : 4);
+
+ /* Disallow memory access beyond GOT slot size. */
+ return (i.tm.operand_types[n].bitfield.byte
+ || i.tm.operand_types[n].bitfield.word
+ || i.tm.operand_types[n].bitfield.dword
+ || (qword && i.tm.operand_types[n].bitfield.qword));
+ }
+
+ return true;
+}
+
static void
output_disp (fragS *insn_start_frag, offsetT insn_start_off)
{
@@ -12785,6 +12844,13 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off)
p = frag_more (size);
reloc_type = reloc (size, pcrel, sign, i.reloc[n]);
+
+ if (!check_GOT_memory (reloc_type, n))
+ {
+ as_bad (_("invalid GOT memory operand"));
+ return;
+ }
+
if (GOT_symbol
&& GOT_symbol == i.op[n].disps->X_add_symbol
&& (((reloc_type == BFD_RELOC_32
diff --git a/gas/testsuite/gas/i386/got-no-relax.d b/gas/testsuite/gas/i386/got-no-relax.d
index acc8055e880..57e44942ef4 100644
--- a/gas/testsuite/gas/i386/got-no-relax.d
+++ b/gas/testsuite/gas/i386/got-no-relax.d
@@ -37,4 +37,7 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: ff 15 00 00 00 00 call \*0x0 a1: R_386_GOT32X foo
[ ]*[a-f0-9]+: ff a0 00 00 00 00 jmp \*0x0\(%eax\) a7: R_386_GOT32 foo
[ ]*[a-f0-9]+: ff 25 00 00 00 00 jmp \*0x0 ad: R_386_GOT32X foo
+[ ]*[a-f0-9]+: c4 e2 7d 78 25 00 00 00 00 vpbroadcastb 0x0,%ymm4 b6: R_386_GOT32 foo
+[ ]*[a-f0-9]+: 62 f5 7c 18 68 05 00 00 00 00 vcvttph2ibs 0x0\{1to8\},%xmm0 c0: R_386_GOT32 foo
+[ ]*[a-f0-9]+: 62 f5 7d 08 7b 05 00 00 00 00 vcvtph2qq 0x0,%xmm0 ca: R_386_GOT32 foo
#pass
diff --git a/gas/testsuite/gas/i386/got.d b/gas/testsuite/gas/i386/got.d
index 9610e2cf2c0..61328c71fe6 100644
--- a/gas/testsuite/gas/i386/got.d
+++ b/gas/testsuite/gas/i386/got.d
@@ -36,4 +36,7 @@ Disassembly of section .text:
[ ]*[a-f0-9]+: ff 15 00 00 00 00 call \*0x0 a1: R_386_GOT32X foo
[ ]*[a-f0-9]+: ff a0 00 00 00 00 jmp \*0x0\(%eax\) a7: R_386_GOT32X foo
[ ]*[a-f0-9]+: ff 25 00 00 00 00 jmp \*0x0 ad: R_386_GOT32X foo
+[ ]*[a-f0-9]+: c4 e2 7d 78 25 00 00 00 00 vpbroadcastb 0x0,%ymm4 b6: R_386_GOT32 foo
+[ ]*[a-f0-9]+: 62 f5 7c 18 68 05 00 00 00 00 vcvttph2ibs 0x0\{1to8\},%xmm0 c0: R_386_GOT32 foo
+[ ]*[a-f0-9]+: 62 f5 7d 08 7b 05 00 00 00 00 vcvtph2qq 0x0,%xmm0 ca: R_386_GOT32 foo
#pass
diff --git a/gas/testsuite/gas/i386/got.s b/gas/testsuite/gas/i386/got.s
index 47194115bc8..c5ae7c89d3a 100644
--- a/gas/testsuite/gas/i386/got.s
+++ b/gas/testsuite/gas/i386/got.s
@@ -40,3 +40,8 @@ _start:
call DWORD PTR [foo@GOT]
jmp DWORD PTR [eax + foo@GOT]
jmp DWORD PTR [foo@GOT]
+
+ .att_syntax prefix
+ vpbroadcastb foo@got,%ymm4 # Byte memory
+ vcvttph2ibs foo@got{1to8}, %xmm0 # Word memory
+ vcvtph2qq foo@got, %xmm0 # Dword memory
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index 34d0a2fab8c..4699fc31bca 100644
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -53,6 +53,7 @@ if [gas_32_check] then {
run_list_test "general" "-al --listing-lhs-width=2"
run_list_test "inval" "-aln"
run_list_test "inval-16" "-al"
+ run_list_test "inval-got" "-al"
run_list_test "segment" "-al"
run_list_test "inval-seg" "-al"
run_list_test "inval-reg" "-al"
diff --git a/gas/testsuite/gas/i386/inval-got.l b/gas/testsuite/gas/i386/inval-got.l
new file mode 100644
index 00000000000..40f4f3d82a3
--- /dev/null
+++ b/gas/testsuite/gas/i386/inval-got.l
@@ -0,0 +1,34 @@
+.*: Assembler messages:
+.*:3: Error: .*
+.*:4: Error: .*
+.*:5: Error: .*
+.*:6: Error: .*
+.*:7: Error: .*
+.*:8: Error: .*
+GAS LISTING .*
+
+
+[ ]*1[ ]+\.text
+[ ]*2[ ]+\# All the followings should be illegal\.
+[ ]*3[ ]+\?\?\?\? 0F011500 lgdt foo@got
+\*\*\*\* Error: invalid GOT memory operand
+[ ]*3[ ]+000000
+[ ]*4[ ]+\?\?\?\? 62F27548 vpermb foo@got, %zmm1, %zmm0
+\*\*\*\* Error: invalid GOT memory operand
+[ ]*4[ ]+8D050000
+[ ]*4[ ]+0000
+[ ]*5[ ]+\?\?\?\? 62F1F518 vmaxpd foo@got\{1to2\}, %xmm1, %xmm0
+\*\*\*\* Error: invalid GOT memory operand
+[ ]*5[ ]+5F050000
+[ ]*5[ ]+0000
+[ ]*6[ ]+\?\?\?\? C5F15F05 vmaxpd foo@got, %xmm1, %xmm0
+\*\*\*\* Error: invalid GOT memory operand
+[ ]*6[ ]+00000000
+[ ]*7[ ]+\?\?\?\? 62F57C08 vcvttph2ibs foo@got, %xmm0
+\*\*\*\* Error: invalid GOT memory operand
+[ ]*7[ ]+68050000
+[ ]*7[ ]+0000
+[ ]*8[ ]+\?\?\?\? 0F5A0500 cvtps2pd foo@GOT, %xmm0
+\*\*\*\* Error: invalid GOT memory operand
+[ ]*8[ ]+000000
+#pass
diff --git a/gas/testsuite/gas/i386/inval-got.s b/gas/testsuite/gas/i386/inval-got.s
new file mode 100644
index 00000000000..398ecd94263
--- /dev/null
+++ b/gas/testsuite/gas/i386/inval-got.s
@@ -0,0 +1,8 @@
+ .text
+# All the followings should be illegal.
+ lgdt foo@got
+ vpermb foo@got, %zmm1, %zmm0
+ vmaxpd foo@got{1to2}, %xmm1, %xmm0
+ vmaxpd foo@got, %xmm1, %xmm0
+ vcvttph2ibs foo@got, %xmm0
+ cvtps2pd foo@GOT, %xmm0
diff --git a/gas/testsuite/gas/i386/x86-64-gotpcrel-2.d b/gas/testsuite/gas/i386/x86-64-gotpcrel-2.d
index 3d07631bd6a..8edc7fe2c44 100644
--- a/gas/testsuite/gas/i386/x86-64-gotpcrel-2.d
+++ b/gas/testsuite/gas/i386/x86-64-gotpcrel-2.d
@@ -8,4 +8,11 @@ Disassembly of section .text:
0+ <foo>:
+[a-f0-9]+: 48 8b 05 00 00 00 00 mov 0x0\(%rip\),%rax # 7 <foo\+0x7> 3: R_X86_64_GOTPCREL foo-0x4
+ +[a-f0-9]+: c4 e2 7d 78 25 00 00 00 00 vpbroadcastb 0x0\(%rip\),%ymm4 # 10 <foo\+0x10> c: R_X86_64_GOTPCREL foo-0x4
+ +[a-f0-9]+: 62 f5 7c 18 68 05 00 00 00 00 vcvttph2ibs 0x0\(%rip\)\{1to8\},%xmm0 # 1a <foo\+0x1a> 16: R_X86_64_GOTPCREL foo-0x4
+ +[a-f0-9]+: 62 f5 7d 08 7b 05 00 00 00 00 vcvtph2qq 0x0\(%rip\),%xmm0 # 24 <foo\+0x24> 20: R_X86_64_GOTPCREL foo-0x4
+ +[a-f0-9]+: 62 f1 f5 18 5f 05 00 00 00 00 vmaxpd 0x0\(%rip\)\{1to2\},%xmm1,%xmm0 # 2e <foo\+0x2e> 2a: R_X86_64_GOTPCREL foo-0x4
+ +[a-f0-9]+: 0f 5a 05 00 00 00 00 cvtps2pd 0x0\(%rip\),%xmm0 # 35 <foo\+0x35> 31: R_X86_64_GOTPCREL foo-0x4
+ +[a-f0-9]+: c5 fc 5a 05 c3 ff ff ff vcvtps2pd -0x3d\(%rip\),%ymm0 # 0 <foo>
+ +[a-f0-9]+: 66 0f 6f 05 00 00 00 00 movdqa 0x0\(%rip\),%xmm0 # 45 <foo\+0x45> 41: R_X86_64_PC32 bar-0x4
#pass
diff --git a/gas/testsuite/gas/i386/x86-64-gotpcrel-2.s b/gas/testsuite/gas/i386/x86-64-gotpcrel-2.s
index db5ddf579a0..6f1c081b6a1 100644
--- a/gas/testsuite/gas/i386/x86-64-gotpcrel-2.s
+++ b/gas/testsuite/gas/i386/x86-64-gotpcrel-2.s
@@ -1,3 +1,10 @@
.text
foo:
movq foo@GOTPCREL(%rip), %rax
+ vpbroadcastb foo@GOTPCREL(%rip), %ymm4 # Byte memory
+ vcvttph2ibs foo@GOTPCREL(%rip){1to8}, %xmm0 # Word memory
+ vcvtph2qq foo@GOTPCREL(%rip), %xmm0 # Dword memory
+ vmaxpd foo@GOTPCREL(%rip){1to2}, %xmm1, %xmm0 # Qword memory
+ cvtps2pd foo@GOTPCREL(%rip), %xmm0 # Qword memory
+ vcvtps2pd foo(%rip), %ymm0 # Xmmword memory
+ movdqa bar(%rip), %xmm0 # Xmmword memory
diff --git a/gas/testsuite/gas/i386/x86-64-inval-got.l b/gas/testsuite/gas/i386/x86-64-inval-got.l
new file mode 100644
index 00000000000..565c080e057
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-inval-got.l
@@ -0,0 +1,34 @@
+.*: Assembler messages:
+.*:3: Error: .*
+.*:4: Error: .*
+.*:5: Error: .*
+.*:6: Error: .*
+.*:7: Error: .*
+.*:8: Error: .*
+GAS LISTING .*
+
+
+[ ]*1[ ]+\.text
+[ ]*2[ ]+\# All the followings should be illegal for x86-64\.
+[ ]*3[ ]+\?\?\?\? 0F011500 lgdt foo@GOTPCREL\(%rip\)
+\*\*\*\* Error: invalid GOT memory operand
+[ ]*3[ ]+000000
+[ ]*4[ ]+\?\?\?\? 62F27548 vpermb foo@GOTPCREL\(%rip\), %zmm1, %zmm0
+\*\*\*\* Error: invalid GOT memory operand
+[ ]*4[ ]+8D050000
+[ ]*4[ ]+0000
+[ ]*5[ ]+\?\?\?\? C5F15F05 vmaxpd foo@GOTPCREL\(%rip\), %xmm1, %xmm0
+\*\*\*\* Error: invalid GOT memory operand
+[ ]*5[ ]+00000000
+[ ]*6[ ]+\?\?\?\? 62F57C08 vcvttph2ibs foo@GOTPCREL\(%rip\), %xmm0
+\*\*\*\* Error: invalid GOT memory operand
+[ ]*6[ ]+68050000
+[ ]*6[ ]+0000
+[ ]*7[ ]+\?\?\?\? C4E27849 ldtilecfg foo@GOTPCREL\(%rip\)
+\*\*\*\* Error: invalid GOT memory operand
+[ ]*7[ ]+05000000
+[ ]*7[ ]+00
+[ ]*8[ ]+\?\?\?\? C5FC5A05 vcvtps2pd foo@GOTPCREL\(%rip\), %ymm0
+\*\*\*\* Error: invalid GOT memory operand
+[ ]*8[ ]+00000000
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-inval-got.s b/gas/testsuite/gas/i386/x86-64-inval-got.s
new file mode 100644
index 00000000000..265ff1976b6
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-inval-got.s
@@ -0,0 +1,8 @@
+ .text
+# All the followings should be illegal for x86-64.
+ lgdt foo@GOTPCREL(%rip)
+ vpermb foo@GOTPCREL(%rip), %zmm1, %zmm0
+ vmaxpd foo@GOTPCREL(%rip), %xmm1, %xmm0
+ vcvttph2ibs foo@GOTPCREL(%rip), %xmm0
+ ldtilecfg foo@GOTPCREL(%rip)
+ vcvtps2pd foo@GOTPCREL(%rip), %ymm0
diff --git a/gas/testsuite/gas/i386/x86-64.exp b/gas/testsuite/gas/i386/x86-64.exp
index edacbaa0f20..f1462e36131 100644
--- a/gas/testsuite/gas/i386/x86-64.exp
+++ b/gas/testsuite/gas/i386/x86-64.exp
@@ -71,6 +71,7 @@ run_dump_test "x86-64-stack"
run_dump_test "x86-64-stack-intel"
run_dump_test "x86-64-stack-suffix"
run_list_test "x86-64-inval" "-al"
+run_list_test "x86-64-inval-got" "-al"
run_list_test "x86-64-segment" "-al"
run_dump_test "x86-64-segovr"
run_list_test "x86-64-inval-seg" "-al"
--
2.48.1
More information about the Binutils
mailing list