[PATCH 3/5] Linux: Implement per-thread file system attributes
Florian Weimer
fweimer@redhat.com
Tue Dec 9 17:31:23 GMT 2025
This commit adds the functions pthread_attr_setperthreadfs_np and
pthread_attr_getperthreadfs_np.
The implementation is based on suppressing the CLONE_FS clone flag when
creating the new thread. The new flag is sticky and is applied to
all threads created from a thread with the PTHREAD_PER_THREAD_NP
attribute.
---
NEWS | 5 +
manual/threads.texi | 95 ++++++
nptl/Makefile | 4 +
nptl/Versions | 2 +
nptl/pthread_attr_getperthreadfs_np.c | 32 ++
nptl/pthread_attr_setperthreadfs_np.c | 39 +++
nptl/pthread_create.c | 20 +-
nptl/tst-pthread-perthreadfs-chroot.c | 255 ++++++++++++++
nptl/tst-pthread-perthreadfs.c | 322 ++++++++++++++++++
sysdeps/nptl/internaltypes.h | 12 +
sysdeps/nptl/pthread.h | 26 +-
sysdeps/unix/sysv/linux/aarch64/libc.abilist | 2 +
sysdeps/unix/sysv/linux/alpha/libc.abilist | 2 +
sysdeps/unix/sysv/linux/arc/libc.abilist | 2 +
sysdeps/unix/sysv/linux/arm/be/libc.abilist | 2 +
sysdeps/unix/sysv/linux/arm/le/libc.abilist | 2 +
sysdeps/unix/sysv/linux/csky/libc.abilist | 2 +
sysdeps/unix/sysv/linux/hppa/libc.abilist | 2 +
sysdeps/unix/sysv/linux/i386/libc.abilist | 2 +
.../sysv/linux/loongarch/lp64/libc.abilist | 2 +
.../sysv/linux/m68k/coldfire/libc.abilist | 2 +
.../unix/sysv/linux/m68k/m680x0/libc.abilist | 2 +
.../sysv/linux/microblaze/be/libc.abilist | 2 +
.../sysv/linux/microblaze/le/libc.abilist | 2 +
.../sysv/linux/mips/mips32/fpu/libc.abilist | 2 +
.../sysv/linux/mips/mips32/nofpu/libc.abilist | 2 +
.../sysv/linux/mips/mips64/n32/libc.abilist | 2 +
.../sysv/linux/mips/mips64/n64/libc.abilist | 2 +
sysdeps/unix/sysv/linux/or1k/libc.abilist | 2 +
.../linux/powerpc/powerpc32/fpu/libc.abilist | 2 +
.../powerpc/powerpc32/nofpu/libc.abilist | 2 +
.../linux/powerpc/powerpc64/be/libc.abilist | 2 +
.../linux/powerpc/powerpc64/le/libc.abilist | 2 +
.../unix/sysv/linux/riscv/rv32/libc.abilist | 2 +
.../unix/sysv/linux/riscv/rv64/libc.abilist | 2 +
.../unix/sysv/linux/s390/s390-32/libc.abilist | 2 +
.../unix/sysv/linux/s390/s390-64/libc.abilist | 2 +
sysdeps/unix/sysv/linux/sh/be/libc.abilist | 2 +
sysdeps/unix/sysv/linux/sh/le/libc.abilist | 2 +
.../sysv/linux/sparc/sparc32/libc.abilist | 2 +
.../sysv/linux/sparc/sparc64/libc.abilist | 2 +
.../unix/sysv/linux/x86_64/64/libc.abilist | 2 +
.../unix/sysv/linux/x86_64/x32/libc.abilist | 2 +
43 files changed, 867 insertions(+), 9 deletions(-)
create mode 100644 nptl/pthread_attr_getperthreadfs_np.c
create mode 100644 nptl/pthread_attr_setperthreadfs_np.c
create mode 100644 nptl/tst-pthread-perthreadfs-chroot.c
create mode 100644 nptl/tst-pthread-perthreadfs.c
diff --git a/NEWS b/NEWS
index 6964ca074e..1bd9f8b795 100644
--- a/NEWS
+++ b/NEWS
@@ -58,6 +58,11 @@ Major new features:
openat and provides a superset of its functionality. It is supported only
in LFS mode and it is a cancellable entrypoint.
+* On Linux, it is now possible to create threads with per-thread current
+ directory, umask, and file system root. The functions
+ pthread_attr_setperthreadfs_np and pthread_attr_getperthreadfs_np have
+ been added in support of that.
+
Deprecated and removed features, and other changes affecting compatibility:
* Support for dumped heaps has been removed - malloc_set_state() now always
diff --git a/manual/threads.texi b/manual/threads.texi
index b9d12479ca..8df694cc43 100644
--- a/manual/threads.texi
+++ b/manual/threads.texi
@@ -1145,6 +1145,7 @@ the standard.
* Default Thread Attributes:: Setting default attributes for
threads in a process.
* Initial Thread Signal Mask:: Setting the initial mask of threads.
+* Enabling Per-Thread Properties:: Additional per-thread properties.
* Thread CPU Affinity:: Limiting which CPUs can run a thread.
* Joining Threads:: Wait for a thread to terminate.
* Thread Names:: Changing the name of a thread.
@@ -1266,6 +1267,100 @@ signal mask and use @code{pthread_sigmask} to apply it to the thread.
If the signal mask was copied to a heap allocation, the copy should be
freed.
+@node Enabling Per-Thread Properties
+@subsubsection Enabling Additional Per-Thread Properties
+
+POSIX mandates that the current directory, file system root, umask
+value, and the current user and group IDs are process-global
+properties. For example, if a thread calls the @code{chdir} function
+to change to a different directory, all threads are eventually
+affected by this change. @Theglibc{} implements an extension which
+allows threads to be created which do not share these properties with
+the rest of the process.
+
+The desired behavior is specified at the time the thread is created,
+using the thread attribute. The following constants are used to
+update the attribute:
+
+@vtable @code
+@item PTHREAD_PER_PROCESS_NP
+@standards{GNU, pthread.h}
+This property in question is globally shared across the entire process.
+This is the default.
+
+@item PTHREAD_PER_THREAD_NP
+@standards{GNU, pthread.h}
+This property in question is thread-specific.
+@end vtable
+
+The @code{PTHREAD_PER_THREAD_NP} flag is sticky, in the sense that all
+threads created by a thread created with this flag have per-thread
+properties, even if they are created with the matching thread
+attribute set to the @code{PTHREAD_PER_PROCESS_NP} flag. If an
+application wants to create new threads sharing properties with the
+main thread, it should create a service thread early (perhaps from an
+ELF constructor) and create these threads using this service thread.
+
+Per-thread properties can be set and examined for an attribute using
+the functions below.
+
+@deftypefun int pthread_attr_setperthreadfs_np (pthread_attr_t *@var{attr}, int @var{scope})
+@standards{GNU, pthread.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Change whether the following properties related to file system access
+are made thread-specific when a new thread is created using the
+attribute @var{attr}:
+
+@itemize @bullet
+@item
+@cindex current directory as a per-thread property
+@cindex per-thread current directory
+@cindex thread-specific current directory
+current directory (as changed by @code{chdir} and related functions)
+
+@item
+@cindex @code{chroot} as a per-thread property
+@cindex per-thread @code{chroot}
+@cindex thread-specific @code{chroot}
+file system root (as changed by @code{chroot})
+
+@item
+@cindex umask as a per-thread property
+@cindex per-thread @code{umask}
+@cindex thread-specific @code{umask}
+umask value (as changed by the function of the same name)
+@end itemize
+
+This function returns zero on success. @var{scope} must be one of the
+constants @code{PTHREAD_PER_PROCESS_NP} or
+@code{PTHREAD_PER_THREAD_NP}, otherwise the function returns
+@code{EINVAL}.
+
+If @var{scope} is @code{PTHREAD_PER_THREAD_NP}, the attribute will
+cause the properties listed above to be specific to the thread. The
+initial values of these properties are copied from the creating
+thread, at thread creation time.
+
+If a thread that has been created with the
+@code{PTHREAD_PER_THREAD_NP} flag creates further threads, these
+threads are implicitly created with the @code{PTHREAD_PER_THREAD_NP}
+flag, ignoring the value of this thread creation attribute.
+(If this behavior is not desirable, it is possible to call
+@samp{unshare (CLONE_FS)} from the new thread instead of creating it
+with the @code{PTHREAD_PER_THREAD_NP} flag.)
+
+This function is a GNU extension and specific to Linux.
+@end deftypefun
+
+@deftypefun int pthread_attr_getperthreadfs_np (pthread_attr_t *restrict @var{attr}, int *restrict @var{scope})
+@standards{GNU, pthread.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Obtain the per-thread status of the file system properties in
+@var{attr} and store it in the location @var{scope}.
+
+This function is a GNU extension and specific to Linux.
+@end deftypefun
+
@node Thread CPU Affinity
@subsubsection Thread CPU Affinity
diff --git a/nptl/Makefile b/nptl/Makefile
index 81d6a5482c..05c6c32a76 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -65,6 +65,7 @@ routines = \
pthread_attr_getdetachstate \
pthread_attr_getguardsize \
pthread_attr_getinheritsched \
+ pthread_attr_getperthreadfs_np \
pthread_attr_getschedparam \
pthread_attr_getschedpolicy \
pthread_attr_getscope \
@@ -77,6 +78,7 @@ routines = \
pthread_attr_setdetachstate \
pthread_attr_setguardsize \
pthread_attr_setinheritsched \
+ pthread_attr_setperthreadfs_np \
pthread_attr_setschedparam \
pthread_attr_setschedpolicy \
pthread_attr_setscope \
@@ -317,6 +319,8 @@ tests = \
tst-pthread-gdb-attach-static \
tst-pthread-getcpuclockid-invalid \
tst-pthread-key1-static \
+ tst-pthread-perthreadfs \
+ tst-pthread-perthreadfs-chroot \
tst-pthread-timedlock-lockloop \
tst-pthread_exit-nothreads \
tst-pthread_exit-nothreads-static \
diff --git a/nptl/Versions b/nptl/Versions
index b813b675b9..c4ff312468 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -382,6 +382,8 @@ libc {
pthread_gettid_np;
}
GLIBC_2.43 {
+ pthread_attr_setperthreadfs_np;
+ pthread_attr_getperthreadfs_np;
}
GLIBC_PRIVATE {
__libc_alloca_cutoff;
diff --git a/nptl/pthread_attr_getperthreadfs_np.c b/nptl/pthread_attr_getperthreadfs_np.c
new file mode 100644
index 0000000000..f5ff348cac
--- /dev/null
+++ b/nptl/pthread_attr_getperthreadfs_np.c
@@ -0,0 +1,32 @@
+/* Read the private file system flag in thread attributes.
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <internaltypes.h>
+
+int
+pthread_attr_getperthreadfs_np (const pthread_attr_t *__restrict attr,
+ int *__restrict scope)
+{
+ struct pthread_attr *iattr = (struct pthread_attr *) attr;
+ if (iattr->flags & ATTR_FLAG_PERTHREADFS)
+ *scope = PTHREAD_PER_THREAD_NP;
+ else
+ *scope = PTHREAD_PER_PROCESS_NP;
+ return 0;
+}
diff --git a/nptl/pthread_attr_setperthreadfs_np.c b/nptl/pthread_attr_setperthreadfs_np.c
new file mode 100644
index 0000000000..2d274cb144
--- /dev/null
+++ b/nptl/pthread_attr_setperthreadfs_np.c
@@ -0,0 +1,39 @@
+/* Change the private file system flag in thread attributes.
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <internaltypes.h>
+#include <errno.h>
+
+int
+pthread_attr_setperthreadfs_np (pthread_attr_t *attr, int scope)
+{
+ struct pthread_attr *iattr = (struct pthread_attr *) attr;
+ switch (scope)
+ {
+ case PTHREAD_PER_PROCESS_NP:
+ iattr->flags &= ~ATTR_FLAG_PERTHREADFS;
+ return 0;
+ break;
+ case PTHREAD_PER_THREAD_NP:
+ iattr->flags |= ATTR_FLAG_PERTHREADFS;
+ return 0;
+ default:
+ return EINVAL;
+ }
+}
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index 19e4ec8064..39a4cf825f 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -253,7 +253,9 @@ static int create_thread (struct pthread *pd, const struct pthread_attr *attr,
CLONE_VM, CLONE_FS, CLONE_FILES
These flags select semantics with shared address space and
- file descriptors according to what POSIX requires.
+ file descriptors according to what POSIX requires. CLONE_FS
+ is optional; it can be controlled using the function
+ pthread_attr_setperthreadfs_np.
CLONE_SIGHAND, CLONE_THREAD
This flag selects the POSIX signal semantics and various
@@ -277,11 +279,13 @@ static int create_thread (struct pthread *pd, const struct pthread_attr *attr,
The termination signal is chosen to be zero which means no signal
is sent. */
- const int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SYSVSEM
- | CLONE_SIGHAND | CLONE_THREAD
- | CLONE_SETTLS | CLONE_PARENT_SETTID
- | CLONE_CHILD_CLEARTID
- | 0);
+ int clone_flags = (CLONE_VM | CLONE_FILES | CLONE_SYSVSEM
+ | CLONE_SIGHAND | CLONE_THREAD
+ | CLONE_SETTLS | CLONE_PARENT_SETTID
+ | CLONE_CHILD_CLEARTID
+ | 0);
+ if ((attr->flags & ATTR_FLAG_PERTHREADFS) == 0)
+ clone_flags |= CLONE_FS;
TLS_DEFINE_INIT_TP (tp, pd);
@@ -695,8 +699,8 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
/* Copy the thread attribute flags. */
struct pthread *self = THREAD_SELF;
- pd->flags = ((iattr->flags & ~(ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET))
- | (self->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)));
+ pd->flags = ((iattr->flags & ~ATTR_FLAGS_IGNORED_ATTR)
+ | (self->flags & ATTR_FLAGS_INHERITED));
/* Inherit rseq registration state. Without seccomp filters, rseq
registration will either always fail or always succeed. */
diff --git a/nptl/tst-pthread-perthreadfs-chroot.c b/nptl/tst-pthread-perthreadfs-chroot.c
new file mode 100644
index 0000000000..094c291baa
--- /dev/null
+++ b/nptl/tst-pthread-perthreadfs-chroot.c
@@ -0,0 +1,255 @@
+/* Test per-thread file system attributes, chroot version.
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+/* This thread is separate from tst-pthread-perthreadfs because it
+ requires chroot support. */
+
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.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 <sys/stat.h>
+#include <unistd.h>
+
+/* Paths for chroot operations. */
+static char *chroot_1;
+static char *chroot_2;
+static char *chroot_3;
+
+/* These paths are used for recognizing chroots. */
+static const char *const chroot_1_marker = "/chroot-1-marker";
+static const char *const chroot_2_marker = "/chroot-2-marker";
+
+/* Directory available in the chroot for a second chroot call. */
+static const char *const next_chroot = "/next_chroot";
+
+/* Return 0 for no chroot, 1 for first chroot, 2 for second chroot, or
+ -1 for error. */
+static int
+which_chroot (void)
+{
+ /* If the full (out-of-chroot) path is present, we are not in a
+ chroot. */
+ if (access (chroot_1, F_OK) == 0)
+ return 0;
+ if (access (chroot_1_marker, F_OK) == 0)
+ return 1;
+ if (access (chroot_2_marker, F_OK) == 0)
+ return 2;
+ return -1;
+}
+
+/* Thread attribute requesting per-thread file system attributes. */
+pthread_attr_t attr_perthreadfs;
+
+/* Used to synchronize operations among the threads. This is needed
+ so that the chroot changes happen in the expected order. */
+static pthread_barrier_t barrier;
+
+static void *
+thread_which_chroot_helper (void *closure)
+{
+ int *result = closure;
+ *result = which_chroot ();
+ return NULL;
+}
+
+static void *
+thread_which_chroot_helper_perthread (void *closure)
+{
+ int *result = closure;
+ *result = which_chroot ();
+ if (*result == 0)
+ /* No /next-chroot available without a first chroot. */
+ xchroot (chroot_3);
+ else
+ xchroot (next_chroot);
+ return NULL;
+}
+
+/* Determine the current chroot on another thread. */
+static int
+thread_which_chroot (void)
+{
+ int result1;
+ pthread_t thr = xpthread_create (NULL, thread_which_chroot_helper, &result1);
+ xpthread_join (thr);
+ /* Same using per-thread attributes. They are supposed to be equal.
+ Also change the chroot to check isolation. */
+ int result2;
+ thr = xpthread_create (&attr_perthreadfs,
+ thread_which_chroot_helper_perthread, &result2);
+ xpthread_join (thr);
+ TEST_COMPARE (result1, result2);
+ return result1;
+}
+
+/* Verify that the file system attributes for the current thread are
+ as expected. */
+static void
+check_attributes (const char *where, int expected_chroot)
+{
+ printf ("info: reading file attributes in %s\n", where);
+ TEST_COMPARE (which_chroot (), expected_chroot);
+ TEST_COMPARE (thread_which_chroot (), expected_chroot);
+}
+
+/* Thread function launched with per-thread file system
+ attributes. */
+static void *
+thread_perthreadfs (void *closure)
+{
+ puts ("info: changing file attributes in thread_perthreadfs");
+ xchroot (chroot_1);
+ check_attributes ("thread_perthreadfs", 1);
+
+ pthread_barrier_wait (&barrier);
+ /* File attributes read in thread_sharedfs here. */
+ pthread_barrier_wait (&barrier);
+ /* File attributes read in main thread here. */
+ pthread_barrier_wait (&barrier);
+ /* File attributes changed in thread_sharedfs here. */
+ pthread_barrier_wait (&barrier);
+
+ check_attributes ("thread_perthreadfs", 1);
+
+ pthread_barrier_wait (&barrier);
+ /* File attributes read in main thread here. */
+ pthread_barrier_wait (&barrier);
+ return NULL;
+}
+
+/* Thread function launched with shared file system attributes. */
+static void *
+thread_sharedfs (void *closure)
+{
+ /* Wait for thread_perthreadfs to update chroot. */
+ pthread_barrier_wait (&barrier);
+
+ check_attributes ("thread_sharedfs", 0);
+
+ pthread_barrier_wait (&barrier);
+ /* File attributes read in main thread here. */
+ pthread_barrier_wait (&barrier);
+
+ puts ("info: changing file attributes in thread_sharedfs");
+ xchroot (chroot_2);
+ check_attributes ("thread_sharedfs", 2);
+
+ pthread_barrier_wait (&barrier);
+ /* File attributes read in thread_perthreadfs here. */
+ pthread_barrier_wait (&barrier);
+ /* File attributes read in main thread here. */
+ pthread_barrier_wait (&barrier);
+ return NULL;
+}
+
+static int
+do_test (void)
+{
+ support_become_root ();
+ if (!support_can_chroot ())
+ FAIL_UNSUPPORTED ("chroot not supported");
+
+ /* Used to revert the effect of chroot. */
+ int original_chroot_fd = xopen ("/", O_DIRECTORY | O_RDONLY, 0);
+
+ TEST_COMPARE (access (chroot_1_marker, F_OK), -1);
+ TEST_COMPARE (access (chroot_2_marker, F_OK), -1);
+ TEST_COMPARE (access (next_chroot, F_OK), -1);
+
+ chroot_1 = support_create_temp_directory
+ ("tst-pthread-perthreadfs-chroot-1-");
+ chroot_2 = support_create_temp_directory
+ ("tst-pthread-perthreadfs-chroot-2-");
+ chroot_3 = support_create_temp_directory
+ ("tst-pthread-perthreadfs-chroot-3-");
+ {
+ char *path = xasprintf ("%s%s", chroot_1, chroot_1_marker);
+ xmkdir (path, 0777);
+ add_temp_file (path);
+ free (path);
+
+ path = xasprintf ("%s%s", chroot_1, next_chroot);
+ xmkdir (path, 0777);
+ add_temp_file (path);
+ free (path);
+
+ path = xasprintf ("%s%s", chroot_2, chroot_2_marker);
+ xmkdir (path, 0777);
+ add_temp_file (path);
+ free (path);
+
+ path = xasprintf ("%s%s", chroot_2, next_chroot);
+ xmkdir (path, 0777);
+ add_temp_file (path);
+ free (path);
+ }
+ TEST_COMPARE (which_chroot (), 0);
+
+ xpthread_barrier_init (&barrier, NULL, 3);
+ xpthread_attr_init (&attr_perthreadfs);
+ TEST_COMPARE (pthread_attr_setperthreadfs_np (&attr_perthreadfs,
+ PTHREAD_PER_THREAD_NP), 0);
+
+ pthread_t thr1 = xpthread_create (&attr_perthreadfs,
+ thread_perthreadfs, NULL);
+ pthread_t thr2 = xpthread_create (NULL, thread_sharedfs, NULL);
+
+ /* Wait for thread_perthreadfs to update chroot. */
+ xpthread_barrier_wait (&barrier);
+ /* File attributes read thread_sharedfs here. */
+ xpthread_barrier_wait (&barrier);
+
+ check_attributes ("main thread", 0);
+
+ xpthread_barrier_wait (&barrier);
+ /* File attributes changed thread_sharedfs here. */
+ xpthread_barrier_wait (&barrier);
+ /* File attributes read in thread_perthreadfs here. */
+ xpthread_barrier_wait (&barrier);
+
+ check_attributes ("main thread", 2);
+
+ xpthread_barrier_wait (&barrier);
+
+ xpthread_join (thr2);
+ xpthread_join (thr1);
+
+ xpthread_attr_destroy (&attr_perthreadfs);
+ xpthread_barrier_destroy (&barrier);
+
+ free (chroot_3);
+ free (chroot_2);
+ free (chroot_1);
+
+ xfchdir (original_chroot_fd);
+ xclose (original_chroot_fd);
+ xchroot (".");
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/nptl/tst-pthread-perthreadfs.c b/nptl/tst-pthread-perthreadfs.c
new file mode 100644
index 0000000000..bb30449808
--- /dev/null
+++ b/nptl/tst-pthread-perthreadfs.c
@@ -0,0 +1,322 @@
+/* Test per-thread file system attributes.
+ 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <support/check.h>
+#include <support/temp_file.h>
+#include <support/xthread.h>
+#include <support/xunistd.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* Original values in the parent process. */
+static char *original_cwd;
+static mode_t original_umask;
+
+/* New values for the attributes, distinct from the old. */
+static char *new_cwd_1;
+static char *new_cwd_2;
+static mode_t new_umask_1;
+static mode_t new_umask_2;
+
+/* Thread attribute requesting per-thread file system attributes. */
+pthread_attr_t attr_perthreadfs;
+
+/* Used to synchronize operations among the threads. This is needed
+ so that the attribute changes happen in the expected order, and
+ that get_umask_unlocked can be used safely. */
+static pthread_barrier_t barrier;
+
+/* Return true if the thread has per-thread file system attributes.
+ Note: This function calls pthread_getattr_np on THR, so the caller
+ has to ensure that the thread is still running (and not merely
+ joinable). */
+static bool
+perthread_flag (pthread_t thr)
+{
+ pthread_attr_t attr;
+ int ret = pthread_getattr_np (thr, &attr);
+ if (ret != 0)
+ {
+ errno = ret;
+ FAIL_EXIT1 ("pthread_getattr_np: %m");
+ }
+ int flag = -1;
+ pthread_attr_getperthreadfs_np (&attr, &flag);
+ if (flag != PTHREAD_PER_THREAD_NP)
+ TEST_COMPARE (flag, PTHREAD_PER_PROCESS_NP);
+ xpthread_attr_destroy (&attr);
+ return flag == PTHREAD_PER_THREAD_NP;
+}
+
+/* Linux does not have getumask, so use synchronization and the umask
+ system call to read the value. */
+static mode_t
+get_umask_unlocked (void)
+{
+ mode_t mask = umask (0);
+ TEST_COMPARE (umask (mask), 0);
+ return mask;
+}
+
+static void *
+thread_get_pwd_helper (void *closure)
+{
+ char *result = get_current_dir_name ();
+ if (closure != NULL)
+ xchdir (closure);
+ return result;
+}
+
+/* Obtain the current directory on another thread. */
+static char *
+thread_get_pwd (void)
+{
+ pthread_t thr = xpthread_create (NULL, thread_get_pwd_helper, NULL);
+ char *path1 = xpthread_join (thr);
+ /* Same using per-thread attributes. They are supposed to be equal.
+ Also change the current directory to check isolation. */
+ thr = xpthread_create (&attr_perthreadfs,
+ thread_get_pwd_helper, (char *) "/");
+ char *path2 = xpthread_join (thr);
+ TEST_COMPARE_STRING (path1, path2);
+ free (path2);
+ return path1;
+}
+
+static void *
+thread_get_umask_helper (void *closure)
+{
+ mode_t *pmask = closure;
+ *pmask = get_umask_unlocked ();
+ return NULL;
+}
+
+static void *
+thread_get_umask_helper_perthread (void *closure)
+{
+ mode_t *pmask = closure;
+ *pmask = get_umask_unlocked ();
+ /* Check isolation. This bit pattern is not used anywhere else. */
+ TEST_COMPARE (umask (*pmask ^ 0101), *pmask);
+ return NULL;
+}
+
+/* Obtain the current umask on another thread. */
+static mode_t
+thread_get_umask_unlocked (void)
+{
+ mode_t mask1;
+ pthread_t thr = xpthread_create (NULL, thread_get_umask_helper, &mask1);
+ xpthread_join (thr);
+ mode_t mask2;
+ thr = xpthread_create (&attr_perthreadfs,
+ thread_get_umask_helper_perthread, &mask2);
+ xpthread_join (thr);
+ TEST_COMPARE (mask1, mask2);
+ return mask1;
+}
+
+/* Verify that the file system attributes for the current thread are
+ as expected. */
+static void
+check_attributes (const char *where, mode_t expected_umask,
+ const char *expected_cwd)
+{
+ printf ("info: reading file attributes in %s\n", where);
+ TEST_COMPARE (get_umask_unlocked (), expected_umask);
+ TEST_COMPARE (thread_get_umask_unlocked (), expected_umask);
+ char *cwd = get_current_dir_name ();
+ TEST_COMPARE_STRING (cwd, expected_cwd);
+ free (cwd);
+ cwd = thread_get_pwd ();
+ TEST_COMPARE_STRING (cwd, expected_cwd);
+ free (cwd);
+}
+
+/* Thread function launched with per-thread file system
+ attributes. */
+static void *
+thread_perthreadfs (void *closure)
+{
+ puts ("info: changing file attributes in thread_perthreadfs");
+ TEST_VERIFY (perthread_flag (pthread_self ()));
+ xchdir (new_cwd_1);
+ TEST_COMPARE (umask (new_umask_1), original_umask);
+ check_attributes ("thread_perthreadfs", new_umask_1, new_cwd_1);
+
+ pthread_barrier_wait (&barrier);
+ /* File attributes read in thread_sharedfs here. */
+ pthread_barrier_wait (&barrier);
+ /* File attributes read in main thread here. */
+ pthread_barrier_wait (&barrier);
+ /* File attributes changed in thread_sharedfs here. */
+ pthread_barrier_wait (&barrier);
+
+ check_attributes ("thread_perthreadfs", new_umask_1, new_cwd_1);
+
+ pthread_barrier_wait (&barrier);
+ /* File attributes read in main thread here. */
+ pthread_barrier_wait (&barrier);
+ return NULL;
+}
+
+/* Launched with PTHREAD_PER_THREAD_NP, but runs the actual test on a
+ PTHREAD_PER_PROCESS_NP thread (with a default attribute). */
+static void *
+thread_perthreadfs_indirect (void *closure)
+{
+ TEST_VERIFY (perthread_flag (pthread_self ()));
+ /* Use the default NULL attribute here. Since the per-thread scope
+ is sticky, it will still result in a per-thread file system
+ thread. */
+ pthread_t thr = xpthread_create (NULL, thread_perthreadfs, closure);
+ return xpthread_join (thr);
+}
+
+/* Thread function launched with shared file system attributes. */
+static void *
+thread_sharedfs (void *closure)
+{
+ TEST_VERIFY (!perthread_flag (pthread_self ()));
+
+ /* Wait for thread_perthreadfs to update current directory and
+ umask. */
+ pthread_barrier_wait (&barrier);
+
+ check_attributes ("thread_sharedfs", original_umask, original_cwd);
+
+ pthread_barrier_wait (&barrier);
+ /* File attributes read in main thread here. */
+ pthread_barrier_wait (&barrier);
+
+ puts ("info: changing file attributes in thread_sharedfs");
+ TEST_COMPARE (umask (new_umask_2), original_umask);
+ xchdir (new_cwd_2);
+ check_attributes ("thread_sharedfs", new_umask_2, new_cwd_2);
+
+ pthread_barrier_wait (&barrier);
+ /* File attributes read in thread_perthreadfs here. */
+ pthread_barrier_wait (&barrier);
+ /* File attributes read in main thread here. */
+ pthread_barrier_wait (&barrier);
+ return NULL;
+}
+
+static int
+do_test (void)
+{
+ original_cwd = get_current_dir_name ();
+ TEST_VERIFY_EXIT (original_cwd != NULL);
+ original_umask = get_umask_unlocked ();
+
+ new_cwd_1 = support_create_temp_directory ("tst-pthread-perthreadfs-1-");
+ new_cwd_2 = support_create_temp_directory ("tst-pthread-perthreadfs-2-");
+ /* Arbitrary bit pattern change to obtain distinct values, so that
+ it is possible to check for actual changes. */
+ new_umask_1 = original_umask ^ 0111;
+ new_umask_2 = original_umask ^ 0222;
+
+ TEST_VERIFY (!perthread_flag (pthread_self ()));
+
+ xpthread_barrier_init (&barrier, NULL, 3);
+ xpthread_attr_init (&attr_perthreadfs);
+ {
+ /* Test: Default is PTHREAD_PER_PROCESS_NP. */
+ int scope = -1;
+ TEST_COMPARE (pthread_attr_getperthreadfs_np (&attr_perthreadfs, &scope),
+ 0);
+ TEST_COMPARE (scope, PTHREAD_PER_PROCESS_NP);
+
+ /* Test: The getter shows the effect of the setter. */
+ TEST_COMPARE (pthread_attr_setperthreadfs_np (&attr_perthreadfs,
+ PTHREAD_PER_THREAD_NP), 0);
+ scope = -1;
+ TEST_COMPARE (pthread_attr_getperthreadfs_np (&attr_perthreadfs, &scope),
+ 0);
+ TEST_COMPARE (scope, PTHREAD_PER_THREAD_NP);
+
+ /* Test: Invalid scope values result in an error, without a
+ change. */
+ TEST_COMPARE (pthread_attr_setperthreadfs_np (&attr_perthreadfs, 2),
+ EINVAL);
+ scope = -1;
+ TEST_COMPARE (pthread_attr_getperthreadfs_np (&attr_perthreadfs, &scope),
+ 0);
+ TEST_COMPARE (scope, PTHREAD_PER_THREAD_NP);
+ }
+
+ /* Two test runs, once with perthreadsfs set to
+ PTHREAD_PER_THREAD_NP directly, once indirectly via inheritance
+ from the current (overriding the PTHREAD_PER_PROCESS_NP
+ default). */
+ for (int do_indirect = 0; do_indirect < 2; ++do_indirect)
+ {
+ printf ("info: test iteration with do_indirect == %d\n", do_indirect);
+ pthread_t thr1;
+ if (do_indirect)
+ thr1 = xpthread_create (&attr_perthreadfs,
+ thread_perthreadfs_indirect, NULL);
+ else
+ thr1 = xpthread_create (&attr_perthreadfs, thread_perthreadfs, NULL);
+ pthread_t thr2 = xpthread_create (NULL, thread_sharedfs, NULL);
+ /* Both threads wait on the barrier before exiting, so they are
+ running at his point, and the call to perthread_flag is
+ safe. */
+ TEST_VERIFY (perthread_flag (thr1));
+ TEST_VERIFY (!perthread_flag (thr2));
+
+ /* Wait for thread_perthreadfs to update current directory and
+ umask. */
+ xpthread_barrier_wait (&barrier);
+ /* File attributes read thread_sharedfs here. */
+ xpthread_barrier_wait (&barrier);
+
+ check_attributes ("main thread", original_umask, original_cwd);
+
+ xpthread_barrier_wait (&barrier);
+ /* File attributes changed thread_sharedfs here. */
+ xpthread_barrier_wait (&barrier);
+ /* File attributes read in thread_perthreadfs here. */
+ xpthread_barrier_wait (&barrier);
+
+ check_attributes ("main thread", new_umask_2, new_cwd_2);
+
+ xpthread_barrier_wait (&barrier);
+
+ xpthread_join (thr2);
+ xpthread_join (thr1);
+
+ xchdir (original_cwd);
+ umask (original_umask);
+ }
+
+ xpthread_attr_destroy (&attr_perthreadfs);
+ xpthread_barrier_destroy (&barrier);
+
+ free (new_cwd_2);
+ free (new_cwd_1);
+ free (original_cwd);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/nptl/internaltypes.h b/sysdeps/nptl/internaltypes.h
index 9169453cc9..f291421dc2 100644
--- a/sysdeps/nptl/internaltypes.h
+++ b/sysdeps/nptl/internaltypes.h
@@ -51,6 +51,18 @@ struct pthread_attr
#define ATTR_FLAG_SCHED_SET 0x0020
#define ATTR_FLAG_POLICY_SET 0x0040
#define ATTR_FLAG_DO_RSEQ 0x0080
+#define ATTR_FLAG_PERTHREADFS 0x0100
+
+/* These flags are not copied from the thread attribute at
+ pthread_create time. */
+#define ATTR_FLAGS_IGNORED_ATTR \
+ (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)
+
+/* These flags are inherited from the current thread during
+ pthread_create even if they are not specified in the thread
+ attribute. */
+#define ATTR_FLAGS_INHERITED \
+ ATTR_FLAG_PERTHREADFS
/* Used to allocate a pthread_attr_t object which is also accessed
internally. */
diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
index 92957a620d..d2280ddc73 100644
--- a/sysdeps/nptl/pthread.h
+++ b/sysdeps/nptl/pthread.h
@@ -149,7 +149,16 @@ enum
#define PTHREAD_PROCESS_SHARED PTHREAD_PROCESS_SHARED
};
-
+#ifdef __USE_GNU
+/* Thread-private or process-global flag. */
+enum
+{
+ PTHREAD_PER_PROCESS_NP,
+# define PTHREAD_PER_PROCESS_NP PTHREAD_PER_PROCESS_NP
+ PTHREAD_PER_THREAD_NP
+# define PTHREAD_PER_THREAD_NP PTHREAD_PER_THREAD_NP
+};
+#endif /* __USE_GNU */
/* Conditional variable handling. */
#define PTHREAD_COND_INITIALIZER { { {0}, {0}, {0, 0}, 0, 0, {0, 0}, 0, 0 } }
@@ -403,6 +412,21 @@ extern int pthread_attr_getaffinity_np (const pthread_attr_t *__attr,
cpu_set_t *__cpuset)
__THROW __nonnull ((1, 3));
+
+/* Control the flag in ATTR whether the thread has its own current
+ directory, file system root, and umask attribute. SCOPE must be
+ PTHREAD_PER_PROCESS_NP or PTHREAD_PER_THREAD_NP. By default, new
+ threads share these attributes with their creating thread
+ (PTHREAD_PER_PROCESS_NP). */
+int pthread_attr_setperthreadfs_np (pthread_attr_t *__attr, int __scope)
+ __THROW __nonnull ((1));
+
+/* Get the per-thread/per-process scope of file system attributes from
+ *ATTR and store it in *SCOPE. */
+int pthread_attr_getperthreadfs_np (const pthread_attr_t *__restrict __attr,
+ int *__restrict __scope)
+ __THROW __nonnull ((1, 2));
+
/* Get the default attributes used by pthread_create in this process. */
extern int pthread_getattr_default_np (pthread_attr_t *__attr)
__THROW __nonnull ((1));
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 3156688add..abc893d3c2 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2774,4 +2774,6 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 8af5b0b581..08ac8d8e1b 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -3121,6 +3121,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist
index 35fcef2cc4..69f616cead 100644
--- a/sysdeps/unix/sysv/linux/arc/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arc/libc.abilist
@@ -2535,4 +2535,6 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
index a6c6b951bf..9d1678320e 100644
--- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist
@@ -2827,6 +2827,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
index e76015fe66..4f3b5affe9 100644
--- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist
@@ -2824,6 +2824,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
index 1fb7cdcad5..4775926d0d 100644
--- a/sysdeps/unix/sysv/linux/csky/libc.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
@@ -2811,4 +2811,6 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 0710ccecf9..d3b8ac7de6 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -2848,6 +2848,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 3afe3a88eb..7bf6d848df 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -3031,6 +3031,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
index c2b3a66d3a..4438857731 100644
--- a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
@@ -2295,4 +2295,6 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index d6855131e8..1ec5185e2a 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -2807,6 +2807,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 4e3fe9c42f..d091f52f10 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -2974,6 +2974,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
index 29f0c5f954..eda99f79cc 100644
--- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
@@ -2860,4 +2860,6 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
index 2ef62838f7..28d85c9a69 100644
--- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
@@ -2857,4 +2857,6 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 031e8961ac..52c206e514 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -2937,6 +2937,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 8dc99d81b4..fa6b7532bd 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -2935,6 +2935,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 054c5b6391..c2a0b18359 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -2943,6 +2943,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 13f0148bc0..8c0e99fb18 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -2845,6 +2845,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/or1k/libc.abilist b/sysdeps/unix/sysv/linux/or1k/libc.abilist
index e7ffe07dd8..1158bb10d6 100644
--- a/sysdeps/unix/sysv/linux/or1k/libc.abilist
+++ b/sysdeps/unix/sysv/linux/or1k/libc.abilist
@@ -2285,4 +2285,6 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index dea4b20f05..bf9faed11f 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -3164,6 +3164,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index b45e127463..7dbe21ba65 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -3209,6 +3209,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
index 942cf6a027..8e8a179363 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
@@ -2918,6 +2918,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
index 65d78e5076..04fa4568bb 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
@@ -2994,4 +2994,6 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
index dcab30d72e..78d4f1f22f 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
@@ -2538,4 +2538,6 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index 796ef35e26..ae0f2ccac9 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -2738,4 +2738,6 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 9bd9f5eb78..7b7c81a68b 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -3162,6 +3162,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 8f2350ee0b..7c81be27f4 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -2955,6 +2955,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
index 7aa98c5aed..f04f22b538 100644
--- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist
@@ -2854,6 +2854,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
index 6bd4f8f63a..ec831f0ad5 100644
--- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist
@@ -2851,6 +2851,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index b52cab2a35..4f40e294fe 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -3185,6 +3185,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index ff99cd4f21..da128a940a 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -2821,6 +2821,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 306cd627fd..3f32a83378 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -2770,6 +2770,8 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
GLIBC_2.5 __readlinkat_chk F
GLIBC_2.5 inet6_opt_append F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 8b9c448742..8105eaadba 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2789,4 +2789,6 @@ GLIBC_2.43 memalignment F
GLIBC_2.43 memset_explicit F
GLIBC_2.43 mseal F
GLIBC_2.43 openat2 F
+GLIBC_2.43 pthread_attr_getperthreadfs_np F
+GLIBC_2.43 pthread_attr_setperthreadfs_np F
GLIBC_2.43 umaxabs F
--
2.52.0
More information about the Libc-alpha
mailing list