Package: release.debian.org Severity: normal X-Debbugs-Cc: gl...@packages.debian.org Control: affects -1 + src:glibc User: release.debian....@packages.debian.org Usertags: unblock
Please pre-approve unblocking of package glibc/2.41-8 [ Reason ] * The upstream stable branch got a few fixes since the last upload and this update pulls them into the debian package. From the changelog: - Fix elf/tst-audit10 test failure on x86 systems without AVX. Closes: #1103303. => This fixes an issue reported by the reproducible builds team, basically the testsuite doesn't run anymore on a host without AVX. This is relatively recent so it went unnoticed, and has been introduced by GCC changes. This comes with additional tests. - Fix pthread_getattr_np failure when executable stack tunable is set. => This fix an issue introduced with the recently added tunable option to make the stack executable. This issue has been reported upstream from a Debian system: https://sourceware.org/bugzilla/show_bug.cgi?id=32897 * In addition to the upstream changes there is also a debconf translation update, and a small change to the debhelper.mk to fix the content of the NEWS.Debian.gz (#1104099). * Finally there are also some Hurd related changes, but they only touches code that is not built on Linux. [ Impact ] If the unblock isn't granted: - Users will get the wrong documentation to make the stack executable - Difference with the upstream stable branch will increase, which might make future updates more complicated (e.g. for a security fix). [ Tests ] The pthread_getattr_np changes comes with additional upstream tests. [ Risks ] I believe the risks are quite low, the changes only affect the ld.so binary, and the version number in the libc.so binary. Other binaries are bit to bit identical to the previous version. The changes to ld.so are only executed with GLIBC_TUNABLES=glibc.rtld.execstack=2. [ Checklist ] [x] all changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in testing [ Other info ] It took me some time to prepare this request, and in the meantime the d-i udeb freeze email arrived. I am fine with any ordering. unblock glibc/2.41-8
diff --git a/debian/changelog b/debian/changelog index bbc1004d..fe504c81 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,34 @@ +glibc (2.41-8) unstable; urgency=medium + + [ Samuel Thibault ] + * debian/testsuite-xfail-debian.mk: xfail tst-execstack-prog-static-tunable + on hurd-any. Drop duplicate unsupported stances commited uptream. + * debian/patches/hurd-i386/git-dup-refcnt.diff: Fix detecting too many dups. + * debian/patches/hurd-i386/git-xstate.diff: Fix restoring SSE state on + signals. + * debian/patches/hurd-i386/local-intr-msg-clobber.diff: Drop now-useless + patch. + * debian/patches/hurd-i386/git-utime-EINVAL.diff: Make *utime*s catch invalid + times. + * debian/patches/hurd-i386/git-xstate-initialized.diff: Fix crash in dash. + * debian/patches/hurd-i386/git-signal-fpe-exceptions.diff: Fix crash in FPE + handlers. + * debian/patches/hurd-i386/git-symlink-eexist.diff: Fix gnulib testsuite. + + [ Adriano Rafael Gomes ] + * Update Brazilian Portuguese debconf translation. Closes: #1103446. + + [ Aurelien Jarno ] + * debian/rules.d/debhelper.mk: do not replace LIBC in debhelper.in files. + This was used for lintian overrides, but it is not used anymore. Closes: + #1104099. + * debian/patches/git-updates.diff: update from upstream stable branch: + - Fix elf/tst-audit10 test failure on x86 systems without AVX. Closes: + #1103303. + - Fix pthread_getattr_np failure when executable stack tunable is set. + + -- Aurelien Jarno <aure...@debian.org> Sat, 10 May 2025 12:45:57 +0200 + glibc (2.41-7) unstable; urgency=medium [ Samuel Thibault ] diff --git a/debian/patches/git-updates.diff b/debian/patches/git-updates.diff index 80295b6a..ea94532b 100644 --- a/debian/patches/git-updates.diff +++ b/debian/patches/git-updates.diff @@ -22,10 +22,10 @@ index d0108d2caa..aa547a443f 100644 $(common-objdir):$(subst $(empty) ,:,$(patsubst ../$(subdir),.,$(rpath-dirs:%=$(common-objpfx)%))) else # build-static diff --git a/NEWS b/NEWS -index b11422b060..8740f5956a 100644 +index b11422b060..51586aaad7 100644 --- a/NEWS +++ b/NEWS -@@ -5,6 +5,28 @@ See the end for copying conditions. +@@ -5,6 +5,31 @@ See the end for copying conditions. Please send GNU C library bug reports via <https://sourceware.org/bugzilla/> using `glibc' in the "product" field. @@ -50,6 +50,9 @@ index b11422b060..8740f5956a 100644 + [32782] nptl: Race conditions in pthread cancellation causing crash + [32786] nptl: PTHREAD_COND_INITIALIZER compatibility with pre-2.41 versions + [32810] Crash on x86-64 if XSAVEC disable via tunable ++ [32882] tst-audit10 fails with SIGILL on CPUs without AVX ++ [32897] dynamic-link: pthread_getattr_np fails when executable stack ++ tunable is set + Version 2.41 @@ -986,7 +989,7 @@ index 4b1d0d8741..3a3ae56a24 100644 $(objpfx)tst-piemod1.so: $(libsupport) diff --git a/elf/dl-execstack-tunable.c b/elf/dl-execstack-tunable.c new file mode 100644 -index 0000000000..6cef1a3036 +index 0000000000..e3b638aeaa --- /dev/null +++ b/elf/dl-execstack-tunable.c @@ -0,0 +1,39 @@ @@ -1023,12 +1026,47 @@ index 0000000000..6cef1a3036 + break; + + case stack_tunable_mode_force: -+ if (_dl_make_stack_executable (&__libc_stack_end) != 0) ++ if (_dl_make_stack_executable (__libc_stack_end) != 0) + _dl_fatal_printf ( +"Fatal glibc error: cannot enable executable stack as tunable requires"); + break; + } +} +diff --git a/elf/dl-execstack.c b/elf/dl-execstack.c +index e4d7dbe7f8..ceec5b2def 100644 +--- a/elf/dl-execstack.c ++++ b/elf/dl-execstack.c +@@ -23,7 +23,7 @@ + so as to mprotect it. */ + + int +-_dl_make_stack_executable (void **stack_endp) ++_dl_make_stack_executable (const void *stack_endp) + { + return ENOSYS; + } +diff --git a/elf/dl-load.c b/elf/dl-load.c +index f905578a65..945dd8a231 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -945,7 +945,7 @@ struct link_map * + _dl_map_object_from_fd (const char *name, const char *origname, int fd, + struct filebuf *fbp, char *realname, + struct link_map *loader, int l_type, int mode, +- void **stack_endp, Lmid_t nsid) ++ const void *stack_endp, Lmid_t nsid) + { + struct link_map *l = NULL; + const ElfW(Ehdr) *header; +@@ -2180,7 +2180,7 @@ _dl_map_object (struct link_map *loader, const char *name, + + void *stack_end = __libc_stack_end; + return _dl_map_object_from_fd (name, origname, fd, &fb, realname, loader, +- type, mode, &stack_end, nsid); ++ type, mode, stack_end, nsid); + } + + struct add_path_state diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c index e34bf5f7ce..758bf9893e 100644 --- a/elf/dl-reloc-static-pie.c @@ -2784,10 +2822,10 @@ index 0000000000..7fb40fdd9e +END (__memset_sve_zva64) +#endif diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h -index e871f27ff2..4b44beb3f4 100644 +index e871f27ff2..ddb34a1588 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h -@@ -695,6 +695,19 @@ extern const ElfW(Phdr) *_dl_phdr; +@@ -695,10 +695,23 @@ extern const ElfW(Phdr) *_dl_phdr; extern size_t _dl_phnum; #endif @@ -2807,6 +2845,11 @@ index e871f27ff2..4b44beb3f4 100644 /* This function changes the permission of the memory region pointed by STACK_ENDP to executable and update the internal memory protection flags for future thread stack creation. */ +-int _dl_make_stack_executable (void **stack_endp) attribute_hidden; ++int _dl_make_stack_executable (const void *stack_endp) attribute_hidden; + + /* Variable pointing to the end of the stack (or close to it). This value + must be constant over the runtime of the application. Some programs diff --git a/sysdeps/ieee754/dbl-64/e_atanh.c b/sysdeps/ieee754/dbl-64/e_atanh.c index 1e09e46f0f..d1c71b2aa4 100644 --- a/sysdeps/ieee754/dbl-64/e_atanh.c @@ -2949,6 +2992,25 @@ index dfe56fc2a0..5ee1d6f35e 100644 { if (sgn) return -st[j].rh - st[j].rl; +diff --git a/sysdeps/mach/hurd/dl-execstack.c b/sysdeps/mach/hurd/dl-execstack.c +index 0617d3a161..dc4719bd38 100644 +--- a/sysdeps/mach/hurd/dl-execstack.c ++++ b/sysdeps/mach/hurd/dl-execstack.c +@@ -26,12 +26,11 @@ extern struct hurd_startup_data *_dl_hurd_data attribute_hidden; + so as to mprotect it. */ + + int +-_dl_make_stack_executable (void **stack_endp) ++_dl_make_stack_executable (const void *stack_endp) + { + /* Challenge the caller. */ +- if (__builtin_expect (*stack_endp != __libc_stack_end, 0)) ++ if (__glibc_unlikely (stack_endp != __libc_stack_end)) + return EPERM; +- *stack_endp = NULL; + + #if IS_IN (rtld) + if (__mprotect ((void *)_dl_hurd_data->stack_base, _dl_hurd_data->stack_size, diff --git a/sysdeps/nptl/bits/thread-shared-types.h b/sysdeps/nptl/bits/thread-shared-types.h index 7c24c0a6be..e614c7f3c9 100644 --- a/sysdeps/nptl/bits/thread-shared-types.h @@ -2988,7 +3050,7 @@ index 050b4ab8d1..9ad36cabe9 100644 /* Cleanup buffers */ diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile -index a123e28a57..2e0ce773a0 100644 +index a123e28a57..7fcbc72bc0 100644 --- a/sysdeps/pthread/Makefile +++ b/sysdeps/pthread/Makefile @@ -106,6 +106,7 @@ tests += \ @@ -2999,6 +3061,35 @@ index a123e28a57..2e0ce773a0 100644 tst-cleanup0 \ tst-cleanup1 \ tst-cleanup2 \ +@@ -271,6 +272,7 @@ tests += \ + tst-spin4 \ + tst-spin5 \ + tst-stack1 \ ++ tst-stack2 \ + tst-stdio1 \ + tst-stdio2 \ + tst-thrd-detach \ +@@ -366,6 +368,7 @@ modules-names += \ + tst-atfork4mod \ + tst-create1mod \ + tst-fini1mod \ ++ tst-stack2-mod \ + tst-tls4moda \ + tst-tls4modb \ + # modules-names +@@ -539,4 +542,12 @@ LDFLAGS-tst-create1 = -Wl,-export-dynamic + $(objpfx)tst-create1: $(shared-thread-library) + $(objpfx)tst-create1.out: $(objpfx)tst-create1mod.so + ++$(objpfx)tst-stack2.out: $(objpfx)tst-stack2-mod.so ++$(objpfx)tst-stack2-mod.so: $(shared-thread-library) ++LDFLAGS-tst-stack2-mod.so = -Wl,-z,execstack ++ifeq ($(have-no-error-execstack),yes) ++LDFLAGS-tst-stack2-mod.so += -Wl,--no-error-execstack ++endif ++tst-stack2-ENV = GLIBC_TUNABLES=glibc.rtld.execstack=2 ++ + endif diff --git a/sysdeps/pthread/tst-cancel32.c b/sysdeps/pthread/tst-cancel32.c new file mode 100644 index 0000000000..ab550c16bf @@ -3078,6 +3169,104 @@ index 0000000000..ab550c16bf +} + +#include <support/test-driver.c> +diff --git a/sysdeps/pthread/tst-stack2-mod.c b/sysdeps/pthread/tst-stack2-mod.c +new file mode 100644 +index 0000000000..806fdbcd8d +--- /dev/null ++++ b/sysdeps/pthread/tst-stack2-mod.c +@@ -0,0 +1,39 @@ ++/* Check if pthread_getattr_np works within modules with non-exectuble ++ stacks (BZ 32897). ++ Copyright (C) 2025 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 <pthread.h> ++ ++bool init_result; ++ ++void ++__attribute__ ((constructor)) ++init (void) ++{ ++ pthread_t me = pthread_self (); ++ pthread_attr_t attr; ++ init_result = pthread_getattr_np (me, &attr) == 0; ++} ++ ++int ++mod_func (void) ++{ ++ pthread_t me = pthread_self (); ++ pthread_attr_t attr; ++ return pthread_getattr_np (me, &attr); ++} +diff --git a/sysdeps/pthread/tst-stack2.c b/sysdeps/pthread/tst-stack2.c +new file mode 100644 +index 0000000000..20ab5af166 +--- /dev/null ++++ b/sysdeps/pthread/tst-stack2.c +@@ -0,0 +1,47 @@ ++/* Check if pthread_getattr_np works within modules with non-exectuble ++ stacks (BZ 32897). ++ Copyright (C) 2025 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 <pthread.h> ++#include <stdbool.h> ++#include <support/xdlfcn.h> ++#include <support/check.h> ++ ++static int ++do_test (void) ++{ ++ { ++ pthread_t me = pthread_self (); ++ pthread_attr_t attr; ++ TEST_COMPARE (pthread_getattr_np (me, &attr), 0); ++ } ++ ++ void *h = xdlopen ("tst-stack2-mod.so", RTLD_NOW); ++ ++ bool *init_result = xdlsym (h, "init_result"); ++ TEST_COMPARE (*init_result, true); ++ ++ int (*mod_func)(void) = xdlsym (h, "mod_func"); ++ TEST_COMPARE (mod_func (), 0); ++ ++ xdlclose (h); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> diff --git a/sysdeps/riscv/dl-machine.h b/sysdeps/riscv/dl-machine.h index a30892f080..dcc3e0883b 100644 --- a/sysdeps/riscv/dl-machine.h @@ -3905,6 +4094,33 @@ index 3656e98eda..39b0b3d19c 100644 #endif +diff --git a/sysdeps/unix/sysv/linux/dl-execstack.c b/sysdeps/unix/sysv/linux/dl-execstack.c +index 9791b339ca..6db9601656 100644 +--- a/sysdeps/unix/sysv/linux/dl-execstack.c ++++ b/sysdeps/unix/sysv/linux/dl-execstack.c +@@ -19,10 +19,10 @@ + #include <ldsodefs.h> + + int +-_dl_make_stack_executable (void **stack_endp) ++_dl_make_stack_executable (const void *stack_endp) + { + /* This gives us the highest/lowest page that needs to be changed. */ +- uintptr_t page = ((uintptr_t) *stack_endp ++ uintptr_t page = ((uintptr_t) stack_endp + & -(intptr_t) GLRO(dl_pagesize)); + + if (__mprotect ((void *) page, GLRO(dl_pagesize), +@@ -35,9 +35,6 @@ _dl_make_stack_executable (void **stack_endp) + ) != 0) + return errno; + +- /* Clear the address. */ +- *stack_endp = NULL; +- + /* Remember that we changed the permission. */ + GL(dl_stack_flags) |= PF_X; + diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h index f89e784243..d2ab4cb829 100644 --- a/sysdeps/unix/sysv/linux/rseq-internal.h @@ -4642,6 +4858,18 @@ index 0000000000..f0024c143d +++ b/sysdeps/x86/tst-gnu2-tls2-x86-noxsavexsavec.c @@ -0,0 +1 @@ +#include <elf/tst-gnu2-tls2.c> +diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile +index 9d31685e02..5723ec1847 100644 +--- a/sysdeps/x86_64/Makefile ++++ b/sysdeps/x86_64/Makefile +@@ -142,7 +142,6 @@ CFLAGS-tst-avxmod.c += $(AVX-CFLAGS) + AVX512-CFLAGS = -mavx512f + CFLAGS-tst-audit10-aux.c += $(AVX512-CFLAGS) + CFLAGS-tst-auditmod10a.c += $(AVX512-CFLAGS) +-CFLAGS-tst-auditmod10b.c += $(AVX512-CFLAGS) + CFLAGS-tst-avx512-aux.c += $(AVX512-CFLAGS) + CFLAGS-tst-avx512mod.c += $(AVX512-CFLAGS) + diff --git a/sysdeps/x86_64/dl-tlsdesc-dynamic.h b/sysdeps/x86_64/dl-tlsdesc-dynamic.h index 9965ddd2c0..4f496de8c8 100644 --- a/sysdeps/x86_64/dl-tlsdesc-dynamic.h @@ -4867,3 +5095,149 @@ index 0000000000..5539b6c61c +# define __tanh __tanh_sse2 +#endif +#include <sysdeps/ieee754/dbl-64/s_tanh.c> +diff --git a/sysdeps/x86_64/tst-auditmod10b.c b/sysdeps/x86_64/tst-auditmod10b.c +index 6eb21b6f06..0b994ef0f0 100644 +--- a/sysdeps/x86_64/tst-auditmod10b.c ++++ b/sysdeps/x86_64/tst-auditmod10b.c +@@ -125,7 +125,6 @@ la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, + + #include <tst-audit.h> + +-#ifdef __AVX512F__ + #include <immintrin.h> + #include <cpuid.h> + +@@ -148,9 +147,37 @@ check_avx512 (void) + return (eax & 0xe6) == 0xe6; + } + +-#else +-#include <emmintrin.h> +-#endif ++void ++__attribute__ ((target ("avx512f"))) ++pltenter_avx512f (La_regs *regs, long int *framesizep) ++{ ++ __m512i zero = _mm512_setzero_si512 (); ++ if (memcmp (®s->lr_vector[0], &zero, sizeof (zero)) ++ || memcmp (®s->lr_vector[1], &zero, sizeof (zero)) ++ || memcmp (®s->lr_vector[2], &zero, sizeof (zero)) ++ || memcmp (®s->lr_vector[3], &zero, sizeof (zero)) ++ || memcmp (®s->lr_vector[4], &zero, sizeof (zero)) ++ || memcmp (®s->lr_vector[5], &zero, sizeof (zero)) ++ || memcmp (®s->lr_vector[6], &zero, sizeof (zero)) ++ || memcmp (®s->lr_vector[7], &zero, sizeof (zero))) ++ abort (); ++ ++ for (int i = 0; i < 8; i++) ++ regs->lr_vector[i].zmm[0] ++ = (La_x86_64_zmm) _mm512_set1_epi64 (i + 1); ++ ++ __m512i zmm = _mm512_set1_epi64 (-1); ++ asm volatile ("vmovdqa64 %0, %%zmm0" : : "x" (zmm) : "xmm0" ); ++ asm volatile ("vmovdqa64 %0, %%zmm1" : : "x" (zmm) : "xmm1" ); ++ asm volatile ("vmovdqa64 %0, %%zmm2" : : "x" (zmm) : "xmm2" ); ++ asm volatile ("vmovdqa64 %0, %%zmm3" : : "x" (zmm) : "xmm3" ); ++ asm volatile ("vmovdqa64 %0, %%zmm4" : : "x" (zmm) : "xmm4" ); ++ asm volatile ("vmovdqa64 %0, %%zmm5" : : "x" (zmm) : "xmm5" ); ++ asm volatile ("vmovdqa64 %0, %%zmm6" : : "x" (zmm) : "xmm6" ); ++ asm volatile ("vmovdqa64 %0, %%zmm7" : : "x" (zmm) : "xmm7" ); ++ ++ *framesizep = 1024; ++} + + ElfW(Addr) + pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, +@@ -160,39 +187,33 @@ pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, + printf ("pltenter: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n", + symname, (long int) sym->st_value, ndx, *flags); + +-#ifdef __AVX512F__ + if (check_avx512 () && strcmp (symname, "audit_test") == 0) ++ pltenter_avx512f (regs, framesizep); ++ ++ return sym->st_value; ++} ++ ++void ++__attribute__ ((target ("avx512f"))) ++pltexit_avx512f (const La_regs *inregs, La_retval *outregs) ++{ ++ __m512i zero = _mm512_setzero_si512 (); ++ if (memcmp (&outregs->lrv_vector0, &zero, sizeof (zero))) ++ abort (); ++ ++ for (int i = 0; i < 8; i++) + { +- __m512i zero = _mm512_setzero_si512 (); +- if (memcmp (®s->lr_vector[0], &zero, sizeof (zero)) +- || memcmp (®s->lr_vector[1], &zero, sizeof (zero)) +- || memcmp (®s->lr_vector[2], &zero, sizeof (zero)) +- || memcmp (®s->lr_vector[3], &zero, sizeof (zero)) +- || memcmp (®s->lr_vector[4], &zero, sizeof (zero)) +- || memcmp (®s->lr_vector[5], &zero, sizeof (zero)) +- || memcmp (®s->lr_vector[6], &zero, sizeof (zero)) +- || memcmp (®s->lr_vector[7], &zero, sizeof (zero))) +- abort (); +- +- for (int i = 0; i < 8; i++) +- regs->lr_vector[i].zmm[0] +- = (La_x86_64_zmm) _mm512_set1_epi64 (i + 1); +- +- __m512i zmm = _mm512_set1_epi64 (-1); +- asm volatile ("vmovdqa64 %0, %%zmm0" : : "x" (zmm) : "xmm0" ); +- asm volatile ("vmovdqa64 %0, %%zmm1" : : "x" (zmm) : "xmm1" ); +- asm volatile ("vmovdqa64 %0, %%zmm2" : : "x" (zmm) : "xmm2" ); +- asm volatile ("vmovdqa64 %0, %%zmm3" : : "x" (zmm) : "xmm3" ); +- asm volatile ("vmovdqa64 %0, %%zmm4" : : "x" (zmm) : "xmm4" ); +- asm volatile ("vmovdqa64 %0, %%zmm5" : : "x" (zmm) : "xmm5" ); +- asm volatile ("vmovdqa64 %0, %%zmm6" : : "x" (zmm) : "xmm6" ); +- asm volatile ("vmovdqa64 %0, %%zmm7" : : "x" (zmm) : "xmm7" ); +- +- *framesizep = 1024; ++ __m512i zmm = _mm512_set1_epi64 (i + 1); ++ if (memcmp (&inregs->lr_vector[i], &zmm, sizeof (zmm)) != 0) ++ abort (); + } +-#endif + +- return sym->st_value; ++ outregs->lrv_vector0.zmm[0] ++ = (La_x86_64_zmm) _mm512_set1_epi64 (0x12349876); ++ ++ __m512i zmm = _mm512_set1_epi64 (-1); ++ asm volatile ("vmovdqa64 %0, %%zmm0" : : "x" (zmm) : "xmm0" ); ++ asm volatile ("vmovdqa64 %0, %%zmm1" : : "x" (zmm) : "xmm1" ); + } + + unsigned int +@@ -204,28 +225,8 @@ pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, + symname, (long int) sym->st_value, ndx, + (ptrdiff_t) outregs->int_retval); + +-#ifdef __AVX512F__ + if (check_avx512 () && strcmp (symname, "audit_test") == 0) +- { +- __m512i zero = _mm512_setzero_si512 (); +- if (memcmp (&outregs->lrv_vector0, &zero, sizeof (zero))) +- abort (); +- +- for (int i = 0; i < 8; i++) +- { +- __m512i zmm = _mm512_set1_epi64 (i + 1); +- if (memcmp (&inregs->lr_vector[i], &zmm, sizeof (zmm)) != 0) +- abort (); +- } +- +- outregs->lrv_vector0.zmm[0] +- = (La_x86_64_zmm) _mm512_set1_epi64 (0x12349876); +- +- __m512i zmm = _mm512_set1_epi64 (-1); +- asm volatile ("vmovdqa64 %0, %%zmm0" : : "x" (zmm) : "xmm0" ); +- asm volatile ("vmovdqa64 %0, %%zmm1" : : "x" (zmm) : "xmm1" ); +- } +-#endif ++ pltexit_avx512f (inregs, outregs); + + return 0; + } diff --git a/debian/patches/hurd-i386/git-dup-refcnt.diff b/debian/patches/hurd-i386/git-dup-refcnt.diff new file mode 100644 index 00000000..d50ff690 --- /dev/null +++ b/debian/patches/hurd-i386/git-dup-refcnt.diff @@ -0,0 +1,152 @@ +commit e150ee870907e1c5ded4aad8d22a92a98f59d243 +Author: Zhaoming Luo <zhming...@163.com> +Date: Mon Mar 10 16:44:09 2025 +0800 + + hurd: Check return value of mach_port_mod_refs() in the dup routine of fcntl() + + Message-ID: <20250310084409.24177-1-zhming...@163.com> + +diff --git a/sysdeps/mach/hurd/dup3.c b/sysdeps/mach/hurd/dup3.c +index 22af45b491..49545ae63a 100644 +--- a/sysdeps/mach/hurd/dup3.c ++++ b/sysdeps/mach/hurd/dup3.c +@@ -69,6 +69,7 @@ __dup3 (int fd, int fd2, int flags) + { + /* Get a hold of the destination descriptor. */ + struct hurd_fd *d2; ++ error_t err; + + __mutex_lock (&_hurd_dtable_lock); + +@@ -107,22 +108,51 @@ __dup3 (int fd, int fd2, int flags) + } + else + { +- /* Give the ports each a user ref for the new descriptor. */ +- __mach_port_mod_refs (__mach_task_self (), port, +- MACH_PORT_RIGHT_SEND, 1); +- if (ctty != MACH_PORT_NULL) +- __mach_port_mod_refs (__mach_task_self (), ctty, +- MACH_PORT_RIGHT_SEND, 1); +- +- /* Install the ports and flags in the new descriptor slot. */ +- __spin_lock (&d2->port.lock); +- if (flags & O_CLOEXEC) +- d2->flags = d_flags | FD_CLOEXEC; +- else +- /* dup clears FD_CLOEXEC. */ +- d2->flags = d_flags & ~FD_CLOEXEC; +- _hurd_port_set (&d2->ctty, ctty); +- _hurd_port_locked_set (&d2->port, port); /* Unlocks D2. */ ++ /* Give the io server port a user ref for the new descriptor. */ ++ err = __mach_port_mod_refs (__mach_task_self (), port, ++ MACH_PORT_RIGHT_SEND, 1); ++ ++ if (err == KERN_UREFS_OVERFLOW) ++ fd2 = __hurd_fail (EMFILE); ++ else if (err) ++ fd2 = __hurd_fail (EINVAL); ++ else if (ctty != MACH_PORT_NULL) ++ { ++ /* We have confirmed the io server port has got a user ref ++ count, now give ctty port a user ref for the new ++ descriptor. */ ++ err = __mach_port_mod_refs (__mach_task_self (), ctty, ++ MACH_PORT_RIGHT_SEND, 1); ++ ++ if (err) ++ { ++ /* In this case the io server port has got a ref count ++ but the ctty port failed to get one, so we need to ++ clean the ref count we just assigned. */ ++ __mach_port_mod_refs (__mach_task_self (), port, ++ MACH_PORT_RIGHT_SEND, -1); ++ ++ if (err == KERN_UREFS_OVERFLOW) ++ fd2 = __hurd_fail (EMFILE); ++ else ++ fd2 = __hurd_fail (EINVAL); ++ } ++ } ++ ++ if (!err) ++ { ++ /* The ref counts of the ports are incremented ++ successfully. */ ++ /* Install the ports and flags in the new descriptor slot. */ ++ __spin_lock (&d2->port.lock); ++ if (flags & O_CLOEXEC) ++ d2->flags = d_flags | FD_CLOEXEC; ++ else ++ /* dup clears FD_CLOEXEC. */ ++ d2->flags = d_flags & ~FD_CLOEXEC; ++ _hurd_port_set (&d2->ctty, ctty); ++ _hurd_port_locked_set (&d2->port, port); /* Unlocks D2. */ ++ } + } + } + +diff --git a/sysdeps/mach/hurd/fcntl.c b/sysdeps/mach/hurd/fcntl.c +index a65c190cac..de576af1b7 100644 +--- a/sysdeps/mach/hurd/fcntl.c ++++ b/sysdeps/mach/hurd/fcntl.c +@@ -83,18 +83,47 @@ __libc_fcntl (int fd, int cmd, ...) + result = -1; + else + { +- /* Give the ports each a user ref for the new descriptor. */ +- __mach_port_mod_refs (__mach_task_self (), port, +- MACH_PORT_RIGHT_SEND, 1); +- if (ctty != MACH_PORT_NULL) +- __mach_port_mod_refs (__mach_task_self (), ctty, +- MACH_PORT_RIGHT_SEND, 1); +- +- /* Install the ports and flags in the new descriptor. */ +- if (ctty != MACH_PORT_NULL) +- _hurd_port_set (&new->ctty, ctty); +- new->flags = flags; +- _hurd_port_locked_set (&new->port, port); /* Unlocks NEW. */ ++ /* Give the io server port a user ref for the new descriptor. */ ++ err = __mach_port_mod_refs (__mach_task_self (), port, ++ MACH_PORT_RIGHT_SEND, 1); ++ ++ if (err == KERN_UREFS_OVERFLOW) ++ result = __hurd_fail (EMFILE); ++ else if (err) ++ result = __hurd_fail (EINVAL); ++ else if (ctty != MACH_PORT_NULL) ++ { ++ /* We have confirmed the io server port has got a user ref ++ count, now give ctty port a user ref for the new ++ descriptor. */ ++ err = __mach_port_mod_refs (__mach_task_self (), ctty, ++ MACH_PORT_RIGHT_SEND, 1); ++ ++ if (err) ++ { ++ /* In this case the io server port has got a ref count ++ but the ctty port fails to get one, so we need to clean ++ the ref count we just assigned. */ ++ __mach_port_mod_refs (__mach_task_self (), port, ++ MACH_PORT_RIGHT_SEND, -1); ++ ++ if (err == KERN_UREFS_OVERFLOW) ++ result = __hurd_fail (EMFILE); ++ else ++ result = __hurd_fail (EINVAL); ++ } ++ } ++ ++ if (!err) ++ { ++ /* The ref counts of the ports are incremented successfully. */ ++ /* Install the ports and flags in the new descriptor. */ ++ if (ctty != MACH_PORT_NULL) ++ _hurd_port_set (&new->ctty, ctty); ++ new->flags = flags; ++ /* Unlocks NEW. */ ++ _hurd_port_locked_set (&new->port, port); ++ } + } + + HURD_CRITICAL_END; diff --git a/debian/patches/hurd-i386/git-signal-fpe-exceptions.diff b/debian/patches/hurd-i386/git-signal-fpe-exceptions.diff new file mode 100644 index 00000000..68468271 --- /dev/null +++ b/debian/patches/hurd-i386/git-signal-fpe-exceptions.diff @@ -0,0 +1,46 @@ +Index: glibc-2.41/sysdeps/mach/hurd/x86/trampoline.c +=================================================================== +--- glibc-2.41.orig/sysdeps/mach/hurd/x86/trampoline.c ++++ glibc-2.41/sysdeps/mach/hurd/x86/trampoline.c +@@ -461,7 +461,10 @@ _hurd_setup_sighandler (struct hurd_sigs + - in gdb: gdb/i386-gnu-tdep.c gnu_sigtramp_code. */ + + #ifdef __x86_64__ +-asm ("rpc_wait_trampoline:\n" ++asm ("trampoline:\n" ++ "fnclex\n" /* Clear any pending exception. */ ++ "jmp _trampoline\n" ++ "rpc_wait_trampoline:\n" + /* This is the entry point when we have an RPC reply message to receive + before running the handler. The MACH_MSG_SEND bit has already been + cleared in the OPTION argument in our %rsi. The interrupted user +@@ -480,7 +483,7 @@ asm ("rpc_wait_trampoline:\n" + /* Switch to the signal stack. */ + "movq %rbx, %rsp\n" + +- "trampoline:\n" ++ "_trampoline:\n" + /* Entry point for running the handler normally. The arguments to the + handler function are on the top of the stack, same as in the i386 + version: +@@ -506,7 +509,10 @@ asm ("rpc_wait_trampoline:\n" + "movq 16(%rsp), %rdi\n" + "ret"); + #else +-asm ("rpc_wait_trampoline:\n"); ++asm ("trampoline:\n" ++ "fnclex\n" /* Clear any pending exception. */ ++ "jmp _trampoline\n" ++ "rpc_wait_trampoline:\n"); + /* This is the entry point when we have an RPC reply message to receive + before running the handler. The MACH_MSG_SEND bit has already been + cleared in the OPTION argument on our stack. The interrupted user +@@ -526,7 +532,7 @@ asm (/* Retry the interrupted mach_msg s + /* Switch to the signal stack. */ + "movl %ebx, %esp\n"); + +- asm ("trampoline:\n"); ++asm ("_trampoline:\n"); + /* Entry point for running the handler normally. The arguments to the + handler function are already on the top of the stack: + diff --git a/debian/patches/hurd-i386/git-symlink-eexist.diff b/debian/patches/hurd-i386/git-symlink-eexist.diff new file mode 100644 index 00000000..5e7324fd --- /dev/null +++ b/debian/patches/hurd-i386/git-symlink-eexist.diff @@ -0,0 +1,22 @@ +commit 1eb32c5788a59b821087f971821536a22a3b65de +Author: Samuel Thibault <samuel.thiba...@ens-lyon.org> +Date: Mon Apr 21 22:21:17 2025 +0200 + + hurd: Make symlink return EEXIST on existing target directory + + The gnulib testsuite does not recognize ENOTDIR for such a situation, + and this error is indeed more comprehensible to users. + +diff --git a/sysdeps/mach/hurd/symlinkat.c b/sysdeps/mach/hurd/symlinkat.c +index e7dfb673df..cb6250e6f0 100644 +--- a/sysdeps/mach/hurd/symlinkat.c ++++ b/sysdeps/mach/hurd/symlinkat.c +@@ -47,7 +47,7 @@ __symlinkat (const char *from, int fd, const char *to) + + if (! *name) + /* Can't link to the existing directory itself. */ +- err = ENOTDIR; ++ err = EEXIST; + else + /* Create a new, unlinked node in the target directory. */ + err = __dir_mkfile (dir, O_WRITE, 0777 & ~_hurd_umask, &node); diff --git a/debian/patches/hurd-i386/git-utime-EINVAL.diff b/debian/patches/hurd-i386/git-utime-EINVAL.diff new file mode 100644 index 00000000..5fe9d2d8 --- /dev/null +++ b/debian/patches/hurd-i386/git-utime-EINVAL.diff @@ -0,0 +1,220 @@ +commit 8a0200c833f261e8eb456bbc4f0f5449e1a5e367 +Author: Samuel Thibault <samuel.thiba...@ens-lyon.org> +Date: Tue Mar 18 18:49:21 2025 +0100 + + hurd: Make *utime*s catch invalid times [BZ #32802] + +diff --git a/sysdeps/mach/hurd/futimens.c b/sysdeps/mach/hurd/futimens.c +index 30ef0a6493..12125299c4 100644 +--- a/sysdeps/mach/hurd/futimens.c ++++ b/sysdeps/mach/hurd/futimens.c +@@ -32,7 +32,9 @@ __futimens (int fd, const struct timespec tsp[2]) + struct timespec atime, mtime; + error_t err; + +- utime_ts_from_tspec (tsp, &atime, &mtime); ++ err = utime_ts_from_tspec (tsp, &atime, &mtime); ++ if (err) ++ return err; + + err = HURD_DPORT_USE (fd, __file_utimens (port, atime, mtime)); + +@@ -40,7 +42,9 @@ __futimens (int fd, const struct timespec tsp[2]) + { + time_value_t atim, mtim; + +- utime_tvalue_from_tspec (tsp, &atim, &mtim); ++ err = utime_tvalue_from_tspec (tsp, &atim, &mtim); ++ if (err) ++ return err; + + err = HURD_DPORT_USE (fd, __file_utimes (port, atim, mtim)); + } +diff --git a/sysdeps/mach/hurd/futimes.c b/sysdeps/mach/hurd/futimes.c +index 20f47f3d28..97385d7dd0 100644 +--- a/sysdeps/mach/hurd/futimes.c ++++ b/sysdeps/mach/hurd/futimes.c +@@ -32,7 +32,9 @@ __futimes (int fd, const struct timeval tvp[2]) + struct timespec atime, mtime; + error_t err; + +- utime_ts_from_tval (tvp, &atime, &mtime); ++ err = utime_ts_from_tval (tvp, &atime, &mtime); ++ if (err) ++ return err; + + err = HURD_DPORT_USE (fd, __file_utimens (port, atime, mtime)); + +@@ -40,7 +42,9 @@ __futimes (int fd, const struct timeval tvp[2]) + { + time_value_t atim, mtim; + +- utime_tvalue_from_tval (tvp, &atim, &mtim); ++ err = utime_tvalue_from_tval (tvp, &atim, &mtim); ++ if (err) ++ return err; + + err = HURD_DPORT_USE (fd, __file_utimes (port, atim, mtim)); + } +diff --git a/sysdeps/mach/hurd/utime-helper.c b/sysdeps/mach/hurd/utime-helper.c +index d88bccd786..6afa871197 100644 +--- a/sysdeps/mach/hurd/utime-helper.c ++++ b/sysdeps/mach/hurd/utime-helper.c +@@ -21,8 +21,14 @@ + #include <stddef.h> + #include <sys/time.h> + ++static inline bool ++check_tval (const struct timeval *tvp) ++{ ++ return tvp->tv_usec >= 0 && tvp->tv_usec < USEC_PER_SEC; ++} ++ + /* Initializes atime/mtime timespec structures from an array of timeval. */ +-static inline void ++static inline error_t + utime_ts_from_tval (const struct timeval tvp[2], + struct timespec *atime, struct timespec *mtime) + { +@@ -37,13 +43,19 @@ utime_ts_from_tval (const struct timeval tvp[2], + } + else + { ++ if (!check_tval (&tvp[0])) ++ return EINVAL; ++ if (!check_tval (&tvp[1])) ++ return EINVAL; ++ + TIMEVAL_TO_TIMESPEC (&tvp[0], atime); + TIMEVAL_TO_TIMESPEC (&tvp[1], mtime); + } ++ return 0; + } + + /* Initializes atime/mtime time_value_t structures from an array of timeval. */ +-static inline void ++static inline error_t + utime_tvalue_from_tval (const struct timeval tvp[2], + time_value_t *atime, time_value_t *mtime) + { +@@ -53,11 +65,17 @@ utime_tvalue_from_tval (const struct timeval tvp[2], + atime->microseconds = mtime->microseconds = -1; + else + { ++ if (!check_tval (&tvp[0])) ++ return EINVAL; ++ if (!check_tval (&tvp[1])) ++ return EINVAL; ++ + atime->seconds = tvp[0].tv_sec; + atime->microseconds = tvp[0].tv_usec; + mtime->seconds = tvp[1].tv_sec; + mtime->microseconds = tvp[1].tv_usec; + } ++ return 0; + } + + /* Changes the access time of the file behind PORT using a timeval array. */ +@@ -67,7 +85,9 @@ hurd_futimes (const file_t port, const struct timeval tvp[2]) + error_t err; + struct timespec atime, mtime; + +- utime_ts_from_tval (tvp, &atime, &mtime); ++ err = utime_ts_from_tval (tvp, &atime, &mtime); ++ if (err) ++ return err; + + err = __file_utimens (port, atime, mtime); + +@@ -75,7 +95,9 @@ hurd_futimes (const file_t port, const struct timeval tvp[2]) + { + time_value_t atim, mtim; + +- utime_tvalue_from_tval (tvp, &atim, &mtim); ++ err = utime_tvalue_from_tval (tvp, &atim, &mtim); ++ if (err) ++ return err; + + err = __file_utimes (port, atim, mtim); + } +@@ -83,8 +105,16 @@ hurd_futimes (const file_t port, const struct timeval tvp[2]) + return err; + } + ++static inline bool ++check_tspec (const struct timespec *tsp) ++{ ++ return tsp->tv_nsec == UTIME_NOW ++ || tsp->tv_nsec == UTIME_OMIT ++ || tsp->tv_nsec >= 0 && tsp->tv_nsec < NSEC_PER_SEC; ++} ++ + /* Initializes atime/mtime timespec structures from an array of timespec. */ +-static inline void ++static inline error_t + utime_ts_from_tspec (const struct timespec tsp[2], + struct timespec *atime, struct timespec *mtime) + { +@@ -99,13 +129,19 @@ utime_ts_from_tspec (const struct timespec tsp[2], + } + else + { ++ if (!check_tspec (&tsp[0])) ++ return EINVAL; ++ if (!check_tspec (&tsp[1])) ++ return EINVAL; ++ + *atime = tsp[0]; + *mtime = tsp[1]; + } ++ return 0; + } + + /* Initializes atime/mtime time_value_t structures from an array of timespec. */ +-static inline void ++static inline error_t + utime_tvalue_from_tspec (const struct timespec tsp[2], + time_value_t *atime, time_value_t *mtime) + { +@@ -115,6 +151,11 @@ utime_tvalue_from_tspec (const struct timespec tsp[2], + atime->microseconds = mtime->microseconds = -1; + else + { ++ if (!check_tspec (&tsp[0])) ++ return EINVAL; ++ if (!check_tspec (&tsp[1])) ++ return EINVAL; ++ + if (tsp[0].tv_nsec == UTIME_NOW) + atime->microseconds = -1; + else if (tsp[0].tv_nsec == UTIME_OMIT) +@@ -128,6 +169,7 @@ utime_tvalue_from_tspec (const struct timespec tsp[2], + else + TIMESPEC_TO_TIME_VALUE (mtime, &(tsp[1])); + } ++ return 0; + } + + /* Changes the access time of the file behind PORT using a timespec array. */ +@@ -137,7 +179,9 @@ hurd_futimens (const file_t port, const struct timespec tsp[2]) + error_t err; + struct timespec atime, mtime; + +- utime_ts_from_tspec (tsp, &atime, &mtime); ++ err = utime_ts_from_tspec (tsp, &atime, &mtime); ++ if (err) ++ return err; + + err = __file_utimens (port, atime, mtime); + +@@ -145,7 +189,9 @@ hurd_futimens (const file_t port, const struct timespec tsp[2]) + { + time_value_t atim, mtim; + +- utime_tvalue_from_tspec (tsp, &atim, &mtim); ++ err = utime_tvalue_from_tspec (tsp, &atim, &mtim); ++ if (err) ++ return err; + + err = __file_utimes (port, atim, mtim); + } diff --git a/debian/patches/hurd-i386/git-xstate-initialized.diff b/debian/patches/hurd-i386/git-xstate-initialized.diff new file mode 100644 index 00000000..65f6d31d --- /dev/null +++ b/debian/patches/hurd-i386/git-xstate-initialized.diff @@ -0,0 +1,108 @@ +commit 8d54b428cfe98c21049f94c8af3bf302e44091e9 +Author: Samuel Thibault <samuel.thiba...@ens-lyon.org> +Date: Mon Apr 21 19:42:27 2025 +0200 + + hurd: Do not restore xstate when it is not initialized + + If the process has never used fp before getting a signal, xstate is set + (and thus the x87 state is not initialized) but xstate->initialized is still + 0, and we should not restore anything. + +diff --git a/sysdeps/mach/hurd/i386/sigreturn.c b/sysdeps/mach/hurd/i386/sigreturn.c +index 37fa984070..dc57d6122c 100644 +--- a/sysdeps/mach/hurd/i386/sigreturn.c ++++ b/sysdeps/mach/hurd/i386/sigreturn.c +@@ -126,24 +126,27 @@ __sigreturn (struct sigcontext *scp) + ss->sigaltstack.ss_flags &= ~SS_ONSTACK; + + #ifdef i386_XFLOAT_STATE +- if ((scp->xstate) && (scp->xstate->initialized)) ++ if (scp->xstate) + { +- unsigned eax, ebx, ecx, edx; +- __cpuid_count(0xd, 0, eax, ebx, ecx, edx); +- switch (scp->xstate->fp_save_kind) +- { +- case 0: // FNSAVE +- asm volatile("frstor %0" : : "m" (scp->xstate->hw_state)); +- break; +- case 1: // FXSAVE +- asm volatile("fxrstor %0" : : "m" (scp->xstate->hw_state), \ +- "a" (eax), "d" (edx)); +- break; +- default: // XSAVE, XSAVEOPT, XSAVEC, XSAVES +- asm volatile("xrstor %0" : : "m" (scp->xstate->hw_state), \ +- "a" (eax), "d" (edx)); +- break; +- } ++ if (scp->xstate->initialized) ++ { ++ unsigned eax, ebx, ecx, edx; ++ __cpuid_count(0xd, 0, eax, ebx, ecx, edx); ++ switch (scp->xstate->fp_save_kind) ++ { ++ case 0: // FNSAVE ++ asm volatile("frstor %0" : : "m" (scp->xstate->hw_state)); ++ break; ++ case 1: // FXSAVE ++ asm volatile("fxrstor %0" : : "m" (scp->xstate->hw_state), \ ++ "a" (eax), "d" (edx)); ++ break; ++ default: // XSAVE, XSAVEOPT, XSAVEC, XSAVES ++ asm volatile("xrstor %0" : : "m" (scp->xstate->hw_state), \ ++ "a" (eax), "d" (edx)); ++ break; ++ } ++ } + } + else + #endif +diff --git a/sysdeps/mach/hurd/x86_64/sigreturn.c b/sysdeps/mach/hurd/x86_64/sigreturn.c +index dff8e76dc8..773c00f86d 100644 +--- a/sysdeps/mach/hurd/x86_64/sigreturn.c ++++ b/sysdeps/mach/hurd/x86_64/sigreturn.c +@@ -119,24 +119,27 @@ __sigreturn (struct sigcontext *scp) + ss->sigaltstack.ss_flags &= ~SS_ONSTACK; + + #ifdef i386_XFLOAT_STATE +- if ((scp->xstate) && (scp->xstate->initialized)) ++ if (scp->xstate) + { +- unsigned eax, ebx, ecx, edx; +- __cpuid_count(0xd, 0, eax, ebx, ecx, edx); +- switch (scp->xstate->fp_save_kind) +- { +- case 0: // FNSAVE +- asm volatile("frstor %0" : : "m" (scp->xstate->hw_state)); +- break; +- case 1: // FXSAVE +- asm volatile("fxrstor %0" : : "m" (scp->xstate->hw_state), \ +- "a" (eax), "d" (edx)); +- break; +- default: // XSAVE, XSAVEOPT, XSAVEC, XSAVES +- asm volatile("xrstor %0" : : "m" (scp->xstate->hw_state), \ +- "a" (eax), "d" (edx)); +- break; +- } ++ if (scp->xstate->initialized) ++ { ++ unsigned eax, ebx, ecx, edx; ++ __cpuid_count(0xd, 0, eax, ebx, ecx, edx); ++ switch (scp->xstate->fp_save_kind) ++ { ++ case 0: // FNSAVE ++ asm volatile("frstor %0" : : "m" (scp->xstate->hw_state)); ++ break; ++ case 1: // FXSAVE ++ asm volatile("fxrstor %0" : : "m" (scp->xstate->hw_state), \ ++ "a" (eax), "d" (edx)); ++ break; ++ default: // XSAVE, XSAVEOPT, XSAVEC, XSAVES ++ asm volatile("xrstor %0" : : "m" (scp->xstate->hw_state), \ ++ "a" (eax), "d" (edx)); ++ break; ++ } ++ } + } + else + #endif diff --git a/debian/patches/hurd-i386/git-xstate.diff b/debian/patches/hurd-i386/git-xstate.diff new file mode 100644 index 00000000..d2caa989 --- /dev/null +++ b/debian/patches/hurd-i386/git-xstate.diff @@ -0,0 +1,648 @@ +commit 6d6a6e2dd2133908e3f5cb8a2ed817ccb2a0bb06 +Author: Luca Dariz <l...@orpolo.org> +Date: Wed Mar 19 18:11:18 2025 +0100 + + hurd: save xstate during signal handling + + * hurd/Makefile: add new tests + * hurd/test-sig-rpc-interrupted.c: check xstate save and restore in + the case where a signal is delivered to a thread which is waiting + for an rpc. This test implements the rpc interruption protocol used + by the hurd servers. It was so far passing on Debian thanks to the + local-intr-msg-clobber.diff patch, which is now obsolete. + * hurd/test-sig-xstate.c: check xstate save and restore in the case + where a signal is delivered to a running thread, making sure that + the xstate is modified in the signal handler. + * hurd/test-xstate.h: add helpers to test xstate + * sysdeps/mach/hurd/i386/bits/sigcontext.h: add xstate to the + sigcontext structure. + + sysdeps/mach/hurd/i386/sigreturn.c: restore xstate from the saved + context + * sysdeps/mach/hurd/x86/trampoline.c: save xstate if + supported. Otherwise we fall back to the previous behaviour of + ignoring xstate. + * sysdeps/mach/hurd/x86_64/bits/sigcontext.h: add xstate to the + sigcontext structure. + * sysdeps/mach/hurd/x86_64/sigreturn.c: restore xstate from the saved + context + + Signed-off-by: Luca Dariz <l...@orpolo.org> + Signed-off-by: Samuel Thibault <samuel.thiba...@ens-lyon.org> + Message-ID: <20250319171118.142163-1-l...@orpolo.org> + +diff --git a/hurd/Makefile b/hurd/Makefile +index cf70b8c65c..cbc3c23b1f 100644 +--- a/hurd/Makefile ++++ b/hurd/Makefile +@@ -19,6 +19,11 @@ subdir := hurd + + include ../Makeconfig + ++tests := test-sig-xstate \ ++ test-sig-rpc-interrupted ++$(objpfx)test-sig-xstate: $(shared-thread-library) ++$(objpfx)test-sig-rpc-interrupted: $(shared-thread-library) $(objdir)/hurd/libhurduser.so ++ + headers = \ + $(interface-headers) \ + hurd.h \ +diff --git a/hurd/test-sig-rpc-interrupted.c b/hurd/test-sig-rpc-interrupted.c +new file mode 100644 +index 0000000000..a89d70e5a4 +--- /dev/null ++++ b/hurd/test-sig-rpc-interrupted.c +@@ -0,0 +1,185 @@ ++/* Test the state save/restore procedures during signal handling when an ++ interruptible RPC is restarted. ++ ++ Copyright (C) 2024 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 <assert.h> ++#include <pthread.h> ++#include <signal.h> ++#include <stdbool.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> ++ ++#include <mach/message.h> ++#include <mach/gnumach.h> ++#include <mach/mach_traps.h> ++#include <mach/mig_errors.h> ++#include <mach-shortcuts.h> ++#include <mach_init.h> ++#include <hurd/io.h> ++#include <hurd/io_reply.h> ++ ++#include <support/check.h> ++#include <support/xthread.h> ++ ++#include "test-xstate.h" ++ ++void handler (int signum, siginfo_t *info, void *context) ++{ ++ printf ("signal %d setting a different CPU state\n", signum); ++ char buf3[XSTATE_BUFFER_SIZE]; ++ memset (buf3, 0x77, XSTATE_BUFFER_SIZE); ++ SET_XSTATE (buf3); ++} ++ ++static const mach_msg_type_t RetCodeCheck = { ++ .msgt_name = (unsigned char) MACH_MSG_TYPE_INTEGER_32, ++ .msgt_size = 32, ++ .msgt_number = 1, ++ .msgt_inline = TRUE, ++ .msgt_longform = FALSE, ++ .msgt_deallocate = FALSE, ++ .msgt_unused = 0 ++}; ++ ++ ++/* Helper thread to simulate a proper RPC interruption during dignal handling */ ++void* fake_interruptor (void *arg) ++{ ++ int err; ++ sigset_t ss; ++ TEST_COMPARE (sigemptyset (&ss), 0); ++ TEST_COMPARE (sigaddset (&ss, SIGUSR1), 0); ++ TEST_COMPARE (sigprocmask (SIG_BLOCK, &ss, NULL), 0); ++ ++ struct { ++ mach_msg_header_t Head; ++ } request; ++ mach_port_t rxport = *((mach_port_t*)arg); ++ err = mach_msg (&request.Head, MACH_RCV_MSG, 0, sizeof (request), rxport, ++ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); ++ TEST_COMPARE (err, MACH_MSG_SUCCESS); ++ TEST_COMPARE (request.Head.msgh_bits, 0x1112); ++ TEST_COMPARE (request.Head.msgh_size, sizeof (request.Head)); ++ TEST_COMPARE (request.Head.msgh_id, 33000); ++ ++ mig_reply_header_t reply; ++ reply.Head = request.Head; ++ reply.Head.msgh_id += 100; ++ reply.RetCodeType = RetCodeCheck; ++ reply.RetCode = KERN_SUCCESS; ++ err = mach_msg (&reply.Head, MACH_SEND_MSG, sizeof (reply), 0, MACH_PORT_NULL, ++ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); ++ TEST_COMPARE (err, MACH_MSG_SUCCESS); ++ ++ return NULL; ++} ++ ++ ++/* Helper thread to send a signal to the main thread in the middle of ++ * an interruptible rpc */ ++void* signal_sender (void *arg) ++{ ++ int err; ++ sigset_t ss; ++ TEST_COMPARE (sigemptyset (&ss), 0); ++ TEST_COMPARE (sigaddset (&ss, SIGUSR1), 0); ++ TEST_COMPARE (sigprocmask (SIG_BLOCK, &ss, NULL), 0); ++ ++ /* Receive the first request, we won't answer to this. */ ++ struct { ++ mach_msg_header_t head; ++ char data[64]; ++ } m1, m2; ++ mach_port_t rxport = *((mach_port_t*)arg); ++ memset (&m1, 0, sizeof (m1)); ++ memset (&m2, 0, sizeof (m2)); ++ err = mach_msg (&m1.head, MACH_RCV_MSG, 0, sizeof (m1), rxport, ++ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); ++ TEST_COMPARE (err, MACH_MSG_SUCCESS); ++ ++ /* interrupt the ongoing rpc with a signal, using the ++ * interruptible rpc protocol */ ++ pthread_t thintr = xpthread_create (NULL, fake_interruptor, arg); ++ TEST_COMPARE (kill (getpid (), SIGUSR1), 0); ++ xpthread_join (thintr); ++ ++ /* Complete the interruption by sending EINTR */ ++ mig_reply_header_t reply; ++ reply.Head = m1.head; ++ reply.Head.msgh_id += 100; ++ reply.RetCodeType = RetCodeCheck; ++ reply.RetCode = EINTR; ++ err = mach_msg (&reply.Head, MACH_SEND_MSG, sizeof (reply), 0, MACH_PORT_NULL, ++ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); ++ TEST_COMPARE (err, MACH_MSG_SUCCESS); ++ ++ /* Receive the retried rpc, and check that it has the same payload ++ * as the first one. Port names might still be different. */ ++ err = mach_msg (&m2.head, MACH_RCV_MSG, 0, sizeof (m2), rxport, ++ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); ++ TEST_COMPARE (m1.head.msgh_bits, m2.head.msgh_bits); ++ TEST_COMPARE (m1.head.msgh_size, m2.head.msgh_size); ++ TEST_COMPARE (m1.head.msgh_id, m2.head.msgh_id); ++ TEST_COMPARE_BLOB (m1.data, sizeof (m1.data), m2.data, sizeof (m2.data)); ++ ++ /* And finally make the rpc succeed by sending a valid reply */ ++ err = io_read_reply (m2.head.msgh_remote_port, MACH_MSG_TYPE_MOVE_SEND_ONCE, ++ KERN_SUCCESS, NULL, 0); ++ TEST_COMPARE (err, MACH_MSG_SUCCESS); ++ ++ return NULL; ++} ++ ++ ++static int do_test (void) ++{ ++#if ! XSTATE_HELPERS_SUPPORTED ++ FAIL_UNSUPPORTED ("Test not supported on this arch."); ++#endif ++ ++ /* Setup signal handling; we need to handle the signal in the main ++ * thread, the other ones will explicitely block SIGUSR1. */ ++ struct sigaction act = { 0 }; ++ act.sa_flags = SA_RESTART; ++ act.sa_sigaction = &handler; ++ TEST_COMPARE (sigaction (SIGUSR1, &act, NULL), 0); ++ ++ mach_port_t fakeio; ++ int err; ++ err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &fakeio); ++ TEST_COMPARE (err, MACH_MSG_SUCCESS); ++ ++ err = mach_port_insert_right (mach_task_self (), fakeio, fakeio, ++ MACH_MSG_TYPE_MAKE_SEND); ++ TEST_COMPARE (err, MACH_MSG_SUCCESS); ++ ++ pthread_t thsender = xpthread_create (NULL, signal_sender, &fakeio); ++ ++ char *buf; ++ mach_msg_type_number_t n; ++ TEST_COMPARE (io_read (fakeio, &buf, &n, 1, 2), 0); ++ ++ xpthread_join (thsender); ++ return EXIT_SUCCESS; ++} ++ ++#include <support/test-driver.c> +diff --git a/hurd/test-sig-xstate.c b/hurd/test-sig-xstate.c +new file mode 100644 +index 0000000000..0a68a44fd7 +--- /dev/null ++++ b/hurd/test-sig-xstate.c +@@ -0,0 +1,94 @@ ++/* Test the state save/restore procedures during signal handling. ++ ++ Copyright (C) 2025 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 <assert.h> ++#include <pthread.h> ++#include <signal.h> ++#include <stdbool.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> ++ ++#include <mach/message.h> ++#include <mach/gnumach.h> ++#include <mach/mach_traps.h> ++#include <mach-shortcuts.h> ++#include <mach_init.h> ++#include <hurd/io.h> ++#include <hurd/io_reply.h> ++ ++#include <support/check.h> ++#include <support/xthread.h> ++ ++#include "test-xstate.h" ++ ++static volatile bool loopflag = true; ++ ++void handler (int signum, siginfo_t *info, void *context) ++{ ++ char buf3[XSTATE_BUFFER_SIZE]; ++ memset (buf3, 0x77, XSTATE_BUFFER_SIZE); ++ SET_XSTATE (buf3); ++ printf ("signal %d setting a different CPU state\n", signum); ++ loopflag = false; ++} ++ ++/* Helper thread to send a signal to the main thread */ ++void* signal_sender (void *arg) ++{ ++ sigset_t ss; ++ assert (! sigemptyset (&ss)); ++ assert (! sigaddset (&ss, SIGUSR1)); ++ assert (! sigprocmask (SIG_BLOCK, &ss, NULL)); ++ ++ TEST_COMPARE (kill (getpid (), SIGUSR1), 0); ++ ++ return NULL; ++} ++ ++static int do_test (void) ++{ ++#if ! XSTATE_HELPERS_SUPPORTED ++ FAIL_UNSUPPORTED ("Test not supported on this arch."); ++#endif ++ ++ struct sigaction act = { 0 }; ++ act.sa_sigaction = &handler; ++ TEST_COMPARE (sigaction (SIGUSR1, &act, NULL), 0); ++ ++ pthread_t thsender = xpthread_create (NULL, signal_sender, NULL); ++ ++ char buf1[XSTATE_BUFFER_SIZE], buf2[XSTATE_BUFFER_SIZE]; ++ memset (buf1, 0x33, XSTATE_BUFFER_SIZE); ++ ++ SET_XSTATE (buf1); ++ ++ while (loopflag) ++ ; ++ ++ GET_XSTATE (buf2); ++ TEST_COMPARE_BLOB (buf1, sizeof (buf1), buf2, sizeof (buf2)); ++ ++ xpthread_join (thsender); ++ return EXIT_SUCCESS; ++} ++ ++#include <support/test-driver.c> +diff --git a/hurd/test-xstate.h b/hurd/test-xstate.h +new file mode 100644 +index 0000000000..a8185dcb07 +--- /dev/null ++++ b/hurd/test-xstate.h +@@ -0,0 +1,40 @@ ++/* Helpers to test XSTATE during signal handling ++ ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <https://www.gnu.org/licenses/>. */ ++ ++#ifndef _TEST_XSTATE_H ++#define _TEST_XSTATE_H ++ ++#if defined __x86_64__ || defined __i386__ ++#define XSTATE_HELPERS_SUPPORTED 1 ++#define XSTATE_BUFFER_SIZE 16 ++#define SET_XSTATE(b) do { \ ++ asm volatile ("movups (%0),%%xmm0" :: "r" (b)); \ ++ } while (0) ++ ++#define GET_XSTATE(b) do { \ ++ asm volatile ("movups %%xmm0,(%0)" :: "r" (b)); \ ++ } while (0) ++ ++#else ++#define XSTATE_HELPERS_SUPPORTED 0 ++#define XSTATE_BUFFER_SIZE 1 ++#define SET_XSTATE(b) ++#endif ++ ++#endif /* _TEST_XSTATE_H */ +diff --git a/sysdeps/mach/hurd/i386/bits/sigcontext.h b/sysdeps/mach/hurd/i386/bits/sigcontext.h +index 6e5e220e9d..c44e4deac6 100644 +--- a/sysdeps/mach/hurd/i386/bits/sigcontext.h ++++ b/sysdeps/mach/hurd/i386/bits/sigcontext.h +@@ -88,6 +88,8 @@ struct sigcontext + struct i386_fp_save sc_fpsave; + struct i386_fp_regs sc_fpregs; + int sc_fpexcsr; /* FPSR including exception bits. */ ++ ++ struct i386_xfloat_state *xstate; + }; + + /* Traditional BSD names for some members. */ +diff --git a/sysdeps/mach/hurd/i386/sigreturn.c b/sysdeps/mach/hurd/i386/sigreturn.c +index ce8df8d02b..37fa984070 100644 +--- a/sysdeps/mach/hurd/i386/sigreturn.c ++++ b/sysdeps/mach/hurd/i386/sigreturn.c +@@ -21,6 +21,8 @@ + #include <stdlib.h> + #include <string.h> + ++#include <cpuid.h> ++ + /* This is run on the thread stack after restoring it, to be able to + unlock SS off sigstack. */ + static void +@@ -123,10 +125,32 @@ __sigreturn (struct sigcontext *scp) + if (scp->sc_onstack) + ss->sigaltstack.ss_flags &= ~SS_ONSTACK; + +- if (scp->sc_fpused) +- /* Restore the FPU state. Mach conveniently stores the state +- in the format the i387 `frstor' instruction uses to restore it. */ +- asm volatile ("frstor %0" : : "m" (scp->sc_fpsave)); ++#ifdef i386_XFLOAT_STATE ++ if ((scp->xstate) && (scp->xstate->initialized)) ++ { ++ unsigned eax, ebx, ecx, edx; ++ __cpuid_count(0xd, 0, eax, ebx, ecx, edx); ++ switch (scp->xstate->fp_save_kind) ++ { ++ case 0: // FNSAVE ++ asm volatile("frstor %0" : : "m" (scp->xstate->hw_state)); ++ break; ++ case 1: // FXSAVE ++ asm volatile("fxrstor %0" : : "m" (scp->xstate->hw_state), \ ++ "a" (eax), "d" (edx)); ++ break; ++ default: // XSAVE, XSAVEOPT, XSAVEC, XSAVES ++ asm volatile("xrstor %0" : : "m" (scp->xstate->hw_state), \ ++ "a" (eax), "d" (edx)); ++ break; ++ } ++ } ++ else ++#endif ++ if (scp->sc_fpused) ++ /* Restore the FPU state. Mach conveniently stores the state ++ in the format the i387 `frstor' instruction uses to restore it. */ ++ asm volatile ("frstor %0" : : "m" (scp->sc_fpsave)); + + { + /* There are convenient instructions to pop state off the stack, so we +diff --git a/sysdeps/mach/hurd/x86/trampoline.c b/sysdeps/mach/hurd/x86/trampoline.c +index 8e2890f8c5..db756e8a1f 100644 +--- a/sysdeps/mach/hurd/x86/trampoline.c ++++ b/sysdeps/mach/hurd/x86/trampoline.c +@@ -26,7 +26,11 @@ + #include "hurdfault.h" + #include <intr-msg.h> + #include <sys/ucontext.h> +- ++#ifdef __x86_64__ ++#include <mach/x86_64/mach_i386.h> ++#else ++#include <mach/i386/mach_i386.h> ++#endif + + /* Fill in a siginfo_t structure for SA_SIGINFO-enabled handlers. */ + static void fill_siginfo (siginfo_t *si, int signo, +@@ -106,6 +110,7 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, const struct sigaction *action + void firewall (void); + void *sigsp; + struct sigcontext *scp; ++ vm_size_t xstate_size; + struct + { + union +@@ -145,6 +150,14 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, const struct sigaction *action + struct hurd_userlink link; + ucontext_t ucontext; + siginfo_t siginfo; ++#ifdef __x86_64__ ++ char _pad2[56]; ++#else ++ char _pad2[20]; ++#endif ++ char xstate[]; ++ /* Don't add anything after xstate, as it's dynamically ++ sized. */ + } *stackframe; + + #ifdef __x86_64__ +@@ -170,6 +183,17 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, const struct sigaction *action + if (! machine_get_basic_state (ss->thread, state)) + return NULL; + ++ /* Initialize the size of the CPU extended state, to be saved during ++ * signal handling */ ++#ifdef i386_XFLOAT_STATE ++ _Static_assert ((sizeof(*stackframe) + sizeof(struct i386_xfloat_state)) % 64 == 0, ++ "stackframe size must be multiple of 64-byte minus " ++ "sizeof(struct i386_xfloat_state), please adjust _pad2"); ++ ++ if (__i386_get_xstate_size(__mach_host_self(), &xstate_size)) ++#endif ++ xstate_size = 0; ++ + /* Save the original SP in the gratuitous `esp' slot. + We may need to reset the SP (the `uesp' slot) to avoid clobbering an + interrupted RPC frame. */ +@@ -196,14 +220,21 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, const struct sigaction *action + #endif + } + +- /* Push the arguments to call `trampoline' on the stack. */ +- sigsp -= sizeof (*stackframe); +-#ifdef __x86_64__ +- /* Align SP at 16 bytes. Coupled with the fact that sigreturn_addr is +- 16-byte aligned within the stackframe struct, this ensures that it ends +- up on a 16-byte aligned address, as required by the ABI. */ +- sigsp = (void *) ((uintptr_t) sigsp & ~15UL); +-#endif ++ /* Push the arguments to call `trampoline' on the stack. ++ * The extended state might have a variable size depending on the platform, ++ * so we dynamically allocate it on the stack frame.*/ ++ sigsp -= sizeof (*stackframe) + xstate_size; ++ ++ /* Align SP at 64 bytes. This is needed for two reasons: ++ * - sigreturn_addr is 16-byte aligned within the stackframe ++ * struct, and this ensures that it ends up on a 16-byte aligned ++ * address, as required by the ABI. ++ * - the XSAVE state needs to be aligned at 64 bytes (on both i386 and ++ * x86_64), so we align the stackframe also at 64 bytes and add the ++ * required padding at the end, see the _pad2 field. ++ */ ++ sigsp = (void *) ((uintptr_t) sigsp & ~63UL); ++ + stackframe = sigsp; + + if (_hurdsig_catch_memory_fault (stackframe)) +@@ -248,14 +279,40 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, const struct sigaction *action + memcpy (&scp->sc_i386_thread_state, + &state->basic, sizeof (state->basic)); + +- /* struct sigcontext is laid out so that starting at sc_fpkind mimics +- a struct i386_float_state. */ +- _Static_assert (offsetof (struct sigcontext, sc_i386_float_state) +- % __alignof__ (struct i386_float_state) == 0, +- "sc_i386_float_state layout mismatch"); +- ok = machine_get_state (ss->thread, state, i386_FLOAT_STATE, +- &state->fpu, &scp->sc_i386_float_state, +- sizeof (state->fpu)); ++ scp->xstate = NULL; ++#ifdef i386_XFLOAT_STATE ++ if (xstate_size > 0) ++ { ++ mach_msg_type_number_t got = (xstate_size / sizeof (int)); ++ ++ ok = (! __thread_get_state (ss->thread, i386_XFLOAT_STATE, ++ (thread_state_t) stackframe->xstate, &got) ++ && got == (xstate_size / sizeof (int))); ++ ++ if (((struct i386_xfloat_state*) stackframe->xstate)->fp_save_kind > 5) ++ /* We support up to XSAVES */ ++ ok = 0; ++ ++ if (ok) ++ { ++ scp->xstate = (struct i386_xfloat_state*) stackframe->xstate; ++ assert((uintptr_t)scp->xstate->hw_state % 64 == 0); ++ } ++ } ++ else ++#endif ++ ok = 0; ++ if (!ok) ++ { ++ /* struct sigcontext is laid out so that starting at sc_fpkind mimics ++ a struct i386_float_state. */ ++ _Static_assert (offsetof (struct sigcontext, sc_i386_float_state) ++ % __alignof__ (struct i386_float_state) == 0, ++ "sc_i386_float_state layout mismatch"); ++ ok = machine_get_state (ss->thread, state, i386_FLOAT_STATE, ++ &state->fpu, &scp->sc_i386_float_state, ++ sizeof (state->fpu)); ++ } + + /* Set up the arguments for the signal handler. */ + stackframe->signo = signo; +diff --git a/sysdeps/mach/hurd/x86_64/bits/sigcontext.h b/sysdeps/mach/hurd/x86_64/bits/sigcontext.h +index 7bac881176..d83795fcbc 100644 +--- a/sysdeps/mach/hurd/x86_64/bits/sigcontext.h ++++ b/sysdeps/mach/hurd/x86_64/bits/sigcontext.h +@@ -96,6 +96,8 @@ struct sigcontext + struct i386_fp_save sc_fpsave; + struct i386_fp_regs sc_fpregs; + int sc_fpexcsr; /* FPSR including exception bits. */ ++ ++ struct i386_xfloat_state *xstate; + }; + + /* Traditional BSD names for some members. */ +diff --git a/sysdeps/mach/hurd/x86_64/sigreturn.c b/sysdeps/mach/hurd/x86_64/sigreturn.c +index 81a2d3ba74..dff8e76dc8 100644 +--- a/sysdeps/mach/hurd/x86_64/sigreturn.c ++++ b/sysdeps/mach/hurd/x86_64/sigreturn.c +@@ -20,6 +20,8 @@ + #include <hurd/msg.h> + #include <stdlib.h> + ++#include <cpuid.h> ++ + /* This is run on the thread stack after restoring it, to be able to + unlock SS off sigstack. */ + void +@@ -116,10 +118,32 @@ __sigreturn (struct sigcontext *scp) + if (scp->sc_onstack) + ss->sigaltstack.ss_flags &= ~SS_ONSTACK; + +- if (scp->sc_fpused) +- /* Restore the FPU state. Mach conveniently stores the state +- in the format the i387 `frstor' instruction uses to restore it. */ +- asm volatile ("frstor %0" : : "m" (scp->sc_fpsave)); ++#ifdef i386_XFLOAT_STATE ++ if ((scp->xstate) && (scp->xstate->initialized)) ++ { ++ unsigned eax, ebx, ecx, edx; ++ __cpuid_count(0xd, 0, eax, ebx, ecx, edx); ++ switch (scp->xstate->fp_save_kind) ++ { ++ case 0: // FNSAVE ++ asm volatile("frstor %0" : : "m" (scp->xstate->hw_state)); ++ break; ++ case 1: // FXSAVE ++ asm volatile("fxrstor %0" : : "m" (scp->xstate->hw_state), \ ++ "a" (eax), "d" (edx)); ++ break; ++ default: // XSAVE, XSAVEOPT, XSAVEC, XSAVES ++ asm volatile("xrstor %0" : : "m" (scp->xstate->hw_state), \ ++ "a" (eax), "d" (edx)); ++ break; ++ } ++ } ++ else ++#endif ++ if (scp->sc_fpused) ++ /* Restore the FPU state. Mach conveniently stores the state ++ in the format the i387 `frstor' instruction uses to restore it. */ ++ asm volatile ("frstor %0" : : "m" (scp->sc_fpsave)); + + /* Copy the registers onto the user's stack, to be able to release the + altstack (by unlocking sigstate). Note that unless an altstack is used, diff --git a/debian/patches/hurd-i386/local-intr-msg-clobber.diff b/debian/patches/hurd-i386/local-intr-msg-clobber.diff deleted file mode 100644 index d4a946fc..00000000 --- a/debian/patches/hurd-i386/local-intr-msg-clobber.diff +++ /dev/null @@ -1,23 +0,0 @@ -Force putting save_data on the stack rather than in SSE register - -The signal management does not yet properly save SSE state, so that save_data -would get overwritten by signal handlers, notably leading to `` shell -replacement getting empty content because then the io_read RPC retry gets an -MIG_BAD_ARGUMENTS error. - -XXX: This is only temporary to fix the common shll replacement issue, and is -waiting for proper SSE state restoration. - -Index: glibc-2.38/hurd/intr-msg.c -=================================================================== ---- glibc-2.38.orig/hurd/intr-msg.c -+++ glibc-2.38/hurd/intr-msg.c -@@ -79,7 +79,7 @@ _hurd_intr_rpc_mach_msg (mach_msg_header - mach_msg_bits_t msgh_bits; - mach_port_t remote_port; - mach_msg_id_t msgid; -- struct clobber save_data; -+ volatile struct clobber save_data; - - if ((option & (MACH_SEND_MSG|MACH_RCV_MSG)) != (MACH_SEND_MSG|MACH_RCV_MSG) - || _hurd_msgport_thread == MACH_PORT_NULL) diff --git a/debian/patches/series b/debian/patches/series index f82a08aa..f45c42a2 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -25,15 +25,19 @@ arm/local-arm-futex.diff # Commited for 2.42 hurd-i386/git-proc_reauth.diff - -# Commited for 2.42 hurd-i386/git-mig-strncpy.diff -hurd-i386/local-pthread_once.diff hurd-i386/git-pthread_sigmask_nothread.diff hurd-i386/git-rt-timedwait-realtime.diff hurd-i386/git-pthread_setcancel.diff +hurd-i386/git-dup-refcnt.diff +hurd-i386/git-xstate.diff +hurd-i386/git-utime-EINVAL.diff +hurd-i386/git-xstate-initialized.diff +hurd-i386/git-signal-fpe-exceptions.diff +hurd-i386/git-symlink-eexist.diff + +hurd-i386/local-pthread_once.diff -hurd-i386/local-intr-msg-clobber.diff hurd-i386/local-enable-ldconfig.diff hurd-i386/tg-sysvshm.diff hurd-i386/tg-thread-cancel.diff diff --git a/debian/po/pt_BR.po b/debian/po/pt_BR.po index a9a29128..a13d5709 100644 --- a/debian/po/pt_BR.po +++ b/debian/po/pt_BR.po @@ -3,17 +3,16 @@ # This file is distributed under the same license as the glibc package. # Felipe Augusto van de Wiel (faw) <f...@debian.org>, 2007-2008. # Fernando Ike de Oliveira (fike) <f...@midstorm.org>, 2013. -# Adriano Rafael Gomes <adrian...@debian.org>, 2014-2023. +# Adriano Rafael Gomes <adrian...@debian.org>, 2014-2025. # msgid "" msgstr "" "Project-Id-Version: glibc\n" "Report-Msgid-Bugs-To: gl...@packages.debian.org\n" "POT-Creation-Date: 2025-01-02 16:30+0000\n" -"PO-Revision-Date: 2023-01-08 13:21-0300\n" +"PO-Revision-Date: 2025-03-21 14:35-0300\n" "Last-Translator: Adriano Rafael Gomes <adrian...@debian.org>\n" -"Language-Team: Brazilian Portuguese <debian-l10n-" -"portugu...@lists.debian.org>\n" +"Language-Team: pt_BR <debian-l10n-portugu...@lists.debian.org>\n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -62,6 +61,8 @@ msgid "" "Please note that the C, C.UTF-8 and POSIX locales are always available and " "do not need to be generated." msgstr "" +"Por favor, note que os locales C, C.UTF-8 e POSIX sempre estão disponíveis e " +"não precisam ser gerados." #. Type: select #. Choices diff --git a/debian/rules.d/debhelper.mk b/debian/rules.d/debhelper.mk index 5440e4ce..6da52d6e 100644 --- a/debian/rules.d/debhelper.mk +++ b/debian/rules.d/debhelper.mk @@ -130,7 +130,6 @@ $(stamp)debhelper-common: -e 'BEGIN {open(IN, "debian/tmp/usr/share/i18n/SUPPORTED"); $$l = join("", grep { !/^C\.UTF-8/ } grep { /UTF-8/ } <IN>);} s/__PROVIDED_LOCALES__/$$l/g;' \ -e 's#DEB_VERSION_UPSTREAM#$(DEB_VERSION_UPSTREAM)#g;' \ -e 's#CURRENT_VER#$(DEB_VERSION)#g;' \ - -e 's#LIBC#$(libc)#g;' \ $$x > $$y ; \ case $$y in \ *.install) \ diff --git a/debian/testsuite-xfail-debian.mk b/debian/testsuite-xfail-debian.mk index 60191e83..99fd1224 100644 --- a/debian/testsuite-xfail-debian.mk +++ b/debian/testsuite-xfail-debian.mk @@ -306,17 +306,6 @@ test-xfail-tst-open-tmpfile = yes test-xfail-tst-closedir-leaks = yes test-xfail-tst-closedir-leaks-mem = yes -# Missing RLIMIT_AS/overcommit enforcement -tests-unsupported += tst-basic7 -tests-unsupported += test-lfs -tests-unsupported += tst-asprintf-null -tests-unsupported += bug18240 -tests-unsupported += tst-vfprintf-width-prec -tests-unsupported += tst-vfprintf-width-prec-mem -tests-unsupported += tst-vfprintf-width-prec-alloc -tests-unsupported += test-bz22786 tst-strtod-overflow -tests-unsupported += tst-tzset - # new in 2.22 test-xfail-tst-prelink = yes @@ -443,6 +432,7 @@ test-xfail-tst-execstack-prog-noexecstack = yes test-xfail-tst-support-process_state = yes test-xfail-tst-audit12 = yes test-xfail-tst-audit28 = yes +test-xfail-tst-execstack-prog-static-tunable = yes # actually never succeded test-xfail-tst-create_format1 = yes