blob: 1a343149c0d80a3c937ec67d95570febf9348df9 [file] [log] [blame]
Brad Bishop19323692019-04-05 15:28:33 -04001From 3f635fb43389b54f682fc9ed2acc0b2aaf4a923d Mon Sep 17 00:00:00 2001
2From: "H.J. Lu" <hjl.tools@gmail.com>
3Date: Mon, 4 Feb 2019 06:31:01 -0800
4Subject: [PATCH] x86-64 memcmp: Use unsigned Jcc instructions on size [BZ
5 #24155]
6
7Since the size argument is unsigned. we should use unsigned Jcc
8instructions, instead of signed, to check size.
9
10Tested on x86-64 and x32, with and without --disable-multi-arch.
11
12 [BZ #24155]
13 CVE-2019-7309
14 * NEWS: Updated for CVE-2019-7309.
15 * sysdeps/x86_64/memcmp.S: Use RDX_LP for size. Clear the
16 upper 32 bits of RDX register for x32. Use unsigned Jcc
17 instructions, instead of signed.
18 * sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memcmp-2.
19 * sysdeps/x86_64/x32/tst-size_t-memcmp-2.c: New test.
20
21CVE: CVE-2019-7309
22Upstream-Status: Backport
23Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
24Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
25---
26 sysdeps/x86_64/memcmp.S | 20 +++---
27 sysdeps/x86_64/x32/Makefile | 3 +-
28 sysdeps/x86_64/x32/tst-size_t-memcmp-2.c | 79 ++++++++++++++++++++++++
29 5 files changed, 111 insertions(+), 10 deletions(-)
30 create mode 100644 sysdeps/x86_64/x32/tst-size_t-memcmp-2.c
31
32diff --git a/sysdeps/x86_64/memcmp.S b/sysdeps/x86_64/memcmp.S
33index 1fc487caa5..1322bb3b92 100644
34--- a/sysdeps/x86_64/memcmp.S
35+++ b/sysdeps/x86_64/memcmp.S
36@@ -21,14 +21,18 @@
37
38 .text
39 ENTRY (memcmp)
40- test %rdx, %rdx
41+#ifdef __ILP32__
42+ /* Clear the upper 32 bits. */
43+ movl %edx, %edx
44+#endif
45+ test %RDX_LP, %RDX_LP
46 jz L(finz)
47 cmpq $1, %rdx
48- jle L(finr1b)
49+ jbe L(finr1b)
50 subq %rdi, %rsi
51 movq %rdx, %r10
52 cmpq $32, %r10
53- jge L(gt32)
54+ jae L(gt32)
55 /* Handle small chunks and last block of less than 32 bytes. */
56 L(small):
57 testq $1, %r10
58@@ -156,7 +160,7 @@ L(A32):
59 movq %r11, %r10
60 andq $-32, %r10
61 cmpq %r10, %rdi
62- jge L(mt16)
63+ jae L(mt16)
64 /* Pre-unroll to be ready for unrolled 64B loop. */
65 testq $32, %rdi
66 jz L(A64)
67@@ -178,7 +182,7 @@ L(A64):
68 movq %r11, %r10
69 andq $-64, %r10
70 cmpq %r10, %rdi
71- jge L(mt32)
72+ jae L(mt32)
73
74 L(A64main):
75 movdqu (%rdi,%rsi), %xmm0
76@@ -216,7 +220,7 @@ L(mt32):
77 movq %r11, %r10
78 andq $-32, %r10
79 cmpq %r10, %rdi
80- jge L(mt16)
81+ jae L(mt16)
82
83 L(A32main):
84 movdqu (%rdi,%rsi), %xmm0
85@@ -254,7 +258,7 @@ L(ATR):
86 movq %r11, %r10
87 andq $-32, %r10
88 cmpq %r10, %rdi
89- jge L(mt16)
90+ jae L(mt16)
91 testq $16, %rdi
92 jz L(ATR32)
93
94@@ -325,7 +329,7 @@ L(ATR64main):
95 movq %r11, %r10
96 andq $-32, %r10
97 cmpq %r10, %rdi
98- jge L(mt16)
99+ jae L(mt16)
100
101 L(ATR32res):
102 movdqa (%rdi,%rsi), %xmm0
103diff --git a/sysdeps/x86_64/x32/Makefile b/sysdeps/x86_64/x32/Makefile
104index 1557724b0c..8748956563 100644
105--- a/sysdeps/x86_64/x32/Makefile
106+++ b/sysdeps/x86_64/x32/Makefile
107@@ -8,7 +8,8 @@ endif
108 ifeq ($(subdir),string)
109 tests += tst-size_t-memchr tst-size_t-memcmp tst-size_t-memcpy \
110 tst-size_t-memrchr tst-size_t-memset tst-size_t-strncasecmp \
111- tst-size_t-strncmp tst-size_t-strncpy tst-size_t-strnlen
112+ tst-size_t-strncmp tst-size_t-strncpy tst-size_t-strnlen \
113+ tst-size_t-memcmp-2
114 endif
115
116 ifeq ($(subdir),wcsmbs)
117diff --git a/sysdeps/x86_64/x32/tst-size_t-memcmp-2.c b/sysdeps/x86_64/x32/tst-size_t-memcmp-2.c
118new file mode 100644
119index 0000000000..d8ae1a0813
120--- /dev/null
121+++ b/sysdeps/x86_64/x32/tst-size_t-memcmp-2.c
122@@ -0,0 +1,79 @@
123+/* Test memcmp with size_t in the lower 32 bits of 64-bit register.
124+ Copyright (C) 2019 Free Software Foundation, Inc.
125+ This file is part of the GNU C Library.
126+
127+ The GNU C Library is free software; you can redistribute it and/or
128+ modify it under the terms of the GNU Lesser General Public
129+ License as published by the Free Software Foundation; either
130+ version 2.1 of the License, or (at your option) any later version.
131+
132+ The GNU C Library is distributed in the hope that it will be useful,
133+ but WITHOUT ANY WARRANTY; without even the implied warranty of
134+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
135+ Lesser General Public License for more details.
136+
137+ You should have received a copy of the GNU Lesser General Public
138+ License along with the GNU C Library; if not, see
139+ <http://www.gnu.org/licenses/>. */
140+
141+#define TEST_MAIN
142+#ifdef WIDE
143+# define TEST_NAME "wmemcmp"
144+#else
145+# define TEST_NAME "memcmp"
146+#endif
147+
148+#include "test-size_t.h"
149+
150+#ifdef WIDE
151+# include <inttypes.h>
152+# include <wchar.h>
153+
154+# define MEMCMP wmemcmp
155+# define CHAR wchar_t
156+#else
157+# define MEMCMP memcmp
158+# define CHAR char
159+#endif
160+
161+IMPL (MEMCMP, 1)
162+
163+typedef int (*proto_t) (const CHAR *, const CHAR *, size_t);
164+
165+static int
166+__attribute__ ((noinline, noclone))
167+do_memcmp (parameter_t a, parameter_t b)
168+{
169+ return CALL (&b, a.p, b.p, a.len);
170+}
171+
172+static int
173+test_main (void)
174+{
175+ test_init ();
176+
177+ parameter_t dest = { { page_size / sizeof (CHAR) }, buf1 };
178+ parameter_t src = { { 0 }, buf2 };
179+
180+ memcpy (buf1, buf2, page_size);
181+
182+ CHAR *p = (CHAR *) buf1;
183+ p[page_size / sizeof (CHAR) - 1] = (CHAR) 1;
184+
185+ int ret = 0;
186+ FOR_EACH_IMPL (impl, 0)
187+ {
188+ src.fn = impl->fn;
189+ int res = do_memcmp (dest, src);
190+ if (res >= 0)
191+ {
192+ error (0, 0, "Wrong result in function %s: %i >= 0",
193+ impl->name, res);
194+ ret = 1;
195+ }
196+ }
197+
198+ return ret ? EXIT_FAILURE : EXIT_SUCCESS;
199+}
200+
201+#include <support/test-driver.c>
202--
2032.17.1
204