mirror of
https://sourceware.org/git/glibc.git
synced 2025-01-11 20:00:07 +00:00
x86-64 memcmp: Use unsigned Jcc instructions on size [BZ #24155]
Since the size argument is unsigned. we should use unsigned Jcc instructions, instead of signed, to check size. Tested on x86-64 and x32, with and without --disable-multi-arch. [BZ #24155] CVE-2019-7309 * NEWS: Updated for CVE-2019-7309. * sysdeps/x86_64/memcmp.S: Use RDX_LP for size. Clear the upper 32 bits of RDX register for x32. Use unsigned Jcc instructions, instead of signed. * sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memcmp-2. * sysdeps/x86_64/x32/tst-size_t-memcmp-2.c: New test.
This commit is contained in:
parent
2ab5741b8a
commit
3f635fb433
11
ChangeLog
11
ChangeLog
@ -1,3 +1,14 @@
|
|||||||
|
2019-02-04 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
|
[BZ #24155]
|
||||||
|
CVE-2019-7309
|
||||||
|
* NEWS: Updated for CVE-2019-7309.
|
||||||
|
* sysdeps/x86_64/memcmp.S: Use RDX_LP for size. Clear the
|
||||||
|
upper 32 bits of RDX register for x32. Use unsigned Jcc
|
||||||
|
instructions, instead of signed.
|
||||||
|
* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memcmp-2.
|
||||||
|
* sysdeps/x86_64/x32/tst-size_t-memcmp-2.c: New test.
|
||||||
|
|
||||||
2019-02-04 Florian Weimer <fweimer@redhat.com>
|
2019-02-04 Florian Weimer <fweimer@redhat.com>
|
||||||
|
|
||||||
* posix/spawn.h (posix_spawn, posix_spawnp): Add __nonnull attribute.
|
* posix/spawn.h (posix_spawn, posix_spawnp): Add __nonnull attribute.
|
||||||
|
8
NEWS
8
NEWS
@ -25,7 +25,13 @@ Changes to build and runtime requirements:
|
|||||||
|
|
||||||
Security related changes:
|
Security related changes:
|
||||||
|
|
||||||
[Add security related changes here]
|
CVE-2019-7309: x86-64 memcmp used signed Jcc instructions to check
|
||||||
|
size. For x86-64, memcmp on an object size larger than SSIZE_MAX
|
||||||
|
has undefined behavior. On x32, the size_t argument may be passed
|
||||||
|
in the lower 32 bits of the 64-bit RDX register with non-zero upper
|
||||||
|
32 bits. When it happened with the sign bit of RDX register set,
|
||||||
|
memcmp gave the wrong result since it treated the size argument as
|
||||||
|
zero. Reported by H.J. Lu.
|
||||||
|
|
||||||
The following bugs are resolved with this release:
|
The following bugs are resolved with this release:
|
||||||
|
|
||||||
|
@ -21,14 +21,18 @@
|
|||||||
|
|
||||||
.text
|
.text
|
||||||
ENTRY (memcmp)
|
ENTRY (memcmp)
|
||||||
test %rdx, %rdx
|
#ifdef __ILP32__
|
||||||
|
/* Clear the upper 32 bits. */
|
||||||
|
movl %edx, %edx
|
||||||
|
#endif
|
||||||
|
test %RDX_LP, %RDX_LP
|
||||||
jz L(finz)
|
jz L(finz)
|
||||||
cmpq $1, %rdx
|
cmpq $1, %rdx
|
||||||
jle L(finr1b)
|
jbe L(finr1b)
|
||||||
subq %rdi, %rsi
|
subq %rdi, %rsi
|
||||||
movq %rdx, %r10
|
movq %rdx, %r10
|
||||||
cmpq $32, %r10
|
cmpq $32, %r10
|
||||||
jge L(gt32)
|
jae L(gt32)
|
||||||
/* Handle small chunks and last block of less than 32 bytes. */
|
/* Handle small chunks and last block of less than 32 bytes. */
|
||||||
L(small):
|
L(small):
|
||||||
testq $1, %r10
|
testq $1, %r10
|
||||||
@ -156,7 +160,7 @@ L(A32):
|
|||||||
movq %r11, %r10
|
movq %r11, %r10
|
||||||
andq $-32, %r10
|
andq $-32, %r10
|
||||||
cmpq %r10, %rdi
|
cmpq %r10, %rdi
|
||||||
jge L(mt16)
|
jae L(mt16)
|
||||||
/* Pre-unroll to be ready for unrolled 64B loop. */
|
/* Pre-unroll to be ready for unrolled 64B loop. */
|
||||||
testq $32, %rdi
|
testq $32, %rdi
|
||||||
jz L(A64)
|
jz L(A64)
|
||||||
@ -178,7 +182,7 @@ L(A64):
|
|||||||
movq %r11, %r10
|
movq %r11, %r10
|
||||||
andq $-64, %r10
|
andq $-64, %r10
|
||||||
cmpq %r10, %rdi
|
cmpq %r10, %rdi
|
||||||
jge L(mt32)
|
jae L(mt32)
|
||||||
|
|
||||||
L(A64main):
|
L(A64main):
|
||||||
movdqu (%rdi,%rsi), %xmm0
|
movdqu (%rdi,%rsi), %xmm0
|
||||||
@ -216,7 +220,7 @@ L(mt32):
|
|||||||
movq %r11, %r10
|
movq %r11, %r10
|
||||||
andq $-32, %r10
|
andq $-32, %r10
|
||||||
cmpq %r10, %rdi
|
cmpq %r10, %rdi
|
||||||
jge L(mt16)
|
jae L(mt16)
|
||||||
|
|
||||||
L(A32main):
|
L(A32main):
|
||||||
movdqu (%rdi,%rsi), %xmm0
|
movdqu (%rdi,%rsi), %xmm0
|
||||||
@ -254,7 +258,7 @@ L(ATR):
|
|||||||
movq %r11, %r10
|
movq %r11, %r10
|
||||||
andq $-32, %r10
|
andq $-32, %r10
|
||||||
cmpq %r10, %rdi
|
cmpq %r10, %rdi
|
||||||
jge L(mt16)
|
jae L(mt16)
|
||||||
testq $16, %rdi
|
testq $16, %rdi
|
||||||
jz L(ATR32)
|
jz L(ATR32)
|
||||||
|
|
||||||
@ -325,7 +329,7 @@ L(ATR64main):
|
|||||||
movq %r11, %r10
|
movq %r11, %r10
|
||||||
andq $-32, %r10
|
andq $-32, %r10
|
||||||
cmpq %r10, %rdi
|
cmpq %r10, %rdi
|
||||||
jge L(mt16)
|
jae L(mt16)
|
||||||
|
|
||||||
L(ATR32res):
|
L(ATR32res):
|
||||||
movdqa (%rdi,%rsi), %xmm0
|
movdqa (%rdi,%rsi), %xmm0
|
||||||
|
@ -8,7 +8,8 @@ endif
|
|||||||
ifeq ($(subdir),string)
|
ifeq ($(subdir),string)
|
||||||
tests += tst-size_t-memchr tst-size_t-memcmp tst-size_t-memcpy \
|
tests += tst-size_t-memchr tst-size_t-memcmp tst-size_t-memcpy \
|
||||||
tst-size_t-memrchr tst-size_t-memset tst-size_t-strncasecmp \
|
tst-size_t-memrchr tst-size_t-memset tst-size_t-strncasecmp \
|
||||||
tst-size_t-strncmp tst-size_t-strncpy tst-size_t-strnlen
|
tst-size_t-strncmp tst-size_t-strncpy tst-size_t-strnlen \
|
||||||
|
tst-size_t-memcmp-2
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(subdir),wcsmbs)
|
ifeq ($(subdir),wcsmbs)
|
||||||
|
79
sysdeps/x86_64/x32/tst-size_t-memcmp-2.c
Normal file
79
sysdeps/x86_64/x32/tst-size_t-memcmp-2.c
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/* Test memcmp with size_t in the lower 32 bits of 64-bit register.
|
||||||
|
Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with the GNU C Library; if not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#define TEST_MAIN
|
||||||
|
#ifdef WIDE
|
||||||
|
# define TEST_NAME "wmemcmp"
|
||||||
|
#else
|
||||||
|
# define TEST_NAME "memcmp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "test-size_t.h"
|
||||||
|
|
||||||
|
#ifdef WIDE
|
||||||
|
# include <inttypes.h>
|
||||||
|
# include <wchar.h>
|
||||||
|
|
||||||
|
# define MEMCMP wmemcmp
|
||||||
|
# define CHAR wchar_t
|
||||||
|
#else
|
||||||
|
# define MEMCMP memcmp
|
||||||
|
# define CHAR char
|
||||||
|
#endif
|
||||||
|
|
||||||
|
IMPL (MEMCMP, 1)
|
||||||
|
|
||||||
|
typedef int (*proto_t) (const CHAR *, const CHAR *, size_t);
|
||||||
|
|
||||||
|
static int
|
||||||
|
__attribute__ ((noinline, noclone))
|
||||||
|
do_memcmp (parameter_t a, parameter_t b)
|
||||||
|
{
|
||||||
|
return CALL (&b, a.p, b.p, a.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
test_main (void)
|
||||||
|
{
|
||||||
|
test_init ();
|
||||||
|
|
||||||
|
parameter_t dest = { { page_size / sizeof (CHAR) }, buf1 };
|
||||||
|
parameter_t src = { { 0 }, buf2 };
|
||||||
|
|
||||||
|
memcpy (buf1, buf2, page_size);
|
||||||
|
|
||||||
|
CHAR *p = (CHAR *) buf1;
|
||||||
|
p[page_size / sizeof (CHAR) - 1] = (CHAR) 1;
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
FOR_EACH_IMPL (impl, 0)
|
||||||
|
{
|
||||||
|
src.fn = impl->fn;
|
||||||
|
int res = do_memcmp (dest, src);
|
||||||
|
if (res >= 0)
|
||||||
|
{
|
||||||
|
error (0, 0, "Wrong result in function %s: %i >= 0",
|
||||||
|
impl->name, res);
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <support/test-driver.c>
|
Loading…
Reference in New Issue
Block a user