Add bounds check to __libc_ifunc_impl_list
authorWilco Dijkstra <wilco.dijkstra@arm.com>
Fri, 10 Jun 2022 16:13:29 +0000 (17:13 +0100)
committerWilco Dijkstra <wdijkstr@arm.com>
Fri, 10 Jun 2022 16:13:29 +0000 (17:13 +0100)
Add a proper bounds check to __libc_ifunc_impl_list. This makes MAX_IFUNC
redundant and fixes several targets that will write outside the array.
To avoid unnecessary large diffs, pass the maximum in the argument 'i' to
IFUNC_IMPL_ADD - 'max' can be used in new ifunc definitions and existing
ones can be updated if desired.

Passes buildmanyglibc.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
include/ifunc-impl-list.h
sysdeps/aarch64/multiarch/ifunc-impl-list.c
sysdeps/arm/armv7/multiarch/ifunc-impl-list.c
sysdeps/i386/i686/multiarch/ifunc-impl-list.c
sysdeps/powerpc/powerpc32/power4/multiarch/ifunc-impl-list.c
sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
sysdeps/s390/multiarch/ifunc-impl-list.c
sysdeps/sparc/sparc64/multiarch/ifunc-impl-list.c
sysdeps/x86_64/multiarch/ifunc-impl-list.c

index 78087f0..00bf48f 100644 (file)
@@ -34,15 +34,15 @@ struct libc_ifunc_impl
 
 /* Add an IFUNC implementation, IMPL, for function FUNC, to ARRAY with
    USABLE at index I and advance I by one.  */
-#define IFUNC_IMPL_ADD(array, i, func, usable, impl) \
+#define IFUNC_IMPL_ADD(array, max, func, usable, impl) \
   extern __typeof (func) impl attribute_hidden; \
-  (array)[i++] = (struct libc_ifunc_impl) { #impl, (void (*) (void)) impl, (usable) };
+  if (n < max) (array)[n++] = (struct libc_ifunc_impl) { #impl, (void (*) (void)) impl, (usable) };
 
 /* Return the number of IFUNC implementations, N, for function FUNC if
    string NAME matches FUNC.  */
-#define IFUNC_IMPL(n, name, func, ...) \
+#define IFUNC_IMPL(max, name, func, ...) \
   if (strcmp (name, #func) == 0) \
-    { \
+    { size_t n = 0;\
       __VA_ARGS__; \
       return n; \
     }
index f6c6d00..4144615 100644 (file)
 #include <init-arch.h>
 #include <stdio.h>
 
-/* Maximum number of IFUNC implementations.  */
-#define MAX_IFUNC      8
-
 size_t
 __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
                        size_t max)
 {
-  assert (max >= MAX_IFUNC);
-
-  size_t i = 0;
+  size_t i = max;
 
   INIT_ARCH ();
 
@@ -76,5 +71,5 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
              IFUNC_IMPL_ADD (array, i, strlen, !mte, __strlen_asimd)
              IFUNC_IMPL_ADD (array, i, strlen, 1, __strlen_mte))
 
-  return i;
+  return 0;
 }
index af9f749..e92bcb2 100644 (file)
@@ -29,7 +29,7 @@ size_t
 __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
                        size_t max)
 {
-  size_t i = 0;
+  size_t i = max;
 
   bool use_neon = true;
 #ifdef __ARM_NEON__
@@ -57,5 +57,5 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
              IFUNC_IMPL_ADD (array, i, memchr, use_neon, __memchr_neon)
              IFUNC_IMPL_ADD (array, i, memchr, 1, __memchr_noneon));
 
-  return i;
+  return 0;
 }
index c014f52..9237b58 100644 (file)
@@ -22,9 +22,6 @@
 #include <ifunc-impl-list.h>
 #include "init-arch.h"
 
-/* Maximum number of IFUNC implementations.  */
-#define MAX_IFUNC      4
-
 /* Fill ARRAY of MAX elements with IFUNC implementations for function
    NAME and return the number of valid entries.  */
 
@@ -32,9 +29,7 @@ size_t
 __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
                        size_t max)
 {
-  assert (max >= MAX_IFUNC);
-
-  size_t i = 0;
+  size_t i = max;
 
   /* Support sysdeps/i386/i686/multiarch/memchr.S.  */
   IFUNC_IMPL (i, name, memchr,
@@ -358,5 +353,5 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
              IFUNC_IMPL_ADD (array, i, strncmp, 1, __strncmp_ia32))
 #endif
 
-  return i;
+  return 0;
 }
index 0189036..e6ef5e6 100644 (file)
 #include <ldsodefs.h>
 #include <ifunc-impl-list.h>
 
-/* Maximum number of IFUNC implementations.  */
-#define MAX_IFUNC      6
-
 size_t
 __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
                        size_t max)
 {
-  assert (max >= MAX_IFUNC);
-
-  size_t i = 0;
+  size_t i = max;
 
   unsigned long int hwcap = GLRO(dl_hwcap);
   /* hwcap contains only the latest supported ISA, the code checks which is
@@ -179,5 +174,5 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
              IFUNC_IMPL_ADD (array, i, strchr, 1,
                              __strchr_ppc))
 
-  return i;
+  return 0;
 }
index ac533a9..5a3c7a5 100644 (file)
 #include <ldsodefs.h>
 #include <ifunc-impl-list.h>
 
-/* Maximum number of IFUNC implementations.  */
-#define MAX_IFUNC      6
-
 size_t
 __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
                        size_t max)
 {
-  assert (max >= MAX_IFUNC);
-
-  size_t i = 0;
+  size_t i = max;
 
   unsigned long int hwcap = GLRO(dl_hwcap);
   unsigned long int hwcap2 = GLRO(dl_hwcap2);
@@ -448,5 +443,5 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
              IFUNC_IMPL_ADD (array, i, strcasestr, 1,
                              __strcasestr_ppc))
 
-  return i;
+  return 0;
 }
index c1902b2..5d0c730 100644 (file)
@@ -66,9 +66,6 @@
 #include <ifunc-wmemset.h>
 #include <ifunc-wmemcmp.h>
 
-/* Maximum number of IFUNC implementations.  */
-#define MAX_IFUNC      3
-
 /* Fill ARRAY of MAX elements with IFUNC implementations for function
    NAME supported on target machine and return the number of valid
    entries.  */
@@ -76,9 +73,7 @@ size_t
 __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
                        size_t max)
 {
-  assert (max >= MAX_IFUNC);
-
-  size_t i = 0;
+  size_t i = max;
 
   /* Get hardware information.  */
   unsigned long int dl_hwcap = GLRO (dl_hwcap);
@@ -670,5 +665,5 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
                )
 #endif /* HAVE_WMEMCMP_IFUNC  */
 
-  return i;
+  return 0;
 }
index 9be12f9..918eb69 100644 (file)
@@ -30,7 +30,7 @@ size_t
 __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
                        size_t max)
 {
-  size_t i = 0;
+  size_t i = max;
   int hwcap;
 
   hwcap = GLRO(dl_hwcap);
@@ -75,5 +75,5 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
                              __memmove_niagara7)
              IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_ultra1));
 
-  return i;
+  return 0;
 }
index 58f3ec8..dc59575 100644 (file)
@@ -23,9 +23,6 @@
 #include <sysdep.h>
 #include "init-arch.h"
 
-/* Maximum number of IFUNC implementations.  */
-#define MAX_IFUNC      5
-
 /* Fill ARRAY of MAX elements with IFUNC implementations for function
    NAME supported on target machine and return the number of valid
    entries.  */
@@ -34,9 +31,7 @@ size_t
 __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
                        size_t max)
 {
-  assert (max >= MAX_IFUNC);
-
-  size_t i = 0;
+  size_t i = max;
 
   /* Support sysdeps/x86_64/multiarch/memcmpeq.c.  */
   IFUNC_IMPL (i, name, __memcmpeq,
@@ -1015,5 +1010,5 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
                              __wmemset_chk_avx512_unaligned))
 #endif
 
-  return i;
+  return 0;
 }