diff --git a/NEWS b/NEWS index ef8ac4acd2..e4fbd9639b 100644 --- a/NEWS +++ b/NEWS @@ -22,6 +22,11 @@ Deprecated and removed features, and other changes affecting compatibility: removal of the LD_TRACE_PRELINKING, and LD_USE_LOAD_BIAS, environment variables and their functionality in the dynamic loader. +* The Linux kernel version check has been removed along with the + LD_ASSUME_KERNEL environment variable. The minimum kernel used to built + glibc is still provided through NT_GNU_ABI_TAG ELF note and also printed + when libc.so is issued directly. + Changes to build and runtime requirements: [Add changes to build and runtime requirements here] diff --git a/config.h.in b/config.h.in index dd650ddd09..bf316439a0 100644 --- a/config.h.in +++ b/config.h.in @@ -135,6 +135,9 @@ /* Linux specific: minimum supported kernel version. */ #undef __LINUX_KERNEL_VERSION +/* Linux specific: __LINUX_KERNEL_VERSION as a string. */ +#undef __LINUX_KERNEL_VERSION_STR + /* Override abi-tags ABI version if necessary. */ #undef __ABI_TAG_VERSION diff --git a/csu/libc-start.c b/csu/libc-start.c index b34bb6dbbc..543560f36c 100644 --- a/csu/libc-start.c +++ b/csu/libc-start.c @@ -313,14 +313,6 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), __stack_chk_guard = stack_chk_guard; # endif -# ifdef DL_SYSDEP_OSCHECK - { - /* This needs to run to initiliaze _dl_osversion before TLS - setup might check it. */ - DL_SYSDEP_OSCHECK (__libc_fatal); - } -# endif - /* Initialize libpthread if linked in. */ if (__pthread_initialize_minimal != NULL) __pthread_initialize_minimal (); diff --git a/csu/version.c b/csu/version.c index 0de4df5b3f..8c0ed79c01 100644 --- a/csu/version.c +++ b/csu/version.c @@ -33,6 +33,9 @@ Compiled by GNU CC version "__VERSION__".\n" #ifdef LIBC_ABIS_STRING LIBC_ABIS_STRING #endif +#ifdef __LINUX_KERNEL_VERSION_STR +"Minimum supported kernel: " __LINUX_KERNEL_VERSION_STR "\n" +#endif "For bug reporting instructions, please see:\n\ "REPORT_BUGS_TO".\n"; diff --git a/elf/dl-cache.c b/elf/dl-cache.c index 88bf78ad7c..8bbf110d02 100644 --- a/elf/dl-cache.c +++ b/elf/dl-cache.c @@ -297,9 +297,6 @@ search_cache (const char *string_table, uint32_t string_table_size, if ((libnew->hwcap & hwcap_exclude) && !named_hwcap) continue; - if (GLRO (dl_osversion) - && libnew->osversion > GLRO (dl_osversion)) - continue; if (_DL_PLATFORMS_COUNT && (libnew->hwcap & _DL_HWCAP_PLATFORM) != 0 && ((libnew->hwcap & _DL_HWCAP_PLATFORM) diff --git a/elf/dl-diagnostics.c b/elf/dl-diagnostics.c index d29bdd6904..dd3871b1e0 100644 --- a/elf/dl-diagnostics.c +++ b/elf/dl-diagnostics.c @@ -231,10 +231,6 @@ print_version (void) void _dl_print_diagnostics (char **environ) { -#ifdef HAVE_DL_DISCOVER_OSVERSION - _dl_diagnostics_print_labeled_value - ("dl_discover_osversion", _dl_discover_osversion ()); -#endif _dl_diagnostics_print_labeled_string ("dl_dst_lib", DL_DST_LIB); _dl_diagnostics_print_labeled_value ("dl_hwcap", GLRO (dl_hwcap)); _dl_diagnostics_print_labeled_value ("dl_hwcap_important", HWCAP_IMPORTANT); @@ -243,7 +239,6 @@ _dl_print_diagnostics (char **environ) ("dl_hwcaps_subdirs", _dl_hwcaps_subdirs); _dl_diagnostics_print_labeled_value ("dl_hwcaps_subdirs_active", _dl_hwcaps_subdirs_active ()); - _dl_diagnostics_print_labeled_value ("dl_osversion", GLRO (dl_osversion)); _dl_diagnostics_print_labeled_value ("dl_pagesize", GLRO (dl_pagesize)); _dl_diagnostics_print_labeled_string ("dl_platform", GLRO (dl_platform)); _dl_diagnostics_print_labeled_string diff --git a/elf/dl-load.c b/elf/dl-load.c index 2fdd612997..2e4a010fc5 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -1591,13 +1591,6 @@ open_verify (const char *name, int fd, [EI_OSABI] = ELFOSABI_SYSV, [EI_ABIVERSION] = 0 }; - static const struct - { - ElfW(Word) vendorlen; - ElfW(Word) datalen; - ElfW(Word) type; - char vendor[4]; - } expected_note = { 4, 16, 1, "GNU" }; /* Initialize it to make the compiler happy. */ const char *errstring = NULL; int errval = 0; @@ -1628,10 +1621,7 @@ open_verify (const char *name, int fd, if (fd != -1) { ElfW(Ehdr) *ehdr; - ElfW(Phdr) *phdr, *ph; - ElfW(Word) *abi_note; - ElfW(Word) *abi_note_malloced = NULL; - unsigned int osversion; + ElfW(Phdr) *phdr; size_t maplength; /* We successfully opened the file. Now verify it is a file @@ -1695,13 +1685,16 @@ open_verify (const char *name, int fd, #endif ) errstring = N_("invalid ELF header"); + else if (ehdr->e_ident[EI_CLASS] != ELFW(CLASS)) { /* This is not a fatal error. On architectures where 32-bit and 64-bit binaries can be run this might happen. */ *found_other_class = true; - goto close_and_out; + __close_nocancel (fd); + __set_errno (ENOENT); + return -1; } else if (ehdr->e_ident[EI_DATA] != byteorder) { @@ -1736,7 +1729,11 @@ open_verify (const char *name, int fd, goto lose; } if (! __glibc_likely (elf_machine_matches_host (ehdr))) - goto close_and_out; + { + __close_nocancel (fd); + __set_errno (ENOENT); + return -1; + } else if (__glibc_unlikely (ehdr->e_type != ET_DYN && ehdr->e_type != ET_EXEC)) { @@ -1758,7 +1755,6 @@ open_verify (const char *name, int fd, if ((size_t) __pread64_nocancel (fd, (void *) phdr, maplength, ehdr->e_phoff) != maplength) { - read_error: errval = errno; errstring = N_("cannot read file data"); goto lose; @@ -1768,73 +1764,12 @@ open_verify (const char *name, int fd, if (__glibc_unlikely (elf_machine_reject_phdr_p (phdr, ehdr->e_phnum, fbp->buf, fbp->len, loader, fd))) - goto close_and_out; + { + __close_nocancel (fd); + __set_errno (ENOENT); + return -1; + } - /* Check .note.ABI-tag if present. */ - for (ph = phdr; ph < &phdr[ehdr->e_phnum]; ++ph) - if (ph->p_type == PT_NOTE && ph->p_filesz >= 32 - && (ph->p_align == 4 || ph->p_align == 8)) - { - ElfW(Addr) size = ph->p_filesz; - - if (ph->p_offset + size <= (size_t) fbp->len) - abi_note = (void *) (fbp->buf + ph->p_offset); - else - { - /* Note: __libc_use_alloca is not usable here, because - thread info may not have been set up yet. */ - if (size < __MAX_ALLOCA_CUTOFF) - abi_note = alloca (size); - else - { - /* There could be multiple PT_NOTEs. */ - abi_note_malloced = realloc (abi_note_malloced, size); - if (abi_note_malloced == NULL) - goto read_error; - - abi_note = abi_note_malloced; - } - if (__pread64_nocancel (fd, (void *) abi_note, size, - ph->p_offset) != size) - { - free (abi_note_malloced); - goto read_error; - } - } - - while (memcmp (abi_note, &expected_note, sizeof (expected_note))) - { - ElfW(Addr) note_size - = ELF_NOTE_NEXT_OFFSET (abi_note[0], abi_note[1], - ph->p_align); - - if (size - 32 < note_size) - { - size = 0; - break; - } - size -= note_size; - abi_note = (void *) abi_note + note_size; - } - - if (size == 0) - continue; - - osversion = (abi_note[5] & 0xff) * 65536 - + (abi_note[6] & 0xff) * 256 - + (abi_note[7] & 0xff); - if (abi_note[4] != __ABI_TAG_OS - || (GLRO(dl_osversion) && GLRO(dl_osversion) < osversion)) - { - close_and_out: - __close_nocancel (fd); - __set_errno (ENOENT); - fd = -1; - } - - break; - } - free (abi_note_malloced); } return fd; diff --git a/elf/dl-support.c b/elf/dl-support.c index 153dd57ad2..1e82e8c554 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -145,8 +145,6 @@ size_t _dl_minsigstacksize = CONSTANT_MINSIGSTKSZ; int _dl_inhibit_cache; -unsigned int _dl_osversion; - /* All known directories in sorted order. */ struct r_search_path_elem *_dl_all_dirs; @@ -327,10 +325,6 @@ _dl_non_dynamic_init (void) DL_PLATFORM_INIT; #endif -#ifdef DL_OSVERSION_INIT - DL_OSVERSION_INIT; -#endif - /* Now determine the length of the platform string. */ if (_dl_platform != NULL) _dl_platformlen = strlen (_dl_platform); diff --git a/elf/rtld.c b/elf/rtld.c index 3b2e05bf4c..a8cf9daef0 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -384,9 +384,6 @@ struct rtld_global_ro _rtld_global_ro attribute_relro = ._dl_error_free = _dl_error_free, ._dl_tls_get_addr_soft = _dl_tls_get_addr_soft, ._dl_libc_freeres = __rtld_libc_freeres, -#ifdef HAVE_DL_DISCOVER_OSVERSION - ._dl_discover_osversion = _dl_discover_osversion -#endif }; /* If we would use strong_alias here the compiler would see a non-hidden definition. This would undo the effect of the previous @@ -1710,10 +1707,6 @@ dl_main (const ElfW(Phdr) *phdr, /* With vDSO setup we can initialize the function pointers. */ setup_vdso_pointers (); -#ifdef DL_SYSDEP_OSCHECK - DL_SYSDEP_OSCHECK (_dl_fatal_printf); -#endif - /* Initialize the data structures for the search paths for shared objects. */ call_init_paths (&state); @@ -2638,14 +2631,6 @@ process_envvars (struct dl_main_state *state) GLRO(dl_dynamic_weak) = 1; break; - case 13: - /* We might have some extra environment variable with length 13 - to handle. */ -#ifdef EXTRA_LD_ENVVARS_13 - EXTRA_LD_ENVVARS_13 -#endif - break; - case 14: /* Where to place the profiling data file. */ if (!__libc_enable_secure diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 5d0369358d..9ae450414e 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -552,8 +552,6 @@ struct rtld_global_ro /* These two are used only internally. */ #define DL_DEBUG_HELP (1 << 10) - /* OS version. */ - EXTERN unsigned int _dl_osversion; /* Platform name. */ EXTERN const char *_dl_platform; EXTERN size_t _dl_platformlen; @@ -701,10 +699,6 @@ struct rtld_global_ro dlopen. */ int (*_dl_find_object) (void *, struct dl_find_object *); -#ifdef HAVE_DL_DISCOVER_OSVERSION - int (*_dl_discover_osversion) (void); -#endif - /* Dynamic linker operations used after static dlopen. */ const struct dlfcn_hook *_dl_dlfcn_hook; diff --git a/sysdeps/unix/sysv/linux/configure b/sysdeps/unix/sysv/linux/configure index 4ff02c9b6d..312055c469 100644 --- a/sysdeps/unix/sysv/linux/configure +++ b/sysdeps/unix/sysv/linux/configure @@ -70,6 +70,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for kernel header at least $minimum_kernel" >&5 $as_echo_n "checking for kernel header at least $minimum_kernel... " >&6; } decnum=`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/(\1 * 65536 + \2 * 256 + \3)/'`; +abinumstr=`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1.\2.\3/'`; abinum=`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1,\2,\3/'`; cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -96,6 +97,10 @@ $as_echo "$libc_minimum_kernel" >&6; } if test "$libc_minimum_kernel" = ok; then cat >>confdefs.h <<_ACEOF #define __LINUX_KERNEL_VERSION $decnum +_ACEOF + + cat >>confdefs.h <<_ACEOF +#define __LINUX_KERNEL_VERSION_STR "$abinumstr" _ACEOF cat >>confdefs.h <<_ACEOF diff --git a/sysdeps/unix/sysv/linux/configure.ac b/sysdeps/unix/sysv/linux/configure.ac index 197b7e66c8..5896d1135b 100644 --- a/sysdeps/unix/sysv/linux/configure.ac +++ b/sysdeps/unix/sysv/linux/configure.ac @@ -50,6 +50,7 @@ fi AC_MSG_CHECKING(for kernel header at least $minimum_kernel) changequote(,)dnl decnum=`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/(\1 * 65536 + \2 * 256 + \3)/'`; +abinumstr=`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1.\2.\3/'`; abinum=`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1,\2,\3/'`; changequote([,])dnl AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[#include @@ -59,6 +60,7 @@ AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[#include AC_MSG_RESULT($libc_minimum_kernel) if test "$libc_minimum_kernel" = ok; then AC_DEFINE_UNQUOTED(__LINUX_KERNEL_VERSION, $decnum) + AC_DEFINE_UNQUOTED(__LINUX_KERNEL_VERSION_STR, "$abinumstr") AC_DEFINE_UNQUOTED(__ABI_TAG_VERSION, $abinum) else AC_MSG_ERROR([*** The available kernel headers are older than the requested diff --git a/sysdeps/unix/sysv/linux/dl-librecon.h b/sysdeps/unix/sysv/linux/dl-librecon.h deleted file mode 100644 index dfebcea4d8..0000000000 --- a/sysdeps/unix/sysv/linux/dl-librecon.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Optional code to distinguish library flavours. - Copyright (C) 2001-2022 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 - . */ - -#ifndef _DL_LIBRECON_H -#define _DL_LIBRECON_H 1 - -static inline void __attribute__ ((unused, always_inline)) -_dl_osversion_init (char *assume_kernel) -{ - unsigned long int i, j, osversion = 0; - char *p = assume_kernel, *q; - - for (i = 0; i < 3; i++, p = q + 1) - { - j = _dl_strtoul (p, &q); - if (j >= 255 || p == q || (i < 2 && *q && *q != '.')) - { - osversion = 0; - break; - } - osversion |= j << (16 - 8 * i); - if (!*q) - break; - } - if (osversion) - GLRO(dl_osversion) = osversion; -} - -/* Recognizing extra environment variables. */ -#define EXTRA_LD_ENVVARS_13 \ - if (memcmp (envline, "ASSUME_KERNEL", 13) == 0) \ - { \ - _dl_osversion_init (&envline[14]); \ - break; \ - } - -#define DL_OSVERSION_INIT \ - do { \ - char *assume_kernel = getenv ("LD_ASSUME_KERNEL"); \ - if (assume_kernel) \ - _dl_osversion_init (assume_kernel); \ - } while (0) - -#endif /* dl-librecon.h */ diff --git a/sysdeps/unix/sysv/linux/dl-osinfo.h b/sysdeps/unix/sysv/linux/dl-osinfo.h index 349d93e8ed..7888915f12 100644 --- a/sysdeps/unix/sysv/linux/dl-osinfo.h +++ b/sysdeps/unix/sysv/linux/dl-osinfo.h @@ -22,31 +22,6 @@ #include #include -#ifndef MIN -# define MIN(a,b) (((a)<(b))?(a):(b)) -#endif - -#define DL_SYSDEP_OSCHECK(FATAL) \ - do { \ - /* Test whether the kernel is new enough. This test is only performed \ - if the library is not compiled to run on all kernels. */ \ - \ - int version = _dl_discover_osversion (); \ - if (__glibc_likely (version >= 0)) \ - { \ - if (__builtin_expect (GLRO(dl_osversion) == 0, 1) \ - || GLRO(dl_osversion) > version) \ - GLRO(dl_osversion) = version; \ - \ - /* Now we can test with the required version. */ \ - if (__LINUX_KERNEL_VERSION > 0 && version < __LINUX_KERNEL_VERSION) \ - /* Not sufficent. */ \ - FATAL ("FATAL: kernel too old\n"); \ - } \ - else if (__LINUX_KERNEL_VERSION > 0) \ - FATAL ("FATAL: cannot determine kernel version\n"); \ - } while (0) - static inline uintptr_t __attribute__ ((always_inline)) _dl_setup_stack_chk_guard (void *dl_random) { diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.c b/sysdeps/unix/sysv/linux/dl-sysdep.c index a67c454673..9e15c5bf69 100644 --- a/sysdeps/unix/sysv/linux/dl-sysdep.c +++ b/sysdeps/unix/sysv/linux/dl-sysdep.c @@ -250,96 +250,3 @@ _dl_show_auxv (void) } #endif /* SHARED */ - - -int -attribute_hidden -_dl_discover_osversion (void) -{ -#ifdef SHARED - if (GLRO(dl_sysinfo_map) != NULL) - { - /* If the kernel-supplied DSO contains a note indicating the kernel's - version, we don't need to call uname or parse any strings. */ - - static const struct - { - ElfW(Nhdr) hdr; - char vendor[8]; - } expected_note = { { sizeof "Linux", sizeof (ElfW(Word)), 0 }, "Linux" }; - const ElfW(Phdr) *const phdr = GLRO(dl_sysinfo_map)->l_phdr; - const ElfW(Word) phnum = GLRO(dl_sysinfo_map)->l_phnum; - for (unsigned int i = 0; i < phnum; ++i) - if (phdr[i].p_type == PT_NOTE) - { - const ElfW(Addr) start = (phdr[i].p_vaddr - + GLRO(dl_sysinfo_map)->l_addr); - const ElfW(Nhdr) *note = (const void *) start; - while ((ElfW(Addr)) (note + 1) - start < phdr[i].p_memsz) - { - if (!memcmp (note, &expected_note, sizeof expected_note)) - return *(const ElfW(Word) *) ((const void *) note - + sizeof expected_note); -#define ROUND(len) (((len) + sizeof note->n_type - 1) & -sizeof note->n_type) - note = ((const void *) (note + 1) - + ROUND (note->n_namesz) + ROUND (note->n_descsz)); -#undef ROUND - } - } - } -#endif /* SHARED */ - - char bufmem[64]; - char *buf = bufmem; - unsigned int version; - int parts; - char *cp; - struct utsname uts; - - /* Try the uname system call. */ - if (__uname (&uts)) - { - /* This was not successful. Now try reading the /proc filesystem. */ - int fd = __open64_nocancel ("/proc/sys/kernel/osrelease", O_RDONLY); - if (fd < 0) - return -1; - ssize_t reslen = __read_nocancel (fd, bufmem, sizeof (bufmem)); - __close_nocancel (fd); - if (reslen <= 0) - /* This also didn't work. We give up since we cannot - make sure the library can actually work. */ - return -1; - buf[MIN (reslen, (ssize_t) sizeof (bufmem) - 1)] = '\0'; - } - else - buf = uts.release; - - /* Now convert it into a number. The string consists of at most - three parts. */ - version = 0; - parts = 0; - cp = buf; - while ((*cp >= '0') && (*cp <= '9')) - { - unsigned int here = *cp++ - '0'; - - while ((*cp >= '0') && (*cp <= '9')) - { - here *= 10; - here += *cp++ - '0'; - } - - ++parts; - version <<= 8; - version |= here; - - if (*cp++ != '.' || parts == 3) - /* Another part following? */ - break; - } - - if (parts < 3) - version <<= 8 * (3 - parts); - - return version; -} diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.h b/sysdeps/unix/sysv/linux/dl-sysdep.h index cb8bf7e6b1..b3ae5cb637 100644 --- a/sysdeps/unix/sysv/linux/dl-sysdep.h +++ b/sysdeps/unix/sysv/linux/dl-sysdep.h @@ -24,10 +24,3 @@ we aren't making direct use of it. So enable this across the board. */ #define NEED_DL_SYSINFO_DSO 1 - - -#ifndef __ASSEMBLER__ -/* Get version of the OS. */ -extern int _dl_discover_osversion (void) attribute_hidden; -# define HAVE_DL_DISCOVER_OSVERSION 1 -#endif diff --git a/sysdeps/unix/sysv/linux/i386/dl-librecon.h b/sysdeps/unix/sysv/linux/i386/dl-librecon.h index 7882679f20..78e3f0d02d 100644 --- a/sysdeps/unix/sysv/linux/i386/dl-librecon.h +++ b/sysdeps/unix/sysv/linux/i386/dl-librecon.h @@ -18,8 +18,6 @@ #ifndef _DL_LIBRECON_H -#include - #define DISTINGUISH_LIB_VERSIONS \ do \ { \