Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP7:GA
glibc.30871
mq-notify-use-after-free.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File mq-notify-use-after-free.patch of Package glibc.30871
From 42d359350510506b87101cf77202fefcbfc790cb Mon Sep 17 00:00:00 2001 From: Andreas Schwab <schwab@linux-m68k.org> Date: Thu, 27 May 2021 12:49:47 +0200 Subject: [PATCH] Use __pthread_attr_copy in mq_notify (bug 27896) Make a deep copy of the pthread attribute object to remove a potential use-after-free issue. CVE-2021-33574: The mq_notify function has a potential use-after-free issue when using a notification type of SIGEV_THREAD and a thread attribute with a non-default affinity mask. Index: glibc-2.31/nptl/Makefile =================================================================== --- glibc-2.31.orig/nptl/Makefile +++ glibc-2.31/nptl/Makefile @@ -146,7 +146,7 @@ libpthread-routines = nptl-init nptlfree mtx_trylock mtx_unlock call_once cnd_broadcast \ cnd_destroy cnd_init cnd_signal cnd_timedwait cnd_wait \ tss_create tss_delete tss_get tss_set pthread_mutex_conf \ - libpthread-compat + libpthread-compat pthread_attr_copy # pthread_setuid pthread_seteuid pthread_setreuid \ # pthread_setresuid \ # pthread_setgid pthread_setegid pthread_setregid \ Index: glibc-2.31/nptl/Versions =================================================================== --- glibc-2.31.orig/nptl/Versions +++ glibc-2.31/nptl/Versions @@ -285,6 +285,7 @@ libpthread { __pthread_clock_gettime; __pthread_clock_settime; __pthread_unwind; __pthread_get_minstack; __pthread_barrier_init; __pthread_barrier_wait; + __pthread_attr_copy; __shm_directory; __libpthread_freeres; } Index: glibc-2.31/nptl/pthreadP.h =================================================================== --- glibc-2.31.orig/nptl/pthreadP.h +++ glibc-2.31/nptl/pthreadP.h @@ -401,6 +401,8 @@ extern int __pthread_mutexattr_init (pth extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *attr); extern int __pthread_mutexattr_settype (pthread_mutexattr_t *attr, int kind); extern int __pthread_attr_destroy (pthread_attr_t *attr); +extern int __pthread_attr_setaffinity_np (pthread_attr_t *, size_t, + const cpu_set_t *); extern int __pthread_attr_getdetachstate (const pthread_attr_t *attr, int *detachstate); extern int __pthread_attr_setdetachstate (pthread_attr_t *attr, @@ -481,6 +483,7 @@ extern int __pthread_clockjoin_ex (pthre #if IS_IN (libpthread) +hidden_proto (__pthread_attr_setaffinity_np) hidden_proto (__pthread_mutex_init) hidden_proto (__pthread_mutex_destroy) hidden_proto (__pthread_mutex_lock) @@ -569,6 +572,11 @@ extern void __wait_lookup_done (void) at # define PTHREAD_STATIC_FN_REQUIRE(name) __asm (".globl " #name); #endif +/* Make a deep copy of the attribute *SOURCE in *TARGET. *TARGET is + not assumed to have been initialized. Returns 0 on success, or a + positive error code otherwise. */ +int __pthread_attr_copy (pthread_attr_t *target, const pthread_attr_t *source); + /* Returns 0 if POL is a valid scheduling policy. */ static inline int check_sched_policy_attr (int pol) Index: glibc-2.31/nptl/pthread_attr_copy.c =================================================================== --- /dev/null +++ glibc-2.31/nptl/pthread_attr_copy.c @@ -0,0 +1,56 @@ +/* Deep copy of a pthread_attr_t object. + Copyright (C) 2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <pthreadP.h> +#include <stdlib.h> + +int +__pthread_attr_copy (pthread_attr_t *target, const pthread_attr_t *source) +{ + /* Avoid overwriting *TARGET until all allocations have + succeeded. */ + union pthread_attr_transparent temp; + temp.external = *source; + + /* Force new allocation. This function has full ownership of temp. */ + temp.internal.cpuset = NULL; + temp.internal.cpusetsize = 0; + + int ret = 0; + + struct pthread_attr *isource = (struct pthread_attr *) source; + + /* Propagate affinity mask information. */ + if (isource->cpusetsize > 0) + ret = __pthread_attr_setaffinity_np (&temp.external, + isource->cpusetsize, + isource->cpuset); + + if (ret != 0) + { + /* Deallocate because we have ownership. */ + pthread_attr_destroy (&temp.external); + return ret; + } + + /* Transfer ownership. *target is not assumed to have been + initialized. */ + *target = temp.external; + return 0; +} Index: glibc-2.31/nptl/pthread_attr_setaffinity.c =================================================================== --- glibc-2.31.orig/nptl/pthread_attr_setaffinity.c +++ glibc-2.31/nptl/pthread_attr_setaffinity.c @@ -25,8 +25,8 @@ int -__pthread_attr_setaffinity_new (pthread_attr_t *attr, size_t cpusetsize, - const cpu_set_t *cpuset) +__pthread_attr_setaffinity_np (pthread_attr_t *attr, size_t cpusetsize, + const cpu_set_t *cpuset) { struct pthread_attr *iattr; @@ -55,7 +55,8 @@ __pthread_attr_setaffinity_new (pthread_ return 0; } -versioned_symbol (libpthread, __pthread_attr_setaffinity_new, +hidden_def (__pthread_attr_setaffinity_np); +versioned_symbol (libpthread, __pthread_attr_setaffinity_np, pthread_attr_setaffinity_np, GLIBC_2_3_4); @@ -64,7 +65,7 @@ int __pthread_attr_setaffinity_old (pthread_attr_t *attr, cpu_set_t *cpuset) { /* The old interface by default assumed a 1024 processor bitmap. */ - return __pthread_attr_setaffinity_new (attr, 128, cpuset); + return __pthread_attr_setaffinity_np (attr, 128, cpuset); } compat_symbol (libpthread, __pthread_attr_setaffinity_old, pthread_attr_setaffinity_np, GLIBC_2_3_3); Index: glibc-2.31/sysdeps/nptl/internaltypes.h =================================================================== --- glibc-2.31.orig/sysdeps/nptl/internaltypes.h +++ glibc-2.31/sysdeps/nptl/internaltypes.h @@ -50,6 +50,14 @@ struct pthread_attr #define ATTR_FLAG_POLICY_SET 0x0040 +/* Used to allocate a pthread_attr_t object which is also accessed + internally. */ +union pthread_attr_transparent +{ + pthread_attr_t external; + struct pthread_attr internal; +}; + /* Mutex attribute data structure. */ struct pthread_mutexattr { Index: glibc-2.31/sysdeps/unix/sysv/linux/mq_notify.c =================================================================== --- glibc-2.31.orig/sysdeps/unix/sysv/linux/mq_notify.c +++ glibc-2.31/sysdeps/unix/sysv/linux/mq_notify.c @@ -134,9 +134,12 @@ helper_thread (void *arg) to wait until it is done with it. */ (void) __pthread_barrier_wait (¬ify_barrier); } - else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED) - /* The only state we keep is the copy of the thread attributes. */ - free (data.attr); + else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED && data.attr != NULL) + { + /* The only state we keep is the copy of the thread attributes. */ + pthread_attr_destroy (data.attr); + free (data.attr); + } } return NULL; } @@ -257,8 +260,14 @@ mq_notify (mqd_t mqdes, const struct sig if (data.attr == NULL) return -1; - memcpy (data.attr, notification->sigev_notify_attributes, - sizeof (pthread_attr_t)); + int ret = __pthread_attr_copy (data.attr, + notification->sigev_notify_attributes); + if (ret != 0) + { + free (data.attr); + __set_errno (ret); + return -1; + } } /* Construct the new request. */ @@ -271,8 +280,11 @@ mq_notify (mqd_t mqdes, const struct sig int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se); /* If it failed, free the allocated memory. */ - if (__glibc_unlikely (retval != 0)) - free (data.attr); + if (retval != 0 && data.attr != NULL) + { + pthread_attr_destroy (data.attr); + free (data.attr); + } return retval; }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor