From: Adhemerval Zanella Date: Mon, 23 Aug 2021 17:46:27 +0000 (-0300) Subject: nptl: Use exit_lock when accessing TID on pthread_setname_np X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2518bb05f6a930d59ab574a443671323b900e79b;p=thirdparty%2Fglibc.git nptl: Use exit_lock when accessing TID on pthread_setname_np Also return EINVAL if the thread is already terminated at the time of the call. Checked on x86_64-linux-gnu. --- diff --git a/nptl/pthread_setname.c b/nptl/pthread_setname.c index 356d2e0368..a129335b3e 100644 --- a/nptl/pthread_setname.c +++ b/nptl/pthread_setname.c @@ -16,21 +16,40 @@ License along with the GNU C Library; see the file COPYING.LIB. If not, see . */ -#include -#include +#include +#include +#include #include +#include #include -#include -#include #include -#include +static int +setname (pid_t tid, const char *name, size_t name_len) +{ + char fname[sizeof ("/proc/self/task//comm") + INT_BUFSIZE_BOUND (pid_t)]; + __snprintf (fname, sizeof (fname), "/proc/self/task/%d/comm", tid); + int fd = __open64_nocancel (fname, O_RDONLY); + if (fd == -1) + return EINVAL; + + int res = 0; + ssize_t n = TEMP_FAILURE_RETRY (__write_nocancel (fd, name, name_len)); + if (n < 0) + res = errno; + else if (n != name_len) + res = EIO; + + __close_nocancel_nostatus (fd); + + return res; +} int __pthread_setname_np (pthread_t th, const char *name) { - const struct pthread *pd = (const struct pthread *) th; + struct pthread *pd = (struct pthread *) th; /* Unfortunately the kernel headers do not export the TASK_COMM_LEN macro. So we have to define it here. */ @@ -42,22 +61,15 @@ __pthread_setname_np (pthread_t th, const char *name) if (pd == THREAD_SELF) return __prctl (PR_SET_NAME, name) ? errno : 0; -#define FMT "/proc/self/task/%u/comm" - char fname[sizeof (FMT) + 8]; - sprintf (fname, FMT, (unsigned int) pd->tid); + /* Block all signals, as required by pd->exit_lock. */ + internal_sigset_t old_mask; + internal_signal_block_all (&old_mask); + __libc_lock_lock (pd->exit_lock); - int fd = __open64_nocancel (fname, O_RDWR); - if (fd == -1) - return errno; - - int res = 0; - ssize_t n = TEMP_FAILURE_RETRY (__write_nocancel (fd, name, name_len)); - if (n < 0) - res = errno; - else if (n != name_len) - res = EIO; + int res = pd->tid > 0 ? setname (pd->tid, name, name_len) : EINVAL; - __close_nocancel_nostatus (fd); + __libc_lock_unlock (pd->exit_lock); + internal_signal_restore_set (&old_mask); return res; } diff --git a/sysdeps/pthread/tst-pthread-exited.c b/sysdeps/pthread/tst-pthread-exited.c index 8f33de44b6..6a602afe3f 100644 --- a/sysdeps/pthread/tst-pthread-exited.c +++ b/sysdeps/pthread/tst-pthread-exited.c @@ -69,6 +69,12 @@ do_test (void) TEST_COMPARE (r, EINVAL); } + { + char thread_name[] = "test"; + int r = pthread_setname_np (thr, thread_name); + TEST_COMPARE (r, EINVAL); + } + xpthread_join (thr); return 0;