diff options
Diffstat (limited to 'debian/patches/git-updates.diff')
-rw-r--r-- | debian/patches/git-updates.diff | 3681 |
1 files changed, 1 insertions, 3680 deletions
diff --git a/debian/patches/git-updates.diff b/debian/patches/git-updates.diff index 6b663310..f9395175 100644 --- a/debian/patches/git-updates.diff +++ b/debian/patches/git-updates.diff @@ -1,3681 +1,2 @@ -GIT update of https://sourceware.org/git/glibc.git/release/2.30/master from glibc-2.30 +GIT update of https://sourceware.org/git/glibc.git/release/2.31/master from glibc-2.31 -diff --git a/ChangeLog b/ChangeLog -index cdb9e14881..bc2f4aae69 100644 ---- a/ChangeLog -+++ b/ChangeLog -@@ -1,3 +1,214 @@ -+2019-08-15 Florian Weimer <fweimer@redhat.com> -+ -+ [BZ #24899] -+ * sysdeps/gnu/bits/utmpx.h (struct utmpx): Add -+ __attribute_nonstring__ to ut_line, ut_id, ut_user, ut_host. -+ * sysdeps/unix/sysv/linux/s390/bits/utmpx.h (struct utmpx): -+ Likewise. -+ * sysdeps/gnu/bits/utmp.h (struct utmp): Add -+ __attribute_nonstring__ to ut_id. -+ * sysdeps/unix/sysv/linux/s390/bits/utmpx.h (struct utmp): -+ Likewise. -+ -+2019-08-28 Florian Weimer <fweimer@redhat.com> -+ -+ [BZ #24902] -+ * login/Makefile (tests): Add tst-pututxline-lockfail. -+ (tst-pututxline-lockfail): Link with -lpthread. -+ * login/utmp_file.c (internal_getut_r): Remove buffer argument. -+ (__libc_getutid_r): Adjust. -+ (__libc_pututline): Likewise. Check for file_offset == -1. -+ * login/tst-pututxline-lockfail.c: New file. -+ -+2019-08-15 Florian Weimer <fweimer@redhat.com> -+ -+ [BZ #24880] -+ * login/utmp_file.c (file_locking_failed): Use struct flock64. -+ (file_locking_unlock): Likewise. -+ -+2019-08-15 Florian Weimer <fweimer@redhat.com> -+ -+ [BZ #24879] -+ login: Disarm timer after utmp lock acquisition. -+ * login/utmp_file.c (struct file_locking): Remove. -+ (try_file_lock): Adjust. -+ (file_lock_restore): Remove function. -+ (__libc_getutent_r): . -+ (internal_getut_r): Likewise. -+ (__libc_getutline_r): Likewise. -+ (__libc_pututline): Likewise. -+ (__libc_updwtmp): Likewise. -+ -+2019-08-15 Florian Weimer <fweimer@redhat.com> -+ -+ * login/utmp_file.c (__libc_updwtmp): Unlock the right file -+ descriptor. -+ * login/Makefile (tests): Add tst-updwtmpx. -+ * login/tst-updwtmpx.c: New file. -+ -+2019-08-13 Florian Weimer <fweimer@redhat.com> -+ -+ * login/utmp_file.c (LOCK_FILE, LOCKING_FAILED, UNLOCK_FILE): -+ Remove macros. -+ (struct file_locking): New. -+ (try_file_lock, file_unlock, file_lock_restore): New functions. -+ (__libc_getutent_r): Use the new functions. -+ (internal_getut_r): Likewise. -+ (__libc_getutline_r): Likewise. -+ (__libc_pututline): Likewise. -+ (__libc_updwtmp): Likewise. -+ -+2019-08-13 Florian Weimer <fweimer@redhat.com> -+ -+ * login/getutid_r.c (__getutid_r): _HAVE_UT_ID and _HAVE_UT_TYPE -+ are always true. -+ * login/getutmp.c (getutmp): _HAVE_UT_TYPE, _HAVE_UT_PID, -+ _HAVE_UT_ID, _HAVE_UT_HOST, _HAVE_UT_TV are always true. -+ * login/getutmpx.c (getutmpx): Likewise. -+ * login/login.c (login): _HAVE_UT_TYPE, _HAVE_UT_PID are always -+ true. -+ * login/logout.c (logout): _HAVE_UT_TYPE, _HAVE_UT_HOST, -+ _HAVE_UT_TV are always true. -+ * login/logwtmp.c (logwtmp): _HAVE_UT_PID, _HAVE_UT_TYPE, -+ _HAVE_UT_HOST, _HAVE_UT_TV are always true. -+ * login/tst-utmp.c: _HAVE_UT_TYPE, _HAVE_UT_TV are always true. -+ * login/utmp_file.c (__libc_setutent): _HAVE_UT_TYPE, _HAVE_UT_ID -+ are always true. -+ (internal_getut_r): _HAVE_UT_TYPE is always true. -+ (__libc_pututline): Likewise. -+ * login/programs/utmpdump.c (print_entry): Assume that -+ _HAVE_UT_TYPE, _HAVE_UT_PID, _HAVE_UT_ID, _HAVE_UT_HOST, -+ _HAVE_UT_TV are always true. -+ * sysdeps/generic/utmp-equal.h (__utmp_equal): _HAVE_UT_TYPE, -+ _HAVE_UT_ID are always true. -+ * sysdeps/gnu/bits/utmp.h: Move to ... -+ * bits/utmp.h: ... here, replacing the old file. -+ -+2019-08-05 Florian Weimer <fweimer@redhat.com> -+ -+ [BZ #23518] -+ * login/uptmp-private.h (struct ufuncs): Remove definition. -+ (__libc_utmp_file_functions, __libc_utmp_unknown_functions) -+ (__libc_utmp_jump_table): Remove declarations. -+ (__libc_setutent, __libc_getutent_r, __libc_getutid_r) -+ (__libc_getutline_r, __libc_pututline, __libc_endutent) -+ (__libc_updwtmp): Declare. -+ * login/getutent_r.c (__libc_utmp_unknown_functions) -+ (__libc_utmp_jump_table, setutent_unknown, getutent_r_unknown) -+ (getutid_r_unknown, getutline_r_unknown, pututline_unknown) -+ (endutent_unknown): Remove definitions. -+ (__setutent): Call __libc_setutent. -+ (__getutent_r): Call __libc_getutent_r. -+ (__pututline): Call __libc_pututline. -+ (__endutent): Call __libc_endutent. -+ * login/getutid_r.c (__getutid_r): Call __libc_getutid_r. -+ * login/getutline_r.c (__getutline_r): Call __libc_getutline_r. -+ * login/updwtmp.c (__updwtmp): Call __libc_updwtmp. -+ * login/utmp_file.c (__libc_utmp_file_functions): Remove definition -+ (__libc_setutent): Rename from stetutent_file. Drop static. -+ (maybe_setutent): New function. -+ (__libc_getutent_r): Rename from getutent_r_file. Drop static. -+ Check for initialization. -+ (__libc_getutid_r): Rename from getutid_r_file. Drop static. -+ Check for initialization. -+ (__libc_getutline_r): Rename from getutline_r_file. Drop static. -+ Check for initialization. -+ (__libc_pututline): Rename from pututline_file. Drop static. -+ Check for initialization. -+ (__libc_endutent): Rename from endutent_file. Drop static. Check -+ for initialization. -+ (__libc_updwtmp): Rename from updwtmp_file. Drop static. -+ * login/utmpname.c (__utmpname): Call __libc_endutent. -+ * sysdeps/unix/getlogin_r (__getlogin_r): Call __libc_setutent, -+ __libc_getutlien_r, __libc_endutent. -+ * manual/users.texi (Who Logged In, Manipulating the Database): -+ Adjust. -+ -+2019-08-15 Florian Weimer <fweimer@redhat.com> -+ -+ * malloc/Makefile (tests): Only add tst-mxfast for -+ $(have-tunables). -+ * malloc/tst-mxfast.c: Fix copyright year. -+ (do_test): Fix GNU style issues. Use TEST_COMPARE instead of -+ assert for checks. -+ -+2019-08-09 DJ Delorie <dj@redhat.com> -+ -+ * elf/dl-tunables.list: Add glibc.malloc.mxfast. -+ * manual/tunables.texi: Document it. -+ * malloc/malloc.c (do_set_mxfast): New. -+ (__libc_mallopt): Call it. -+ * malloc/arena.c: Add mxfast tunable. -+ * malloc/tst-mxfast.c: New. -+ * malloc/Makefile: Add it. -+ -+2019-08-08 Niklas Hambüchen <mail@nh2.me> -+ Carlos O'Donell <carlos@redhat.com> -+ -+ [BZ #24026] -+ * malloc/malloc.c (__malloc_info): Account for top chunk. -+ -+2019-11-01 Dragan Mladjenovic <dmladjenovic@wavecomp.com> -+ -+ * sysdeps/unix/sysv/linux/mips/Makefile -+ (test-xfail-check-execstack): -+ Move under mips-has-gnustack != yes. -+ (CFLAGS-.o*, ASFLAGS-.o*): New rules. -+ Apply -Wa,-execstack if mips-force-execstack == yes. -+ * sysdeps/unix/sysv/linux/mips/configure: Regenerated. -+ * sysdeps/unix/sysv/linux/mips/configure.ac -+ (mips-force-execstack): New var. -+ Set to yes for hard-float builds with minimum_kernel < 4.8.0 -+ or minimum_kernel not set at all. -+ (mips-has-gnustack): New var. -+ Use value of libc_cv_as_noexecstack -+ if mips-force-execstack != yes, otherwise set to no. -+ -+2019-10-08 Gabriel F. T. Gomes <gabrielftg@linux.ibm.com> -+ -+ * Makefile: Fix locale dependency for a couple of tests. -+ ($(objpfx)tst-strftime2.out): New rule. -+ ($(objpfx)tst-strftime3.out): Likewise. -+ -+2019-09-20 Joseph Myers <joseph@codesourcery.com> -+ -+ * sysdeps/unix/sysv/linux/riscv/vfork.S: Do not include -+ <linux/sched.h>. -+ (CLONE_VM): New macro. -+ (CLONE_VFORK): Likewise. -+ -+2019-09-14 Aurelien Jarno <aurelien@aurel32.net> -+ -+ [BZ #24986] -+ * sysdeps/unix/alpha/getegid.S: Move to ... -+ * sysdeps/unix/sysv/linux/alpha/getegid.S: ... here. -+ * sysdeps/unix/alpha/geteuid.S: Move to ... -+ * sysdeps/unix/sysv/linux/alpha/geteuid.S: ... here. -+ * sysdeps/unix/alpha/getppid.S: Move to ... -+ * sysdeps/unix/sysv/linux/alpha/getppid.S: ... here -+ -+2019-09-08 Adhemerval Zanella <adhemerval.zanella@linaro.org> -+ -+ * sysdeps/hppa/fpu/libm-test-ulps: Update. -+ -+2019-09-03 Aurelien Jarno <aurelien@aurel32.net> -+ -+ * sysdeps/alpha/fpu/libm-test-ulps: Regenerated using GCC 9.2. -+ -+2019-08-28 Rafal Luzynski <digitalfreak@lingonborough.com> -+ -+ [BZ #24682] -+ * NEWS: Mention this bug fixed. -+ * localedata/locales/bo_CN (first_weekday): Add, set to 2 (Monday). -+ * localedata/locales/ug_CN (first_weekday): Likewise. -+ * localedata/locales/zh_CN (first_weekday): Likewise. -+ -+2019-08-01 Florian Weimer <fweimer@redhat.com> -+ -+ [BZ #24867] -+ * malloc/malloc.c (__malloc_info): Remove unwanted leading -+ whitespace. -+ - 2019-08-01 Carlos O'Donell <carlos@redhat.com> - - * version.h (RELEASE): Set to "stable". -diff --git a/NEWS b/NEWS -index ee9ed4de5a..15df670edc 100644 ---- a/NEWS -+++ b/NEWS -@@ -4,6 +4,38 @@ See the end for copying conditions. - - Please send GNU C library bug reports via <https://sourceware.org/bugzilla/> - using `glibc' in the "product" field. -+ -+Version 2.30.1 -+ -+Security related changes: -+ -+CVE-2019-19126: ld.so failed to ignore the LD_PREFER_MAP_32BIT_EXEC -+ environment variable during program execution after a security -+ transition, allowing local attackers to restrict the possible mapping -+ addresses for loaded libraries and thus bypass ASLR for a setuid -+ program. Reported by Marcin Kościelnicki. -+ -+The following bugs are resolved with this release: -+ -+ [23518] login: Remove utmp backend jump tables -+ [24682] localedata: zh_CN first weekday should be Monday per GB/T -+ 7408-2005 -+ [24867] malloc: Remove unwanted leading whitespace in malloc_info -+ [24879] login: Disarm timer after utmp lock acquisition -+ [24880] login: Use struct flock64 in utmp -+ [24882] login: Acquire write lock early in pututline -+ [24986] alpha: new getegid, geteuid and getppid syscalls used -+ unconditionally -+ [24899] login: Add nonstring attributes to struct utmp, struct utmpx -+ [24902] login: pututxline could fail to overwrite existing entries -+ [25066] FAIL: nptl/tst-tls1 on hppa -+ [25189] Don't use a custom wrapper macro around __has_include -+ [25203] libio: Disable vtable validation for pre-2.1 interposed handles -+ [25204] Ignore LD_PREFER_MAP_32BIT_EXEC for SUID programs -+ [25225] ld.so fails to link on x86 if GCC defaults to -fcf-protection -+ [25232] No const correctness for strchr et al. for Clang++ -+ [25401] Remove incorrect alloc_size attribute from pvalloc -+ - - Version 2.30 - -diff --git a/bits/utmp.h b/bits/utmp.h -index 4c36ca19ce..854b342164 100644 ---- a/bits/utmp.h -+++ b/bits/utmp.h -@@ -1,4 +1,4 @@ --/* The `struct utmp' type, describing entries in the utmp file. Generic/BSDish -+/* The `struct utmp' type, describing entries in the utmp file. - Copyright (C) 1993-2019 Free Software Foundation, Inc. - This file is part of the GNU C Library. - -@@ -21,29 +21,107 @@ - #endif - - #include <paths.h> --#include <time.h> -+#include <sys/time.h> -+#include <sys/types.h> -+#include <bits/wordsize.h> - - --#define UT_NAMESIZE 8 --#define UT_LINESIZE 8 --#define UT_HOSTSIZE 16 -+#define UT_LINESIZE 32 -+#define UT_NAMESIZE 32 -+#define UT_HOSTSIZE 256 - - -+/* The structure describing an entry in the database of -+ previous logins. */ - struct lastlog - { -- time_t ll_time; -+#if __WORDSIZE_TIME64_COMPAT32 -+ int32_t ll_time; -+#else -+ __time_t ll_time; -+#endif - char ll_line[UT_LINESIZE]; - char ll_host[UT_HOSTSIZE]; - }; - --struct utmp -+ -+/* The structure describing the status of a terminated process. This -+ type is used in `struct utmp' below. */ -+struct exit_status - { -- char ut_line[UT_LINESIZE]; -- char ut_user[UT_NAMESIZE]; --#define ut_name ut_user -- char ut_host[UT_HOSTSIZE]; -- long int ut_time; -+ short int e_termination; /* Process termination status. */ -+ short int e_exit; /* Process exit status. */ - }; - - --#define _HAVE_UT_HOST 1 /* We have the ut_host field. */ -+/* The structure describing an entry in the user accounting database. */ -+struct utmp -+{ -+ short int ut_type; /* Type of login. */ -+ pid_t ut_pid; /* Process ID of login process. */ -+ char ut_line[UT_LINESIZE] -+ __attribute_nonstring__; /* Devicename. */ -+ char ut_id[4] -+ __attribute_nonstring__; /* Inittab ID. */ -+ char ut_user[UT_NAMESIZE] -+ __attribute_nonstring__; /* Username. */ -+ char ut_host[UT_HOSTSIZE] -+ __attribute_nonstring__; /* Hostname for remote login. */ -+ struct exit_status ut_exit; /* Exit status of a process marked -+ as DEAD_PROCESS. */ -+/* The ut_session and ut_tv fields must be the same size when compiled -+ 32- and 64-bit. This allows data files and shared memory to be -+ shared between 32- and 64-bit applications. */ -+#if __WORDSIZE_TIME64_COMPAT32 -+ int32_t ut_session; /* Session ID, used for windowing. */ -+ struct -+ { -+ int32_t tv_sec; /* Seconds. */ -+ int32_t tv_usec; /* Microseconds. */ -+ } ut_tv; /* Time entry was made. */ -+#else -+ long int ut_session; /* Session ID, used for windowing. */ -+ struct timeval ut_tv; /* Time entry was made. */ -+#endif -+ -+ int32_t ut_addr_v6[4]; /* Internet address of remote host. */ -+ char __glibc_reserved[20]; /* Reserved for future use. */ -+}; -+ -+/* Backwards compatibility hacks. */ -+#define ut_name ut_user -+#ifndef _NO_UT_TIME -+/* We have a problem here: `ut_time' is also used otherwise. Define -+ _NO_UT_TIME if the compiler complains. */ -+# define ut_time ut_tv.tv_sec -+#endif -+#define ut_xtime ut_tv.tv_sec -+#define ut_addr ut_addr_v6[0] -+ -+ -+/* Values for the `ut_type' field of a `struct utmp'. */ -+#define EMPTY 0 /* No valid user accounting information. */ -+ -+#define RUN_LVL 1 /* The system's runlevel. */ -+#define BOOT_TIME 2 /* Time of system boot. */ -+#define NEW_TIME 3 /* Time after system clock changed. */ -+#define OLD_TIME 4 /* Time when system clock changed. */ -+ -+#define INIT_PROCESS 5 /* Process spawned by the init process. */ -+#define LOGIN_PROCESS 6 /* Session leader of a logged in user. */ -+#define USER_PROCESS 7 /* Normal process. */ -+#define DEAD_PROCESS 8 /* Terminated process. */ -+ -+#define ACCOUNTING 9 -+ -+/* Old Linux name for the EMPTY type. */ -+#define UT_UNKNOWN EMPTY -+ -+ -+/* Tell the user that we have a modern system with UT_HOST, UT_PID, -+ UT_TYPE, UT_ID and UT_TV fields. */ -+#define _HAVE_UT_TYPE 1 -+#define _HAVE_UT_PID 1 -+#define _HAVE_UT_ID 1 -+#define _HAVE_UT_TV 1 -+#define _HAVE_UT_HOST 1 -diff --git a/configure b/configure -index c773c487b5..6d26b8246f 100755 ---- a/configure -+++ b/configure -@@ -3777,11 +3777,32 @@ else - fi - - -+cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+/* end confdefs.h. */ -+ -+int -+main () -+{ -+ -+#ifndef __CET__ -+#error no CET compiler support -+#endif -+ ; -+ return 0; -+} -+_ACEOF -+if ac_fn_c_try_compile "$LINENO"; then : -+ libc_cv_compiler_default_cet=yes -+else -+ libc_cv_compiler_default_cet=no -+fi -+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -+ - # Check whether --enable-cet was given. - if test "${enable_cet+set}" = set; then : - enableval=$enable_cet; enable_cet=$enableval - else -- enable_cet=no -+ enable_cet=$libc_cv_compiler_default_cet - fi - - -diff --git a/configure.ac b/configure.ac -index 598ba6c4ae..7436485419 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -472,11 +472,18 @@ AC_ARG_ENABLE([mathvec], - [build_mathvec=$enableval], - [build_mathvec=notset]) - -+AC_TRY_COMPILE([], [ -+#ifndef __CET__ -+# error no CET compiler support -+#endif], -+ [libc_cv_compiler_default_cet=yes], -+ [libc_cv_compiler_default_cet=no]) -+ - AC_ARG_ENABLE([cet], - AC_HELP_STRING([--enable-cet], - [enable Intel Control-flow Enforcement Technology (CET), x86 only]), - [enable_cet=$enableval], -- [enable_cet=no]) -+ [enable_cet=$libc_cv_compiler_default_cet]) - - # We keep the original values in `$config_*' and never modify them, so we - # can write them unchanged into config.make. Everything else uses -diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list -index 1fc2d8886b..525c3767b5 100644 ---- a/elf/dl-tunables.list -+++ b/elf/dl-tunables.list -@@ -85,6 +85,11 @@ glibc { - tcache_unsorted_limit { - type: SIZE_T - } -+ mxfast { -+ type: SIZE_T -+ minval: 0 -+ security_level: SXID_IGNORE -+ } - } - cpu { - hwcap_mask { -diff --git a/libio/oldstdfiles.c b/libio/oldstdfiles.c -index 2b861cd754..7503cdd62d 100644 ---- a/libio/oldstdfiles.c -+++ b/libio/oldstdfiles.c -@@ -83,6 +83,11 @@ _IO_check_libio (void) - = stderr->_vtable_offset = - ((int) sizeof (struct _IO_FILE) - - (int) sizeof (struct _IO_FILE_complete)); -+ -+ if (_IO_stdin_.vtable != &_IO_old_file_jumps -+ || _IO_stdout_.vtable != &_IO_old_file_jumps -+ || _IO_stderr_.vtable != &_IO_old_file_jumps) -+ IO_set_accept_foreign_vtables (&_IO_vtable_check); - } - } - -diff --git a/localedata/locales/bo_CN b/localedata/locales/bo_CN -index 90cbc7807b..9df91a1721 100644 ---- a/localedata/locales/bo_CN -+++ b/localedata/locales/bo_CN -@@ -128,6 +128,7 @@ t_fmt_ampm "<U0F46><U0F74><U0F0B><U0F5A><U0F7C><U0F51>/ - <U0025><U0070>" - - week 7;19971130;1 -+first_weekday 2 - END LC_TIME - - LC_MESSAGES -diff --git a/localedata/locales/ug_CN b/localedata/locales/ug_CN -index 1ba583c588..83d15c90e4 100644 ---- a/localedata/locales/ug_CN -+++ b/localedata/locales/ug_CN -@@ -165,6 +165,7 @@ am_pm "";"" - date_fmt "%a<U060C> %d-%m-%Y<U060C> %T" - - week 7;19971130;1 -+first_weekday 2 - END LC_TIME - - LC_MESSAGES -diff --git a/localedata/locales/zh_CN b/localedata/locales/zh_CN -index 62a46415c1..cd4b33602a 100644 ---- a/localedata/locales/zh_CN -+++ b/localedata/locales/zh_CN -@@ -139,6 +139,7 @@ t_fmt_ampm "%p %I<U65F6>%M<U5206>%S<U79D2>" - - date_fmt "%Y<U5E74> %m<U6708> %d<U65E5> %A %H:%M:%S %Z" - week 7;19971130;1 -+first_weekday 2 - END LC_TIME - - LC_MESSAGES -diff --git a/login/Makefile b/login/Makefile -index 92535f0aec..4fd8195e73 100644 ---- a/login/Makefile -+++ b/login/Makefile -@@ -43,7 +43,8 @@ endif - subdir-dirs = programs - vpath %.c programs - --tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin -+tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin tst-updwtmpx \ -+ tst-pututxline-lockfail tst-pututxline-cache - - # Build the -lutil library with these extra functions. - extra-libs := libutil -@@ -71,3 +72,6 @@ endif - $(inst_libexecdir)/pt_chown: $(objpfx)pt_chown $(+force) - $(make-target-directory) - -$(INSTALL_PROGRAM) -m 4755 -o root $< $@ -+ -+$(objpfx)tst-pututxline-lockfail: $(shared-thread-library) -+$(objpfx)tst-pututxline-cache: $(shared-thread-library) -diff --git a/login/getutent_r.c b/login/getutent_r.c -index 98ffc5d1c6..fd13be8a1e 100644 ---- a/login/getutent_r.c -+++ b/login/getutent_r.c -@@ -23,115 +23,16 @@ - - #include "utmp-private.h" - -- --/* Functions defined here. */ --static int setutent_unknown (void); --static int getutent_r_unknown (struct utmp *buffer, struct utmp **result); --static int getutid_r_unknown (const struct utmp *line, struct utmp *buffer, -- struct utmp **result); --static int getutline_r_unknown (const struct utmp *id, struct utmp *buffer, -- struct utmp **result); --static struct utmp *pututline_unknown (const struct utmp *data); --static void endutent_unknown (void); -- --/* Initial Jump table. */ --const struct utfuncs __libc_utmp_unknown_functions = --{ -- setutent_unknown, -- getutent_r_unknown, -- getutid_r_unknown, -- getutline_r_unknown, -- pututline_unknown, -- endutent_unknown, -- NULL --}; -- --/* Currently selected backend. */ --const struct utfuncs *__libc_utmp_jump_table = &__libc_utmp_unknown_functions; -- - /* We need to protect the opening of the file. */ - __libc_lock_define_initialized (, __libc_utmp_lock attribute_hidden) - - --static int --setutent_unknown (void) --{ -- int result; -- -- result = (*__libc_utmp_file_functions.setutent) (); -- if (result) -- __libc_utmp_jump_table = &__libc_utmp_file_functions; -- -- return result; --} -- -- --static int --getutent_r_unknown (struct utmp *buffer, struct utmp **result) --{ -- /* The backend was not yet initialized. */ -- if (setutent_unknown ()) -- return (*__libc_utmp_jump_table->getutent_r) (buffer, result); -- -- /* Not available. */ -- *result = NULL; -- return -1; --} -- -- --static int --getutid_r_unknown (const struct utmp *id, struct utmp *buffer, -- struct utmp **result) --{ -- /* The backend was not yet initialized. */ -- if (setutent_unknown ()) -- return (*__libc_utmp_jump_table->getutid_r) (id, buffer, result); -- -- /* Not available. */ -- *result = NULL; -- return -1; --} -- -- --static int --getutline_r_unknown (const struct utmp *line, struct utmp *buffer, -- struct utmp **result) --{ -- /* The backend was not yet initialized. */ -- if (setutent_unknown ()) -- return (*__libc_utmp_jump_table->getutline_r) (line, buffer, result); -- -- /* Not available. */ -- *result = NULL; -- return -1; --} -- -- --static struct utmp * --pututline_unknown (const struct utmp *data) --{ -- /* The backend was not yet initialized. */ -- if (setutent_unknown ()) -- return (*__libc_utmp_jump_table->pututline) (data); -- -- /* Not available. */ -- return NULL; --} -- -- --static void --endutent_unknown (void) --{ -- /* Nothing to do. */ --} -- -- - void - __setutent (void) - { - __libc_lock_lock (__libc_utmp_lock); - -- (*__libc_utmp_jump_table->setutent) (); -+ __libc_setutent (); - - __libc_lock_unlock (__libc_utmp_lock); - } -@@ -145,7 +46,7 @@ __getutent_r (struct utmp *buffer, struct utmp **result) - - __libc_lock_lock (__libc_utmp_lock); - -- retval = (*__libc_utmp_jump_table->getutent_r) (buffer, result); -+ retval = __libc_getutent_r (buffer, result); - - __libc_lock_unlock (__libc_utmp_lock); - -@@ -162,7 +63,7 @@ __pututline (const struct utmp *data) - - __libc_lock_lock (__libc_utmp_lock); - -- buffer = (*__libc_utmp_jump_table->pututline) (data); -+ buffer = __libc_pututline (data); - - __libc_lock_unlock (__libc_utmp_lock); - -@@ -177,8 +78,7 @@ __endutent (void) - { - __libc_lock_lock (__libc_utmp_lock); - -- (*__libc_utmp_jump_table->endutent) (); -- __libc_utmp_jump_table = &__libc_utmp_unknown_functions; -+ __libc_endutent (); - - __libc_lock_unlock (__libc_utmp_lock); - } -diff --git a/login/getutid_r.c b/login/getutid_r.c -index 34ea61d8f4..460d94be0c 100644 ---- a/login/getutid_r.c -+++ b/login/getutid_r.c -@@ -32,7 +32,6 @@ __libc_lock_define (extern, __libc_utmp_lock attribute_hidden) - int - __getutid_r (const struct utmp *id, struct utmp *buffer, struct utmp **result) - { --#if (_HAVE_UT_ID - 0) && (_HAVE_UT_TYPE - 0) - int retval; - - /* Test whether ID has any of the legal types. */ -@@ -49,15 +48,11 @@ __getutid_r (const struct utmp *id, struct utmp *buffer, struct utmp **result) - - __libc_lock_lock (__libc_utmp_lock); - -- retval = (*__libc_utmp_jump_table->getutid_r) (id, buffer, result); -+ retval = __libc_getutid_r (id, buffer, result); - - __libc_lock_unlock (__libc_utmp_lock); - - return retval; --#else /* !_HAVE_UT_ID && !_HAVE_UT_TYPE */ -- __set_errno (ENOSYS); -- return -1; --#endif - } - libc_hidden_def (__getutid_r) - weak_alias (__getutid_r, getutid_r) -diff --git a/login/getutline_r.c b/login/getutline_r.c -index 110b89e438..f03255dbbd 100644 ---- a/login/getutline_r.c -+++ b/login/getutline_r.c -@@ -36,7 +36,7 @@ __getutline_r (const struct utmp *line, struct utmp *buffer, - - __libc_lock_lock (__libc_utmp_lock); - -- retval = (*__libc_utmp_jump_table->getutline_r) (line, buffer, result); -+ retval = __libc_getutline_r (line, buffer, result); - - __libc_lock_unlock (__libc_utmp_lock); - -diff --git a/login/getutmp.c b/login/getutmp.c -index 73bc15d781..4e3be11216 100644 ---- a/login/getutmp.c -+++ b/login/getutmp.c -@@ -23,23 +23,11 @@ - void - getutmp (const struct utmpx *utmpx, struct utmp *utmp) - { --#if _HAVE_UT_TYPE - 0 - utmp->ut_type = utmpx->ut_type; --#endif --#if _HAVE_UT_PID - 0 - utmp->ut_pid = utmpx->ut_pid; --#endif - memcpy (utmp->ut_line, utmpx->ut_line, sizeof (utmp->ut_line)); - memcpy (utmp->ut_user, utmpx->ut_user, sizeof (utmp->ut_user)); --#if _HAVE_UT_ID - 0 - memcpy (utmp->ut_id, utmpx->ut_id, sizeof (utmp->ut_id)); --#endif --#if _HAVE_UT_HOST - 0 - memcpy (utmp->ut_host, utmpx->ut_host, sizeof (utmp->ut_host)); --#endif --#if _HAVE_UT_TV - 0 - utmp->ut_tv = utmpx->ut_tv; --#else -- utmp->ut_time = utmpx->ut_time; --#endif - } -diff --git a/login/getutmpx.c b/login/getutmpx.c -index b181d9bc30..da28d339ab 100644 ---- a/login/getutmpx.c -+++ b/login/getutmpx.c -@@ -24,24 +24,11 @@ void - getutmpx (const struct utmp *utmp, struct utmpx *utmpx) - { - memset (utmpx, 0, sizeof (struct utmpx)); -- --#if _HAVE_UT_TYPE - 0 - utmpx->ut_type = utmp->ut_type; --#endif --#if _HAVE_UT_PID - 0 - utmpx->ut_pid = utmp->ut_pid; --#endif - memcpy (utmpx->ut_line, utmp->ut_line, sizeof (utmp->ut_line)); - memcpy (utmpx->ut_user, utmp->ut_user, sizeof (utmp->ut_user)); --#if _HAVE_UT_ID - 0 - memcpy (utmpx->ut_id, utmp->ut_id, sizeof (utmp->ut_id)); --#endif --#if _HAVE_UT_HOST - 0 - memcpy (utmpx->ut_host, utmp->ut_host, sizeof (utmp->ut_host)); --#endif --#if _HAVE_UT_TV - 0 - utmpx->ut_tv = utmp->ut_tv; --#else -- utmpx->ut_time = utmp->ut_time; --#endif - } -diff --git a/login/login.c b/login/login.c -index 09ef3f75a5..b7d638c692 100644 ---- a/login/login.c -+++ b/login/login.c -@@ -91,12 +91,8 @@ login (const struct utmp *ut) - struct utmp copy = *ut; - - /* Fill in those fields we supply. */ --#if _HAVE_UT_TYPE - 0 - copy.ut_type = USER_PROCESS; --#endif --#if _HAVE_UT_PID - 0 - copy.ut_pid = getpid (); --#endif - - /* Seek tty. */ - found_tty = tty_name (STDIN_FILENO, &tty, sizeof (_tty)); -diff --git a/login/logout.c b/login/logout.c -index 85254d0324..5015c1af0b 100644 ---- a/login/logout.c -+++ b/login/logout.c -@@ -36,9 +36,7 @@ logout (const char *line) - setutent (); - - /* Fill in search information. */ --#if _HAVE_UT_TYPE - 0 - tmp.ut_type = USER_PROCESS; --#endif - strncpy (tmp.ut_line, line, sizeof tmp.ut_line); - - /* Read the record. */ -@@ -46,20 +44,12 @@ logout (const char *line) - { - /* Clear information about who & from where. */ - memset (ut->ut_name, '\0', sizeof ut->ut_name); --#if _HAVE_UT_HOST - 0 - memset (ut->ut_host, '\0', sizeof ut->ut_host); --#endif --#if _HAVE_UT_TV - 0 - struct timeval tv; - __gettimeofday (&tv, NULL); - ut->ut_tv.tv_sec = tv.tv_sec; - ut->ut_tv.tv_usec = tv.tv_usec; --#else -- ut->ut_time = time (NULL); --#endif --#if _HAVE_UT_TYPE - 0 - ut->ut_type = DEAD_PROCESS; --#endif - - if (pututline (ut) != NULL) - result = 1; -diff --git a/login/logwtmp.c b/login/logwtmp.c -index f53187121c..50d14976c7 100644 ---- a/login/logwtmp.c -+++ b/login/logwtmp.c -@@ -30,26 +30,16 @@ logwtmp (const char *line, const char *name, const char *host) - - /* Set information in new entry. */ - memset (&ut, 0, sizeof (ut)); --#if _HAVE_UT_PID - 0 - ut.ut_pid = getpid (); --#endif --#if _HAVE_UT_TYPE - 0 - ut.ut_type = name[0] ? USER_PROCESS : DEAD_PROCESS; --#endif - strncpy (ut.ut_line, line, sizeof ut.ut_line); - strncpy (ut.ut_name, name, sizeof ut.ut_name); --#if _HAVE_UT_HOST - 0 - strncpy (ut.ut_host, host, sizeof ut.ut_host); --#endif - --#if _HAVE_UT_TV - 0 - struct timeval tv; - __gettimeofday (&tv, NULL); - ut.ut_tv.tv_sec = tv.tv_sec; - ut.ut_tv.tv_usec = tv.tv_usec; --#else -- ut.ut_time = time (NULL); --#endif - - updwtmp (_PATH_WTMP, &ut); - } -diff --git a/login/programs/utmpdump.c b/login/programs/utmpdump.c -index 4c312f0939..85d8e31b43 100644 ---- a/login/programs/utmpdump.c -+++ b/login/programs/utmpdump.c -@@ -37,47 +37,11 @@ print_entry (struct utmp *up) - temp_tv.tv_sec = up->ut_tv.tv_sec; - temp_tv.tv_usec = up->ut_tv.tv_usec; - -- (printf) ( -- /* The format string. */ --#if _HAVE_UT_TYPE -- "[%d] " --#endif --#if _HAVE_UT_PID -- "[%05d] " --#endif --#if _HAVE_UT_ID -- "[%-4.4s] " --#endif -- "[%-8.8s] [%-12.12s]" --#if _HAVE_UT_HOST -- " [%-16.16s]" --#endif -- " [%-15.15s]" --#if _HAVE_UT_TV -- " [%ld]" --#endif -- "\n" -- /* The arguments. */ --#if _HAVE_UT_TYPE -- , up->ut_type --#endif --#if _HAVE_UT_PID -- , up->ut_pid --#endif --#if _HAVE_UT_ID -- , up->ut_id --#endif -- , up->ut_user, up->ut_line --#if _HAVE_UT_HOST -- , up->ut_host --#endif --#if _HAVE_UT_TV -- , 4 + ctime (&temp_tv.tv_sec) -- , (long int) temp_tv.tv_usec --#else -- , 4 + ctime (&up->ut_time) --#endif -- ); -+ printf ("[%d] [%05d] [%-4.4s] [%-8.8s] [%-12.12s] [%-16.16s] [%-15.15s]" -+ " [%ld]\n", -+ up->ut_type, up->ut_pid, up->ut_id, up->ut_user, up->ut_line, -+ up->ut_host, 4 + ctime (&temp_tv.tv_sec), -+ (long int) temp_tv.tv_usec); - } - - int -diff --git a/login/tst-pututxline-cache.c b/login/tst-pututxline-cache.c -new file mode 100644 -index 0000000000..3f30dd1776 ---- /dev/null -+++ b/login/tst-pututxline-cache.c -@@ -0,0 +1,193 @@ -+/* Test case for cache invalidation after concurrent write (bug 24882). -+ Copyright (C) 2019 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; see the file COPYING.LIB. If -+ not, see <http://www.gnu.org/licenses/>. */ -+ -+/* This test writes an entry to the utmpx file, reads it (so that it -+ is cached) in process1, and overwrites the same entry in process2 -+ with something that does not match the search criteria. At this -+ point, the cache of the first process is stale, and when process1 -+ attempts to write a new record which would have gone to the same -+ place (as indicated by the cache), it needs to realize that it has -+ to pick a different slot because the old slot is now used for -+ something else. */ -+ -+#include <errno.h> -+#include <stdlib.h> -+#include <string.h> -+#include <support/check.h> -+#include <support/namespace.h> -+#include <support/support.h> -+#include <support/temp_file.h> -+#include <support/xthread.h> -+#include <support/xunistd.h> -+#include <utmp.h> -+#include <utmpx.h> -+ -+/* Set to the path of the utmp file. */ -+static char *utmp_file; -+ -+/* Used to synchronize the subprocesses. The barrier itself is -+ allocated in shared memory. */ -+static pthread_barrier_t *barrier; -+ -+/* setutxent with error checking. */ -+static void -+xsetutxent (void) -+{ -+ errno = 0; -+ setutxent (); -+ TEST_COMPARE (errno, 0); -+} -+ -+/* getutxent with error checking. */ -+static struct utmpx * -+xgetutxent (void) -+{ -+ errno = 0; -+ struct utmpx *result = getutxent (); -+ if (result == NULL) -+ FAIL_EXIT1 ("getutxent: %m"); -+ return result; -+} -+ -+static void -+put_entry (const char *id, pid_t pid, const char *user, const char *line) -+{ -+ struct utmpx ut = -+ { -+ .ut_type = LOGIN_PROCESS, -+ .ut_pid = pid, -+ .ut_host = "localhost", -+ }; -+ strcpy (ut.ut_id, id); -+ strncpy (ut.ut_user, user, sizeof (ut.ut_user)); -+ strncpy (ut.ut_line, line, sizeof (ut.ut_line)); -+ TEST_VERIFY (pututxline (&ut) != NULL); -+} -+ -+/* Use two cooperating subprocesses to avoid issues related to -+ unlock-on-close semantics of POSIX advisory locks. */ -+ -+static __attribute__ ((noreturn)) void -+process1 (void) -+{ -+ TEST_COMPARE (utmpname (utmp_file), 0); -+ -+ /* Create an entry. */ -+ xsetutxent (); -+ put_entry ("1", 101, "root", "process1"); -+ -+ /* Retrieve the entry. This will fill the internal cache. */ -+ { -+ errno = 0; -+ setutxent (); -+ TEST_COMPARE (errno, 0); -+ struct utmpx ut = -+ { -+ .ut_type = LOGIN_PROCESS, -+ .ut_line = "process1", -+ }; -+ struct utmpx *result = getutxline (&ut); -+ if (result == NULL) -+ FAIL_EXIT1 ("getutxline (\"process1\"): %m"); -+ TEST_COMPARE (result->ut_pid, 101); -+ } -+ -+ /* Signal the other process to overwrite the entry. */ -+ xpthread_barrier_wait (barrier); -+ -+ /* Wait for the other process to complete the write operation. */ -+ xpthread_barrier_wait (barrier); -+ -+ /* Add another entry. Note: This time, there is no setutxent call. */ -+ put_entry ("1", 103, "root", "process1"); -+ -+ _exit (0); -+} -+ -+static void -+process2 (void *closure) -+{ -+ /* Wait for the first process to write its entry. */ -+ xpthread_barrier_wait (barrier); -+ -+ /* Truncate the file. The glibc interface does not support -+ re-purposing records, but an external expiration mechanism may -+ trigger this. */ -+ TEST_COMPARE (truncate64 (utmp_file, 0), 0); -+ -+ /* Write the replacement entry. */ -+ TEST_COMPARE (utmpname (utmp_file), 0); -+ xsetutxent (); -+ put_entry ("2", 102, "user", "process2"); -+ -+ /* Signal the other process that the entry has been replaced. */ -+ xpthread_barrier_wait (barrier); -+} -+ -+static int -+do_test (void) -+{ -+ xclose (create_temp_file ("tst-tumpx-cache-write-", &utmp_file)); -+ { -+ pthread_barrierattr_t attr; -+ xpthread_barrierattr_init (&attr); -+ xpthread_barrierattr_setpshared (&attr, PTHREAD_SCOPE_PROCESS); -+ barrier = support_shared_allocate (sizeof (*barrier)); -+ xpthread_barrier_init (barrier, &attr, 2); -+ } -+ -+ /* Run both subprocesses in parallel. */ -+ { -+ pid_t pid1 = xfork (); -+ if (pid1 == 0) -+ process1 (); -+ support_isolate_in_subprocess (process2, NULL); -+ int status; -+ xwaitpid (pid1, &status, 0); -+ TEST_COMPARE (status, 0); -+ } -+ -+ /* Check that the utmpx database contains the expected records. */ -+ { -+ TEST_COMPARE (utmpname (utmp_file), 0); -+ xsetutxent (); -+ -+ struct utmpx *ut = xgetutxent (); -+ TEST_COMPARE_STRING (ut->ut_id, "2"); -+ TEST_COMPARE (ut->ut_pid, 102); -+ TEST_COMPARE_STRING (ut->ut_user, "user"); -+ TEST_COMPARE_STRING (ut->ut_line, "process2"); -+ -+ ut = xgetutxent (); -+ TEST_COMPARE_STRING (ut->ut_id, "1"); -+ TEST_COMPARE (ut->ut_pid, 103); -+ TEST_COMPARE_STRING (ut->ut_user, "root"); -+ TEST_COMPARE_STRING (ut->ut_line, "process1"); -+ -+ if (getutxent () != NULL) -+ FAIL_EXIT1 ("additional utmpx entry"); -+ } -+ -+ xpthread_barrier_destroy (barrier); -+ support_shared_free (barrier); -+ free (utmp_file); -+ -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/login/tst-pututxline-lockfail.c b/login/tst-pututxline-lockfail.c -new file mode 100644 -index 0000000000..47c25dc065 ---- /dev/null -+++ b/login/tst-pututxline-lockfail.c -@@ -0,0 +1,176 @@ -+/* Test the lock upgrade path in tst-pututxline. -+ Copyright (C) 2019 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; see the file COPYING.LIB. If -+ not, see <http://www.gnu.org/licenses/>. */ -+ -+/* pututxline upgrades the read lock on the file to a write lock. -+ This test verifies that if the lock upgrade fails, the utmp -+ subsystem remains in a consistent state, so that pututxline can be -+ called again. */ -+ -+#include <errno.h> -+#include <fcntl.h> -+#include <stdlib.h> -+#include <support/check.h> -+#include <support/namespace.h> -+#include <support/support.h> -+#include <support/temp_file.h> -+#include <support/xthread.h> -+#include <support/xunistd.h> -+#include <unistd.h> -+#include <utmp.h> -+#include <utmpx.h> -+ -+/* Path to the temporary utmp file. */ -+static char *path; -+ -+/* Used to synchronize the subprocesses. The barrier itself is -+ allocated in shared memory. */ -+static pthread_barrier_t *barrier; -+ -+/* Use pututxline to write an entry for PID. */ -+static struct utmpx * -+write_entry (pid_t pid) -+{ -+ struct utmpx ut = -+ { -+ .ut_type = LOGIN_PROCESS, -+ .ut_id = "1", -+ .ut_user = "root", -+ .ut_pid = pid, -+ .ut_line = "entry", -+ .ut_host = "localhost", -+ }; -+ return pututxline (&ut); -+} -+ -+/* Create the initial entry in a subprocess, so that the utmp -+ subsystem in the original process is not disturbed. */ -+static void -+subprocess_create_entry (void *closure) -+{ -+ TEST_COMPARE (utmpname (path), 0); -+ TEST_VERIFY (write_entry (101) != NULL); -+} -+ -+/* Acquire an advisory read lock on PATH. */ -+__attribute__ ((noreturn)) static void -+subprocess_lock_file (void) -+{ -+ int fd = xopen (path, O_RDONLY, 0); -+ -+ struct flock64 fl = -+ { -+ .l_type = F_RDLCK, -+ fl.l_whence = SEEK_SET, -+ }; -+ TEST_COMPARE (fcntl64 (fd, F_SETLKW, &fl), 0); -+ -+ /* Signal to the main process that the lock has been acquired. */ -+ xpthread_barrier_wait (barrier); -+ -+ /* Wait for the unlock request from the main process. */ -+ xpthread_barrier_wait (barrier); -+ -+ /* Implicitly unlock the file. */ -+ xclose (fd); -+ -+ /* Overwrite the existing entry. */ -+ TEST_COMPARE (utmpname (path), 0); -+ errno = 0; -+ setutxent (); -+ TEST_COMPARE (errno, 0); -+ TEST_VERIFY (write_entry (102) != NULL); -+ errno = 0; -+ endutxent (); -+ TEST_COMPARE (errno, 0); -+ -+ _exit (0); -+} -+ -+static int -+do_test (void) -+{ -+ xclose (create_temp_file ("tst-pututxline-lockfail-", &path)); -+ -+ { -+ pthread_barrierattr_t attr; -+ xpthread_barrierattr_init (&attr); -+ xpthread_barrierattr_setpshared (&attr, PTHREAD_SCOPE_PROCESS); -+ barrier = support_shared_allocate (sizeof (*barrier)); -+ xpthread_barrier_init (barrier, &attr, 2); -+ xpthread_barrierattr_destroy (&attr); -+ } -+ -+ /* Write the initial entry. */ -+ support_isolate_in_subprocess (subprocess_create_entry, NULL); -+ -+ pid_t locker_pid = xfork (); -+ if (locker_pid == 0) -+ subprocess_lock_file (); -+ -+ /* Wait for the file locking to complete. */ -+ xpthread_barrier_wait (barrier); -+ -+ /* Try to add another entry. This attempt will fail, with EINTR or -+ EAGAIN. */ -+ TEST_COMPARE (utmpname (path), 0); -+ TEST_VERIFY (write_entry (102) == NULL); -+ if (errno != EINTR) -+ TEST_COMPARE (errno, EAGAIN); -+ -+ /* Signal the subprocess to overwrite the entry. */ -+ xpthread_barrier_wait (barrier); -+ -+ /* Wait for write and unlock to complete. */ -+ { -+ int status; -+ xwaitpid (locker_pid, &status, 0); -+ TEST_COMPARE (status, 0); -+ } -+ -+ /* The file is no longer locked, so this operation will succeed. */ -+ TEST_VERIFY (write_entry (103) != NULL); -+ errno = 0; -+ endutxent (); -+ TEST_COMPARE (errno, 0); -+ -+ /* Check that there is just one entry with the expected contents. -+ If pututxline becomes desynchronized internally, the entry is not -+ overwritten (bug 24902). */ -+ errno = 0; -+ setutxent (); -+ TEST_COMPARE (errno, 0); -+ struct utmpx *ut = getutxent (); -+ TEST_VERIFY_EXIT (ut != NULL); -+ TEST_COMPARE (ut->ut_type, LOGIN_PROCESS); -+ TEST_COMPARE_STRING (ut->ut_id, "1"); -+ TEST_COMPARE_STRING (ut->ut_user, "root"); -+ TEST_COMPARE (ut->ut_pid, 103); -+ TEST_COMPARE_STRING (ut->ut_line, "entry"); -+ TEST_COMPARE_STRING (ut->ut_host, "localhost"); -+ TEST_VERIFY (getutxent () == NULL); -+ errno = 0; -+ endutxent (); -+ TEST_COMPARE (errno, 0); -+ -+ xpthread_barrier_destroy (barrier); -+ support_shared_free (barrier); -+ free (path); -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/login/tst-updwtmpx.c b/login/tst-updwtmpx.c -new file mode 100644 -index 0000000000..0a4a27daeb ---- /dev/null -+++ b/login/tst-updwtmpx.c -@@ -0,0 +1,112 @@ -+/* Basic test coverage for updwtmpx. -+ Copyright (C) 2019 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; see the file COPYING.LIB. If -+ not, see <http://www.gnu.org/licenses/>. */ -+ -+/* This program runs a series of tests. Each one calls updwtmpx -+ twice, to write two records, optionally with misalignment in the -+ file, and reads back the results. */ -+ -+#include <errno.h> -+#include <stdlib.h> -+#include <support/check.h> -+#include <support/descriptors.h> -+#include <support/support.h> -+#include <support/temp_file.h> -+#include <support/test-driver.h> -+#include <support/xunistd.h> -+#include <unistd.h> -+#include <utmpx.h> -+ -+static int -+do_test (void) -+{ -+ /* Two entries filled with an arbitrary bit pattern. */ -+ struct utmpx entries[2]; -+ unsigned char pad; -+ { -+ unsigned char *p = (unsigned char *) &entries[0]; -+ for (size_t i = 0; i < sizeof (entries); ++i) -+ { -+ p[i] = i; -+ } -+ /* Make sure that the first and second entry and the padding are -+ different. */ -+ p[sizeof (struct utmpx)] = p[0] + 1; -+ pad = p[0] + 2; -+ } -+ -+ char *path; -+ int fd = create_temp_file ("tst-updwtmpx-", &path); -+ -+ /* Used to check that updwtmpx does not leave an open file -+ descriptor around. */ -+ struct support_descriptors *descriptors = support_descriptors_list (); -+ -+ /* updwtmpx is expected to remove misalignment. Optionally insert -+ one byte of misalignment at the start and in the middle (after -+ the first entry). */ -+ for (int misaligned_start = 0; misaligned_start < 2; ++misaligned_start) -+ for (int misaligned_middle = 0; misaligned_middle < 2; ++misaligned_middle) -+ { -+ if (test_verbose > 0) -+ printf ("info: misaligned_start=%d misaligned_middle=%d\n", -+ misaligned_start, misaligned_middle); -+ -+ xftruncate (fd, 0); -+ TEST_COMPARE (pwrite64 (fd, &pad, misaligned_start, 0), -+ misaligned_start); -+ -+ /* Write first entry and check it. */ -+ errno = 0; -+ updwtmpx (path, &entries[0]); -+ TEST_COMPARE (errno, 0); -+ support_descriptors_check (descriptors); -+ TEST_COMPARE (xlseek (fd, 0, SEEK_END), sizeof (struct utmpx)); -+ struct utmpx buffer; -+ TEST_COMPARE (pread64 (fd, &buffer, sizeof (buffer), 0), -+ sizeof (buffer)); -+ TEST_COMPARE_BLOB (&entries[0], sizeof (entries[0]), -+ &buffer, sizeof (buffer)); -+ -+ /* Middle mis-alignmet. */ -+ TEST_COMPARE (pwrite64 (fd, &pad, misaligned_middle, -+ sizeof (struct utmpx)), misaligned_middle); -+ -+ /* Write second entry and check both entries. */ -+ errno = 0; -+ updwtmpx (path, &entries[1]); -+ TEST_COMPARE (errno, 0); -+ support_descriptors_check (descriptors); -+ TEST_COMPARE (xlseek (fd, 0, SEEK_END), 2 * sizeof (struct utmpx)); -+ TEST_COMPARE (pread64 (fd, &buffer, sizeof (buffer), 0), -+ sizeof (buffer)); -+ TEST_COMPARE_BLOB (&entries[0], sizeof (entries[0]), -+ &buffer, sizeof (buffer)); -+ TEST_COMPARE (pread64 (fd, &buffer, sizeof (buffer), sizeof (buffer)), -+ sizeof (buffer)); -+ TEST_COMPARE_BLOB (&entries[1], sizeof (entries[1]), -+ &buffer, sizeof (buffer)); -+ } -+ -+ support_descriptors_free (descriptors); -+ free (path); -+ xclose (fd); -+ -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/login/tst-utmp.c b/login/tst-utmp.c -index ce48e8326e..02d0c1fe8c 100644 ---- a/login/tst-utmp.c -+++ b/login/tst-utmp.c -@@ -39,8 +39,6 @@ - #endif - - --#if defined UTMPX || _HAVE_UT_TYPE -- - /* Prototype for our test function. */ - static int do_test (int argc, char *argv[]); - -@@ -75,11 +73,7 @@ do_prepare (int argc, char *argv[]) - - struct utmp entry[] = - { --#if defined UTMPX || _HAVE_UT_TV - #define UT(a) .ut_tv = { .tv_sec = (a)} --#else --#define UT(a) .ut_time = (a) --#endif - - { .ut_type = BOOT_TIME, .ut_pid = 1, UT(1000) }, - { .ut_type = RUN_LVL, .ut_pid = 1, UT(2000) }, -@@ -167,11 +161,7 @@ simulate_login (const char *line, const char *user) - entry[n].ut_pid = (entry_pid += 27); - entry[n].ut_type = USER_PROCESS; - strncpy (entry[n].ut_user, user, sizeof (entry[n].ut_user)); --#if defined UTMPX || _HAVE_UT_TV - 0 - entry[n].ut_tv.tv_sec = (entry_time += 1000); --#else -- entry[n].ut_time = (entry_time += 1000); --#endif - setutent (); - - if (pututline (&entry[n]) == NULL) -@@ -201,11 +191,7 @@ simulate_logout (const char *line) - { - entry[n].ut_type = DEAD_PROCESS; - strncpy (entry[n].ut_user, "", sizeof (entry[n].ut_user)); --#if defined UTMPX || _HAVE_UT_TV - 0 - entry[n].ut_tv.tv_sec = (entry_time += 1000); --#else -- entry[n].ut_time = (entry_time += 1000); --#endif - setutent (); - - if (pututline (&entry[n]) == NULL) -@@ -390,14 +376,3 @@ do_test (int argc, char *argv[]) - - return result; - } -- --#else -- --/* No field 'ut_type' in struct utmp. */ --int --main (void) --{ -- return 0; --} -- --#endif -diff --git a/login/updwtmp.c b/login/updwtmp.c -index b9bccd9b67..387e580828 100644 ---- a/login/updwtmp.c -+++ b/login/updwtmp.c -@@ -29,7 +29,7 @@ __updwtmp (const char *wtmp_file, const struct utmp *utmp) - { - const char *file_name = TRANSFORM_UTMP_FILE_NAME (wtmp_file); - -- (*__libc_utmp_file_functions.updwtmp) (file_name, utmp); -+ __libc_updwtmp (file_name, utmp); - } - libc_hidden_def (__updwtmp) - weak_alias (__updwtmp, updwtmp) -diff --git a/login/utmp-private.h b/login/utmp-private.h -index a82a923657..d60461d644 100644 ---- a/login/utmp-private.h -+++ b/login/utmp-private.h -@@ -24,24 +24,17 @@ - #include <utmp.h> - #include <libc-lock.h> - --/* The structure describing the functions in a backend. */ --struct utfuncs --{ -- int (*setutent) (void); -- int (*getutent_r) (struct utmp *, struct utmp **); -- int (*getutid_r) (const struct utmp *, struct utmp *, struct utmp **); -- int (*getutline_r) (const struct utmp *, struct utmp *, struct utmp **); -- struct utmp *(*pututline) (const struct utmp *); -- void (*endutent) (void); -- int (*updwtmp) (const char *, const struct utmp *); --}; -- --/* The tables from the services. */ --extern const struct utfuncs __libc_utmp_file_functions attribute_hidden; --extern const struct utfuncs __libc_utmp_unknown_functions attribute_hidden; -- --/* Currently selected backend. */ --extern const struct utfuncs *__libc_utmp_jump_table attribute_hidden; -+/* These functions check for initialization, but not perform any -+ locking. */ -+int __libc_setutent (void) attribute_hidden; -+int __libc_getutent_r (struct utmp *, struct utmp **) attribute_hidden; -+int __libc_getutid_r (const struct utmp *, struct utmp *, struct utmp **) -+ attribute_hidden; -+int __libc_getutline_r (const struct utmp *, struct utmp *, struct utmp **) -+ attribute_hidden; -+struct utmp *__libc_pututline (const struct utmp *) attribute_hidden; -+void __libc_endutent (void) attribute_hidden; -+int __libc_updwtmp (const char *, const struct utmp *) attribute_hidden; - - /* Current file name. */ - extern const char *__libc_utmp_file_name attribute_hidden; -diff --git a/login/utmp_file.c b/login/utmp_file.c -index b19d3caf0d..e98bc31899 100644 ---- a/login/utmp_file.c -+++ b/login/utmp_file.c -@@ -43,6 +43,25 @@ static off64_t file_offset; - /* Cache for the last read entry. */ - static struct utmp last_entry; - -+/* Returns true if *ENTRY matches last_entry, based on -+ data->ut_type. */ -+static bool -+matches_last_entry (const struct utmp *data) -+{ -+ if (file_offset <= 0) -+ /* Nothing has been read. last_entry is stale and cannot match. */ -+ return false; -+ -+ if (data->ut_type == RUN_LVL -+ || data->ut_type == BOOT_TIME -+ || data->ut_type == OLD_TIME -+ || data->ut_type == NEW_TIME) -+ /* For some entry types, only a type match is required. */ -+ return data->ut_type == last_entry.ut_type; -+ else -+ /* For the process-related entries, a full match is needed. */ -+ return __utmp_equal (&last_entry, data); -+} - - /* Locking timeout. */ - #ifndef TIMEOUT -@@ -52,90 +71,70 @@ static struct utmp last_entry; - /* Do-nothing handler for locking timeout. */ - static void timeout_handler (int signum) {}; - --/* LOCK_FILE(fd, type) failure_statement -- attempts to get a lock on the utmp file referenced by FD. If it fails, -- the failure_statement is executed, otherwise it is skipped. -- LOCKING_FAILED() -- jumps into the UNLOCK_FILE macro and ensures cleanup of LOCK_FILE. -- UNLOCK_FILE(fd) -- unlocks the utmp file referenced by FD and performs the cleanup of -- LOCK_FILE. -- */ --#define LOCK_FILE(fd, type) \ --{ \ -- struct flock fl; \ -- struct sigaction action, old_action; \ -- unsigned int old_timeout; \ -- \ -- /* Cancel any existing alarm. */ \ -- old_timeout = alarm (0); \ -- \ -- /* Establish signal handler. */ \ -- action.sa_handler = timeout_handler; \ -- __sigemptyset (&action.sa_mask); \ -- action.sa_flags = 0; \ -- __sigaction (SIGALRM, &action, &old_action); \ -- \ -- alarm (TIMEOUT); \ -- \ -- /* Try to get the lock. */ \ -- memset (&fl, '\0', sizeof (struct flock)); \ -- fl.l_type = (type); \ -- fl.l_whence = SEEK_SET; \ -- if (__fcntl64_nocancel ((fd), F_SETLKW, &fl) < 0) -- --#define LOCKING_FAILED() \ -- goto unalarm_return -- --#define UNLOCK_FILE(fd) \ -- /* Unlock the file. */ \ -- fl.l_type = F_UNLCK; \ -- __fcntl64_nocancel ((fd), F_SETLKW, &fl); \ -- \ -- unalarm_return: \ -- /* Reset the signal handler and alarm. We must reset the alarm \ -- before resetting the handler so our alarm does not generate a \ -- spurious SIGALRM seen by the user. However, we cannot just set \ -- the user's old alarm before restoring the handler, because then \ -- it's possible our handler could catch the user alarm's SIGARLM \ -- and then the user would never see the signal he expected. */ \ -- alarm (0); \ -- __sigaction (SIGALRM, &old_action, NULL); \ -- if (old_timeout != 0) \ -- alarm (old_timeout); \ --} while (0) -- -- --/* Functions defined here. */ --static int setutent_file (void); --static int getutent_r_file (struct utmp *buffer, struct utmp **result); --static int getutid_r_file (const struct utmp *key, struct utmp *buffer, -- struct utmp **result); --static int getutline_r_file (const struct utmp *key, struct utmp *buffer, -- struct utmp **result); --static struct utmp *pututline_file (const struct utmp *data); --static void endutent_file (void); --static int updwtmp_file (const char *file, const struct utmp *utmp); -- --/* Jump table for file functions. */ --const struct utfuncs __libc_utmp_file_functions = -+ -+/* try_file_lock (LOCKING, FD, TYPE) returns true if the locking -+ operation failed and recovery needs to be performed. -+ -+ file_unlock (FD) removes the lock (which must have been -+ successfully acquired). */ -+ -+static bool -+try_file_lock (int fd, int type) - { -- setutent_file, -- getutent_r_file, -- getutid_r_file, -- getutline_r_file, -- pututline_file, -- endutent_file, -- updwtmp_file --}; -+ /* Cancel any existing alarm. */ -+ int old_timeout = alarm (0); -+ -+ /* Establish signal handler. */ -+ struct sigaction old_action; -+ struct sigaction action; -+ action.sa_handler = timeout_handler; -+ __sigemptyset (&action.sa_mask); -+ action.sa_flags = 0; -+ __sigaction (SIGALRM, &action, &old_action); -+ -+ alarm (TIMEOUT); -+ -+ /* Try to get the lock. */ -+ struct flock64 fl = -+ { -+ .l_type = type, -+ .l_whence = SEEK_SET, -+ }; -+ -+ bool status = __fcntl64_nocancel (fd, F_SETLKW, &fl) < 0; -+ int saved_errno = errno; -+ -+ /* Reset the signal handler and alarm. We must reset the alarm -+ before resetting the handler so our alarm does not generate a -+ spurious SIGALRM seen by the user. However, we cannot just set -+ the user's old alarm before restoring the handler, because then -+ it's possible our handler could catch the user alarm's SIGARLM and -+ then the user would never see the signal he expected. */ -+ alarm (0); -+ __sigaction (SIGALRM, &old_action, NULL); -+ if (old_timeout != 0) -+ alarm (old_timeout); -+ -+ __set_errno (saved_errno); -+ return status; -+} - -+static void -+file_unlock (int fd) -+{ -+ struct flock64 fl = -+ { -+ .l_type = F_UNLCK, -+ }; -+ __fcntl64_nocancel (fd, F_SETLKW, &fl); -+} - - #ifndef TRANSFORM_UTMP_FILE_NAME - # define TRANSFORM_UTMP_FILE_NAME(file_name) (file_name) - #endif - --static int --setutent_file (void) -+int -+__libc_setutent (void) - { - if (file_fd < 0) - { -@@ -153,56 +152,68 @@ setutent_file (void) - __lseek64 (file_fd, 0, SEEK_SET); - file_offset = 0; - -- /* Make sure the entry won't match. */ --#if _HAVE_UT_TYPE - 0 -- last_entry.ut_type = -1; --#else -- last_entry.ut_line[0] = '\177'; --# if _HAVE_UT_ID - 0 -- last_entry.ut_id[0] = '\0'; --# endif --#endif -- - return 1; - } - -+/* Preform initialization if necessary. */ -+static bool -+maybe_setutent (void) -+{ -+ return file_fd >= 0 || __libc_setutent (); -+} - --static int --getutent_r_file (struct utmp *buffer, struct utmp **result) -+/* Reads the entry at file_offset, storing it in last_entry and -+ updating file_offset on success. Returns -1 for a read error, 0 -+ for EOF, and 1 for a successful read. last_entry and file_offset -+ are only updated on a successful and complete read. */ -+static ssize_t -+read_last_entry (void) - { -- ssize_t nbytes; -+ struct utmp buffer; -+ ssize_t nbytes = __pread64_nocancel (file_fd, &buffer, sizeof (buffer), -+ file_offset); -+ if (nbytes < 0) -+ return -1; -+ else if (nbytes != sizeof (buffer)) -+ /* Assume EOF. */ -+ return 0; -+ else -+ { -+ last_entry = buffer; -+ file_offset += sizeof (buffer); -+ return 1; -+ } -+} - -- assert (file_fd >= 0); -+int -+__libc_getutent_r (struct utmp *buffer, struct utmp **result) -+{ -+ int saved_errno = errno; - -- if (file_offset == -1l) -+ if (!maybe_setutent ()) - { - /* Not available. */ - *result = NULL; - return -1; - } - -- LOCK_FILE (file_fd, F_RDLCK) -- { -- nbytes = 0; -- LOCKING_FAILED (); -- } -- -- /* Read the next entry. */ -- nbytes = __read_nocancel (file_fd, &last_entry, sizeof (struct utmp)); -+ if (try_file_lock (file_fd, F_RDLCK)) -+ return -1; - -- UNLOCK_FILE (file_fd); -+ ssize_t nbytes = read_last_entry (); -+ file_unlock (file_fd); - -- if (nbytes != sizeof (struct utmp)) -+ if (nbytes <= 0) /* Read error or EOF. */ - { -- if (nbytes != 0) -- file_offset = -1l; -+ if (nbytes == 0) -+ /* errno should be unchanged to indicate success. A premature -+ EOF is treated like an EOF (missing complete record at the -+ end). */ -+ __set_errno (saved_errno); - *result = NULL; - return -1; - } - -- /* Update position pointer. */ -- file_offset += sizeof (struct utmp); -- - memcpy (buffer, &last_entry, sizeof (struct utmp)); - *result = buffer; - -@@ -210,82 +221,55 @@ getutent_r_file (struct utmp *buffer, struct utmp **result) - } - - -+/* Search for *ID, updating last_entry and file_offset. Return 0 on -+ success and -1 on failure. Does not perform locking; for that see -+ internal_getut_r below. */ - static int --internal_getut_r (const struct utmp *id, struct utmp *buffer, -- bool *lock_failed) -+internal_getut_nolock (const struct utmp *id) - { -- int result = -1; -- -- LOCK_FILE (file_fd, F_RDLCK) -- { -- *lock_failed = true; -- LOCKING_FAILED (); -- } -- --#if _HAVE_UT_TYPE - 0 -- if (id->ut_type == RUN_LVL || id->ut_type == BOOT_TIME -- || id->ut_type == OLD_TIME || id->ut_type == NEW_TIME) -+ while (1) - { -- /* Search for next entry with type RUN_LVL, BOOT_TIME, -- OLD_TIME, or NEW_TIME. */ -- -- while (1) -+ ssize_t nbytes = read_last_entry (); -+ if (nbytes < 0) -+ return -1; -+ if (nbytes == 0) - { -- /* Read the next entry. */ -- if (__read_nocancel (file_fd, buffer, sizeof (struct utmp)) -- != sizeof (struct utmp)) -- { -- __set_errno (ESRCH); -- file_offset = -1l; -- goto unlock_return; -- } -- file_offset += sizeof (struct utmp); -- -- if (id->ut_type == buffer->ut_type) -- break; -+ /* End of file reached. */ -+ __set_errno (ESRCH); -+ return -1; - } -- } -- else --#endif /* _HAVE_UT_TYPE */ -- { -- /* Search for the next entry with the specified ID and with type -- INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, or DEAD_PROCESS. */ - -- while (1) -- { -- /* Read the next entry. */ -- if (__read_nocancel (file_fd, buffer, sizeof (struct utmp)) -- != sizeof (struct utmp)) -- { -- __set_errno (ESRCH); -- file_offset = -1l; -- goto unlock_return; -- } -- file_offset += sizeof (struct utmp); -- -- if (__utmp_equal (buffer, id)) -- break; -- } -+ if (matches_last_entry (id)) -+ break; - } - -- result = 0; -+ return 0; -+} - --unlock_return: -- UNLOCK_FILE (file_fd); -+/* Search for *ID, updating last_entry and file_offset. Return 0 on -+ success and -1 on failure. If the locking operation failed, write -+ true to *LOCK_FAILED. */ -+static int -+internal_getut_r (const struct utmp *id, bool *lock_failed) -+{ -+ if (try_file_lock (file_fd, F_RDLCK)) -+ { -+ *lock_failed = true; -+ return -1; -+ } - -+ int result = internal_getut_nolock (id); -+ file_unlock (file_fd); - return result; - } - -- - /* For implementing this function we don't use the getutent_r function - because we can avoid the reposition on every new entry this way. */ --static int --getutid_r_file (const struct utmp *id, struct utmp *buffer, -- struct utmp **result) -+int -+__libc_getutid_r (const struct utmp *id, struct utmp *buffer, -+ struct utmp **result) - { -- assert (file_fd >= 0); -- -- if (file_offset == -1l) -+ if (!maybe_setutent ()) - { - *result = NULL; - return -1; -@@ -294,7 +278,7 @@ getutid_r_file (const struct utmp *id, struct utmp *buffer, - /* We don't have to distinguish whether we can lock the file or - whether there is no entry. */ - bool lock_failed = false; -- if (internal_getut_r (id, &last_entry, &lock_failed) < 0) -+ if (internal_getut_r (id, &lock_failed) < 0) - { - *result = NULL; - return -1; -@@ -306,69 +290,65 @@ getutid_r_file (const struct utmp *id, struct utmp *buffer, - return 0; - } - -- - /* For implementing this function we don't use the getutent_r function - because we can avoid the reposition on every new entry this way. */ --static int --getutline_r_file (const struct utmp *line, struct utmp *buffer, -- struct utmp **result) -+int -+__libc_getutline_r (const struct utmp *line, struct utmp *buffer, -+ struct utmp **result) - { -- assert (file_fd >= 0); -- -- if (file_offset == -1l) -+ if (!maybe_setutent ()) - { - *result = NULL; - return -1; - } - -- LOCK_FILE (file_fd, F_RDLCK) -+ if (try_file_lock (file_fd, F_RDLCK)) - { - *result = NULL; -- LOCKING_FAILED (); -+ return -1; - } - - while (1) - { -- /* Read the next entry. */ -- if (__read_nocancel (file_fd, &last_entry, sizeof (struct utmp)) -- != sizeof (struct utmp)) -+ ssize_t nbytes = read_last_entry (); -+ if (nbytes < 0) -+ { -+ file_unlock (file_fd); -+ *result = NULL; -+ return -1; -+ } -+ if (nbytes == 0) - { -+ /* End of file reached. */ -+ file_unlock (file_fd); - __set_errno (ESRCH); -- file_offset = -1l; - *result = NULL; -- goto unlock_return; -+ return -1; - } -- file_offset += sizeof (struct utmp); - - /* Stop if we found a user or login entry. */ -- if ( --#if _HAVE_UT_TYPE - 0 -- (last_entry.ut_type == USER_PROCESS -+ if ((last_entry.ut_type == USER_PROCESS - || last_entry.ut_type == LOGIN_PROCESS) -- && --#endif -- !strncmp (line->ut_line, last_entry.ut_line, sizeof line->ut_line)) -+ && (strncmp (line->ut_line, last_entry.ut_line, sizeof line->ut_line) -+ == 0)) - break; - } - -+ file_unlock (file_fd); - memcpy (buffer, &last_entry, sizeof (struct utmp)); - *result = buffer; - --unlock_return: -- UNLOCK_FILE (file_fd); -- -- return ((*result == NULL) ? -1 : 0); -+ return 0; - } - - --static struct utmp * --pututline_file (const struct utmp *data) -+struct utmp * -+__libc_pututline (const struct utmp *data) - { -- struct utmp buffer; -- struct utmp *pbuf; -- int found; -+ if (!maybe_setutent ()) -+ return NULL; - -- assert (file_fd >= 0); -+ struct utmp *pbuf; - - if (! file_writable) - { -@@ -380,8 +360,7 @@ pututline_file (const struct utmp *data) - if (new_fd == -1) - return NULL; - -- if (__lseek64 (new_fd, __lseek64 (file_fd, 0, SEEK_CUR), SEEK_SET) == -1 -- || __dup2 (new_fd, file_fd) < 0) -+ if (__dup2 (new_fd, file_fd) < 0) - { - __close_nocancel_nostatus (new_fd); - return NULL; -@@ -390,95 +369,96 @@ pututline_file (const struct utmp *data) - file_writable = true; - } - -+ /* Exclude other writers before validating the cache. */ -+ if (try_file_lock (file_fd, F_WRLCK)) -+ return NULL; -+ - /* Find the correct place to insert the data. */ -- if (file_offset > 0 -- && ( --#if _HAVE_UT_TYPE - 0 -- (last_entry.ut_type == data->ut_type -- && (last_entry.ut_type == RUN_LVL -- || last_entry.ut_type == BOOT_TIME -- || last_entry.ut_type == OLD_TIME -- || last_entry.ut_type == NEW_TIME)) -- || --#endif -- __utmp_equal (&last_entry, data))) -- found = 1; -- else -+ bool found = false; -+ if (matches_last_entry (data)) - { -- bool lock_failed = false; -- found = internal_getut_r (data, &buffer, &lock_failed); -- -- if (__builtin_expect (lock_failed, false)) -+ /* Read back the entry under the write lock. */ -+ file_offset -= sizeof (last_entry); -+ ssize_t nbytes = read_last_entry (); -+ if (nbytes < 0) - { -- __set_errno (EAGAIN); -+ file_unlock (file_fd); - return NULL; - } -- } - -- LOCK_FILE (file_fd, F_WRLCK) -- { -- pbuf = NULL; -- LOCKING_FAILED (); -+ if (nbytes == 0) -+ /* End of file reached. */ -+ found = false; -+ else -+ found = matches_last_entry (data); - } - -- if (found < 0) -+ if (!found) -+ /* Search forward for the entry. */ -+ found = internal_getut_nolock (data) >= 0; -+ -+ off64_t write_offset; -+ if (!found) - { - /* We append the next entry. */ -- file_offset = __lseek64 (file_fd, 0, SEEK_END); -- if (file_offset % sizeof (struct utmp) != 0) -- { -- file_offset -= file_offset % sizeof (struct utmp); -- __ftruncate64 (file_fd, file_offset); -- -- if (__lseek64 (file_fd, 0, SEEK_END) < 0) -- { -- pbuf = NULL; -- goto unlock_return; -- } -- } -+ write_offset = __lseek64 (file_fd, 0, SEEK_END); -+ -+ /* Round down to the next multiple of the entry size. This -+ ensures any partially-written record is overwritten by the -+ new record. */ -+ write_offset = (write_offset / sizeof (struct utmp) -+ * sizeof (struct utmp)); - } - else -+ /* Overwrite last_entry. */ -+ write_offset = file_offset - sizeof (struct utmp); -+ -+ /* Write the new data. */ -+ ssize_t nbytes; -+ if (__lseek64 (file_fd, write_offset, SEEK_SET) < 0 -+ || (nbytes = __write_nocancel (file_fd, data, sizeof (struct utmp))) < 0) - { -- /* We replace the just read entry. */ -- file_offset -= sizeof (struct utmp); -- __lseek64 (file_fd, file_offset, SEEK_SET); -+ /* There is no need to recover the file position because all -+ reads use pread64, and any future write is preceded by -+ another seek. */ -+ file_unlock (file_fd); -+ return NULL; - } - -- /* Write the new data. */ -- if (__write_nocancel (file_fd, data, sizeof (struct utmp)) -- != sizeof (struct utmp)) -+ if (nbytes != sizeof (struct utmp)) - { - /* If we appended a new record this is only partially written. - Remove it. */ -- if (found < 0) -- (void) __ftruncate64 (file_fd, file_offset); -- pbuf = NULL; -- } -- else -- { -- file_offset += sizeof (struct utmp); -- pbuf = (struct utmp *) data; -+ if (!found) -+ (void) __ftruncate64 (file_fd, write_offset); -+ file_unlock (file_fd); -+ /* Assume that the write failure was due to missing disk -+ space. */ -+ __set_errno (ENOSPC); -+ return NULL; - } - -- unlock_return: -- UNLOCK_FILE (file_fd); -+ file_unlock (file_fd); -+ file_offset = write_offset + sizeof (struct utmp); -+ pbuf = (struct utmp *) data; - - return pbuf; - } - - --static void --endutent_file (void) -+void -+__libc_endutent (void) - { -- assert (file_fd >= 0); -- -- __close_nocancel_nostatus (file_fd); -- file_fd = -1; -+ if (file_fd >= 0) -+ { -+ __close_nocancel_nostatus (file_fd); -+ file_fd = -1; -+ } - } - - --static int --updwtmp_file (const char *file, const struct utmp *utmp) -+int -+__libc_updwtmp (const char *file, const struct utmp *utmp) - { - int result = -1; - off64_t offset; -@@ -489,8 +469,11 @@ updwtmp_file (const char *file, const struct utmp *utmp) - if (fd < 0) - return -1; - -- LOCK_FILE (fd, F_WRLCK) -- LOCKING_FAILED (); -+ if (try_file_lock (fd, F_WRLCK)) -+ { -+ __close_nocancel_nostatus (fd); -+ return -1; -+ } - - /* Remember original size of log file. */ - offset = __lseek64 (fd, 0, SEEK_END); -@@ -516,7 +499,7 @@ updwtmp_file (const char *file, const struct utmp *utmp) - result = 0; - - unlock_return: -- UNLOCK_FILE (fd); -+ file_unlock (fd); - - /* Close WTMP file. */ - __close_nocancel_nostatus (fd); -diff --git a/login/utmpname.c b/login/utmpname.c -index c3da183d5b..8f94b19caf 100644 ---- a/login/utmpname.c -+++ b/login/utmpname.c -@@ -42,8 +42,7 @@ __utmpname (const char *file) - __libc_lock_lock (__libc_utmp_lock); - - /* Close the old file. */ -- (*__libc_utmp_jump_table->endutent) (); -- __libc_utmp_jump_table = &__libc_utmp_unknown_functions; -+ __libc_endutent (); - - if (strcmp (file, __libc_utmp_file_name) != 0) - { -diff --git a/malloc/Makefile b/malloc/Makefile -index d2fba29953..9698574bba 100644 ---- a/malloc/Makefile -+++ b/malloc/Makefile -@@ -27,7 +27,7 @@ headers := $(dist-headers) obstack.h mcheck.h - tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ - tst-mcheck tst-mallocfork tst-trim1 \ - tst-malloc-usable tst-realloc tst-reallocarray tst-posix_memalign \ -- tst-pvalloc tst-memalign tst-mallopt \ -+ tst-pvalloc tst-pvalloc-fortify tst-memalign tst-mallopt \ - tst-malloc-backtrace tst-malloc-thread-exit \ - tst-malloc-thread-fail tst-malloc-fork-deadlock \ - tst-mallocfork2 \ -@@ -54,7 +54,7 @@ tests-internal += \ - tst-dynarray-at-fail \ - - ifneq (no,$(have-tunables)) --tests += tst-malloc-usable-tunables -+tests += tst-malloc-usable-tunables tst-mxfast - tests-static += tst-malloc-usable-static-tunables - endif - -@@ -196,6 +196,8 @@ tst-malloc-usable-static-ENV = $(tst-malloc-usable-ENV) - tst-malloc-usable-tunables-ENV = GLIBC_TUNABLES=glibc.malloc.check=3 - tst-malloc-usable-static-tunables-ENV = $(tst-malloc-usable-tunables-ENV) - -+tst-mxfast-ENV = GLIBC_TUNABLES=glibc.malloc.tcache_count=0:glibc.malloc.mxfast=0 -+ - ifeq ($(experimental-malloc),yes) - CPPFLAGS-malloc.c += -DUSE_TCACHE=1 - else -diff --git a/malloc/arena.c b/malloc/arena.c -index 8309c1334c..a32eb403ec 100644 ---- a/malloc/arena.c -+++ b/malloc/arena.c -@@ -236,6 +236,7 @@ TUNABLE_CALLBACK_FNDECL (set_tcache_max, size_t) - TUNABLE_CALLBACK_FNDECL (set_tcache_count, size_t) - TUNABLE_CALLBACK_FNDECL (set_tcache_unsorted_limit, size_t) - #endif -+TUNABLE_CALLBACK_FNDECL (set_mxfast, size_t) - #else - /* Initialization routine. */ - #include <string.h> -@@ -323,6 +324,7 @@ ptmalloc_init (void) - TUNABLE_GET (tcache_unsorted_limit, size_t, - TUNABLE_CALLBACK (set_tcache_unsorted_limit)); - # endif -+ TUNABLE_GET (mxfast, size_t, TUNABLE_CALLBACK (set_mxfast)); - #else - const char *s = NULL; - if (__glibc_likely (_environ != NULL)) -diff --git a/malloc/malloc.c b/malloc/malloc.c -index 00ce48cf58..8c68b21b2b 100644 ---- a/malloc/malloc.c -+++ b/malloc/malloc.c -@@ -1621,7 +1621,7 @@ static INTERNAL_SIZE_T global_max_fast; - - #define set_max_fast(s) \ - global_max_fast = (((s) == 0) \ -- ? SMALLBIN_WIDTH : ((s + SIZE_SZ) & ~MALLOC_ALIGN_MASK)) -+ ? MIN_CHUNK_SIZE / 2 : ((s + SIZE_SZ) & ~MALLOC_ALIGN_MASK)) - - static inline INTERNAL_SIZE_T - get_max_fast (void) -@@ -5115,6 +5115,19 @@ do_set_tcache_unsorted_limit (size_t value) - } - #endif - -+static inline int -+__always_inline -+do_set_mxfast (size_t value) -+{ -+ if (value >= 0 && value <= MAX_FAST_SIZE) -+ { -+ LIBC_PROBE (memory_mallopt_mxfast, 2, value, get_max_fast ()); -+ set_max_fast (value); -+ return 1; -+ } -+ return 0; -+} -+ - int - __libc_mallopt (int param_number, int value) - { -@@ -5134,13 +5147,7 @@ __libc_mallopt (int param_number, int value) - switch (param_number) - { - case M_MXFAST: -- if (value >= 0 && value <= MAX_FAST_SIZE) -- { -- LIBC_PROBE (memory_mallopt_mxfast, 2, value, get_max_fast ()); -- set_max_fast (value); -- } -- else -- res = 0; -+ do_set_mxfast (value); - break; - - case M_TRIM_THRESHOLD: -@@ -5406,6 +5413,12 @@ __malloc_info (int options, FILE *fp) - - __libc_lock_lock (ar_ptr->mutex); - -+ /* Account for top chunk. The top-most available chunk is -+ treated specially and is never in any bin. See "initial_top" -+ comments. */ -+ avail = chunksize (ar_ptr->top); -+ nblocks = 1; /* Top always exists. */ -+ - for (size_t i = 0; i < NFASTBINS; ++i) - { - mchunkptr p = fastbin (ar_ptr, i); -@@ -5491,7 +5504,7 @@ __malloc_info (int options, FILE *fp) - - for (size_t i = 0; i < nsizes; ++i) - if (sizes[i].count != 0 && i != NFASTBINS) -- fprintf (fp, " \ -+ fprintf (fp, "\ - <size from=\"%zu\" to=\"%zu\" total=\"%zu\" count=\"%zu\"/>\n", - sizes[i].from, sizes[i].to, sizes[i].total, sizes[i].count); - -diff --git a/malloc/malloc.h b/malloc/malloc.h -index 70d8282bdc..f62c6c594c 100644 ---- a/malloc/malloc.h -+++ b/malloc/malloc.h -@@ -71,8 +71,7 @@ extern void *valloc (size_t __size) __THROW __attribute_malloc__ - - /* Equivalent to valloc(minimum-page-that-holds(n)), that is, round up - __size to nearest pagesize. */ --extern void *pvalloc (size_t __size) __THROW __attribute_malloc__ -- __attribute_alloc_size__ ((1)) __wur; -+extern void *pvalloc (size_t __size) __THROW __attribute_malloc__ __wur; - - /* Underlying allocation function; successive calls should return - contiguous pieces of memory. */ -diff --git a/malloc/tst-mxfast.c b/malloc/tst-mxfast.c -new file mode 100644 -index 0000000000..7a7750bc71 ---- /dev/null -+++ b/malloc/tst-mxfast.c -@@ -0,0 +1,50 @@ -+/* Test that glibc.malloc.mxfast tunable works. -+ Copyright (C) 2019 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/>. */ -+ -+/* This test verifies that setting the glibc.malloc.mxfast tunable to -+ zero results in free'd blocks being returned to the small bins, not -+ the fast bins. */ -+ -+#include <malloc.h> -+#include <support/check.h> -+ -+int -+do_test (void) -+{ -+ struct mallinfo m; -+ char *volatile p1; -+ char *volatile p2; -+ -+ /* Arbitrary value; must be in default fastbin range. */ -+ p1 = malloc (3); -+ /* Something large so that p1 isn't a "top block" */ -+ p2 = malloc (512); -+ free (p1); -+ -+ m = mallinfo (); -+ -+ /* This will fail if there are any blocks in the fastbins. */ -+ TEST_COMPARE (m.smblks, 0); -+ -+ /* To keep gcc happy. */ -+ free (p2); -+ -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/malloc/tst-pvalloc-fortify.c b/malloc/tst-pvalloc-fortify.c -new file mode 100644 -index 0000000000..391b7fa2f5 ---- /dev/null -+++ b/malloc/tst-pvalloc-fortify.c -@@ -0,0 +1,48 @@ -+/* Test fortify-source allocation size handling in pvalloc (bug 25401). -+ Copyright (C) 2020 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; see the file COPYING.LIB. If -+ not, see <https://www.gnu.org/licenses/>. */ -+ -+#undef _FORTIFY_SOURCE -+#define _FORTIFY_SOURCE 2 -+#include <malloc.h> -+#include <string.h> -+#include <support/check.h> -+#include <support/xunistd.h> -+#include <unistd.h> -+ -+static int -+do_test (void) -+{ -+ /* The test below assumes that pvalloc rounds up the allocation size -+ to at least 8. */ -+ TEST_VERIFY (xsysconf (_SC_PAGESIZE) >= 8); -+ -+ void *p = pvalloc (5); -+ TEST_VERIFY_EXIT (p != NULL); -+ -+ /* This is valid assuming the page size is at least 8 because -+ pvalloc rounds up the allocation size to a multiple of the page -+ size. Due to bug 25041, this used to trigger a compiler -+ warning. */ -+ strcpy (p, "abcdefg"); -+ -+ asm ("" : : "g" (p) : "memory"); /* Optimization barrier. */ -+ TEST_VERIFY (malloc_usable_size (p) >= xsysconf (_SC_PAGESIZE)); -+ return 0; -+} -+ -+#include <support/test-driver.c> -diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h -index f1bd994a10..b1695376dc 100644 ---- a/misc/sys/cdefs.h -+++ b/misc/sys/cdefs.h -@@ -412,14 +412,6 @@ - # define __glibc_has_attribute(attr) 0 - #endif - --#ifdef __has_include --/* Do not use a function-like macro, so that __has_include can inhibit -- macro expansion. */ --# define __glibc_has_include __has_include --#else --# define __glibc_has_include(header) 0 --#endif -- - #if (!defined _Noreturn \ - && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \ - && !__GNUC_PREREQ (4,7)) -diff --git a/string/string.h b/string/string.h -index c38eea971f..608ed496b9 100644 ---- a/string/string.h -+++ b/string/string.h -@@ -33,7 +33,8 @@ __BEGIN_DECLS - #include <stddef.h> - - /* Tell the caller that we provide correct C++ prototypes. */ --#if defined __cplusplus && __GNUC_PREREQ (4, 4) -+#if defined __cplusplus && (__GNUC_PREREQ (4, 4) \ -+ || __glibc_clang_prereq (3, 5)) - # define __CORRECT_ISO_CPP_STRING_H_PROTO - #endif - -diff --git a/string/test-strstr.c b/string/test-strstr.c -index df6dbc251e..daed9a2705 100644 ---- a/string/test-strstr.c -+++ b/string/test-strstr.c -@@ -139,16 +139,45 @@ check1 (void) - static void - check2 (void) - { -- const char s1[] = ", enable_static, \0, enable_shared, "; -+ const char s1_stack[] = ", enable_static, \0, enable_shared, "; -+ const size_t s1_byte_count = 18; -+ const char *s2_stack = &(s1_stack[s1_byte_count]); -+ const size_t s2_byte_count = 18; - char *exp_result; -- char *s2 = (void *) buf1 + page_size - 18; -+ const size_t page_size_real = getpagesize (); - -- strcpy (s2, s1); -- exp_result = stupid_strstr (s1, s1 + 18); -+ /* Haystack at end of page. The following page is protected. */ -+ char *s1_page_end = (void *) buf1 + page_size - s1_byte_count; -+ strcpy (s1_page_end, s1_stack); -+ -+ /* Haystack which crosses a page boundary. -+ Note: page_size is at least 2 * getpagesize. See test_init. */ -+ char *s1_page_cross = (void *) buf1 + page_size_real - 8; -+ strcpy (s1_page_cross, s1_stack); -+ -+ /* Needle at end of page. The following page is protected. */ -+ char *s2_page_end = (void *) buf2 + page_size - s2_byte_count; -+ strcpy (s2_page_end, s2_stack); -+ -+ /* Needle which crosses a page boundary. -+ Note: page_size is at least 2 * getpagesize. See test_init. */ -+ char *s2_page_cross = (void *) buf2 + page_size_real - 8; -+ strcpy (s2_page_cross, s2_stack); -+ -+ exp_result = stupid_strstr (s1_stack, s2_stack); - FOR_EACH_IMPL (impl, 0) - { -- check_result (impl, s1, s1 + 18, exp_result); -- check_result (impl, s2, s1 + 18, exp_result); -+ check_result (impl, s1_stack, s2_stack, exp_result); -+ check_result (impl, s1_stack, s2_page_end, exp_result); -+ check_result (impl, s1_stack, s2_page_cross, exp_result); -+ -+ check_result (impl, s1_page_end, s2_stack, exp_result); -+ check_result (impl, s1_page_end, s2_page_end, exp_result); -+ check_result (impl, s1_page_end, s2_page_cross, exp_result); -+ -+ check_result (impl, s1_page_cross, s2_stack, exp_result); -+ check_result (impl, s1_page_cross, s2_page_end, exp_result); -+ check_result (impl, s1_page_cross, s2_page_cross, exp_result); - } - } - -diff --git a/sysdeps/alpha/fpu/libm-test-ulps b/sysdeps/alpha/fpu/libm-test-ulps -index 0f77dd2ed0..89c4527a81 100644 ---- a/sysdeps/alpha/fpu/libm-test-ulps -+++ b/sysdeps/alpha/fpu/libm-test-ulps -@@ -1084,10 +1084,10 @@ ildouble: 1 - ldouble: 1 - - Function: Real part of "cpow_downward": --double: 2 --float: 4 --idouble: 2 --ifloat: 4 -+double: 5 -+float: 8 -+idouble: 5 -+ifloat: 8 - ildouble: 6 - ldouble: 6 - -@@ -1100,10 +1100,10 @@ ildouble: 2 - ldouble: 2 - - Function: Real part of "cpow_towardzero": --double: 2 --float: 4 --idouble: 2 --ifloat: 4 -+double: 5 -+float: 8 -+idouble: 5 -+ifloat: 8 - ildouble: 6 - ldouble: 6 - -diff --git a/sysdeps/generic/not-cancel.h b/sysdeps/generic/not-cancel.h -index f3d862651e..724c3e5e71 100644 ---- a/sysdeps/generic/not-cancel.h -+++ b/sysdeps/generic/not-cancel.h -@@ -41,6 +41,8 @@ - (void) __close (fd) - #define __read_nocancel(fd, buf, n) \ - __read (fd, buf, n) -+#define __pread64_nocancel(fd, buf, count, offset) \ -+ __pread64 (fd, buf, count, offset) - #define __write_nocancel(fd, buf, n) \ - __write (fd, buf, n) - #define __writev_nocancel_nostatus(fd, iov, n) \ -diff --git a/sysdeps/generic/utmp-equal.h b/sysdeps/generic/utmp-equal.h -index d077147a7a..d61cbb3300 100644 ---- a/sysdeps/generic/utmp-equal.h -+++ b/sysdeps/generic/utmp-equal.h -@@ -27,26 +27,16 @@ - static int - __utmp_equal (const struct utmp *entry, const struct utmp *match) - { -- return -- ( --#if _HAVE_UT_TYPE - 0 -- (entry->ut_type == INIT_PROCESS -- || entry->ut_type == LOGIN_PROCESS -- || entry->ut_type == USER_PROCESS -- || entry->ut_type == DEAD_PROCESS) -- && -- (match->ut_type == INIT_PROCESS -- || match->ut_type == LOGIN_PROCESS -- || match->ut_type == USER_PROCESS -- || match->ut_type == DEAD_PROCESS) -- && --#endif --#if _HAVE_UT_ID - 0 -- (entry->ut_id[0] && match->ut_id[0] -- ? strncmp (entry->ut_id, match->ut_id, sizeof match->ut_id) == 0 -- : strncmp (entry->ut_line, match->ut_line, sizeof match->ut_line) == 0) --#else -- strncmp (entry->ut_line, match->ut_line, sizeof match->ut_line) == 0 --#endif -- ); -+ return (entry->ut_type == INIT_PROCESS -+ || entry->ut_type == LOGIN_PROCESS -+ || entry->ut_type == USER_PROCESS -+ || entry->ut_type == DEAD_PROCESS) -+ && (match->ut_type == INIT_PROCESS -+ || match->ut_type == LOGIN_PROCESS -+ || match->ut_type == USER_PROCESS -+ || match->ut_type == DEAD_PROCESS) -+ && (entry->ut_id[0] && match->ut_id[0] -+ ? strncmp (entry->ut_id, match->ut_id, sizeof match->ut_id) == 0 -+ : (strncmp (entry->ut_line, match->ut_line, sizeof match->ut_line) -+ == 0)); - } -diff --git a/sysdeps/gnu/bits/utmp.h b/sysdeps/gnu/bits/utmp.h -deleted file mode 100644 -index 7357034cb6..0000000000 ---- a/sysdeps/gnu/bits/utmp.h -+++ /dev/null -@@ -1,126 +0,0 @@ --/* The `struct utmp' type, describing entries in the utmp file. GNU version. -- Copyright (C) 1993-2019 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/>. */ -- --#ifndef _UTMP_H --# error "Never include <bits/utmp.h> directly; use <utmp.h> instead." --#endif -- --#include <paths.h> --#include <sys/time.h> --#include <sys/types.h> --#include <bits/wordsize.h> -- -- --#define UT_LINESIZE 32 --#define UT_NAMESIZE 32 --#define UT_HOSTSIZE 256 -- -- --/* The structure describing an entry in the database of -- previous logins. */ --struct lastlog -- { --#if __WORDSIZE_TIME64_COMPAT32 -- int32_t ll_time; --#else -- __time_t ll_time; --#endif -- char ll_line[UT_LINESIZE]; -- char ll_host[UT_HOSTSIZE]; -- }; -- -- --/* The structure describing the status of a terminated process. This -- type is used in `struct utmp' below. */ --struct exit_status -- { -- short int e_termination; /* Process termination status. */ -- short int e_exit; /* Process exit status. */ -- }; -- -- --/* The structure describing an entry in the user accounting database. */ --struct utmp --{ -- short int ut_type; /* Type of login. */ -- pid_t ut_pid; /* Process ID of login process. */ -- char ut_line[UT_LINESIZE] -- __attribute_nonstring__; /* Devicename. */ -- char ut_id[4]; /* Inittab ID. */ -- char ut_user[UT_NAMESIZE] -- __attribute_nonstring__; /* Username. */ -- char ut_host[UT_HOSTSIZE] -- __attribute_nonstring__; /* Hostname for remote login. */ -- struct exit_status ut_exit; /* Exit status of a process marked -- as DEAD_PROCESS. */ --/* The ut_session and ut_tv fields must be the same size when compiled -- 32- and 64-bit. This allows data files and shared memory to be -- shared between 32- and 64-bit applications. */ --#if __WORDSIZE_TIME64_COMPAT32 -- int32_t ut_session; /* Session ID, used for windowing. */ -- struct -- { -- int32_t tv_sec; /* Seconds. */ -- int32_t tv_usec; /* Microseconds. */ -- } ut_tv; /* Time entry was made. */ --#else -- long int ut_session; /* Session ID, used for windowing. */ -- struct timeval ut_tv; /* Time entry was made. */ --#endif -- -- int32_t ut_addr_v6[4]; /* Internet address of remote host. */ -- char __glibc_reserved[20]; /* Reserved for future use. */ --}; -- --/* Backwards compatibility hacks. */ --#define ut_name ut_user --#ifndef _NO_UT_TIME --/* We have a problem here: `ut_time' is also used otherwise. Define -- _NO_UT_TIME if the compiler complains. */ --# define ut_time ut_tv.tv_sec --#endif --#define ut_xtime ut_tv.tv_sec --#define ut_addr ut_addr_v6[0] -- -- --/* Values for the `ut_type' field of a `struct utmp'. */ --#define EMPTY 0 /* No valid user accounting information. */ -- --#define RUN_LVL 1 /* The system's runlevel. */ --#define BOOT_TIME 2 /* Time of system boot. */ --#define NEW_TIME 3 /* Time after system clock changed. */ --#define OLD_TIME 4 /* Time when system clock changed. */ -- --#define INIT_PROCESS 5 /* Process spawned by the init process. */ --#define LOGIN_PROCESS 6 /* Session leader of a logged in user. */ --#define USER_PROCESS 7 /* Normal process. */ --#define DEAD_PROCESS 8 /* Terminated process. */ -- --#define ACCOUNTING 9 -- --/* Old Linux name for the EMPTY type. */ --#define UT_UNKNOWN EMPTY -- -- --/* Tell the user that we have a modern system with UT_HOST, UT_PID, -- UT_TYPE, UT_ID and UT_TV fields. */ --#define _HAVE_UT_TYPE 1 --#define _HAVE_UT_PID 1 --#define _HAVE_UT_ID 1 --#define _HAVE_UT_TV 1 --#define _HAVE_UT_HOST 1 -diff --git a/sysdeps/gnu/bits/utmpx.h b/sysdeps/gnu/bits/utmpx.h -index 472a7d57d3..2beadbf587 100644 ---- a/sysdeps/gnu/bits/utmpx.h -+++ b/sysdeps/gnu/bits/utmpx.h -@@ -56,10 +56,14 @@ struct utmpx - { - short int ut_type; /* Type of login. */ - __pid_t ut_pid; /* Process ID of login process. */ -- char ut_line[__UT_LINESIZE]; /* Devicename. */ -- char ut_id[4]; /* Inittab ID. */ -- char ut_user[__UT_NAMESIZE]; /* Username. */ -- char ut_host[__UT_HOSTSIZE]; /* Hostname for remote login. */ -+ char ut_line[__UT_LINESIZE] -+ __attribute_nonstring__; /* Devicename. */ -+ char ut_id[4] -+ __attribute_nonstring__; /* Inittab ID. */ -+ char ut_user[__UT_NAMESIZE] -+ __attribute_nonstring__; /* Username. */ -+ char ut_host[__UT_HOSTSIZE] -+ __attribute_nonstring__; /* Hostname for remote login. */ - struct __exit_status ut_exit; /* Exit status of a process marked - as DEAD_PROCESS. */ - -diff --git a/sysdeps/hppa/fpu/libm-test-ulps b/sysdeps/hppa/fpu/libm-test-ulps -index d0c4dea001..2c61a7ae91 100644 ---- a/sysdeps/hppa/fpu/libm-test-ulps -+++ b/sysdeps/hppa/fpu/libm-test-ulps -@@ -544,9 +544,9 @@ idouble: 1 - ifloat: 1 - - Function: Imaginary part of "ccos_downward": --double: 2 -+double: 3 - float: 3 --idouble: 2 -+idouble: 3 - ifloat: 3 - - Function: Real part of "ccos_towardzero": -@@ -556,9 +556,9 @@ idouble: 1 - ifloat: 2 - - Function: Imaginary part of "ccos_towardzero": --double: 2 -+double: 3 - float: 3 --idouble: 2 -+idouble: 3 - ifloat: 3 - - Function: Real part of "ccos_upward": -@@ -588,27 +588,27 @@ idouble: 1 - ifloat: 1 - - Function: Real part of "ccosh_downward": --double: 1 -+double: 2 - float: 3 --idouble: 1 -+idouble: 2 - ifloat: 3 - - Function: Imaginary part of "ccosh_downward": --double: 2 -+double: 3 - float: 3 --idouble: 2 -+idouble: 3 - ifloat: 3 - - Function: Real part of "ccosh_towardzero": --double: 1 -+double: 2 - float: 3 --idouble: 1 -+idouble: 2 - ifloat: 3 - - Function: Imaginary part of "ccosh_towardzero": --double: 2 -+double: 3 - float: 3 --idouble: 2 -+idouble: 3 - ifloat: 3 - - Function: Real part of "ccosh_upward": -@@ -636,27 +636,27 @@ idouble: 1 - ifloat: 2 - - Function: Real part of "cexp_downward": --double: 1 -+double: 2 - float: 2 --idouble: 1 -+idouble: 2 - ifloat: 2 - - Function: Imaginary part of "cexp_downward": --double: 1 -+double: 3 - float: 3 --idouble: 1 -+idouble: 3 - ifloat: 3 - - Function: Real part of "cexp_towardzero": --double: 1 -+double: 2 - float: 2 --idouble: 1 -+idouble: 2 - ifloat: 2 - - Function: Imaginary part of "cexp_towardzero": --double: 1 -+double: 3 - float: 3 --idouble: 1 -+idouble: 3 - ifloat: 3 - - Function: Real part of "cexp_upward": -@@ -666,9 +666,9 @@ idouble: 1 - ifloat: 2 - - Function: Imaginary part of "cexp_upward": --double: 1 -+double: 3 - float: 2 --idouble: 1 -+idouble: 3 - ifloat: 2 - - Function: Real part of "clog": -@@ -800,21 +800,21 @@ idouble: 1 - ifloat: 1 - - Function: "cosh_downward": --double: 1 -+double: 2 - float: 1 --idouble: 1 -+idouble: 2 - ifloat: 1 - - Function: "cosh_towardzero": --double: 1 -+double: 2 - float: 1 --idouble: 1 -+idouble: 2 - ifloat: 1 - - Function: "cosh_upward": --double: 1 -+double: 2 - float: 2 --idouble: 1 -+idouble: 2 - ifloat: 2 - - Function: Real part of "cpow": -@@ -834,9 +834,9 @@ ildouble: 2 - ldouble: 2 - - Function: Real part of "cpow_downward": --double: 4 -+double: 5 - float: 8 --idouble: 4 -+idouble: 5 - ifloat: 8 - - Function: Imaginary part of "cpow_downward": -@@ -846,9 +846,9 @@ idouble: 2 - ifloat: 2 - - Function: Real part of "cpow_towardzero": --double: 4 -+double: 5 - float: 8 --idouble: 4 -+idouble: 5 - ifloat: 8 - - Function: Imaginary part of "cpow_towardzero": -@@ -876,9 +876,9 @@ idouble: 1 - ifloat: 1 - - Function: Real part of "csin_downward": --double: 2 -+double: 3 - float: 3 --idouble: 2 -+idouble: 3 - ifloat: 3 - - Function: Imaginary part of "csin_downward": -@@ -888,9 +888,9 @@ idouble: 1 - ifloat: 2 - - Function: Real part of "csin_towardzero": --double: 2 -+double: 3 - float: 3 --idouble: 2 -+idouble: 3 - ifloat: 3 - - Function: Imaginary part of "csin_towardzero": -@@ -930,9 +930,9 @@ idouble: 2 - ifloat: 2 - - Function: Imaginary part of "csinh_downward": --double: 2 -+double: 3 - float: 3 --idouble: 2 -+idouble: 3 - ifloat: 3 - - Function: Real part of "csinh_towardzero": -@@ -942,9 +942,9 @@ idouble: 2 - ifloat: 2 - - Function: Imaginary part of "csinh_towardzero": --double: 2 -+double: 3 - float: 3 --idouble: 2 -+idouble: 3 - ifloat: 3 - - Function: Real part of "csinh_upward": -@@ -1172,15 +1172,15 @@ ildouble: 6 - ldouble: 6 - - Function: "exp10_downward": --double: 2 -+double: 3 - float: 1 --idouble: 2 -+idouble: 3 - ifloat: 1 - - Function: "exp10_towardzero": --double: 2 -+double: 3 - float: 1 --idouble: 2 -+idouble: 3 - ifloat: 1 - - Function: "exp10_upward": -diff --git a/sysdeps/s390/dl-procinfo.c b/sysdeps/s390/dl-procinfo.c -index 44c9901800..1307ec41de 100644 ---- a/sysdeps/s390/dl-procinfo.c -+++ b/sysdeps/s390/dl-procinfo.c -@@ -63,11 +63,11 @@ PROCINFO_CLASS const char _dl_s390_cap_flags[19][9] - #if !defined PROCINFO_DECL && defined SHARED - ._dl_s390_platforms - #else --PROCINFO_CLASS const char _dl_s390_platforms[9][7] -+PROCINFO_CLASS const char _dl_s390_platforms[10][7] - #endif - #ifndef PROCINFO_DECL - = { -- "g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12", "z13", "z14" -+ "g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12", "z13", "z14", "z15" - } - #endif - #if !defined SHARED || defined PROCINFO_DECL -diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h -index 3b1f6a642b..689e961ced 100644 ---- a/sysdeps/s390/dl-procinfo.h -+++ b/sysdeps/s390/dl-procinfo.h -@@ -23,7 +23,7 @@ - - #define _DL_HWCAP_COUNT 19 - --#define _DL_PLATFORMS_COUNT 9 -+#define _DL_PLATFORMS_COUNT 10 - - /* The kernel provides up to 32 capability bits with elf_hwcap. */ - #define _DL_FIRST_PLATFORM 32 -diff --git a/sysdeps/s390/strstr-arch13.S b/sysdeps/s390/strstr-arch13.S -index 929b026adf..faa969849e 100644 ---- a/sysdeps/s390/strstr-arch13.S -+++ b/sysdeps/s390/strstr-arch13.S -@@ -164,7 +164,7 @@ ENTRY(STRSTR_ARCH13) - vfenezb %v19,%v18,%v18 /* Search zero in loaded needle bytes. */ - veclb %v19,%v21 /* Zero index <= max loaded byte index? */ - jle .Lneedle_loaded /* -> v18 contains full needle. */ -- vl %v16,0(%r3) /* Load needle beyond page boundary. */ -+ vl %v18,0(%r3) /* Load needle beyond page boundary. */ - vfenezb %v19,%v18,%v18 - j .Lneedle_loaded - END(STRSTR_ARCH13) -diff --git a/sysdeps/unix/alpha/getegid.S b/sysdeps/unix/alpha/getegid.S -deleted file mode 100644 -index 167009d17a..0000000000 ---- a/sysdeps/unix/alpha/getegid.S -+++ /dev/null -@@ -1,26 +0,0 @@ --/* Copyright (C) 1991-2019 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/>. */ -- --#include <sysdep.h> -- -- --PSEUDO (__getegid, getxgid, 0) -- MOVE (r1, r0) -- ret --PSEUDO_END (__getegid) -- --weak_alias (__getegid, getegid) -diff --git a/sysdeps/unix/alpha/geteuid.S b/sysdeps/unix/alpha/geteuid.S -deleted file mode 100644 -index 39413779f7..0000000000 ---- a/sysdeps/unix/alpha/geteuid.S -+++ /dev/null -@@ -1,26 +0,0 @@ --/* Copyright (C) 1991-2019 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/>. */ -- --#include <sysdep.h> -- -- --PSEUDO (__geteuid, getxuid, 0) -- MOVE (r1, r0) -- ret --PSEUDO_END (__geteuid) -- --weak_alias (__geteuid, geteuid) -diff --git a/sysdeps/unix/alpha/getppid.S b/sysdeps/unix/alpha/getppid.S -deleted file mode 100644 -index 4d291181bd..0000000000 ---- a/sysdeps/unix/alpha/getppid.S -+++ /dev/null -@@ -1,26 +0,0 @@ --/* Copyright (C) 1991-2019 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/>. */ -- --#include <sysdep.h> -- -- --PSEUDO (__getppid, getxpid, 0) -- MOVE (r1, r0) -- ret --PSEUDO_END (__getppid) -- --weak_alias (__getppid, getppid) -diff --git a/sysdeps/unix/getlogin_r.c b/sysdeps/unix/getlogin_r.c -index 6c564d3b59..88971a9931 100644 ---- a/sysdeps/unix/getlogin_r.c -+++ b/sysdeps/unix/getlogin_r.c -@@ -64,8 +64,8 @@ __getlogin_r (char *name, size_t name_len) - held so that our search is thread-safe. */ - - __libc_lock_lock (__libc_utmp_lock); -- (*__libc_utmp_jump_table->setutent) (); -- result = (*__libc_utmp_jump_table->getutline_r) (&line, &buffer, &ut); -+ __libc_setutent (); -+ result = __libc_getutline_r (&line, &buffer, &ut); - if (result < 0) - { - if (errno == ESRCH) -@@ -74,8 +74,7 @@ __getlogin_r (char *name, size_t name_len) - else - result = errno; - } -- (*__libc_utmp_jump_table->endutent) (); -- __libc_utmp_jump_table = &__libc_utmp_unknown_functions; -+ __libc_endutent (); - __libc_lock_unlock (__libc_utmp_lock); - - if (result == 0) -diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile -index 1ab6bcbfc8..a7980a60f6 100644 ---- a/sysdeps/unix/sysv/linux/Makefile -+++ b/sysdeps/unix/sysv/linux/Makefile -@@ -212,8 +212,8 @@ sysdep_routines += xstatconv internal_statvfs internal_statvfs64 \ - close_nocancel fcntl_nocancel nanosleep_nocancel \ - open_nocancel open64_nocancel \ - openat_nocancel openat64_nocancel \ -- pause_nocancel read_nocancel waitpid_nocancel \ -- write_nocancel statx_cp -+ pause_nocancel read_nocancel pread64_nocancel \ -+ waitpid_nocancel write_nocancel statx_cp - - sysdep_headers += bits/fcntl-linux.h - -diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions -index 1ca102a9e2..d385085c61 100644 ---- a/sysdeps/unix/sysv/linux/Versions -+++ b/sysdeps/unix/sysv/linux/Versions -@@ -182,6 +182,7 @@ libc { - __syscall_rt_sigqueueinfo; - __open_nocancel; - __read_nocancel; -+ __pread64_nocancel; - __close_nocancel; - __sigtimedwait; - # functions used by nscd -diff --git a/sysdeps/unix/sysv/linux/alpha/getegid.S b/sysdeps/unix/sysv/linux/alpha/getegid.S -new file mode 100644 -index 0000000000..167009d17a ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/alpha/getegid.S -@@ -0,0 +1,26 @@ -+/* Copyright (C) 1991-2019 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/>. */ -+ -+#include <sysdep.h> -+ -+ -+PSEUDO (__getegid, getxgid, 0) -+ MOVE (r1, r0) -+ ret -+PSEUDO_END (__getegid) -+ -+weak_alias (__getegid, getegid) -diff --git a/sysdeps/unix/sysv/linux/alpha/geteuid.S b/sysdeps/unix/sysv/linux/alpha/geteuid.S -new file mode 100644 -index 0000000000..39413779f7 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/alpha/geteuid.S -@@ -0,0 +1,26 @@ -+/* Copyright (C) 1991-2019 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/>. */ -+ -+#include <sysdep.h> -+ -+ -+PSEUDO (__geteuid, getxuid, 0) -+ MOVE (r1, r0) -+ ret -+PSEUDO_END (__geteuid) -+ -+weak_alias (__geteuid, geteuid) -diff --git a/sysdeps/unix/sysv/linux/alpha/getppid.S b/sysdeps/unix/sysv/linux/alpha/getppid.S -new file mode 100644 -index 0000000000..4d291181bd ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/alpha/getppid.S -@@ -0,0 +1,26 @@ -+/* Copyright (C) 1991-2019 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/>. */ -+ -+#include <sysdep.h> -+ -+ -+PSEUDO (__getppid, getxpid, 0) -+ MOVE (r1, r0) -+ ret -+PSEUDO_END (__getppid) -+ -+weak_alias (__getppid, getppid) -diff --git a/sysdeps/unix/sysv/linux/bits/statx.h b/sysdeps/unix/sysv/linux/bits/statx.h -index 206878723f..aaccfdc2dc 100644 ---- a/sysdeps/unix/sysv/linux/bits/statx.h -+++ b/sysdeps/unix/sysv/linux/bits/statx.h -@@ -26,11 +26,13 @@ - - /* Use "" to work around incorrect macro expansion of the - __has_include argument (GCC PR 80005). */ --#if __glibc_has_include ("linux/stat.h") --# include "linux/stat.h" --# ifdef STATX_TYPE --# define __statx_timestamp_defined 1 --# define __statx_defined 1 -+#ifdef __has_include -+# if __has_include ("linux/stat.h") -+# include "linux/stat.h" -+# ifdef STATX_TYPE -+# define __statx_timestamp_defined 1 -+# define __statx_defined 1 -+# endif - # endif - #endif - -diff --git a/sysdeps/unix/sysv/linux/hppa/clone.S b/sysdeps/unix/sysv/linux/hppa/clone.S -index 79fa4f6147..1c0325e199 100644 ---- a/sysdeps/unix/sysv/linux/hppa/clone.S -+++ b/sysdeps/unix/sysv/linux/hppa/clone.S -@@ -73,13 +73,18 @@ ENTRY(__clone) - #endif - - /* Sanity check arguments. */ -- comib,=,n 0, %arg0, .LerrorSanity /* no NULL function pointers */ -- comib,=,n 0, %arg1, .LerrorSanity /* no NULL stack pointers */ -+ comib,=,n 0,%arg0,.LerrorSanity /* no NULL function pointers */ -+ comib,=,n 0,%arg1,.LerrorSanity /* no NULL stack pointers */ -+ -+ /* Ensure stack argument is 8-byte aligned. */ -+ ldo 7(%r25),%r25 -+ depi 0,31,3,%r25 - - /* Save the function pointer, arg, and flags on the new stack. */ - stwm %r26, 64(%r25) - stw %r23, -60(%r25) - stw %r24, -56(%r25) -+ - /* Clone arguments are (int flags, void * child_stack) */ - copy %r24, %r26 /* flags are first */ - /* User stack pointer is in the correct register already */ -diff --git a/sysdeps/unix/sysv/linux/mips/Makefile b/sysdeps/unix/sysv/linux/mips/Makefile -index 8217f42e75..03044e7365 100644 ---- a/sysdeps/unix/sysv/linux/mips/Makefile -+++ b/sysdeps/unix/sysv/linux/mips/Makefile -@@ -63,14 +63,25 @@ sysdep-dl-routines += dl-static - - sysdep_routines += dl-vdso - endif -- --# Supporting non-executable stacks on MIPS requires changes to both --# the Linux kernel and glibc. See --# <https://sourceware.org/ml/libc-alpha/2016-01/msg00567.html> and --# <https://sourceware.org/ml/libc-alpha/2016-01/msg00719.html>. -+# If the compiler doesn't use GNU.stack note, -+# this test is expected to fail. -+ifneq ($(mips-has-gnustack),yes) - test-xfail-check-execstack = yes - endif -+endif - - ifeq ($(subdir),stdlib) - gen-as-const-headers += ucontext_i.sym - endif -+ -+ifeq ($(mips-force-execstack),yes) -+CFLAGS-.o += -Wa,-execstack -+CFLAGS-.os += -Wa,-execstack -+CFLAGS-.op += -Wa,-execstack -+CFLAGS-.oS += -Wa,-execstack -+ -+ASFLAGS-.o += -Wa,-execstack -+ASFLAGS-.os += -Wa,-execstack -+ASFLAGS-.op += -Wa,-execstack -+ASFLAGS-.oS += -Wa,-execstack -+endif -diff --git a/sysdeps/unix/sysv/linux/mips/configure b/sysdeps/unix/sysv/linux/mips/configure -index 1ee7f41a36..25f98e0c7b 100644 ---- a/sysdeps/unix/sysv/linux/mips/configure -+++ b/sysdeps/unix/sysv/linux/mips/configure -@@ -475,3 +475,44 @@ if test -z "$arch_minimum_kernel"; then - arch_minimum_kernel=4.5.0 - fi - fi -+ -+# Check if we are supposed to run on kernels older than 4.8.0. If so, -+# force executable stack to avoid potential runtime problems with fpu -+# emulation. -+# NOTE: The check below assumes that in absence of user-provided minumum_kernel -+# we will default to arch_minimum_kernel which is currently less than 4.8.0 for -+# all known configurations. If this changes, the check must be updated. -+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler must use executable stack" >&5 -+$as_echo_n "checking whether the compiler must use executable stack... " >&6; } -+if ${libc_cv_mips_force_execstack+:} false; then : -+ $as_echo_n "(cached) " >&6 -+else -+ libc_cv_mips_force_execstack=no -+ if test $libc_mips_float = hard; then -+ if test -n "$minimum_kernel"; then -+ -+ min_version=$((`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1 \* 65536 + \2 \* 256 + \3/'`)) -+ -+ if test $min_version -lt 264192; then -+ libc_cv_mips_force_execstack=yes -+ fi -+ else -+ libc_cv_mips_force_execstack=yes -+ fi -+ fi -+fi -+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_mips_force_execstack" >&5 -+$as_echo "$libc_cv_mips_force_execstack" >&6; } -+ -+libc_mips_has_gnustack=$libc_cv_as_noexecstack -+ -+if test $libc_cv_mips_force_execstack = yes; then -+ libc_mips_has_gnustack=no -+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: forcing executable stack for pre-4.8.0 Linux kernels" >&5 -+$as_echo "$as_me: WARNING: forcing executable stack for pre-4.8.0 Linux kernels" >&2;} -+fi -+ -+config_vars="$config_vars -+mips-force-execstack = ${libc_cv_mips_force_execstack}" -+config_vars="$config_vars -+mips-has-gnustack = ${libc_mips_has_gnustack}" -diff --git a/sysdeps/unix/sysv/linux/mips/configure.ac b/sysdeps/unix/sysv/linux/mips/configure.ac -index 9147aa4582..3db1b32b08 100644 ---- a/sysdeps/unix/sysv/linux/mips/configure.ac -+++ b/sysdeps/unix/sysv/linux/mips/configure.ac -@@ -134,3 +134,35 @@ if test -z "$arch_minimum_kernel"; then - arch_minimum_kernel=4.5.0 - fi - fi -+ -+# Check if we are supposed to run on kernels older than 4.8.0. If so, -+# force executable stack to avoid potential runtime problems with fpu -+# emulation. -+# NOTE: The check below assumes that in absence of user-provided minumum_kernel -+# we will default to arch_minimum_kernel which is currently less than 4.8.0 for -+# all known configurations. If this changes, the check must be updated. -+AC_CACHE_CHECK([whether the compiler must use executable stack], -+ libc_cv_mips_force_execstack, [dnl -+libc_cv_mips_force_execstack=no -+ if test $libc_mips_float = hard; then -+ if test -n "$minimum_kernel"; then -+ changequote(,) -+ min_version=$((`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1 \* 65536 + \2 \* 256 + \3/'`)) -+ changequote([,]) -+ if test $min_version -lt 264192; then -+ libc_cv_mips_force_execstack=yes -+ fi -+ else -+ libc_cv_mips_force_execstack=yes -+ fi -+ fi]) -+ -+libc_mips_has_gnustack=$libc_cv_as_noexecstack -+ -+if test $libc_cv_mips_force_execstack = yes; then -+ libc_mips_has_gnustack=no -+ AC_MSG_WARN([forcing executable stack for pre-4.8.0 Linux kernels]) -+fi -+ -+LIBC_CONFIG_VAR([mips-force-execstack],[${libc_cv_mips_force_execstack}]) -+LIBC_CONFIG_VAR([mips-has-gnustack],[${libc_mips_has_gnustack}]) -diff --git a/sysdeps/unix/sysv/linux/not-cancel.h b/sysdeps/unix/sysv/linux/not-cancel.h -index 16cc31cba5..bf7d80125a 100644 ---- a/sysdeps/unix/sysv/linux/not-cancel.h -+++ b/sysdeps/unix/sysv/linux/not-cancel.h -@@ -43,6 +43,9 @@ __typeof (openat64) __openat64_nocancel; - /* Non cancellable read syscall. */ - __typeof (__read) __read_nocancel; - -+/* Non cancellable pread syscall (LFS version). */ -+__typeof (__pread64) __pread64_nocancel; -+ - /* Uncancelable write. */ - __typeof (__write) __write_nocancel; - -@@ -84,6 +87,7 @@ hidden_proto (__open64_nocancel) - hidden_proto (__openat_nocancel) - hidden_proto (__openat64_nocancel) - hidden_proto (__read_nocancel) -+hidden_proto (__pread64_nocancel) - hidden_proto (__write_nocancel) - hidden_proto (__close_nocancel) - hidden_proto (__waitpid_nocancel) -diff --git a/sysdeps/unix/sysv/linux/pread64_nocancel.c b/sysdeps/unix/sysv/linux/pread64_nocancel.c -new file mode 100644 -index 0000000000..dab61260e5 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/pread64_nocancel.c -@@ -0,0 +1,32 @@ -+/* Linux pread64() syscall implementation -- non-cancellable. -+ Copyright (C) 2019 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/>. */ -+ -+#include <unistd.h> -+#include <sysdep-cancel.h> -+#include <not-cancel.h> -+ -+#ifndef __NR_pread64 -+# define __NR_pread64 __NR_pread -+#endif -+ -+ssize_t -+__pread64_nocancel (int fd, void *buf, size_t count, off64_t offset) -+{ -+ return INLINE_SYSCALL_CALL (pread64, fd, buf, count, SYSCALL_LL64_PRW (offset)); -+} -+hidden_def (__pread64_nocancel) -diff --git a/sysdeps/unix/sysv/linux/riscv/vfork.S b/sysdeps/unix/sysv/linux/riscv/vfork.S -index 67373f181b..dc173d6b47 100644 ---- a/sysdeps/unix/sysv/linux/riscv/vfork.S -+++ b/sysdeps/unix/sysv/linux/riscv/vfork.S -@@ -21,9 +21,12 @@ - #include <sys/asm.h> - #include <sysdep.h> - #define __ASSEMBLY__ --#include <linux/sched.h> - #include <asm/signal.h> - -+#define CLONE_VM 0x00000100 /* Set if VM shared between processes. */ -+#define CLONE_VFORK 0x00004000 /* Set if the parent wants the child to -+ wake it up on mm_release. */ -+ - .text - LEAF (__libc_vfork) - -diff --git a/sysdeps/unix/sysv/linux/s390/bits/utmp.h b/sysdeps/unix/sysv/linux/s390/bits/utmp.h -index 862115c6f8..0569c3b784 100644 ---- a/sysdeps/unix/sysv/linux/s390/bits/utmp.h -+++ b/sysdeps/unix/sysv/linux/s390/bits/utmp.h -@@ -61,7 +61,8 @@ struct utmp - pid_t ut_pid; /* Process ID of login process. */ - char ut_line[UT_LINESIZE] - __attribute_nonstring__; /* Devicename. */ -- char ut_id[4]; /* Inittab ID. */ -+ char ut_id[4] -+ __attribute_nonstring__; /* Inittab ID. */ - char ut_user[UT_NAMESIZE] - __attribute_nonstring__; /* Username. */ - char ut_host[UT_HOSTSIZE] -diff --git a/sysdeps/unix/sysv/linux/s390/bits/utmpx.h b/sysdeps/unix/sysv/linux/s390/bits/utmpx.h -index ea3e860a2d..737d9dca05 100644 ---- a/sysdeps/unix/sysv/linux/s390/bits/utmpx.h -+++ b/sysdeps/unix/sysv/linux/s390/bits/utmpx.h -@@ -56,10 +56,14 @@ struct utmpx - { - short int ut_type; /* Type of login. */ - __pid_t ut_pid; /* Process ID of login process. */ -- char ut_line[__UT_LINESIZE]; /* Devicename. */ -- char ut_id[4]; /* Inittab ID. */ -- char ut_user[__UT_NAMESIZE]; /* Username. */ -- char ut_host[__UT_HOSTSIZE]; /* Hostname for remote login. */ -+ char ut_line[__UT_LINESIZE] -+ __attribute_nonstring__; /* Devicename. */ -+ char ut_id[4] -+ __attribute_nonstring__; /* Inittab ID. */ -+ char ut_user[__UT_NAMESIZE] -+ __attribute_nonstring__; /* Username. */ -+ char ut_host[__UT_HOSTSIZE] -+ __attribute_nonstring__; /* Hostname for remote login. */ - struct __exit_status ut_exit; /* Exit status of a process marked - as DEAD_PROCESS. */ - -diff --git a/sysdeps/unix/sysv/linux/test-errno-linux.c b/sysdeps/unix/sysv/linux/test-errno-linux.c -index cb979d44bd..aaa9eadc0a 100644 ---- a/sysdeps/unix/sysv/linux/test-errno-linux.c -+++ b/sysdeps/unix/sysv/linux/test-errno-linux.c -@@ -160,8 +160,9 @@ do_test (void) - fails |= test_wrp (EINVAL, poll, &pollfd, -1, 0); - /* quotactl returns ENOSYS for kernels not configured with - CONFIG_QUOTA, and may return EPERM if called within certain types -- of containers. */ -- fails |= test_wrp2 (LIST (ENODEV, ENOSYS, EPERM), -+ of containers. Linux 5.4 added additional argument validation -+ and can return EINVAL. */ -+ fails |= test_wrp2 (LIST (ENODEV, ENOSYS, EPERM, EINVAL), - quotactl, Q_GETINFO, NULL, -1, (caddr_t) &dqblk); - fails |= test_wrp (EINVAL, sched_getparam, -1, &sch_param); - fails |= test_wrp (EINVAL, sched_getscheduler, -1); -diff --git a/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h b/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h -index 975cbe2950..df2cdfdb6b 100644 ---- a/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h -+++ b/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h -@@ -31,7 +31,8 @@ - environment variable, LD_PREFER_MAP_32BIT_EXEC. */ - #define EXTRA_LD_ENVVARS \ - case 21: \ -- if (memcmp (envline, "PREFER_MAP_32BIT_EXEC", 21) == 0) \ -+ if (!__libc_enable_secure \ -+ && memcmp (envline, "PREFER_MAP_32BIT_EXEC", 21) == 0) \ - GLRO(dl_x86_cpu_features).feature[index_arch_Prefer_MAP_32BIT_EXEC] \ - |= bit_arch_Prefer_MAP_32BIT_EXEC; \ - break; -diff --git a/time/Makefile b/time/Makefile -index a428f55245..63b8d735ea 100644 ---- a/time/Makefile -+++ b/time/Makefile -@@ -57,6 +57,8 @@ include ../gen-locales.mk - - $(objpfx)tst-ftime_l.out: $(gen-locales) - $(objpfx)tst-strptime.out: $(gen-locales) -+$(objpfx)tst-strftime2.out: $(gen-locales) -+$(objpfx)tst-strftime3.out: $(gen-locales) - endif - - tz-cflags = -DTZDIR='"$(zonedir)"' \ |