[v2] debug: Fix fortified realpath C++ ODR violation (BZ 30516)
Checks
Context |
Check |
Description |
redhat-pt-bot/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
redhat-pt-bot/TryBot-32bit |
success
|
Build for i686
|
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_glibc_check--master-arm |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 |
fail
|
Testing failed
|
linaro-tcwg-bot/tcwg_glibc_build--master-arm |
success
|
Testing passed
|
redhat-pt-bot/TryBot-still_applies |
warning
|
Patch no longer applies to master
|
Commit Message
Although fortify wrappers are built with always_inline attribute,
C++ modules imports a precompiled header module foo.pcm generated from
foo.h which may differ if the translation unit includes or not limit.h.
Although GCC does not fully support C++ modules yet, this is a
problem when using C++ modules with clang.
To avoid lower C diagnostic coverage, a new installed header is added
that adds namespace-clean macro with value similar to current one
(__PATH_MAX). A test is also added to check if the kernel decides to
change it.
Checked on x86_64-linux-gnu.
---
bits/stdlib_lim.h | 26 ++++++++++
stdlib/Makefile | 1 +
stdlib/bits/stdlib.h | 6 ++-
sysdeps/unix/sysv/linux/Makefile | 10 ++++
sysdeps/unix/sysv/linux/bits/stdlib_lim.h | 26 ++++++++++
sysdeps/unix/sysv/linux/tst-limits-consts.py | 54 ++++++++++++++++++++
6 files changed, 121 insertions(+), 2 deletions(-)
create mode 100644 bits/stdlib_lim.h
create mode 100644 sysdeps/unix/sysv/linux/bits/stdlib_lim.h
create mode 100755 sysdeps/unix/sysv/linux/tst-limits-consts.py
Comments
Ping.
On 03/07/23 15:04, Adhemerval Zanella wrote:
> Although fortify wrappers are built with always_inline attribute,
> C++ modules imports a precompiled header module foo.pcm generated from
> foo.h which may differ if the translation unit includes or not limit.h.
>
> Although GCC does not fully support C++ modules yet, this is a
> problem when using C++ modules with clang.
>
> To avoid lower C diagnostic coverage, a new installed header is added
> that adds namespace-clean macro with value similar to current one
> (__PATH_MAX). A test is also added to check if the kernel decides to
> change it.
>
> Checked on x86_64-linux-gnu.
> ---
> bits/stdlib_lim.h | 26 ++++++++++
> stdlib/Makefile | 1 +
> stdlib/bits/stdlib.h | 6 ++-
> sysdeps/unix/sysv/linux/Makefile | 10 ++++
> sysdeps/unix/sysv/linux/bits/stdlib_lim.h | 26 ++++++++++
> sysdeps/unix/sysv/linux/tst-limits-consts.py | 54 ++++++++++++++++++++
> 6 files changed, 121 insertions(+), 2 deletions(-)
> create mode 100644 bits/stdlib_lim.h
> create mode 100644 sysdeps/unix/sysv/linux/bits/stdlib_lim.h
> create mode 100755 sysdeps/unix/sysv/linux/tst-limits-consts.py
>
> diff --git a/bits/stdlib_lim.h b/bits/stdlib_lim.h
> new file mode 100644
> index 0000000000..f0295490c0
> --- /dev/null
> +++ b/bits/stdlib_lim.h
> @@ -0,0 +1,26 @@
> +/* Implementation limits related to stdlib.h - generic version.
> + Copyright (C) 2023 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
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifndef _BITS_STDLIB_LIM_H
> +#define _BITS_STDLIB_LIM_H 1
> +
> +/* Same as PATH_MAX, but defined in the implementation namespace so it can
> + be used in places where including limits.h is not possible. */
> +#undef __PATH_MAX
> +
> +#endif
> diff --git a/stdlib/Makefile b/stdlib/Makefile
> index 0975f55ee6..726a109b67 100644
> --- a/stdlib/Makefile
> +++ b/stdlib/Makefile
> @@ -33,6 +33,7 @@ headers := \
> bits/stdlib-float.h \
> bits/stdlib-ldbl.h \
> bits/stdlib.h \
> + bits/stdlib_lim.h \
> bits/time64.h \
> bits/timesize.h \
> bits/types/error_t.h \
> diff --git a/stdlib/bits/stdlib.h b/stdlib/bits/stdlib.h
> index c6c0082ad5..ed54c24fd4 100644
> --- a/stdlib/bits/stdlib.h
> +++ b/stdlib/bits/stdlib.h
> @@ -20,6 +20,8 @@
> # error "Never include <bits/stdlib.h> directly; use <stdlib.h> instead."
> #endif
>
> +#include <bits/stdlib_lim.h>
> +
> extern char *__realpath_chk (const char *__restrict __name,
> char *__restrict __resolved,
> size_t __resolvedlen) __THROW __wur;
> @@ -41,8 +43,8 @@ __NTH (realpath (const char *__restrict __name, char *__restrict __resolved))
> if (sz == (size_t) -1)
> return __realpath_alias (__name, __resolved);
>
> -#if defined _LIBC_LIMITS_H_ && defined PATH_MAX
> - if (__glibc_unsafe_len (PATH_MAX, sizeof (char), sz))
> +#ifdef __PATH_MAX
> + if (__glibc_unsafe_len (__PATH_MAX, sizeof (char), sz))
> return __realpath_chk_warn (__name, __resolved, sz);
> #endif
> return __realpath_chk (__name, __resolved, sz);
> diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
> index 23a84cf225..5fc559568f 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -376,6 +376,16 @@ $(objpfx)tst-mount-consts.out: ../sysdeps/unix/sysv/linux/tst-mount-consts.py
> < /dev/null > $@ 2>&1; $(evaluate-test)
> $(objpfx)tst-mount-consts.out: $(sysdeps-linux-python-deps)
>
> +tests-special += \
> + $(objpfx)tst-limits-consts.out \
> + # tests-special
> +$(objpfx)tst-limits-consts.out: ../sysdeps/unix/sysv/linux/tst-limits-consts.py
> + $(sysdeps-linux-python) \
> + ../sysdeps/unix/sysv/linux/tst-limits-consts.py \
> + $(sysdeps-linux-python-cc) \
> + < /dev/null > $@ 2>&1; $(evaluate-test)
> +$(objpfx)tst-limits-consts.out: $(sysdeps-linux-python-deps)
> +
> tests-special += \
> $(objpfx)tst-mount-compile.out \
> # tests-special
> diff --git a/sysdeps/unix/sysv/linux/bits/stdlib_lim.h b/sysdeps/unix/sysv/linux/bits/stdlib_lim.h
> new file mode 100644
> index 0000000000..935c9836d8
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/stdlib_lim.h
> @@ -0,0 +1,26 @@
> +/* Implementation limits related to stdlib.h - Linux version.
> + Copyright (C) 2023 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
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifndef _BITS_STDLIB_LIM_H
> +#define _BITS_STDLIB_LIM_H
> +
> +/* Same as PATH_MAX, but defined in the implementation namespace so it can
> + be used in places where including limits.h is not possible. */
> +#define __PATH_MAX 4096
> +
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/tst-limits-consts.py b/sysdeps/unix/sysv/linux/tst-limits-consts.py
> new file mode 100755
> index 0000000000..6abbc6e379
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/tst-limits-consts.py
> @@ -0,0 +1,54 @@
> +#!/usr/bin/python3
> +# Test that glibc's limits.h constants match the kernel's.
> +# Copyright (C) 2022-2023 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
> +# <https://www.gnu.org/licenses/>.
> +
> +import argparse
> +import sys
> +
> +import glibcextract
> +import glibcsyscalls
> +
> +
> +def main():
> + """The main entry point."""
> + parser = argparse.ArgumentParser(
> + description="Test that glibc's limits.h constants "
> + "match the kernel's.")
> + parser.add_argument('--cc', metavar='CC',
> + help='C compiler (including options) to use')
> + args = parser.parse_args()
> +
> + def check_single(kcte, cte):
> + macros_1 = glibcextract.compute_macro_consts(
> + '#include <linux/limits.h>\n',
> + args.cc,
> + kcte)
> + macros_2 = glibcextract.compute_macro_consts(
> + '#include <bits/stdlib_lim.h>\n',
> + args.cc,
> + cte)
> + ret = 1
> + for (k1, v1), (k2, v2) in zip(macros_1.items(), macros_2.items()):
> + if v1 == v2:
> + ret = 0
> + return ret
> +
> + sys.exit(check_single('PATH_MAX', '__PATH_MAX'))
> +
> +if __name__ == '__main__':
> + main()
new file mode 100644
@@ -0,0 +1,26 @@
+/* Implementation limits related to stdlib.h - generic version.
+ Copyright (C) 2023 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
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _BITS_STDLIB_LIM_H
+#define _BITS_STDLIB_LIM_H 1
+
+/* Same as PATH_MAX, but defined in the implementation namespace so it can
+ be used in places where including limits.h is not possible. */
+#undef __PATH_MAX
+
+#endif
@@ -33,6 +33,7 @@ headers := \
bits/stdlib-float.h \
bits/stdlib-ldbl.h \
bits/stdlib.h \
+ bits/stdlib_lim.h \
bits/time64.h \
bits/timesize.h \
bits/types/error_t.h \
@@ -20,6 +20,8 @@
# error "Never include <bits/stdlib.h> directly; use <stdlib.h> instead."
#endif
+#include <bits/stdlib_lim.h>
+
extern char *__realpath_chk (const char *__restrict __name,
char *__restrict __resolved,
size_t __resolvedlen) __THROW __wur;
@@ -41,8 +43,8 @@ __NTH (realpath (const char *__restrict __name, char *__restrict __resolved))
if (sz == (size_t) -1)
return __realpath_alias (__name, __resolved);
-#if defined _LIBC_LIMITS_H_ && defined PATH_MAX
- if (__glibc_unsafe_len (PATH_MAX, sizeof (char), sz))
+#ifdef __PATH_MAX
+ if (__glibc_unsafe_len (__PATH_MAX, sizeof (char), sz))
return __realpath_chk_warn (__name, __resolved, sz);
#endif
return __realpath_chk (__name, __resolved, sz);
@@ -376,6 +376,16 @@ $(objpfx)tst-mount-consts.out: ../sysdeps/unix/sysv/linux/tst-mount-consts.py
< /dev/null > $@ 2>&1; $(evaluate-test)
$(objpfx)tst-mount-consts.out: $(sysdeps-linux-python-deps)
+tests-special += \
+ $(objpfx)tst-limits-consts.out \
+ # tests-special
+$(objpfx)tst-limits-consts.out: ../sysdeps/unix/sysv/linux/tst-limits-consts.py
+ $(sysdeps-linux-python) \
+ ../sysdeps/unix/sysv/linux/tst-limits-consts.py \
+ $(sysdeps-linux-python-cc) \
+ < /dev/null > $@ 2>&1; $(evaluate-test)
+$(objpfx)tst-limits-consts.out: $(sysdeps-linux-python-deps)
+
tests-special += \
$(objpfx)tst-mount-compile.out \
# tests-special
new file mode 100644
@@ -0,0 +1,26 @@
+/* Implementation limits related to stdlib.h - Linux version.
+ Copyright (C) 2023 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
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _BITS_STDLIB_LIM_H
+#define _BITS_STDLIB_LIM_H
+
+/* Same as PATH_MAX, but defined in the implementation namespace so it can
+ be used in places where including limits.h is not possible. */
+#define __PATH_MAX 4096
+
+#endif
new file mode 100755
@@ -0,0 +1,54 @@
+#!/usr/bin/python3
+# Test that glibc's limits.h constants match the kernel's.
+# Copyright (C) 2022-2023 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
+# <https://www.gnu.org/licenses/>.
+
+import argparse
+import sys
+
+import glibcextract
+import glibcsyscalls
+
+
+def main():
+ """The main entry point."""
+ parser = argparse.ArgumentParser(
+ description="Test that glibc's limits.h constants "
+ "match the kernel's.")
+ parser.add_argument('--cc', metavar='CC',
+ help='C compiler (including options) to use')
+ args = parser.parse_args()
+
+ def check_single(kcte, cte):
+ macros_1 = glibcextract.compute_macro_consts(
+ '#include <linux/limits.h>\n',
+ args.cc,
+ kcte)
+ macros_2 = glibcextract.compute_macro_consts(
+ '#include <bits/stdlib_lim.h>\n',
+ args.cc,
+ cte)
+ ret = 1
+ for (k1, v1), (k2, v2) in zip(macros_1.items(), macros_2.items()):
+ if v1 == v2:
+ ret = 0
+ return ret
+
+ sys.exit(check_single('PATH_MAX', '__PATH_MAX'))
+
+if __name__ == '__main__':
+ main()