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()
