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.30/master from glibc-2.30
Gbp-Pq: Name git-updates.diff
+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".
Please send GNU C library bug reports via <https://sourceware.org/bugzilla/>
using `glibc' in the "product" field.
+\f
+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.
+
+CVE-2020-10029: Trigonometric functions on x86 targets suffered from stack
+ corruption when they were passed a pseudo-zero argument. Reported by Guido
+ Vranken / ForAllSecure Mayhem.
+
+CVE-2020-1751: A defect in the PowerPC backtrace function could cause an
+ out-of-bounds write when executed in a signal frame context.
+
+CVE-2020-1752: A use-after-free vulnerability in the glob function when
+ expanding ~user has been fixed.
+
+The following bugs are resolved with this release:
+
+ [20543] Please move from .gnu.linkonce to comdat
+ [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
+ [25487] sinl() stack corruption from crafted input (CVE-2020-10029)
+ [25523] MIPS/Linux inline syscall template is miscompiled
+ [25635] arm: Wrong sysdep order selection for soft-fp
+ [25715] system() returns wrong errors when posix_spawn fails
+
\f
Version 2.30
-/* 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.
#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
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
-o conftest conftest.S 1>&5 2>&5; then
# Do a link to see if the backend supports IFUNC relocs.
$READELF -r conftest 1>&5
- LC_ALL=C $READELF -r conftest | grep 'no relocations' >/dev/null || {
+ LC_ALL=C $READELF -Wr conftest | grep -q 'IRELATIVE\|R_SPARC_JMP_IREL' && {
libc_cv_ld_gnu_indirect_function=yes
}
fi
[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
-o conftest conftest.S 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
# Do a link to see if the backend supports IFUNC relocs.
$READELF -r conftest 1>&AS_MESSAGE_LOG_FD
- LC_ALL=C $READELF -r conftest | grep 'no relocations' >/dev/null || {
+ LC_ALL=C $READELF -Wr conftest | grep -q 'IRELATIVE\|R_SPARC_JMP_IREL' && {
libc_cv_ld_gnu_indirect_function=yes
}
fi
}
/* Symbol names are not available for static functions, so we do not
check do_test. */
+
+ /* Check that backtrace does not return more than what fits in the array
+ (bug 25423). */
+ for (int j = 0; j < NUM_FUNCTIONS; j++)
+ {
+ n = backtrace (addresses, j);
+ if (n > j)
+ {
+ FAIL ();
+ return;
+ }
+ }
}
NO_INLINE int
tcache_unsorted_limit {
type: SIZE_T
}
+ mxfast {
+ type: SIZE_T
+ minval: 0
+ security_level: SXID_IGNORE
+ }
}
cpu {
hwcap_mask {
= 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);
}
}
<U0025><U0070>"
week 7;19971130;1
+first_weekday 2
END LC_TIME
LC_MESSAGES
date_fmt "%a<U060C> %d-%m-%Y<U060C> %T"
week 7;19971130;1
+first_weekday 2
END LC_TIME
LC_MESSAGES
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
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
$(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)
#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);
}
__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);
__libc_lock_lock (__libc_utmp_lock);
- buffer = (*__libc_utmp_jump_table->pututline) (data);
+ buffer = __libc_pututline (data);
__libc_lock_unlock (__libc_utmp_lock);
{
__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);
}
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. */
__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)
__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);
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
}
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
}
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));
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. */
{
/* 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;
/* 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);
}
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
--- /dev/null
+/* 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>
--- /dev/null
+/* 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>
--- /dev/null
+/* 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>
#endif
-#if defined UTMPX || _HAVE_UT_TYPE
-
/* Prototype for our test function. */
static int do_test (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) },
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)
{
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)
return result;
}
-
-#else
-
-/* No field 'ut_type' in struct utmp. */
-int
-main (void)
-{
- return 0;
-}
-
-#endif
{
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)
#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;
/* 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
/* 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)
{
__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;
}
+/* 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;
/* 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;
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)
{
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;
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;
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);
result = 0;
unlock_return:
- UNLOCK_FILE (fd);
+ file_unlock (fd);
/* Close WTMP file. */
__close_nocancel_nostatus (fd);
__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)
{
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 \
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
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
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>
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))
#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)
}
#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)
{
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:
__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);
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);
/* 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. */
progress. Checked by liveness_signal_handler. */
static volatile sig_atomic_t progress_indicator = 1;
+/* Set to 1 if an error occurs in the signal handler. */
+static volatile sig_atomic_t error_indicator = 0;
+
static void
sigusr1_handler (int signo)
{
if (pid == -1)
{
write_message ("error: fork\n");
- abort ();
+ error_indicator = 1;
+ return;
}
if (pid == 0)
_exit (0);
if (ret < 0)
{
write_message ("error: waitpid\n");
- abort ();
+ error_indicator = 1;
+ return;
}
if (status != 0)
{
write_message ("error: unexpected exit status from subprocess\n");
- abort ();
+ error_indicator = 1;
+ return;
}
}
}
}
+/* Children processes. */
+static pid_t sigusr1_sender_pids[5] = { 0 };
+static pid_t sigusr2_sender_pid = 0;
+
+static void
+kill_children (void)
+{
+ for (size_t i = 0; i < array_length (sigusr1_sender_pids); ++i)
+ if (sigusr1_sender_pids[i] > 0)
+ kill (sigusr1_sender_pids[i], SIGKILL);
+ if (sigusr2_sender_pid > 0)
+ kill (sigusr2_sender_pid, SIGKILL);
+}
+
static int
do_test (void)
{
+ atexit (kill_children);
+
/* shared->barrier is intialized along with sigusr1_sender_pids
below. */
shared = support_shared_allocate (sizeof (*shared));
return 1;
}
- pid_t sigusr2_sender_pid = xfork ();
+ sigusr2_sender_pid = xfork ();
if (sigusr2_sender_pid == 0)
signal_sender (SIGUSR2, true);
/* Send SIGUSR1 signals from several processes. Hopefully, one
signal will hit one of the ciritical functions. Use a barrier to
avoid sending signals while not running fork/free/malloc. */
- pid_t sigusr1_sender_pids[5];
{
pthread_barrierattr_t attr;
xpthread_barrierattr_init (&attr);
}
for (size_t i = 0; i < array_length (sigusr1_sender_pids); ++i)
{
- sigusr1_sender_pids[i] = fork ();
+ sigusr1_sender_pids[i] = xfork ();
if (sigusr1_sender_pids[i] == 0)
signal_sender (SIGUSR1, false);
}
++malloc_signals;
xpthread_barrier_wait (&shared->barrier);
- if (objects[slot] == NULL)
+ if (objects[slot] == NULL || error_indicator != 0)
{
printf ("error: malloc: %m\n");
for (size_t i = 0; i < array_length (sigusr1_sender_pids); ++i)
for (int slot = 0; slot < malloc_objects; ++slot)
free (objects[slot]);
- for (size_t i = 0; i < array_length (sigusr1_sender_pids); ++i)
- kill (sigusr1_sender_pids[i], SIGKILL);
- kill (sigusr2_sender_pid, SIGKILL);
-
printf ("info: signals received during fork: %u\n", fork_signals);
printf ("info: signals received during free: %u\n", free_signals);
printf ("info: signals received during malloc: %u\n", malloc_signals);
--- /dev/null
+/* 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>
--- /dev/null
+/* 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>
# 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))
{
size_t home_len = strlen (p->pw_dir);
size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
- char *d;
+ char *d, *newp;
+ bool use_alloca = glob_use_alloca (alloca_used,
+ home_len + rest_len + 1);
- if (__glibc_unlikely (malloc_dirname))
- free (dirname);
- malloc_dirname = 0;
-
- if (glob_use_alloca (alloca_used, home_len + rest_len + 1))
- dirname = alloca_account (home_len + rest_len + 1,
- alloca_used);
+ if (use_alloca)
+ newp = alloca_account (home_len + rest_len + 1, alloca_used);
else
{
- dirname = malloc (home_len + rest_len + 1);
- if (dirname == NULL)
+ newp = malloc (home_len + rest_len + 1);
+ if (newp == NULL)
{
scratch_buffer_free (&pwtmpbuf);
retval = GLOB_NOSPACE;
goto out;
}
- malloc_dirname = 1;
}
- d = mempcpy (dirname, p->pw_dir, home_len);
+ d = mempcpy (newp, p->pw_dir, home_len);
if (end_name != NULL)
d = mempcpy (d, end_name, rest_len);
*d = '\0';
+ if (__glibc_unlikely (malloc_dirname))
+ free (dirname);
+ dirname = newp;
+ malloc_dirname = !use_alloca;
+
dirlen = home_len + rest_len;
dirname_modified = 1;
}
<http://www.gnu.org/licenses/>. */
#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <paths.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/temp_file.h>
+#include <support/support.h>
+
+static char *tmpdir;
+static long int namemax;
+
+static void
+do_prepare (int argc, char *argv[])
+{
+ tmpdir = support_create_temp_directory ("tst-system-");
+ /* Include the last '/0'. */
+ namemax = pathconf (tmpdir, _PC_NAME_MAX) + 1;
+ TEST_VERIFY_EXIT (namemax != -1);
+}
+#define PREPARE do_prepare
+
+struct args
+{
+ const char *command;
+ int exit_status;
+ int term_sig;
+ const char *path;
+};
+
+static void
+call_system (void *closure)
+{
+ struct args *args = (struct args *) closure;
+ int ret;
+
+ if (args->path != NULL)
+ TEST_COMPARE (setenv ("PATH", args->path, 1), 0);
+ ret = system (args->command);
+ if (args->term_sig == 0)
+ {
+ /* Expect regular termination. */
+ TEST_VERIFY (WIFEXITED (ret) != 0);
+ TEST_COMPARE (WEXITSTATUS (ret), args->exit_status);
+ }
+ else
+ {
+ /* status_or_signal < 0. Expect termination by signal. */
+ TEST_VERIFY (WIFSIGNALED (ret) != 0);
+ TEST_COMPARE (WTERMSIG (ret), args->term_sig);
+ }
+}
static int
do_test (void)
{
- return system (":");
-}
+ TEST_VERIFY (system (NULL) != 0);
+ {
+ char cmd[namemax];
+ memset (cmd, 'a', sizeof(cmd));
+ cmd[sizeof(cmd) - 1] = '\0';
+
+ struct support_capture_subprocess result;
+ result = support_capture_subprocess (call_system,
+ &(struct args) {
+ cmd, 127, 0, tmpdir
+ });
+ support_capture_subprocess_check (&result, "system", 0, sc_allow_stderr);
+
+ char *returnerr = xasprintf ("%s: 1: %s: not found\n",
+ basename(_PATH_BSHELL), cmd);
+ TEST_COMPARE_STRING (result.err.buffer, returnerr);
+ free (returnerr);
+ }
+
+ {
+ char cmd[namemax + 1];
+ memset (cmd, 'a', sizeof(cmd));
+ cmd[sizeof(cmd) - 1] = '\0';
+
+ struct support_capture_subprocess result;
+ result = support_capture_subprocess (call_system,
+ &(struct args) {
+ cmd, 127, 0, tmpdir
+ });
+ support_capture_subprocess_check (&result, "system", 0, sc_allow_stderr);
+
+ char *returnerr = xasprintf ("%s: 1: %s: File name too long\n",
+ basename(_PATH_BSHELL), cmd);
+ TEST_COMPARE_STRING (result.err.buffer, returnerr);
+ free (returnerr);
+ }
+
+ {
+ struct support_capture_subprocess result;
+ result = support_capture_subprocess (call_system,
+ &(struct args) {
+ "kill -USR1 $$", 0, SIGUSR1
+ });
+ support_capture_subprocess_check (&result, "system", 0, sc_allow_none);
+ }
+
+ {
+ struct support_capture_subprocess result;
+ result = support_capture_subprocess (call_system,
+ &(struct args) { "echo ...", 0 });
+ support_capture_subprocess_check (&result, "system", 0, sc_allow_stdout);
+ TEST_COMPARE_STRING (result.out.buffer, "...\n");
+ }
+
+ {
+ struct support_capture_subprocess result;
+ result = support_capture_subprocess (call_system,
+ &(struct args) { "exit 1", 1 });
+ support_capture_subprocess_check (&result, "system", 0, sc_allow_none);
+ }
+
+ TEST_COMPARE (system (":"), 0);
+
+ return 0;
+}
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
+#include <support/test-driver.c>
#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
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);
}
}
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
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
(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) \
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));
}
+++ /dev/null
-/* 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
{
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. */
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":
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":
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":
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":
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":
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":
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":
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":
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":
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":
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":
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":
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":
# define SETUP_PIC_REG(reg) \
.ifndef GET_PC_THUNK(reg); \
- .section .gnu.linkonce.t.GET_PC_THUNK(reg),"ax",@progbits; \
+ .section .text.GET_PC_THUNK(reg),"axG",@progbits,GET_PC_THUNK(reg),comdat; \
.globl GET_PC_THUNK(reg); \
.hidden GET_PC_THUNK(reg); \
.p2align 4; \
# define SETUP_PIC_REG_STR(reg) \
".ifndef " GET_PC_THUNK_STR (reg) "\n" \
- ".section .gnu.linkonce.t." GET_PC_THUNK_STR (reg) ",\"ax\",@progbits\n" \
+ ".section .text." GET_PC_THUNK_STR (reg) ",\"axG\",@progbits," \
+ GET_PC_THUNK_STR (reg) ",comdat\n" \
".globl " GET_PC_THUNK_STR (reg) "\n" \
".hidden " GET_PC_THUNK_STR (reg) "\n" \
".p2align 4\n" \
# <http://www.gnu.org/licenses/>.
ifeq ($(subdir),math)
-tests += test-canonical-ldbl-96 test-totalorderl-ldbl-96
+tests += test-canonical-ldbl-96 test-totalorderl-ldbl-96 test-sinl-pseudo
+ifeq ($(have-ssp),yes)
+CFLAGS-test-sinl-pseudo.c += -fstack-protector-all
endif
+endif # $(subdir) == math
return 0;
}
+ if ((i0 & 0x80000000) == 0)
+ {
+ /* Pseudo-zero and unnormal representations are not valid
+ representations of long double. We need to avoid stack
+ corruption in __kernel_rem_pio2, which expects input in a
+ particular normal form, but those representations do not need
+ to be consistently handled like any particular floating-point
+ value. */
+ y[1] = y[0] = __builtin_nanl ("");
+ return 0;
+ }
+
/* Split the 64 bits of the mantissa into three 24-bit integers
stored in a double array. */
exp = j0 - 23;
--- /dev/null
+/* Test sinl for pseudo-zeros and unnormals for ldbl-96 (bug 25487).
+ 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; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <math.h>
+#include <math_ldbl.h>
+#include <stdint.h>
+
+static int
+do_test (void)
+{
+ for (int i = 0; i < 64; i++)
+ {
+ uint64_t sig = i == 63 ? 0 : 1ULL << i;
+ long double ld;
+ SET_LDOUBLE_WORDS (ld, 0x4141,
+ sig >> 32, sig & 0xffffffffULL);
+ /* The requirement is that no stack overflow occurs when the
+ pseudo-zero or unnormal goes through range reduction. */
+ volatile long double ldr;
+ ldr = sinl (ld);
+ (void) ldr;
+ }
+ return 0;
+}
+
+#include <support/test-driver.c>
static int
do_system (const char *line)
{
- int status;
+ int status = -1;
+ int ret;
pid_t pid;
struct sigaction sa;
#ifndef _LIBC_REENTRANT
__posix_spawnattr_setflags (&spawn_attr,
POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK);
- status = __posix_spawn (&pid, SHELL_PATH, 0, &spawn_attr,
- (char *const[]){ (char*) SHELL_NAME,
- (char*) "-c",
- (char *) line, NULL },
- __environ);
+ ret = __posix_spawn (&pid, SHELL_PATH, 0, &spawn_attr,
+ (char *const[]){ (char *) SHELL_NAME,
+ (char *) "-c",
+ (char *) line, NULL },
+ __environ);
__posix_spawnattr_destroy (&spawn_attr);
- if (status == 0)
+ if (ret == 0)
{
/* Cancellation results in cleanup handlers running as exceptions in
the block where they were installed, so it is safe to reference
}
DO_UNLOCK ();
+ if (ret != 0)
+ __set_errno (ret);
+
return status;
}
}
if (gregset)
{
+ if (count + 1 == size)
+ break;
array[++count] = (void*)((*gregset)[PT_NIP]);
current = (void*)((*gregset)[PT_R1]);
}
if (is_sigtramp_address (current->return_address))
{
struct signal_frame_64 *sigframe = (struct signal_frame_64*) current;
+ if (count + 1 == size)
+ break;
array[++count] = (void*) sigframe->uc.uc_mcontext.gp_regs[PT_NIP];
current = (void*) sigframe->uc.uc_mcontext.gp_regs[PT_R1];
}
#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
#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
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)
+++ /dev/null
-/* 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)
+++ /dev/null
-/* 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)
+++ /dev/null
-/* 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)
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)
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)
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
__syscall_rt_sigqueueinfo;
__open_nocancel;
__read_nocancel;
+ __pread64_nocancel;
__close_nocancel;
__sigtimedwait;
# functions used by nscd
--- /dev/null
+/* 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)
--- /dev/null
+/* 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)
--- /dev/null
+/* 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)
/* 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
#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 */
# define inline_syscall0(name,dummy) \
({ \
- register long __ret __asm__("r3"); \
- register long __r12 __asm__("r12") = name; \
+ register long int __ret __asm__("r3"); \
+ register long int __r12 __asm__("r12") = name; \
__asm__ __volatile__( "brki r14,8; nop;" \
: "=r"(__ret) \
: "r"(__r12) \
# define inline_syscall1(name,arg1) \
({ \
- register long __ret __asm__("r3"); \
- register long __r12 __asm__("r12") = name; \
- register long __r5 __asm__("r5") = (long)(arg1); \
+ long int __arg1 = (long int) (arg1); \
+ register long int __ret __asm__("r3"); \
+ register long int __r12 __asm__("r12") = name; \
+ register long int __r5 __asm__("r5") = __arg1; \
__asm__ __volatile__( "brki r14,8; nop;" \
: "=r"(__ret) \
: "r"(__r5), "r"(__r12) \
# define inline_syscall2(name,arg1,arg2) \
({ \
- register long __ret __asm__("r3"); \
- register long __r12 __asm__("r12") = name; \
- register long __r5 __asm__("r5") = (long)(arg1); \
- register long __r6 __asm__("r6") = (long)(arg2); \
+ long int __arg1 = (long int) (arg1); \
+ long int __arg2 = (long int) (arg2); \
+ register long int __ret __asm__("r3"); \
+ register long int __r12 __asm__("r12") = name; \
+ register long int __r5 __asm__("r5") = __arg1; \
+ register long int __r6 __asm__("r6") = __arg2; \
__asm__ __volatile__( "brki r14,8; nop;" \
: "=r"(__ret) \
: "r"(__r5), "r"(__r6), "r"(__r12) \
# define inline_syscall3(name,arg1,arg2,arg3) \
({ \
- register long __ret __asm__("r3"); \
- register long __r12 __asm__("r12") = name; \
- register long __r5 __asm__("r5") = (long)(arg1); \
- register long __r6 __asm__("r6") = (long)(arg2); \
- register long __r7 __asm__("r7") = (long)(arg3); \
+ long int __arg1 = (long int) (arg1); \
+ long int __arg2 = (long int) (arg2); \
+ long int __arg3 = (long int) (arg3); \
+ register long int __ret __asm__("r3"); \
+ register long int __r12 __asm__("r12") = name; \
+ register long int __r5 __asm__("r5") = __arg1; \
+ register long int __r6 __asm__("r6") = __arg2; \
+ register long int __r7 __asm__("r7") = __arg3; \
__asm__ __volatile__( "brki r14,8; nop;" \
: "=r"(__ret) \
: "r"(__r5), "r"(__r6), "r"(__r7), "r"(__r12) \
# define inline_syscall4(name,arg1,arg2,arg3,arg4) \
({ \
- register long __ret __asm__("r3"); \
- register long __r12 __asm__("r12") = name; \
- register long __r5 __asm__("r5") = (long)(arg1); \
- register long __r6 __asm__("r6") = (long)(arg2); \
- register long __r7 __asm__("r7") = (long)(arg3); \
- register long __r8 __asm__("r8") = (long)(arg4); \
+ long int __arg1 = (long int) (arg1); \
+ long int __arg2 = (long int) (arg2); \
+ long int __arg3 = (long int) (arg3); \
+ long int __arg4 = (long int) (arg4); \
+ register long int __ret __asm__("r3"); \
+ register long int __r12 __asm__("r12") = name; \
+ register long int __r5 __asm__("r5") = __arg1; \
+ register long int __r6 __asm__("r6") = __arg2; \
+ register long int __r7 __asm__("r7") = __arg3; \
+ register long int __r8 __asm__("r8") = __arg4; \
__asm__ __volatile__( "brki r14,8; nop;" \
: "=r"(__ret) \
: "r"(__r5), "r"(__r6), "r"(__r7), "r"(__r8),"r"(__r12) \
# define inline_syscall5(name,arg1,arg2,arg3,arg4,arg5) \
({ \
- register long __ret __asm__("r3"); \
- register long __r12 __asm__("r12") = name; \
- register long __r5 __asm__("r5") = (long)(arg1); \
- register long __r6 __asm__("r6") = (long)(arg2); \
- register long __r7 __asm__("r7") = (long)(arg3); \
- register long __r8 __asm__("r8") = (long)(arg4); \
- register long __r9 __asm__("r9") = (long)(arg5); \
+ long int __arg1 = (long int) (arg1); \
+ long int __arg2 = (long int) (arg2); \
+ long int __arg3 = (long int) (arg3); \
+ long int __arg4 = (long int) (arg4); \
+ long int __arg5 = (long int) (arg5); \
+ register long int __ret __asm__("r3"); \
+ register long int __r12 __asm__("r12") = name; \
+ register long int __r5 __asm__("r5") = __arg1; \
+ register long int __r6 __asm__("r6") = __arg2; \
+ register long int __r7 __asm__("r7") = __arg3; \
+ register long int __r8 __asm__("r8") = __arg4; \
+ register long int __r9 __asm__("r9") = __arg5; \
__asm__ __volatile__( "brki r14,8; nop;" \
: "=r"(__ret) \
: "r"(__r5), "r"(__r6), "r"(__r7), "r"(__r8),"r"(__r9), "r"(__r12) \
# define inline_syscall6(name,arg1,arg2,arg3,arg4,arg5,arg6) \
({ \
- register long __ret __asm__("r3"); \
- register long __r12 __asm__("r12") = name; \
- register long __r5 __asm__("r5") = (long)(arg1); \
- register long __r6 __asm__("r6") = (long)(arg2); \
- register long __r7 __asm__("r7") = (long)(arg3); \
- register long __r8 __asm__("r8") = (long)(arg4); \
- register long __r9 __asm__("r9") = (long)(arg5); \
- register long __r10 __asm__("r10") = (long)(arg6); \
+ long int __arg1 = (long int) (arg1); \
+ long int __arg2 = (long int) (arg2); \
+ long int __arg3 = (long int) (arg3); \
+ long int __arg4 = (long int) (arg4); \
+ long int __arg5 = (long int) (arg5); \
+ long int __arg6 = (long int) (arg6); \
+ register long int __ret __asm__("r3"); \
+ register long int __r12 __asm__("r12") = name; \
+ register long int __r5 __asm__("r5") = __arg1; \
+ register long int __r6 __asm__("r6") = __arg2; \
+ register long int __r7 __asm__("r7") = __arg3; \
+ register long int __r8 __asm__("r8") = __arg4; \
+ register long int __r9 __asm__("r9") = __arg5; \
+ register long int __r10 __asm__("r10") = __arg6; \
__asm__ __volatile__( "brki r14,8; nop;" \
: "=r"(__ret) \
: "r"(__r5), "r"(__r6), "r"(__r7), "r"(__r8),"r"(__r9), "r"(__r10), \
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
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}"
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}])
.text
.set nomips16
-/* long long __mips_syscall5 (long arg1, long arg2, long arg3, long arg4,
- long arg5,
- long number) */
+/* long long int __mips_syscall5 (long int arg1, long int arg2, long int arg3,
+ long int arg4, long int arg5,
+ long int number) */
ENTRY(__mips_syscall5)
lw v0, 20(sp)
.text
.set nomips16
-/* long long __mips_syscall6 (long arg1, long arg2, long arg3, long arg4,
- long arg5, long arg6,
- long number) */
+/* long long int __mips_syscall6 (long int arg1, long int arg2, long int arg3,
+ long int arg4, long int arg5, long int arg6,
+ long int number) */
ENTRY(__mips_syscall6)
lw v0, 24(sp)
.text
.set nomips16
-/* long long __mips_syscall7 (long arg1, long arg2, long arg3, long arg4,
- long arg5, long arg6, long arg7,
- long number) */
+/* long long int __mips_syscall7 (long int arg1, long int arg2, long int arg3,
+ long int arg4, long int arg5, long int arg6,
+ long int arg7,
+ long int number) */
ENTRY(__mips_syscall7)
lw v0, 28(sp)
#ifndef MIPS16_SYSCALL_H
#define MIPS16_SYSCALL_H 1
-long long __nomips16 __mips16_syscall0 (long number);
+long long int __nomips16 __mips16_syscall0 (long int number);
#define __mips16_syscall0(dummy, number) \
- __mips16_syscall0 ((long) (number))
+ __mips16_syscall0 ((long int) (number))
-long long __nomips16 __mips16_syscall1 (long a0,
- long number);
+long long int __nomips16 __mips16_syscall1 (long int a0,
+ long int number);
#define __mips16_syscall1(a0, number) \
- __mips16_syscall1 ((long) (a0), \
- (long) (number))
+ __mips16_syscall1 ((long int) (a0), \
+ (long int) (number))
-long long __nomips16 __mips16_syscall2 (long a0, long a1,
- long number);
+long long int __nomips16 __mips16_syscall2 (long int a0, long int a1,
+ long int number);
#define __mips16_syscall2(a0, a1, number) \
- __mips16_syscall2 ((long) (a0), (long) (a1), \
- (long) (number))
+ __mips16_syscall2 ((long int) (a0), (long int) (a1), \
+ (long int) (number))
-long long __nomips16 __mips16_syscall3 (long a0, long a1, long a2,
- long number);
+long long int __nomips16 __mips16_syscall3 (long int a0, long int a1,
+ long int a2,
+ long int number);
#define __mips16_syscall3(a0, a1, a2, number) \
- __mips16_syscall3 ((long) (a0), (long) (a1), (long) (a2), \
- (long) (number))
+ __mips16_syscall3 ((long int) (a0), (long int) (a1), \
+ (long int) (a2), \
+ (long int) (number))
-long long __nomips16 __mips16_syscall4 (long a0, long a1, long a2, long a3,
- long number);
+long long int __nomips16 __mips16_syscall4 (long int a0, long int a1,
+ long int a2, long int a3,
+ long int number);
#define __mips16_syscall4(a0, a1, a2, a3, number) \
- __mips16_syscall4 ((long) (a0), (long) (a1), (long) (a2), \
- (long) (a3), \
- (long) (number))
+ __mips16_syscall4 ((long int) (a0), (long int) (a1), \
+ (long int) (a2), (long int) (a3), \
+ (long int) (number))
/* The remaining ones use regular MIPS wrappers. */
#define __mips16_syscall5(a0, a1, a2, a3, a4, number) \
- __mips_syscall5 ((long) (a0), (long) (a1), (long) (a2), \
- (long) (a3), (long) (a4), \
- (long) (number))
+ __mips_syscall5 ((long int) (a0), (long int) (a1), \
+ (long int) (a2), (long int) (a3), \
+ (long int) (a4), \
+ (long int) (number))
#define __mips16_syscall6(a0, a1, a2, a3, a4, a5, number) \
- __mips_syscall6 ((long) (a0), (long) (a1), (long) (a2), \
- (long) (a3), (long) (a4), (long) (a5), \
- (long) (number))
+ __mips_syscall6 ((long int) (a0), (long int) (a1), \
+ (long int) (a2), (long int) (a3), \
+ (long int) (a4), (long int) (a5), \
+ (long int) (number))
#define __mips16_syscall7(a0, a1, a2, a3, a4, a5, a6, number) \
- __mips_syscall7 ((long) (a0), (long) (a1), (long) (a2), \
- (long) (a3), (long) (a4), (long) (a5), \
- (long) (a6), \
- (long) (number))
+ __mips_syscall7 ((long int) (a0), (long int) (a1), \
+ (long int) (a2), (long int) (a3), \
+ (long int) (a4), (long int) (a5), \
+ (long int) (a6), \
+ (long int) (number))
#endif
#undef __mips16_syscall0
-long long __nomips16
-__mips16_syscall0 (long number)
+long long int __nomips16
+__mips16_syscall0 (long int number)
{
union __mips_syscall_return ret;
ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 0);
#undef __mips16_syscall1
-long long __nomips16
-__mips16_syscall1 (long a0,
- long number)
+long long int __nomips16
+__mips16_syscall1 (long int a0,
+ long int number)
{
union __mips_syscall_return ret;
ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 1,
#undef __mips16_syscall2
-long long __nomips16
-__mips16_syscall2 (long a0, long a1,
- long number)
+long long int __nomips16
+__mips16_syscall2 (long int a0, long int a1,
+ long int number)
{
union __mips_syscall_return ret;
ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 2,
#undef __mips16_syscall3
-long long __nomips16
-__mips16_syscall3 (long a0, long a1, long a2,
- long number)
+long long int __nomips16
+__mips16_syscall3 (long int a0, long int a1, long int a2,
+ long int number)
{
union __mips_syscall_return ret;
ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 3,
#undef __mips16_syscall4
-long long __nomips16
-__mips16_syscall4 (long a0, long a1, long a2, long a3,
- long number)
+long long int __nomips16
+__mips16_syscall4 (long int a0, long int a1, long int a2, long int a3,
+ long int number)
{
union __mips_syscall_return ret;
ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 4,
#undef INLINE_SYSCALL
#define INLINE_SYSCALL(name, nr, args...) \
({ INTERNAL_SYSCALL_DECL (_sc_err); \
- long result_var = INTERNAL_SYSCALL (name, _sc_err, nr, args); \
+ long int result_var = INTERNAL_SYSCALL (name, _sc_err, nr, args); \
if ( INTERNAL_SYSCALL_ERROR_P (result_var, _sc_err) ) \
{ \
__set_errno (INTERNAL_SYSCALL_ERRNO (result_var, _sc_err)); \
result_var; })
#undef INTERNAL_SYSCALL_DECL
-#define INTERNAL_SYSCALL_DECL(err) long err __attribute__ ((unused))
+#define INTERNAL_SYSCALL_DECL(err) long int err __attribute__ ((unused))
#undef INTERNAL_SYSCALL_ERROR_P
-#define INTERNAL_SYSCALL_ERROR_P(val, err) ((void) (val), (long) (err))
+#define INTERNAL_SYSCALL_ERROR_P(val, err) ((void) (val), (long int) (err))
#undef INTERNAL_SYSCALL_ERRNO
#define INTERNAL_SYSCALL_ERRNO(val, err) ((void) (err), val)
union __mips_syscall_return
{
- long long val;
+ long long int val;
struct
{
- long v0;
- long v1;
+ long int v0;
+ long int v1;
}
reg;
};
#define internal_syscall0(v0_init, input, number, err, dummy...) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long __s0 asm ("$16") __attribute__ ((unused)) \
+ register long int __s0 asm ("$16") __attribute__ ((unused)) \
= (number); \
- register long __v0 asm ("$2"); \
- register long __a3 asm ("$7"); \
+ register long int __v0 asm ("$2"); \
+ register long int __a3 asm ("$7"); \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
#define internal_syscall1(v0_init, input, number, err, arg1) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long __s0 asm ("$16") __attribute__ ((unused)) \
+ long int _arg1 = (long int) (arg1); \
+ register long int __s0 asm ("$16") __attribute__ ((unused)) \
= (number); \
- register long __v0 asm ("$2"); \
- register long __a0 asm ("$4") = (long) (arg1); \
- register long __a3 asm ("$7"); \
+ register long int __v0 asm ("$2"); \
+ register long int __a0 asm ("$4") = _arg1; \
+ register long int __a3 asm ("$7"); \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
#define internal_syscall2(v0_init, input, number, err, arg1, arg2) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long __s0 asm ("$16") __attribute__ ((unused)) \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
+ register long int __s0 asm ("$16") __attribute__ ((unused)) \
= (number); \
- register long __v0 asm ("$2"); \
- register long __a0 asm ("$4") = (long) (arg1); \
- register long __a1 asm ("$5") = (long) (arg2); \
- register long __a3 asm ("$7"); \
+ register long int __v0 asm ("$2"); \
+ register long int __a0 asm ("$4") = _arg1; \
+ register long int __a1 asm ("$5") = _arg2; \
+ register long int __a3 asm ("$7"); \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
#define internal_syscall3(v0_init, input, number, err, \
arg1, arg2, arg3) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long __s0 asm ("$16") __attribute__ ((unused)) \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
+ long int _arg3 = (long int) (arg3); \
+ register long int __s0 asm ("$16") __attribute__ ((unused)) \
= (number); \
- register long __v0 asm ("$2"); \
- register long __a0 asm ("$4") = (long) (arg1); \
- register long __a1 asm ("$5") = (long) (arg2); \
- register long __a2 asm ("$6") = (long) (arg3); \
- register long __a3 asm ("$7"); \
+ register long int __v0 asm ("$2"); \
+ register long int __a0 asm ("$4") = _arg1; \
+ register long int __a1 asm ("$5") = _arg2; \
+ register long int __a2 asm ("$6") = _arg3; \
+ register long int __a3 asm ("$7"); \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
#define internal_syscall4(v0_init, input, number, err, \
arg1, arg2, arg3, arg4) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long __s0 asm ("$16") __attribute__ ((unused)) \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
+ long int _arg3 = (long int) (arg3); \
+ long int _arg4 = (long int) (arg4); \
+ register long int __s0 asm ("$16") __attribute__ ((unused)) \
= (number); \
- register long __v0 asm ("$2"); \
- register long __a0 asm ("$4") = (long) (arg1); \
- register long __a1 asm ("$5") = (long) (arg2); \
- register long __a2 asm ("$6") = (long) (arg3); \
- register long __a3 asm ("$7") = (long) (arg4); \
+ register long int __v0 asm ("$2"); \
+ register long int __a0 asm ("$4") = _arg1; \
+ register long int __a1 asm ("$5") = _arg2; \
+ register long int __a2 asm ("$6") = _arg3; \
+ register long int __a3 asm ("$7") = _arg4; \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
compiler specifics required for the stack arguments to be pushed,
which would be the case if these syscalls were inlined. */
-long long __nomips16 __mips_syscall5 (long arg1, long arg2, long arg3,
- long arg4, long arg5,
- long number);
+long long int __nomips16 __mips_syscall5 (long int arg1, long int arg2,
+ long int arg3, long int arg4,
+ long int arg5,
+ long int number);
libc_hidden_proto (__mips_syscall5, nomips16)
#define internal_syscall5(v0_init, input, number, err, \
arg1, arg2, arg3, arg4, arg5) \
({ \
union __mips_syscall_return _sc_ret; \
- _sc_ret.val = __mips_syscall5 ((long) (arg1), \
- (long) (arg2), \
- (long) (arg3), \
- (long) (arg4), \
- (long) (arg5), \
- (long) (number)); \
+ _sc_ret.val = __mips_syscall5 ((long int) (arg1), \
+ (long int) (arg2), \
+ (long int) (arg3), \
+ (long int) (arg4), \
+ (long int) (arg5), \
+ (long int) (number)); \
err = _sc_ret.reg.v1; \
_sc_ret.reg.v0; \
})
-long long __nomips16 __mips_syscall6 (long arg1, long arg2, long arg3,
- long arg4, long arg5, long arg6,
- long number);
+long long int __nomips16 __mips_syscall6 (long int arg1, long int arg2,
+ long int arg3, long int arg4,
+ long int arg5, long int arg6,
+ long int number);
libc_hidden_proto (__mips_syscall6, nomips16)
#define internal_syscall6(v0_init, input, number, err, \
arg1, arg2, arg3, arg4, arg5, arg6) \
({ \
union __mips_syscall_return _sc_ret; \
- _sc_ret.val = __mips_syscall6 ((long) (arg1), \
- (long) (arg2), \
- (long) (arg3), \
- (long) (arg4), \
- (long) (arg5), \
- (long) (arg6), \
- (long) (number)); \
+ _sc_ret.val = __mips_syscall6 ((long int) (arg1), \
+ (long int) (arg2), \
+ (long int) (arg3), \
+ (long int) (arg4), \
+ (long int) (arg5), \
+ (long int) (arg6), \
+ (long int) (number)); \
err = _sc_ret.reg.v1; \
_sc_ret.reg.v0; \
})
-long long __nomips16 __mips_syscall7 (long arg1, long arg2, long arg3,
- long arg4, long arg5, long arg6,
- long arg7,
- long number);
+long long int __nomips16 __mips_syscall7 (long int arg1, long int arg2,
+ long int arg3, long int arg4,
+ long int arg5, long int arg6,
+ long int arg7,
+ long int number);
libc_hidden_proto (__mips_syscall7, nomips16)
#define internal_syscall7(v0_init, input, number, err, \
arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
({ \
union __mips_syscall_return _sc_ret; \
- _sc_ret.val = __mips_syscall7 ((long) (arg1), \
- (long) (arg2), \
- (long) (arg3), \
- (long) (arg4), \
- (long) (arg5), \
- (long) (arg6), \
- (long) (arg7), \
- (long) (number)); \
+ _sc_ret.val = __mips_syscall7 ((long int) (arg1), \
+ (long int) (arg2), \
+ (long int) (arg3), \
+ (long int) (arg4), \
+ (long int) (arg5), \
+ (long int) (arg6), \
+ (long int) (arg7), \
+ (long int) (number)); \
err = _sc_ret.reg.v1; \
_sc_ret.reg.v0; \
})
#define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...) \
({ \
long _ret = funcptr (args); \
- err = ((unsigned long) (_ret) >= (unsigned long) -4095L); \
+ err = ((unsigned long) (_ret) >= (unsigned long int) -4095L); \
if (err) \
_ret = -_ret; \
_ret; \
/* Convert X to a long long, without losing any bits if it is one
already or warning if it is a 32-bit pointer. */
-#define ARGIFY(X) ((long long) (__typeof__ ((X) - (X))) (X))
+#define ARGIFY(X) ((long long int) (__typeof__ ((X) - (X))) (X))
/* Define a macro which expands into the inline wrapper code for a system
call. */
#undef INLINE_SYSCALL
#define INLINE_SYSCALL(name, nr, args...) \
({ INTERNAL_SYSCALL_DECL (_sc_err); \
- long result_var = INTERNAL_SYSCALL (name, _sc_err, nr, args); \
+ long int result_var = INTERNAL_SYSCALL (name, _sc_err, nr, args); \
if ( INTERNAL_SYSCALL_ERROR_P (result_var, _sc_err) ) \
{ \
__set_errno (INTERNAL_SYSCALL_ERRNO (result_var, _sc_err)); \
result_var; })
#undef INTERNAL_SYSCALL_DECL
-#define INTERNAL_SYSCALL_DECL(err) long err __attribute__ ((unused))
+#define INTERNAL_SYSCALL_DECL(err) long int err __attribute__ ((unused))
#undef INTERNAL_SYSCALL_ERROR_P
-#define INTERNAL_SYSCALL_ERROR_P(val, err) ((void) (val), (long) (err))
+#define INTERNAL_SYSCALL_ERROR_P(val, err) ((void) (val), (long int) (err))
#undef INTERNAL_SYSCALL_ERRNO
#define INTERNAL_SYSCALL_ERRNO(val, err) ((void) (err), val)
#define internal_syscall0(v0_init, input, number, err, dummy...) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long long __s0 asm ("$16") __attribute__ ((unused)) \
+ register long long int __s0 asm ("$16") __attribute__ ((unused))\
= (number); \
- register long long __v0 asm ("$2"); \
- register long long __a3 asm ("$7"); \
+ register long long int __v0 asm ("$2"); \
+ register long long int __a3 asm ("$7"); \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
#define internal_syscall1(v0_init, input, number, err, arg1) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long long __s0 asm ("$16") __attribute__ ((unused)) \
+ long long int _arg1 = ARGIFY (arg1); \
+ register long long int __s0 asm ("$16") __attribute__ ((unused))\
= (number); \
- register long long __v0 asm ("$2"); \
- register long long __a0 asm ("$4") = ARGIFY (arg1); \
- register long long __a3 asm ("$7"); \
+ register long long int __v0 asm ("$2"); \
+ register long long int __a0 asm ("$4") = _arg1; \
+ register long long int __a3 asm ("$7"); \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
#define internal_syscall2(v0_init, input, number, err, arg1, arg2) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long long __s0 asm ("$16") __attribute__ ((unused)) \
+ long long int _arg1 = ARGIFY (arg1); \
+ long long int _arg2 = ARGIFY (arg2); \
+ register long long int __s0 asm ("$16") __attribute__ ((unused))\
= (number); \
- register long long __v0 asm ("$2"); \
- register long long __a0 asm ("$4") = ARGIFY (arg1); \
- register long long __a1 asm ("$5") = ARGIFY (arg2); \
- register long long __a3 asm ("$7"); \
+ register long long int __v0 asm ("$2"); \
+ register long long int __a0 asm ("$4") = _arg1; \
+ register long long int __a1 asm ("$5") = _arg2; \
+ register long long int __a3 asm ("$7"); \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
#define internal_syscall3(v0_init, input, number, err, \
arg1, arg2, arg3) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long long __s0 asm ("$16") __attribute__ ((unused)) \
+ long long int _arg1 = ARGIFY (arg1); \
+ long long int _arg2 = ARGIFY (arg2); \
+ long long int _arg3 = ARGIFY (arg3); \
+ register long long int __s0 asm ("$16") __attribute__ ((unused))\
= (number); \
- register long long __v0 asm ("$2"); \
- register long long __a0 asm ("$4") = ARGIFY (arg1); \
- register long long __a1 asm ("$5") = ARGIFY (arg2); \
- register long long __a2 asm ("$6") = ARGIFY (arg3); \
- register long long __a3 asm ("$7"); \
+ register long long int __v0 asm ("$2"); \
+ register long long int __a0 asm ("$4") = _arg1; \
+ register long long int __a1 asm ("$5") = _arg2; \
+ register long long int __a2 asm ("$6") = _arg3; \
+ register long long int __a3 asm ("$7"); \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
#define internal_syscall4(v0_init, input, number, err, \
arg1, arg2, arg3, arg4) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long long __s0 asm ("$16") __attribute__ ((unused)) \
+ long long int _arg1 = ARGIFY (arg1); \
+ long long int _arg2 = ARGIFY (arg2); \
+ long long int _arg3 = ARGIFY (arg3); \
+ long long int _arg4 = ARGIFY (arg4); \
+ register long long int __s0 asm ("$16") __attribute__ ((unused))\
= (number); \
- register long long __v0 asm ("$2"); \
- register long long __a0 asm ("$4") = ARGIFY (arg1); \
- register long long __a1 asm ("$5") = ARGIFY (arg2); \
- register long long __a2 asm ("$6") = ARGIFY (arg3); \
- register long long __a3 asm ("$7") = ARGIFY (arg4); \
+ register long long int __v0 asm ("$2"); \
+ register long long int __a0 asm ("$4") = _arg1; \
+ register long long int __a1 asm ("$5") = _arg2; \
+ register long long int __a2 asm ("$6") = _arg3; \
+ register long long int __a3 asm ("$7") = _arg4; \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
#define internal_syscall5(v0_init, input, number, err, \
arg1, arg2, arg3, arg4, arg5) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long long __s0 asm ("$16") __attribute__ ((unused)) \
+ long long int _arg1 = ARGIFY (arg1); \
+ long long int _arg2 = ARGIFY (arg2); \
+ long long int _arg3 = ARGIFY (arg3); \
+ long long int _arg4 = ARGIFY (arg4); \
+ long long int _arg5 = ARGIFY (arg5); \
+ register long long int __s0 asm ("$16") __attribute__ ((unused))\
= (number); \
- register long long __v0 asm ("$2"); \
- register long long __a0 asm ("$4") = ARGIFY (arg1); \
- register long long __a1 asm ("$5") = ARGIFY (arg2); \
- register long long __a2 asm ("$6") = ARGIFY (arg3); \
- register long long __a3 asm ("$7") = ARGIFY (arg4); \
- register long long __a4 asm ("$8") = ARGIFY (arg5); \
+ register long long int __v0 asm ("$2"); \
+ register long long int __a0 asm ("$4") = _arg1; \
+ register long long int __a1 asm ("$5") = _arg2; \
+ register long long int __a2 asm ("$6") = _arg3; \
+ register long long int __a3 asm ("$7") = _arg4; \
+ register long long int __a4 asm ("$8") = _arg5; \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
#define internal_syscall6(v0_init, input, number, err, \
arg1, arg2, arg3, arg4, arg5, arg6) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long long __s0 asm ("$16") __attribute__ ((unused)) \
+ long long int _arg1 = ARGIFY (arg1); \
+ long long int _arg2 = ARGIFY (arg2); \
+ long long int _arg3 = ARGIFY (arg3); \
+ long long int _arg4 = ARGIFY (arg4); \
+ long long int _arg5 = ARGIFY (arg5); \
+ long long int _arg6 = ARGIFY (arg6); \
+ register long long int __s0 asm ("$16") __attribute__ ((unused))\
= (number); \
- register long long __v0 asm ("$2"); \
- register long long __a0 asm ("$4") = ARGIFY (arg1); \
- register long long __a1 asm ("$5") = ARGIFY (arg2); \
- register long long __a2 asm ("$6") = ARGIFY (arg3); \
- register long long __a3 asm ("$7") = ARGIFY (arg4); \
- register long long __a4 asm ("$8") = ARGIFY (arg5); \
- register long long __a5 asm ("$9") = ARGIFY (arg6); \
+ register long long int __v0 asm ("$2"); \
+ register long long int __a0 asm ("$4") = _arg1; \
+ register long long int __a1 asm ("$5") = _arg2; \
+ register long long int __a2 asm ("$6") = _arg3; \
+ register long long int __a3 asm ("$7") = _arg4; \
+ register long long int __a4 asm ("$8") = _arg5; \
+ register long long int __a5 asm ("$9") = _arg6; \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
#define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...) \
({ \
long _ret = funcptr (args); \
- err = ((unsigned long) (_ret) >= (unsigned long) -4095L); \
+ err = ((unsigned long) (_ret) >= (unsigned long int) -4095L); \
if (err) \
_ret = -_ret; \
_ret; \
#undef INLINE_SYSCALL
#define INLINE_SYSCALL(name, nr, args...) \
({ INTERNAL_SYSCALL_DECL (_sc_err); \
- long result_var = INTERNAL_SYSCALL (name, _sc_err, nr, args); \
+ long int result_var = INTERNAL_SYSCALL (name, _sc_err, nr, args); \
if ( INTERNAL_SYSCALL_ERROR_P (result_var, _sc_err) ) \
{ \
__set_errno (INTERNAL_SYSCALL_ERRNO (result_var, _sc_err)); \
result_var; })
#undef INTERNAL_SYSCALL_DECL
-#define INTERNAL_SYSCALL_DECL(err) long err __attribute__ ((unused))
+#define INTERNAL_SYSCALL_DECL(err) long int err __attribute__ ((unused))
#undef INTERNAL_SYSCALL_ERROR_P
-#define INTERNAL_SYSCALL_ERROR_P(val, err) ((void) (val), (long) (err))
+#define INTERNAL_SYSCALL_ERROR_P(val, err) ((void) (val), (long int) (err))
#undef INTERNAL_SYSCALL_ERRNO
#define INTERNAL_SYSCALL_ERRNO(val, err) ((void) (err), val)
#define internal_syscall0(v0_init, input, number, err, dummy...) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long __s0 asm ("$16") __attribute__ ((unused)) \
+ register long int __s0 asm ("$16") __attribute__ ((unused)) \
= (number); \
- register long __v0 asm ("$2"); \
- register long __a3 asm ("$7"); \
+ register long int __v0 asm ("$2"); \
+ register long int __a3 asm ("$7"); \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
#define internal_syscall1(v0_init, input, number, err, arg1) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long __s0 asm ("$16") __attribute__ ((unused)) \
+ long int _arg1 = (long int) (arg1); \
+ register long int __s0 asm ("$16") __attribute__ ((unused)) \
= (number); \
- register long __v0 asm ("$2"); \
- register long __a0 asm ("$4") = (long) (arg1); \
- register long __a3 asm ("$7"); \
+ register long int __v0 asm ("$2"); \
+ register long int __a0 asm ("$4") = _arg1; \
+ register long int __a3 asm ("$7"); \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
#define internal_syscall2(v0_init, input, number, err, arg1, arg2) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long __s0 asm ("$16") __attribute__ ((unused)) \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
+ register long int __s0 asm ("$16") __attribute__ ((unused)) \
= (number); \
- register long __v0 asm ("$2"); \
- register long __a0 asm ("$4") = (long) (arg1); \
- register long __a1 asm ("$5") = (long) (arg2); \
- register long __a3 asm ("$7"); \
+ register long int __v0 asm ("$2"); \
+ register long int __a0 asm ("$4") = _arg1; \
+ register long int __a1 asm ("$5") = _arg2; \
+ register long int __a3 asm ("$7"); \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
#define internal_syscall3(v0_init, input, number, err, \
arg1, arg2, arg3) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long __s0 asm ("$16") __attribute__ ((unused)) \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
+ long int _arg3 = (long int) (arg3); \
+ register long int __s0 asm ("$16") __attribute__ ((unused)) \
= (number); \
- register long __v0 asm ("$2"); \
- register long __a0 asm ("$4") = (long) (arg1); \
- register long __a1 asm ("$5") = (long) (arg2); \
- register long __a2 asm ("$6") = (long) (arg3); \
- register long __a3 asm ("$7"); \
+ register long int __v0 asm ("$2"); \
+ register long int __a0 asm ("$4") = _arg1; \
+ register long int __a1 asm ("$5") = _arg2; \
+ register long int __a2 asm ("$6") = _arg3; \
+ register long int __a3 asm ("$7"); \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
#define internal_syscall4(v0_init, input, number, err, \
arg1, arg2, arg3, arg4) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long __s0 asm ("$16") __attribute__ ((unused)) \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
+ long int _arg3 = (long int) (arg3); \
+ long int _arg4 = (long int) (arg4); \
+ register long int __s0 asm ("$16") __attribute__ ((unused)) \
= (number); \
- register long __v0 asm ("$2"); \
- register long __a0 asm ("$4") = (long) (arg1); \
- register long __a1 asm ("$5") = (long) (arg2); \
- register long __a2 asm ("$6") = (long) (arg3); \
- register long __a3 asm ("$7") = (long) (arg4); \
+ register long int __v0 asm ("$2"); \
+ register long int __a0 asm ("$4") = _arg1; \
+ register long int __a1 asm ("$5") = _arg2; \
+ register long int __a2 asm ("$6") = _arg3; \
+ register long int __a3 asm ("$7") = _arg4; \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
#define internal_syscall5(v0_init, input, number, err, \
arg1, arg2, arg3, arg4, arg5) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long __s0 asm ("$16") __attribute__ ((unused)) \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
+ long int _arg3 = (long int) (arg3); \
+ long int _arg4 = (long int) (arg4); \
+ long int _arg5 = (long int) (arg5); \
+ register long int __s0 asm ("$16") __attribute__ ((unused)) \
= (number); \
- register long __v0 asm ("$2"); \
- register long __a0 asm ("$4") = (long) (arg1); \
- register long __a1 asm ("$5") = (long) (arg2); \
- register long __a2 asm ("$6") = (long) (arg3); \
- register long __a3 asm ("$7") = (long) (arg4); \
- register long __a4 asm ("$8") = (long) (arg5); \
+ register long int __v0 asm ("$2"); \
+ register long int __a0 asm ("$4") = _arg1; \
+ register long int __a1 asm ("$5") = _arg2; \
+ register long int __a2 asm ("$6") = _arg3; \
+ register long int __a3 asm ("$7") = _arg4; \
+ register long int __a4 asm ("$8") = _arg5; \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
#define internal_syscall6(v0_init, input, number, err, \
arg1, arg2, arg3, arg4, arg5, arg6) \
({ \
- long _sys_result; \
+ long int _sys_result; \
\
{ \
- register long __s0 asm ("$16") __attribute__ ((unused)) \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
+ long int _arg3 = (long int) (arg3); \
+ long int _arg4 = (long int) (arg4); \
+ long int _arg5 = (long int) (arg5); \
+ long int _arg6 = (long int) (arg6); \
+ register long int __s0 asm ("$16") __attribute__ ((unused)) \
= (number); \
- register long __v0 asm ("$2"); \
- register long __a0 asm ("$4") = (long) (arg1); \
- register long __a1 asm ("$5") = (long) (arg2); \
- register long __a2 asm ("$6") = (long) (arg3); \
- register long __a3 asm ("$7") = (long) (arg4); \
- register long __a4 asm ("$8") = (long) (arg5); \
- register long __a5 asm ("$9") = (long) (arg6); \
+ register long int __v0 asm ("$2"); \
+ register long int __a0 asm ("$4") = _arg1; \
+ register long int __a1 asm ("$5") = _arg2; \
+ register long int __a2 asm ("$6") = _arg3; \
+ register long int __a3 asm ("$7") = _arg4; \
+ register long int __a4 asm ("$8") = _arg5; \
+ register long int __a5 asm ("$9") = _arg6; \
__asm__ volatile ( \
".set\tnoreorder\n\t" \
v0_init \
#define INTERNAL_VSYSCALL_CALL(funcptr, err, nr, args...) \
({ \
long _ret = funcptr (args); \
- err = ((unsigned long) (_ret) >= (unsigned long) -4095L); \
+ err = ((unsigned long) (_ret) >= (unsigned long int) -4095L); \
if (err) \
_ret = -_ret; \
_ret; \
#include <sys/asm.h>
/* Usage:
- long syscall (syscall_number, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
+ long int syscall (syscall_number, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
We need to do some arg shifting, syscall_number will be in v0. */
/* Non cancellable read syscall. */
__typeof (__read) __read_nocancel;
+/* Non cancellable pread syscall (LFS version). */
+__typeof (__pread64) __pread64_nocancel;
+
/* Uncancelable write. */
__typeof (__write) __write_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)
--- /dev/null
+/* 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)
# define internal_syscall1(number, err, arg0) \
({ \
long int _sys_result; \
+ long int _arg0 = (long int) (arg0); \
\
{ \
register long int __a7 asm ("a7") = number; \
- register long int __a0 asm ("a0") = (long int) (arg0); \
+ register long int __a0 asm ("a0") = _arg0; \
__asm__ volatile ( \
"scall\n\t" \
: "+r" (__a0) \
# define internal_syscall2(number, err, arg0, arg1) \
({ \
long int _sys_result; \
+ long int _arg0 = (long int) (arg0); \
+ long int _arg1 = (long int) (arg1); \
\
{ \
register long int __a7 asm ("a7") = number; \
- register long int __a0 asm ("a0") = (long int) (arg0); \
- register long int __a1 asm ("a1") = (long int) (arg1); \
+ register long int __a0 asm ("a0") = _arg0; \
+ register long int __a1 asm ("a1") = _arg1; \
__asm__ volatile ( \
"scall\n\t" \
: "+r" (__a0) \
# define internal_syscall3(number, err, arg0, arg1, arg2) \
({ \
long int _sys_result; \
+ long int _arg0 = (long int) (arg0); \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
\
{ \
register long int __a7 asm ("a7") = number; \
- register long int __a0 asm ("a0") = (long int) (arg0); \
- register long int __a1 asm ("a1") = (long int) (arg1); \
- register long int __a2 asm ("a2") = (long int) (arg2); \
+ register long int __a0 asm ("a0") = _arg0; \
+ register long int __a1 asm ("a1") = _arg1; \
+ register long int __a2 asm ("a2") = _arg2; \
__asm__ volatile ( \
"scall\n\t" \
: "+r" (__a0) \
# define internal_syscall4(number, err, arg0, arg1, arg2, arg3) \
({ \
long int _sys_result; \
+ long int _arg0 = (long int) (arg0); \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
+ long int _arg3 = (long int) (arg3); \
\
{ \
register long int __a7 asm ("a7") = number; \
- register long int __a0 asm ("a0") = (long int) (arg0); \
- register long int __a1 asm ("a1") = (long int) (arg1); \
- register long int __a2 asm ("a2") = (long int) (arg2); \
- register long int __a3 asm ("a3") = (long int) (arg3); \
+ register long int __a0 asm ("a0") = _arg0; \
+ register long int __a1 asm ("a1") = _arg1; \
+ register long int __a2 asm ("a2") = _arg2; \
+ register long int __a3 asm ("a3") = _arg3; \
__asm__ volatile ( \
"scall\n\t" \
: "+r" (__a0) \
# define internal_syscall5(number, err, arg0, arg1, arg2, arg3, arg4) \
({ \
long int _sys_result; \
+ long int _arg0 = (long int) (arg0); \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
+ long int _arg3 = (long int) (arg3); \
+ long int _arg4 = (long int) (arg4); \
\
{ \
register long int __a7 asm ("a7") = number; \
- register long int __a0 asm ("a0") = (long int) (arg0); \
- register long int __a1 asm ("a1") = (long int) (arg1); \
- register long int __a2 asm ("a2") = (long int) (arg2); \
- register long int __a3 asm ("a3") = (long int) (arg3); \
- register long int __a4 asm ("a4") = (long int) (arg4); \
+ register long int __a0 asm ("a0") = _arg0; \
+ register long int __a1 asm ("a1") = _arg1; \
+ register long int __a2 asm ("a2") = _arg2; \
+ register long int __a3 asm ("a3") = _arg3; \
+ register long int __a4 asm ("a4") = _arg4; \
__asm__ volatile ( \
"scall\n\t" \
: "+r" (__a0) \
# define internal_syscall6(number, err, arg0, arg1, arg2, arg3, arg4, arg5) \
({ \
long int _sys_result; \
+ long int _arg0 = (long int) (arg0); \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
+ long int _arg3 = (long int) (arg3); \
+ long int _arg4 = (long int) (arg4); \
+ long int _arg5 = (long int) (arg5); \
\
{ \
register long int __a7 asm ("a7") = number; \
- register long int __a0 asm ("a0") = (long int) (arg0); \
- register long int __a1 asm ("a1") = (long int) (arg1); \
- register long int __a2 asm ("a2") = (long int) (arg2); \
- register long int __a3 asm ("a3") = (long int) (arg3); \
- register long int __a4 asm ("a4") = (long int) (arg4); \
- register long int __a5 asm ("a5") = (long int) (arg5); \
+ register long int __a0 asm ("a0") = _arg0; \
+ register long int __a1 asm ("a1") = _arg1; \
+ register long int __a2 asm ("a2") = _arg2; \
+ register long int __a3 asm ("a3") = _arg3; \
+ register long int __a4 asm ("a4") = _arg4; \
+ register long int __a5 asm ("a5") = _arg5; \
__asm__ volatile ( \
"scall\n\t" \
: "+r" (__a0) \
# define internal_syscall7(number, err, arg0, arg1, arg2, arg3, arg4, arg5, arg6) \
({ \
long int _sys_result; \
+ long int _arg0 = (long int) (arg0); \
+ long int _arg1 = (long int) (arg1); \
+ long int _arg2 = (long int) (arg2); \
+ long int _arg3 = (long int) (arg3); \
+ long int _arg4 = (long int) (arg4); \
+ long int _arg5 = (long int) (arg5); \
+ long int _arg6 = (long int) (arg6); \
\
{ \
register long int __a7 asm ("a7") = number; \
- register long int __a0 asm ("a0") = (long int) (arg0); \
- register long int __a1 asm ("a1") = (long int) (arg1); \
- register long int __a2 asm ("a2") = (long int) (arg2); \
- register long int __a3 asm ("a3") = (long int) (arg3); \
- register long int __a4 asm ("a4") = (long int) (arg4); \
- register long int __a5 asm ("a5") = (long int) (arg5); \
- register long int __a6 asm ("a6") = (long int) (arg6); \
+ register long int __a0 asm ("a0") = _arg0; \
+ register long int __a1 asm ("a1") = _arg1; \
+ register long int __a2 asm ("a2") = _arg2; \
+ register long int __a3 asm ("a3") = _arg3; \
+ register long int __a4 asm ("a4") = _arg4; \
+ register long int __a5 asm ("a5") = _arg5; \
+ register long int __a6 asm ("a6") = _arg6; \
__asm__ volatile ( \
"scall\n\t" \
: "+r" (__a0) \
#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)
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]
{
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. */
sysdep_routines += getshmlba
endif
+ifeq ($(subdir),signal)
+sysdep_routines += sigreturn_stub
+endif
+
ifeq ($(subdir),nptl)
# pull in __syscall_error routine
-libpthread-routines += sysdep
-libpthread-shared-only-routines += sysdep
+libpthread-routines += sysdep sigreturn_stub
+libpthread-shared-only-routines += sysdep sigreturn_stub
endif
#include <kernel_sigaction.h>
#include <sysdep.h>
-static void __rt_sigreturn_stub (void);
-static void __sigreturn_stub (void);
+void __rt_sigreturn_stub (void);
+void __sigreturn_stub (void);
#define STUB(act, sigsetsize) \
(act) ? ((unsigned long)((act->sa_flags & SA_SIGINFO) \
(sigsetsize)
#include <sysdeps/unix/sysv/linux/sigaction.c>
-
-static
-inhibit_stack_protector
-void
-__rt_sigreturn_stub (void)
-{
- __asm__ ("mov %0, %%g1\n\t"
- "ta 0x10\n\t"
- : /* no outputs */
- : "i" (__NR_rt_sigreturn));
-}
-
-static
-inhibit_stack_protector
-void
-__sigreturn_stub (void)
-{
- __asm__ ("mov %0, %%g1\n\t"
- "ta 0x10\n\t"
- : /* no outputs */
- : "i" (__NR_sigreturn));
-}
--- /dev/null
+/* Sigreturn stub function used on sa_restore field.
+ 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; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+/* These functions must not change the register window or the stack
+ pointer [1].
+
+ [1] https://lkml.org/lkml/2016/5/27/465 */
+
+ENTRY (__rt_sigreturn_stub)
+ mov __NR_rt_sigreturn, %g1
+ ta 0x10
+END (__rt_sigreturn_stub)
+
+ENTRY (__sigreturn_stub)
+ mov __NR_sigreturn, %g1
+ ta 0x10
+END (__sigreturn_stub)
#include <syscall.h>
#include <sysdep.h>
-static void __rt_sigreturn_stub (void);
+/* Defined on sigreturn_stub.S. */
+void __rt_sigreturn_stub (void);
#define STUB(act, sigsetsize) \
(((unsigned long) &__rt_sigreturn_stub) - 8), \
(sigsetsize)
#include <sysdeps/unix/sysv/linux/sigaction.c>
-
-static
-inhibit_stack_protector
-void
-__rt_sigreturn_stub (void)
-{
- __asm__ ("mov %0, %%g1\n\t"
- "ta 0x6d\n\t"
- : /* no outputs */
- : "i" (__NR_rt_sigreturn));
-}
--- /dev/null
+/* Sigreturn stub function used on sa_restore field.
+ 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; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+/* This function must not change the register window or the stack
+ pointer [1].
+
+ [1] https://lkml.org/lkml/2016/5/27/465 */
+
+ENTRY (__rt_sigreturn_stub)
+ mov __NR_rt_sigreturn, %g1
+ ta 0x6d
+END (__rt_sigreturn_stub)
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);
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;
$(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)"' \