diff mbox

[2/2] Add an x86 IFUNC testcase for [BZ #20019]

Message ID 20161004184621.GB27454@intel.com
State New
Headers show

Commit Message

H.J. Lu Oct. 4, 2016, 6:46 p.m. UTC
If an IFUNC function is called before the providing shared library is
unrelocated, ld.so may segfault.  Add a testcase to verify that ld.so
will issue a diagnostic and won't segfault in this case.

Tested on i686 and x86-64.  OK for master?

H.J.
---
	[BZ #20019]
	* sysdeps/x86/Makefile (tests): Add tst-ifunc1.
	(tests-special): Add $(objpfx)tst-ifunc1.out.
	($(objpfx)tst-ifunc1.out): New rule.
	(extra-test-objs): Add tst-ifunc1 objects.
	($(objpfx)tst-ifunc1): New.
	($(objpfx)tst-ifuncmod1a.so): New rule.
	($(objpfx)tst-ifuncmod1b.so): LIkewise.
	($(objpfx)tst-ifuncmod1a.os): LIkewise.
	($(objpfx)tst-ifuncmod1b.os): LIkewise.
	* sysdeps/x86/tst-ifunc1.c: New file.
	* sysdeps/x86/tst-ifunc1.sh: LIkewise.
	* sysdeps/x86/tst-ifuncmod1a.c: LIkewise.
	* sysdeps/x86/tst-ifuncmod1b.c: LIkewise.
---
 sysdeps/x86/Makefile         | 25 +++++++++++++++++++++++++
 sysdeps/x86/tst-ifunc1.c     | 26 ++++++++++++++++++++++++++
 sysdeps/x86/tst-ifunc1.sh    | 35 +++++++++++++++++++++++++++++++++++
 sysdeps/x86/tst-ifuncmod1a.c | 27 +++++++++++++++++++++++++++
 sysdeps/x86/tst-ifuncmod1b.c | 23 +++++++++++++++++++++++
 5 files changed, 136 insertions(+)
 create mode 100644 sysdeps/x86/tst-ifunc1.c
 create mode 100755 sysdeps/x86/tst-ifunc1.sh
 create mode 100644 sysdeps/x86/tst-ifuncmod1a.c
 create mode 100644 sysdeps/x86/tst-ifuncmod1b.c

Comments

Joseph Myers Oct. 4, 2016, 9:27 p.m. UTC | #1
On Tue, 4 Oct 2016, H.J. Lu wrote:

> If an IFUNC function is called before the providing shared library is
> unrelocated, ld.so may segfault.  Add a testcase to verify that ld.so
> will issue a diagnostic and won't segfault in this case.
> 
> Tested on i686 and x86-64.  OK for master?

I can't see anything x86-specific about these tests.  If they are meant to 
work, they should work on all architectures, and so should be 
architecture-independent.  Is the architecture-specific thing the use of 
memmove as a function that uses IFUNCs?  If so, the tests should still 
work on other architectures, just maybe be less effective as tests (and 
other architecture maintainers could always add a hook to use another 
function instead of memmove).

If you suspect other architectures might have similar bugs requiring fixes 
for these tests to pass but don't want to make such changes yourself, you 
should follow the usual process for changes made only for some 
architectures: post a detailed description of how to tell whether the 
change is needed for your architecture and how to make the change, CC: to 
the relevant architecture maintainers, and add an entry to 
https://sourceware.org/glibc/wiki/PortStatus (once the x86 changes are 
in), listing the possibly affected (i.e. IFUNC-supporting?) architectures 
on that page.
H.J. Lu Oct. 4, 2016, 10:21 p.m. UTC | #2
On Tue, Oct 4, 2016 at 2:27 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> On Tue, 4 Oct 2016, H.J. Lu wrote:
>
>> If an IFUNC function is called before the providing shared library is
>> unrelocated, ld.so may segfault.  Add a testcase to verify that ld.so
>> will issue a diagnostic and won't segfault in this case.
>>
>> Tested on i686 and x86-64.  OK for master?
>
> I can't see anything x86-specific about these tests.  If they are meant to
> work, they should work on all architectures, and so should be
> architecture-independent.  Is the architecture-specific thing the use of
> memmove as a function that uses IFUNCs?  If so, the tests should still
> work on other architectures, just maybe be less effective as tests (and
> other architecture maintainers could always add a hook to use another
> function instead of memmove).

The result of this test is IFUNC implementation specific.  The older
x86 IFUNC implementation had

# define INIT_ARCH() \
  do                                                    \
    if (__cpu_features.kind == arch_kind_unknown)       \
      __init_cpu_features ();                           \
  while (0)

The new implementation assumed that relocations in libc.so were
processed first.  It is hard for me to tell if other IFUNC implementations
have the similar restriction.

> If you suspect other architectures might have similar bugs requiring fixes
> for these tests to pass but don't want to make such changes yourself, you
> should follow the usual process for changes made only for some
> architectures: post a detailed description of how to tell whether the
> change is needed for your architecture and how to make the change, CC: to
> the relevant architecture maintainers, and add an entry to
> https://sourceware.org/glibc/wiki/PortStatus (once the x86 changes are
> in), listing the possibly affected (i.e. IFUNC-supporting?) architectures
> on that page.
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
Joseph Myers Oct. 4, 2016, 10:55 p.m. UTC | #3
On Tue, 4 Oct 2016, H.J. Lu wrote:

> On Tue, Oct 4, 2016 at 2:27 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> > On Tue, 4 Oct 2016, H.J. Lu wrote:
> >
> >> If an IFUNC function is called before the providing shared library is
> >> unrelocated, ld.so may segfault.  Add a testcase to verify that ld.so
> >> will issue a diagnostic and won't segfault in this case.
> >>
> >> Tested on i686 and x86-64.  OK for master?
> >
> > I can't see anything x86-specific about these tests.  If they are meant to
> > work, they should work on all architectures, and so should be
> > architecture-independent.  Is the architecture-specific thing the use of
> > memmove as a function that uses IFUNCs?  If so, the tests should still
> > work on other architectures, just maybe be less effective as tests (and
> > other architecture maintainers could always add a hook to use another
> > function instead of memmove).
> 
> The result of this test is IFUNC implementation specific.  The older
> x86 IFUNC implementation had
> 
> # define INIT_ARCH() \
>   do                                                    \
>     if (__cpu_features.kind == arch_kind_unknown)       \
>       __init_cpu_features ();                           \
>   while (0)
> 
> The new implementation assumed that relocations in libc.so were
> processed first.  It is hard for me to tell if other IFUNC implementations
> have the similar restriction.

You seem to be saying there was some bug in the x86 IFUNC implementation 
such that you don't know whether a corresponding bug might be present for 
other architectures or not.  That is a very strong indication that the 
tests should be architecture-independent, so that people can use the 
results of those tests on other architectures to tell whether those other 
architectures need fixing as well.
H.J. Lu Oct. 5, 2016, 12:05 a.m. UTC | #4
On Tue, Oct 4, 2016 at 3:55 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> On Tue, 4 Oct 2016, H.J. Lu wrote:
>
>> On Tue, Oct 4, 2016 at 2:27 PM, Joseph Myers <joseph@codesourcery.com> wrote:
>> > On Tue, 4 Oct 2016, H.J. Lu wrote:
>> >
>> >> If an IFUNC function is called before the providing shared library is
>> >> unrelocated, ld.so may segfault.  Add a testcase to verify that ld.so
>> >> will issue a diagnostic and won't segfault in this case.
>> >>
>> >> Tested on i686 and x86-64.  OK for master?
>> >
>> > I can't see anything x86-specific about these tests.  If they are meant to
>> > work, they should work on all architectures, and so should be
>> > architecture-independent.  Is the architecture-specific thing the use of
>> > memmove as a function that uses IFUNCs?  If so, the tests should still
>> > work on other architectures, just maybe be less effective as tests (and
>> > other architecture maintainers could always add a hook to use another
>> > function instead of memmove).
>>
>> The result of this test is IFUNC implementation specific.  The older
>> x86 IFUNC implementation had
>>
>> # define INIT_ARCH() \
>>   do                                                    \
>>     if (__cpu_features.kind == arch_kind_unknown)       \
>>       __init_cpu_features ();                           \
>>   while (0)
>>
>> The new implementation assumed that relocations in libc.so were
>> processed first.  It is hard for me to tell if other IFUNC implementations
>> have the similar restriction.
>
> You seem to be saying there was some bug in the x86 IFUNC implementation

It is a limitation.

> such that you don't know whether a corresponding bug might be present for
> other architectures or not.  That is a very strong indication that the
> tests should be architecture-independent, so that people can use the
> results of those tests on other architectures to tell whether those other
> architectures need fixing as well.
>

I can try __builtin_memcpy, instread of __builtin_memmove.   There are 2
acceptable results.  One is ld.so issues an error and the other is program runs.
On x86, ld.so issues an error.  I don't know what should happen on others.
Joseph Myers Oct. 5, 2016, 12:09 a.m. UTC | #5
On Wed, 5 Oct 2016, H.J. Lu wrote:

> I can try __builtin_memcpy, instread of __builtin_memmove.   There are 2
> acceptable results.  One is ld.so issues an error and the other is program runs.
> On x86, ld.so issues an error.  I don't know what should happen on others.

You could make the test pass on either of those results (while failing if 
ld.so crashes).
diff mbox

Patch

diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
index 0d0326c2..6907b46 100644
--- a/sysdeps/x86/Makefile
+++ b/sysdeps/x86/Makefile
@@ -7,4 +7,29 @@  sysdep-dl-routines += dl-get-cpu-features
 
 tests += tst-get-cpu-features
 tests-static += tst-get-cpu-features-static
+
+ifeq ($(build-shared),yes)
+tests += tst-ifunc1
+tests-special += $(objpfx)tst-ifunc1.out
+$(objpfx)tst-ifunc1.out: ../sysdeps/x86/tst-ifunc1.sh $(objpfx)tst-ifunc1
+	$(BASH) $< $(objpfx) '$(test-via-rtld-prefix)' \
+	  '$(test-wrapper-env)' '$(run-program-env)'; \
+	$(evaluate-test)
+
+# Since tst-ifuncmod1a.so and tst-ifuncmod1b.so aren't linked against
+# libc.so, use special rules to build them.
+extra-test-objs += tst-ifunc1 tst-ifuncmod1a.os tst-ifuncmod1b.os \
+		   tst-ifuncmod1a.os tst-ifuncmod1b.os
+
+$(objpfx)tst-ifunc1: $(objpfx)tst-ifuncmod1a.so
+$(objpfx)tst-ifuncmod1a.so: $(objpfx)tst-ifuncmod1a.os \
+			    $(objpfx)tst-ifuncmod1b.so
+	$(CC) -Wl,-z,now -shared -nostdlib -nostartfiles -o $@ $^
+$(objpfx)tst-ifuncmod1b.so: $(objpfx)tst-ifuncmod1b.os
+	$(CC) -Wl,-z,now -shared -nostdlib -nostartfiles -o $@ $^
+$(objpfx)tst-ifuncmod1a.os: ../sysdeps/x86/tst-ifuncmod1a.c
+	$(CC) -fPIC -c -o $@ $^
+$(objpfx)tst-ifuncmod1b.os: ../sysdeps/x86/tst-ifuncmod1b.c
+	$(CC) -fPIC -c -o $@ $^
+endif
 endif
diff --git a/sysdeps/x86/tst-ifunc1.c b/sysdeps/x86/tst-ifunc1.c
new file mode 100644
index 0000000..735153f
--- /dev/null
+++ b/sysdeps/x86/tst-ifunc1.c
@@ -0,0 +1,26 @@ 
+/* Test case for x86 IFUNC.
+   Copyright (C) 2016 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/>.  */
+
+extern void foo (void);
+
+int
+main (void)
+{
+  foo ();
+  return 0;
+}
diff --git a/sysdeps/x86/tst-ifunc1.sh b/sysdeps/x86/tst-ifunc1.sh
new file mode 100755
index 0000000..5f5afe0
--- /dev/null
+++ b/sysdeps/x86/tst-ifunc1.sh
@@ -0,0 +1,35 @@ 
+#!/bin/bash
+# An x86 IFUNC test.
+# Copyright (C) 2016 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/>.
+
+set -e
+
+objpfx=$1; shift
+test_via_rtld_prefix=$1; shift
+test_wrapper_env=$1; shift
+run_program_env=$1; shift
+logfile=${objpfx}tst-ifunc1.out
+
+> $logfile
+fail=0
+
+${test_wrapper_env} \
+${run_program_env} \
+${objpfx}tst-ifunc1 2>&1 | grep Relink >> $logfile || fail=1
+
+exit $fail
diff --git a/sysdeps/x86/tst-ifuncmod1a.c b/sysdeps/x86/tst-ifuncmod1a.c
new file mode 100644
index 0000000..a1c27ed
--- /dev/null
+++ b/sysdeps/x86/tst-ifuncmod1a.c
@@ -0,0 +1,27 @@ 
+/* Test case for x86 IFUNC.
+   Copyright (C) 2016 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/>.  */
+
+void bar (void *dst, void *src);
+
+void
+foo (void)
+{
+  char dst[50];
+  char src[50];
+  bar (dst, src);
+}
diff --git a/sysdeps/x86/tst-ifuncmod1b.c b/sysdeps/x86/tst-ifuncmod1b.c
new file mode 100644
index 0000000..e6e9e9b
--- /dev/null
+++ b/sysdeps/x86/tst-ifuncmod1b.c
@@ -0,0 +1,23 @@ 
+/* Test case for x86 IFUNC.
+   Copyright (C) 2016 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/>.  */
+
+void
+bar (void *dst, void *src)
+{
+  __builtin_memmove (dst, src, 40);
+}