commit 9f48a8abb2b2762bf2fc8449bc5871a5b986f508 Author: Andreas K. Hüttel Date: Tue Jan 28 18:45:20 2025 +0100 Remove advisories from release branch Signed-off-by: Andreas K. Hüttel diff --git a/ADVISORIES b/ADVISORIES new file mode 100644 index 0000000000..d4e33f2df3 --- /dev/null +++ b/ADVISORIES @@ -0,0 +1,2 @@ +For the GNU C Library Security Advisories, see the git master branch: +https://sourceware.org/git/?p=glibc.git;a=tree;f=advisories;hb=HEAD diff --git a/advisories/GLIBC-SA-2023-0001 b/advisories/GLIBC-SA-2023-0001 deleted file mode 100644 index 3d19c91b6a..0000000000 --- a/advisories/GLIBC-SA-2023-0001 +++ /dev/null @@ -1,14 +0,0 @@ -printf: incorrect output for integers with thousands separator and width field - -When the printf family of functions is called with a format specifier -that uses an (enable grouping) and a minimum width -specifier, the resulting output could be larger than reasonably expected -by a caller that computed a tight bound on the buffer size. The -resulting larger than expected output could result in a buffer overflow -in the printf family of functions. - -CVE-Id: CVE-2023-25139 -Public-Date: 2023-02-02 -Vulnerable-Commit: e88b9f0e5cc50cab57a299dc7efe1a4eb385161d (2.37) -Fix-Commit: c980549cc6a1c03c23cc2fe3e7b0fe626a0364b0 (2.38) -Fix-Commit: 07b9521fc6369d000216b96562ff7c0ed32a16c4 (2.37-4) diff --git a/advisories/GLIBC-SA-2023-0002 b/advisories/GLIBC-SA-2023-0002 deleted file mode 100644 index 5122669a64..0000000000 --- a/advisories/GLIBC-SA-2023-0002 +++ /dev/null @@ -1,15 +0,0 @@ -getaddrinfo: Stack read overflow in no-aaaa mode - -If the system is configured in no-aaaa mode via /etc/resolv.conf, -getaddrinfo is called for the AF_UNSPEC address family, and a DNS -response is received over TCP that is larger than 2048 bytes, -getaddrinfo may potentially disclose stack contents via the returned -address data, or crash. - -CVE-Id: CVE-2023-4527 -Public-Date: 2023-09-12 -Vulnerable-Commit: f282cdbe7f436c75864e5640a409a10485e9abb2 (2.36) -Fix-Commit: bd77dd7e73e3530203be1c52c8a29d08270cb25d (2.39) -Fix-Commit: 4ea972b7edd7e36610e8cde18bf7a8149d7bac4f (2.36-113) -Fix-Commit: b7529346025a130fee483d42178b5c118da971bb (2.37-38) -Fix-Commit: b25508dd774b617f99419bdc3cf2ace4560cd2d6 (2.38-19) diff --git a/advisories/GLIBC-SA-2023-0003 b/advisories/GLIBC-SA-2023-0003 deleted file mode 100644 index d3aef80348..0000000000 --- a/advisories/GLIBC-SA-2023-0003 +++ /dev/null @@ -1,15 +0,0 @@ -getaddrinfo: Potential use-after-free - -When an NSS plugin only implements the _gethostbyname2_r and -_getcanonname_r callbacks, getaddrinfo could use memory that was freed -during buffer resizing, potentially causing a crash or read or write to -arbitrary memory. - -CVE-Id: CVE-2023-4806 -Public-Date: 2023-09-12 -Fix-Commit: 973fe93a5675c42798b2161c6f29c01b0e243994 (2.39) -Fix-Commit: e09ee267c03e3150c2c9ba28625ab130705a485e (2.34-420) -Fix-Commit: e3ccb230a961b4797510e6a1f5f21fd9021853e7 (2.35-270) -Fix-Commit: a9728f798ec7f05454c95637ee6581afaa9b487d (2.36-115) -Fix-Commit: 6529a7466c935f36e9006b854d6f4e1d4876f942 (2.37-39) -Fix-Commit: 00ae4f10b504bc4564e9f22f00907093f1ab9338 (2.38-20) diff --git a/advisories/GLIBC-SA-2023-0004 b/advisories/GLIBC-SA-2023-0004 deleted file mode 100644 index 5286a7aa54..0000000000 --- a/advisories/GLIBC-SA-2023-0004 +++ /dev/null @@ -1,16 +0,0 @@ -tunables: local privilege escalation through buffer overflow - -If a tunable of the form NAME=NAME=VAL is passed in the environment of a -setuid program and NAME is valid, it may result in a buffer overflow, -which could be exploited to achieve escalated privileges. This flaw was -introduced in glibc 2.34. - -CVE-Id: CVE-2023-4911 -Public-Date: 2023-10-03 -Vulnerable-Commit: 2ed18c5b534d9e92fc006202a5af0df6b72e7aca (2.34) -Fix-Commit: 1056e5b4c3f2d90ed2b4a55f96add28da2f4c8fa (2.39) -Fix-Commit: dcc367f148bc92e7f3778a125f7a416b093964d9 (2.34-423) -Fix-Commit: c84018a05aec80f5ee6f682db0da1130b0196aef (2.35-274) -Fix-Commit: 22955ad85186ee05834e47e665056148ca07699c (2.36-118) -Fix-Commit: b4e23c75aea756b4bddc4abcf27a1c6dca8b6bd3 (2.37-45) -Fix-Commit: 750a45a783906a19591fb8ff6b7841470f1f5701 (2.38-27) diff --git a/advisories/GLIBC-SA-2023-0005 b/advisories/GLIBC-SA-2023-0005 deleted file mode 100644 index cc4eb90b82..0000000000 --- a/advisories/GLIBC-SA-2023-0005 +++ /dev/null @@ -1,18 +0,0 @@ -getaddrinfo: DoS due to memory leak - -The fix for CVE-2023-4806 introduced a memory leak when an application -calls getaddrinfo for AF_INET6 with AI_CANONNAME, AI_ALL and AI_V4MAPPED -flags set. - -CVE-Id: CVE-2023-5156 -Public-Date: 2023-09-25 -Vulnerable-Commit: e09ee267c03e3150c2c9ba28625ab130705a485e (2.34-420) -Vulnerable-Commit: e3ccb230a961b4797510e6a1f5f21fd9021853e7 (2.35-270) -Vulnerable-Commit: a9728f798ec7f05454c95637ee6581afaa9b487d (2.36-115) -Vulnerable-Commit: 6529a7466c935f36e9006b854d6f4e1d4876f942 (2.37-39) -Vulnerable-Commit: 00ae4f10b504bc4564e9f22f00907093f1ab9338 (2.38-20) -Fix-Commit: 8006457ab7e1cd556b919f477348a96fe88f2e49 (2.34-421) -Fix-Commit: 17092c0311f954e6f3c010f73ce3a78c24ac279a (2.35-272) -Fix-Commit: 856bac55f98dc840e7c27cfa82262b933385de90 (2.36-116) -Fix-Commit: 4473d1b87d04b25cdd0e0354814eeaa421328268 (2.37-42) -Fix-Commit: 5ee59ca371b99984232d7584fe2b1a758b4421d3 (2.38-24) diff --git a/advisories/GLIBC-SA-2024-0001 b/advisories/GLIBC-SA-2024-0001 deleted file mode 100644 index 28931c75ae..0000000000 --- a/advisories/GLIBC-SA-2024-0001 +++ /dev/null @@ -1,15 +0,0 @@ -syslog: Heap buffer overflow in __vsyslog_internal - -__vsyslog_internal did not handle a case where printing a SYSLOG_HEADER -containing a long program name failed to update the required buffer -size, leading to the allocation and overflow of a too-small buffer on -the heap. - -CVE-Id: CVE-2023-6246 -Public-Date: 2024-01-30 -Vulnerable-Commit: 52a5be0df411ef3ff45c10c7c308cb92993d15b1 (2.37) -Fix-Commit: 6bd0e4efcc78f3c0115e5ea9739a1642807450da (2.39) -Fix-Commit: 23514c72b780f3da097ecf33a793b7ba9c2070d2 (2.38-42) -Fix-Commit: 97a4292aa4a2642e251472b878d0ec4c46a0e59a (2.37-57) -Vulnerable-Commit: b0e7888d1fa2dbd2d9e1645ec8c796abf78880b9 (2.36-16) -Fix-Commit: d1a83b6767f68b3cb5b4b4ea2617254acd040c82 (2.36-126) diff --git a/advisories/GLIBC-SA-2024-0002 b/advisories/GLIBC-SA-2024-0002 deleted file mode 100644 index 940bfcf2fc..0000000000 --- a/advisories/GLIBC-SA-2024-0002 +++ /dev/null @@ -1,15 +0,0 @@ -syslog: Heap buffer overflow in __vsyslog_internal - -__vsyslog_internal used the return value of snprintf/vsnprintf to -calculate buffer sizes for memory allocation. If these functions (for -any reason) failed and returned -1, the resulting buffer would be too -small to hold output. - -CVE-Id: CVE-2023-6779 -Public-Date: 2024-01-30 -Vulnerable-Commit: 52a5be0df411ef3ff45c10c7c308cb92993d15b1 (2.37) -Fix-Commit: 7e5a0c286da33159d47d0122007aac016f3e02cd (2.39) -Fix-Commit: d0338312aace5bbfef85e03055e1212dd0e49578 (2.38-43) -Fix-Commit: 67062eccd9a65d7fda9976a56aeaaf6c25a80214 (2.37-58) -Vulnerable-Commit: b0e7888d1fa2dbd2d9e1645ec8c796abf78880b9 (2.36-16) -Fix-Commit: 2bc9d7c002bdac38b5c2a3f11b78e309d7765b83 (2.36-127) diff --git a/advisories/GLIBC-SA-2024-0003 b/advisories/GLIBC-SA-2024-0003 deleted file mode 100644 index b43a5150ab..0000000000 --- a/advisories/GLIBC-SA-2024-0003 +++ /dev/null @@ -1,13 +0,0 @@ -syslog: Integer overflow in __vsyslog_internal - -__vsyslog_internal calculated a buffer size by adding two integers, but -did not first check if the addition would overflow. - -CVE-Id: CVE-2023-6780 -Public-Date: 2024-01-30 -Vulnerable-Commit: 52a5be0df411ef3ff45c10c7c308cb92993d15b1 (2.37) -Fix-Commit: ddf542da94caf97ff43cc2875c88749880b7259b (2.39) -Fix-Commit: d37c2b20a4787463d192b32041c3406c2bd91de0 (2.38-44) -Fix-Commit: 2b58cba076e912961ceaa5fa58588e4b10f791c0 (2.37-59) -Vulnerable-Commit: b0e7888d1fa2dbd2d9e1645ec8c796abf78880b9 (2.36-16) -Fix-Commit: b9b7d6a27aa0632f334352fa400771115b3c69b7 (2.36-128) diff --git a/advisories/GLIBC-SA-2024-0004 b/advisories/GLIBC-SA-2024-0004 deleted file mode 100644 index 08df2b3118..0000000000 --- a/advisories/GLIBC-SA-2024-0004 +++ /dev/null @@ -1,28 +0,0 @@ -ISO-2022-CN-EXT: fix out-of-bound writes when writing escape sequence - -The iconv() function in the GNU C Library versions 2.39 and older may -overflow the output buffer passed to it by up to 4 bytes when converting -strings to the ISO-2022-CN-EXT character set, which may be used to -crash an application or overwrite a neighbouring variable. - -ISO-2022-CN-EXT uses escape sequences to indicate character set changes -(as specified by RFC 1922). While the SOdesignation has the expected -bounds checks, neither SS2designation nor SS3designation have its; -allowing a write overflow of 1, 2, or 3 bytes with fixed values: -'$+I', '$+J', '$+K', '$+L', '$+M', or '$*H'. - -CVE-Id: CVE-2024-2961 -Public-Date: 2024-04-17 -Vulnerable-Commit: 755104edc75c53f4a0e7440334e944ad3c6b32fc (2.1.93-169) -Fix-Commit: f9dc609e06b1136bb0408be9605ce7973a767ada (2.40) -Fix-Commit: 31da30f23cddd36db29d5b6a1c7619361b271fb4 (2.39-31) -Fix-Commit: e1135387deded5d73924f6ca20c72a35dc8e1bda (2.38-66) -Fix-Commit: 89ce64b269a897a7780e4c73a7412016381c6ecf (2.37-89) -Fix-Commit: 4ed98540a7fd19f458287e783ae59c41e64df7b5 (2.36-164) -Fix-Commit: 36280d1ce5e245aabefb877fe4d3c6cff95dabfa (2.35-315) -Fix-Commit: a8b0561db4b9847ebfbfec20075697d5492a363c (2.34-459) -Fix-Commit: ed4f16ff6bed3037266f1fa682ebd32a18fce29c (2.33-263) -Fix-Commit: 682ad4c8623e611a971839990ceef00346289cc9 (2.32-140) -Fix-Commit: 3703c32a8d304c1ee12126134ce69be965f38000 (2.31-154) - -Reported-By: Charles Fol diff --git a/advisories/GLIBC-SA-2024-0005 b/advisories/GLIBC-SA-2024-0005 deleted file mode 100644 index a59596610a..0000000000 --- a/advisories/GLIBC-SA-2024-0005 +++ /dev/null @@ -1,22 +0,0 @@ -nscd: Stack-based buffer overflow in netgroup cache - -If the Name Service Cache Daemon's (nscd) fixed size cache is exhausted -by client requests then a subsequent client request for netgroup data -may result in a stack-based buffer overflow. This flaw was introduced -in glibc 2.15 when the cache was added to nscd. - -This vulnerability is only present in the nscd binary. - -CVE-Id: CVE-2024-33599 -Public-Date: 2024-04-23 -Vulnerable-Commit: 684ae515993269277448150a1ca70db3b94aa5bd (2.15) -Fix-Commit: 69c58d5ef9f584ea198bd00f7964d364d0e6b921 (2.31-155) -Fix-Commit: a77064893bfe8a701770e2f53a4d33805bc47a5a (2.32-141) -Fix-Commit: 5c75001a96abcd50cbdb74df24c3f013188d076e (2.33-264) -Fix-Commit: 52f73e5c4e29b14e79167272297977f360ae1e97 (2.34-460) -Fix-Commit: 7a95873543ce225376faf13bb71c43dea6d24f86 (2.35-316) -Fix-Commit: caa3151ca460bdd9330adeedd68c3112d97bffe4 (2.36-165) -Fix-Commit: f75c298e747b2b8b41b1c2f551c011a52c41bfd1 (2.37-91) -Fix-Commit: 5968aebb86164034b8f8421b4abab2f837a5bdaf (2.38-72) -Fix-Commit: 1263d583d2e28afb8be53f8d6922f0842036f35d (2.39-35) -Fix-Commit: 87801a8fd06db1d654eea3e4f7626ff476a9bdaa (2.40) diff --git a/advisories/GLIBC-SA-2024-0006 b/advisories/GLIBC-SA-2024-0006 deleted file mode 100644 index d44148d3d9..0000000000 --- a/advisories/GLIBC-SA-2024-0006 +++ /dev/null @@ -1,32 +0,0 @@ -nscd: Null pointer crash after notfound response - -If the Name Service Cache Daemon's (nscd) cache fails to add a not-found -netgroup response to the cache, the client request can result in a null -pointer dereference. This flaw was introduced in glibc 2.15 when the -cache was added to nscd. - -This vulnerability is only present in the nscd binary. - -CVE-Id: CVE-2024-33600 -Public-Date: 2024-04-24 -Vulnerable-Commit: 684ae515993269277448150a1ca70db3b94aa5bd (2.15) -Fix-Commit: b048a482f088e53144d26a61c390bed0210f49f2 (2.40) -Fix-Commit: 7835b00dbce53c3c87bbbb1754a95fb5e58187aa (2.40) -Fix-Commit: c99f886de54446cd4447db6b44be93dabbdc2f8b (2.39-37) -Fix-Commit: 5a508e0b508c8ad53bd0d2fb48fd71b242626341 (2.39-36) -Fix-Commit: 2ae9446c1b7a3064743b4a51c0bbae668ee43e4c (2.38-74) -Fix-Commit: 541ea5172aa658c4bd5c6c6d6fd13903c3d5bb0a (2.38-73) -Fix-Commit: a8070b31043c7585c36ba68a74298c4f7af075c3 (2.37-93) -Fix-Commit: 5eea50c4402e39588de98aa1d4469a79774703d4 (2.37-92) -Fix-Commit: f205b3af56740e3b014915b1bd3b162afe3407ef (2.36-167) -Fix-Commit: c34f470a615b136170abd16142da5dd0c024f7d1 (2.36-166) -Fix-Commit: bafadc589fbe21ae330e8c2af74db9da44a17660 (2.35-318) -Fix-Commit: 4370bef52b0f3f3652c6aa13d7a9bb3ac079746d (2.35-317) -Fix-Commit: 1f94122289a9bf7dba573f5d60327aaa2b85cf2e (2.34-462) -Fix-Commit: 966d6ac9e40222b84bb21674cc4f83c8d72a5a26 (2.34-461) -Fix-Commit: e3eef1b8fbdd3a7917af466ca9c4b7477251ca79 (2.33-266) -Fix-Commit: f20a8d696b13c6261b52a6434899121f8b19d5a7 (2.33-265) -Fix-Commit: be602180146de37582a3da3a0caa4b719645de9c (2.32-143) -Fix-Commit: 394eae338199078b7961b051c191539870742d7b (2.32-142) -Fix-Commit: 8d7949183760170c61e55def723c1d8050187874 (2.31-157) -Fix-Commit: 304ce5fe466c4762b21b36c26926a4657b59b53e (2.31-156) diff --git a/advisories/GLIBC-SA-2024-0007 b/advisories/GLIBC-SA-2024-0007 deleted file mode 100644 index b6928fa27a..0000000000 --- a/advisories/GLIBC-SA-2024-0007 +++ /dev/null @@ -1,28 +0,0 @@ -nscd: netgroup cache may terminate daemon on memory allocation failure - -The Name Service Cache Daemon's (nscd) netgroup cache uses xmalloc or -xrealloc and these functions may terminate the process due to a memory -allocation failure resulting in a denial of service to the clients. The -flaw was introduced in glibc 2.15 when the cache was added to nscd. - -This vulnerability is only present in the nscd binary. - -Subsequent refactoring of the netgroup cache only added more uses of -xmalloc and xrealloc. Uses of xmalloc and xrealloc in other parts of -nscd only occur during startup of the daemon and so are not affected by -client requests that could trigger an out of memory followed by -termination. - -CVE-Id: CVE-2024-33601 -Public-Date: 2024-04-24 -Vulnerable-Commit: 684ae515993269277448150a1ca70db3b94aa5bd (2.15) -Fix-Commit: c04a21e050d64a1193a6daab872bca2528bda44b (2.40) -Fix-Commit: a9a8d3eebb145779a18d90e3966009a1daa63cd8 (2.39-38) -Fix-Commit: 71af8ca864345d39b746d5cee84b94b430fad5db (2.38-75) -Fix-Commit: 6e106dc214d6a033a4e945d1c6cf58061f1c5f1f (2.37-94) -Fix-Commit: b6742463694b1dfdd5120b91ee21cf05d15ec2e2 (2.36-168) -Fix-Commit: 7a5864cac60e06000394128a5a2817b03542f5a3 (2.35-319) -Fix-Commit: 86f1d5f4129c373ac6fb6df5bcf38273838843cb (2.34-463) -Fix-Commit: 4d27d4b9a188786fc6a56745506cec2acfc51f83 (2.33-267) -Fix-Commit: 3ed195a8ec89da281e3c4bf887a13d281b72d8f4 (2.32-144) -Fix-Commit: bbf5a58ccb55679217f94de706164d15372fbbc0 (2.31-158) diff --git a/advisories/GLIBC-SA-2024-0008 b/advisories/GLIBC-SA-2024-0008 deleted file mode 100644 index d93e2a6f0b..0000000000 --- a/advisories/GLIBC-SA-2024-0008 +++ /dev/null @@ -1,26 +0,0 @@ -nscd: netgroup cache assumes NSS callback uses in-buffer strings - -The Name Service Cache Daemon's (nscd) netgroup cache can corrupt memory -when the NSS callback does not store all strings in the provided buffer. -The flaw was introduced in glibc 2.15 when the cache was added to nscd. - -This vulnerability is only present in the nscd binary. - -There is no guarantee from the NSS callback API that the returned -strings are all within the buffer. However, the netgroup cache code -assumes that the NSS callback uses in-buffer strings and if it doesn't -the buffer resizing logic could lead to potential memory corruption. - -CVE-Id: CVE-2024-33602 -Public-Date: 2024-04-24 -Vulnerable-Commit: 684ae515993269277448150a1ca70db3b94aa5bd (2.15) -Fix-Commit: c04a21e050d64a1193a6daab872bca2528bda44b (2.40) -Fix-Commit: a9a8d3eebb145779a18d90e3966009a1daa63cd8 (2.39-38) -Fix-Commit: 71af8ca864345d39b746d5cee84b94b430fad5db (2.38-75) -Fix-Commit: 6e106dc214d6a033a4e945d1c6cf58061f1c5f1f (2.37-94) -Fix-Commit: b6742463694b1dfdd5120b91ee21cf05d15ec2e2 (2.36-168) -Fix-Commit: 7a5864cac60e06000394128a5a2817b03542f5a3 (2.35-319) -Fix-Commit: 86f1d5f4129c373ac6fb6df5bcf38273838843cb (2.34-463) -Fix-Commit: 4d27d4b9a188786fc6a56745506cec2acfc51f83 (2.33-267) -Fix-Commit: 3ed195a8ec89da281e3c4bf887a13d281b72d8f4 (2.32-144) -Fix-Commit: bbf5a58ccb55679217f94de706164d15372fbbc0 (2.31-158) diff --git a/advisories/GLIBC-SA-2025-0001 b/advisories/GLIBC-SA-2025-0001 deleted file mode 100644 index 45f8b8f181..0000000000 --- a/advisories/GLIBC-SA-2025-0001 +++ /dev/null @@ -1,25 +0,0 @@ -assert: Buffer overflow when printing assertion failure message - -When the assert() function fails, it does not allocate enough space for the -assertion failure message string and size information, which may lead to a -buffer overflow if the message string size aligns to page size. - -This bug can be triggered when an assertion in a program fails. The assertion -failure message is allocated to allow developers to see this failure in core -dumps and it typically includes, in addition to the invariant assertion -string and function name, the name of the program. If the name of the failing -program is user controlled, for example on a local system, this could allow an -attacker to control the assertion failure to trigger this buffer overflow. - -The only viable vector for exploitation of this bug is local, if a setuid -program exists that has an existing bug that results in an assertion failure. -No such program has been discovered at the time of publishing this advisory, -but the presence of custom setuid programs, although strongly discouraged as a -security practice, cannot be discounted. - -CVE-Id: CVE-2025-0395 -Public-Date: 2025-01-22 -Vulnerable-Commit: f8a3b5bf8fa1d0c43d2458e03cc109a04fdef194 (2.13-175) -Fix-Commit: 68ee0f704cb81e9ad0a78c644a83e1e9cd2ee578 (2.41) -Fix-Commit: 7d4b6bcae91f29d7b4daf15bab06b66cf1d2217c (2.40-66) -Reported-By: Qualys Security Advisory diff --git a/advisories/README b/advisories/README deleted file mode 100644 index b8f8a829ca..0000000000 --- a/advisories/README +++ /dev/null @@ -1,77 +0,0 @@ -GNU C Library Security Advisory Format -====================================== - -Security advisories in this directory follow a simple git commit log -format, with a heading and free-format description augmented with tags -to allow parsing key information. References to code changes are -specific to the glibc repository and follow a specific format: - - Tag-name: (release-version) - -The indicates a specific commit in the repository. The -release-version indicates the publicly consumable release in which this -commit is known to exist. The release-version is derived from the -git-describe format, (i.e. stripped out from glibc-2.34.NNN-gxxxx) and -is of the form 2.34-NNN. If the -NNN suffix is absent, it means that -the change is in that release tarball, otherwise the change is on the -release/2.YY/master branch and not in any released tarball. - -The following tags are currently being used: - -CVE-Id: -This is the CVE-Id assigned under the CVE Program -(https://www.cve.org/). - -Public-Date: -The date this issue became publicly known. - -Vulnerable-Commit: -The commit that introduced this vulnerability. There could be multiple -entries, one for each release branch in the glibc repository; the -release-version portion of this tag should tell you which branch this is -on. - -Fix-Commit: -The commit that fixed this vulnerability. There could be multiple -entries for each release branch in the glibc repository, indicating that -all of those commits contributed to fixing that issue in each of those -branches. - -Reported-By: -The entity that reported this issue. There could be multiple entries, one for -each reporter. - -Adding an Advisory ------------------- - -An advisory for a CVE needs to be added on the master branch in two steps: - -1. Add the text of the advisory without any Fix-Commit tags along with - the fix for the CVE. Add the Vulnerable-Commit tag, if applicable. - The advisories directory does not exist in release branches, so keep - the advisory text commit distinct from the code changes, to ease - backports. Ask for the GLIBC-SA advisory number from the security - team. - -2. Finish all backports on release branches and then back on the msater - branch, add all commit refs to the advisory using the Fix-Commit - tags. Don't bother adding the release-version subscript since the - next step will overwrite it. - -3. Run the process-advisories.sh script in the scripts directory on the - advisory: - - scripts/process-advisories.sh update GLIBC-SA-YYYY-NNNN - - (replace YYYY-NNNN with the actual advisory number). - -4. Verify the updated advisory and push the result. - -Getting a NEWS snippet from advisories --------------------------------------- - -Run: - - scripts/process-advisories.sh news - -and copy the content into the NEWS file. commit 0a7c7a3e283a55d1bfaa48fdef063a32a4689a2b Author: Andreas K. Hüttel Date: Tue Jan 28 21:11:22 2025 +0100 NEWS: start new section Signed-off-by: Andreas K. Hüttel diff --git a/NEWS b/NEWS index b11422b060..0fef024e7f 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,12 @@ See the end for copying conditions. Please send GNU C library bug reports via using `glibc' in the "product" field. + +Version 2.41.1 + +The following bugs were resolved with this release: + + Version 2.41 commit bdccbfbc52d3f6957768a0b9d5bd7bc4c90f2744 Author: Adhemerval Zanella Date: Fri Jan 31 10:27:39 2025 -0300 math: Fix log10p1f internal table value (BZ 32626) It was copied wrong from CORE-MATH. (cherry picked from commit c79277a16785c8ae96d821414f4d31d654a0177c) diff --git a/NEWS b/NEWS index 0fef024e7f..91709980ef 100644 --- a/NEWS +++ b/NEWS @@ -9,7 +9,8 @@ Version 2.41.1 The following bugs were resolved with this release: - + [32626] math: math: log10p1f is not correctly rounded + [32627] math: math: sinhf is not correctly rounded Version 2.41 diff --git a/math/auto-libm-test-in b/math/auto-libm-test-in index 01ba689aa8..c0627dc7eb 100644 --- a/math/auto-libm-test-in +++ b/math/auto-libm-test-in @@ -7291,6 +7291,8 @@ log10p1 -0x1p-125 log10p1 -0x1p-1021 log10p1 -0x1p-16381 +log10p1 0x1.27f7dap-17 + log10p1 0x7.2a4368p-4 log10p1 0x6.d3a118p-4 log10p1 0x5.03f228p+0 diff --git a/math/auto-libm-test-out-log10p1 b/math/auto-libm-test-out-log10p1 index 87bdb0bcde..f5ce965720 100644 --- a/math/auto-libm-test-out-log10p1 +++ b/math/auto-libm-test-out-log10p1 @@ -1789,6 +1789,31 @@ log10p1 -0x1p-16381 = log10p1 tonearest binary128 -0x8p-16384 : -0x3.796f62a4dca1c654d56eaabeb4dp-16384 : inexact-ok underflow errno-erange-ok = log10p1 towardzero binary128 -0x8p-16384 : -0x3.796f62a4dca1c654d56eaabeb4ccp-16384 : inexact-ok underflow errno-erange-ok = log10p1 upward binary128 -0x8p-16384 : -0x3.796f62a4dca1c654d56eaabeb4ccp-16384 : inexact-ok underflow errno-erange-ok +log10p1 0x1.27f7dap-17 += log10p1 downward binary32 0x9.3fbedp-20 : 0x4.044b5p-20 : inexact-ok += log10p1 tonearest binary32 0x9.3fbedp-20 : 0x4.044b5p-20 : inexact-ok += log10p1 towardzero binary32 0x9.3fbedp-20 : 0x4.044b5p-20 : inexact-ok += log10p1 upward binary32 0x9.3fbedp-20 : 0x4.044b58p-20 : inexact-ok += log10p1 downward binary64 0x9.3fbedp-20 : 0x4.044b5157872ep-20 : inexact-ok += log10p1 tonearest binary64 0x9.3fbedp-20 : 0x4.044b5157872e4p-20 : inexact-ok += log10p1 towardzero binary64 0x9.3fbedp-20 : 0x4.044b5157872ep-20 : inexact-ok += log10p1 upward binary64 0x9.3fbedp-20 : 0x4.044b5157872e4p-20 : inexact-ok += log10p1 downward intel96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok += log10p1 tonearest intel96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok += log10p1 towardzero intel96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok += log10p1 upward intel96 0x9.3fbedp-20 : 0x4.044b5157872e287p-20 : inexact-ok += log10p1 downward m68k96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok += log10p1 tonearest m68k96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok += log10p1 towardzero m68k96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok += log10p1 upward m68k96 0x9.3fbedp-20 : 0x4.044b5157872e287p-20 : inexact-ok += log10p1 downward binary128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d808p-20 : inexact-ok += log10p1 tonearest binary128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d80cp-20 : inexact-ok += log10p1 towardzero binary128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d808p-20 : inexact-ok += log10p1 upward binary128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d80cp-20 : inexact-ok += log10p1 downward ibm128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d8p-20 : inexact-ok += log10p1 tonearest ibm128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d8p-20 : inexact-ok += log10p1 towardzero ibm128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d8p-20 : inexact-ok += log10p1 upward ibm128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287dap-20 : inexact-ok log10p1 0x7.2a4368p-4 = log10p1 downward binary32 0x7.2a4368p-4 : 0x2.9248dcp-4 : inexact-ok = log10p1 tonearest binary32 0x7.2a4368p-4 : 0x2.9248ep-4 : inexact-ok diff --git a/sysdeps/ieee754/flt-32/s_log10p1f.c b/sysdeps/ieee754/flt-32/s_log10p1f.c index 64deb1eeda..4e11d55d49 100644 --- a/sysdeps/ieee754/flt-32/s_log10p1f.c +++ b/sysdeps/ieee754/flt-32/s_log10p1f.c @@ -70,7 +70,7 @@ __log10p1f (float x) }; static const double tl[] = { - 0x1.562ec497ef351p-43, 0x1.b9476892ea99cp-8, 0x1.b5e909c959eecp-7, + -0x1.562ec497ef351p-43, 0x1.b9476892ea99cp-8, 0x1.b5e909c959eecp-7, 0x1.45f4f59ec84fp-6, 0x1.af5f92cbcf2aap-6, 0x1.0ba01a6069052p-5, 0x1.3ed119b99dd41p-5, 0x1.714834298a088p-5, 0x1.a30a9d98309c1p-5, 0x1.d41d51266b9d9p-5, 0x1.02428c0f62dfcp-4, 0x1.1a23444eea521p-4, commit d85a7719536f4892f2b53d4594e18f6d096c2882 Author: Adhemerval Zanella Date: Fri Jan 31 10:34:32 2025 -0300 math: Fix sinhf for some inputs (BZ 32627) The logic was copied wrong from CORE-MATH. diff --git a/math/auto-libm-test-in b/math/auto-libm-test-in index c0627dc7eb..5f465b31f1 100644 --- a/math/auto-libm-test-in +++ b/math/auto-libm-test-in @@ -8300,6 +8300,7 @@ sinh -0x1.3dda8ap+0 sinh -0x5.ee9218p-4 sinh -0x1.bcfc98p+0 sinh -0x6.9bbb6df7c5d08p-4 +sinh 0x1.250bfep-11 # the next value generates larger error bounds on x86_64 (ldbl-96) sinh 0x2.c5d376167f4052f4p+12 sinh max diff --git a/math/auto-libm-test-out-sinh b/math/auto-libm-test-out-sinh index 0b77a77eeb..3924e19d86 100644 --- a/math/auto-libm-test-out-sinh +++ b/math/auto-libm-test-out-sinh @@ -2115,6 +2115,31 @@ sinh -0x6.9bbb6df7c5d08p-4 = sinh tonearest ibm128 -0x6.9bbb6df7c5d08p-4 : -0x6.cc3ddf003dcda77f8f9e892e36p-4 : inexact-ok = sinh towardzero ibm128 -0x6.9bbb6df7c5d08p-4 : -0x6.cc3ddf003dcda77f8f9e892e36p-4 : inexact-ok = sinh upward ibm128 -0x6.9bbb6df7c5d08p-4 : -0x6.cc3ddf003dcda77f8f9e892e36p-4 : inexact-ok +sinh 0x1.250bfep-11 += sinh downward binary32 0x2.4a17fcp-12 : 0x2.4a17fcp-12 : inexact-ok += sinh tonearest binary32 0x2.4a17fcp-12 : 0x2.4a17fcp-12 : inexact-ok += sinh towardzero binary32 0x2.4a17fcp-12 : 0x2.4a17fcp-12 : inexact-ok += sinh upward binary32 0x2.4a17fcp-12 : 0x2.4a18p-12 : inexact-ok += sinh downward binary64 0x2.4a17fcp-12 : 0x2.4a17fdffffffep-12 : inexact-ok += sinh tonearest binary64 0x2.4a17fcp-12 : 0x2.4a17fep-12 : inexact-ok += sinh towardzero binary64 0x2.4a17fcp-12 : 0x2.4a17fdffffffep-12 : inexact-ok += sinh upward binary64 0x2.4a17fcp-12 : 0x2.4a17fep-12 : inexact-ok += sinh downward intel96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87cp-12 : inexact-ok += sinh tonearest intel96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff88p-12 : inexact-ok += sinh towardzero intel96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87cp-12 : inexact-ok += sinh upward intel96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff88p-12 : inexact-ok += sinh downward m68k96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87cp-12 : inexact-ok += sinh tonearest m68k96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff88p-12 : inexact-ok += sinh towardzero m68k96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87cp-12 : inexact-ok += sinh upward m68k96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff88p-12 : inexact-ok += sinh downward binary128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ec88p-12 : inexact-ok += sinh tonearest binary128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ec8ap-12 : inexact-ok += sinh towardzero binary128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ec88p-12 : inexact-ok += sinh upward binary128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ec8ap-12 : inexact-ok += sinh downward ibm128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ecp-12 : inexact-ok += sinh tonearest ibm128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786edp-12 : inexact-ok += sinh towardzero ibm128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ecp-12 : inexact-ok += sinh upward ibm128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786edp-12 : inexact-ok sinh 0x2.c5d376167f4052f4p+12 = sinh downward binary32 0x2.c5d378p+12 : 0xf.fffffp+124 : inexact-ok overflow errno-erange-ok = sinh tonearest binary32 0x2.c5d378p+12 : plus_infty : inexact-ok overflow errno-erange diff --git a/sysdeps/ieee754/flt-32/e_sinhf.c b/sysdeps/ieee754/flt-32/e_sinhf.c index c007c7d174..dee96fc7cb 100644 --- a/sysdeps/ieee754/flt-32/e_sinhf.c +++ b/sysdeps/ieee754/flt-32/e_sinhf.c @@ -83,7 +83,7 @@ __ieee754_sinhf (float x) { /* |x| <= 0x1.250bfep-11 */ if (__glibc_unlikely (ux < 0x66000000u)) /* |x| < 0x1p-24 */ return fmaf (x, fabsf (x), x); - if (__glibc_unlikely (st.uarg == asuint (ux))) + if (__glibc_unlikely (st.uarg == ux)) { float sgn = copysignf (1.0f, x); return sgn * st.rh + sgn * st.rl; commit cb7f20653724029be89224ed3a35d627cc5b4163 Author: John David Anglin Date: Wed Jan 29 16:51:16 2025 -0500 nptl: Correct stack size attribute when stack grows up [BZ #32574] Set stack size attribute to the size of the mmap'd region only when the size of the remaining stack space is less than the size of the mmap'd region. This was reversed. As a result, the initial stack size was only 135168 bytes. On architectures where the stack grows down, the initial stack size is approximately 8384512 bytes with the default rlimit settings. The small main stack size on hppa broke applications like ruby that check for stack overflows. Signed-off-by: John David Anglin diff --git a/nptl/pthread_getattr_np.c b/nptl/pthread_getattr_np.c index e98e2df152..43dd16d59c 100644 --- a/nptl/pthread_getattr_np.c +++ b/nptl/pthread_getattr_np.c @@ -145,9 +145,9 @@ __pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr) > (size_t) iattr->stackaddr - last_to) iattr->stacksize = (size_t) iattr->stackaddr - last_to; #else - /* The limit might be too high. */ + /* The limit might be too low. */ if ((size_t) iattr->stacksize - > to - (size_t) iattr->stackaddr) + < to - (size_t) iattr->stackaddr) iattr->stacksize = to - (size_t) iattr->stackaddr; #endif /* We succeed and no need to look further. */ commit cf88351b685da86667e17d344414a70696ac82f1 Author: Adhemerval Zanella Date: Sun Feb 2 16:57:49 2025 -0300 math: Fix tanf for some inputs (BZ 32630) The logic was copied wrong from CORE-MATH. (cherry picked from commit 09e7f4d594b4308fbea18e3044148d67b59757c9) diff --git a/NEWS b/NEWS index 91709980ef..cc98ab54c2 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,8 @@ The following bugs were resolved with this release: [32626] math: math: log10p1f is not correctly rounded [32627] math: math: sinhf is not correctly rounded + [32630] math: math: tanf is not correctly rounded for all rounding + modes Version 2.41 diff --git a/math/auto-libm-test-in b/math/auto-libm-test-in index 5f465b31f1..4f194da19d 100644 --- a/math/auto-libm-test-in +++ b/math/auto-libm-test-in @@ -8664,6 +8664,7 @@ tan 0x1.1ad374p+0 tan -0x1.0d55b8p+0 tan 1.57079697 tan -1.57079697 +tan 0x1.ada6aap+27 tan 0x1p-5 tan 0x1p-10 tan 0x1p-15 diff --git a/math/auto-libm-test-out-tan b/math/auto-libm-test-out-tan index 7d00d03e1d..1d5999ab90 100644 --- a/math/auto-libm-test-out-tan +++ b/math/auto-libm-test-out-tan @@ -2532,6 +2532,31 @@ tan -1.57079697 = tan tonearest ibm128 -0x1.921fc00ece4f02f278ade6ad9fp+0 : 0x1.7b91a0851bbbafa14cf21c2b5c8p+20 : inexact-ok = tan towardzero ibm128 -0x1.921fc00ece4f02f278ade6ad9fp+0 : 0x1.7b91a0851bbbafa14cf21c2b5cp+20 : inexact-ok = tan upward ibm128 -0x1.921fc00ece4f02f278ade6ad9fp+0 : 0x1.7b91a0851bbbafa14cf21c2b5c8p+20 : inexact-ok +tan 0x1.ada6aap+27 += tan downward binary32 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok += tan tonearest binary32 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok += tan towardzero binary32 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok += tan upward binary32 0xd.6d355p+24 : 0x3.d0060cp-4 : inexact-ok += tan downward binary64 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok += tan tonearest binary64 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok += tan towardzero binary64 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok += tan upward binary64 0xd.6d355p+24 : 0x3.d006080000002p-4 : inexact-ok += tan downward intel96 0xd.6d355p+24 : 0x3.d006080000000504p-4 : inexact-ok += tan tonearest intel96 0xd.6d355p+24 : 0x3.d006080000000508p-4 : inexact-ok += tan towardzero intel96 0xd.6d355p+24 : 0x3.d006080000000504p-4 : inexact-ok += tan upward intel96 0xd.6d355p+24 : 0x3.d006080000000508p-4 : inexact-ok += tan downward m68k96 0xd.6d355p+24 : 0x3.d006080000000504p-4 : inexact-ok += tan tonearest m68k96 0xd.6d355p+24 : 0x3.d006080000000508p-4 : inexact-ok += tan towardzero m68k96 0xd.6d355p+24 : 0x3.d006080000000504p-4 : inexact-ok += tan upward m68k96 0xd.6d355p+24 : 0x3.d006080000000508p-4 : inexact-ok += tan downward binary128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c15ap-4 : inexact-ok += tan tonearest binary128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c15ap-4 : inexact-ok += tan towardzero binary128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c15ap-4 : inexact-ok += tan upward binary128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c15cp-4 : inexact-ok += tan downward ibm128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c1p-4 : inexact-ok += tan tonearest ibm128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c1p-4 : inexact-ok += tan towardzero ibm128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c1p-4 : inexact-ok += tan upward ibm128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c2p-4 : inexact-ok tan 0x1p-5 = tan downward binary32 0x8p-8 : 0x8.00aabp-8 : inexact-ok = tan tonearest binary32 0x8p-8 : 0x8.00aacp-8 : inexact-ok diff --git a/sysdeps/ieee754/flt-32/s_tanf.c b/sysdeps/ieee754/flt-32/s_tanf.c index dfe56fc2a0..5ee1d6f35e 100644 --- a/sysdeps/ieee754/flt-32/s_tanf.c +++ b/sysdeps/ieee754/flt-32/s_tanf.c @@ -166,7 +166,7 @@ __tanf (float x) uint32_t sgn = t >> 31; for (int j = 0; j < array_length (st); j++) { - if (__glibc_unlikely (asfloat (st[j].arg) == ax)) + if (__glibc_unlikely (asuint (st[j].arg) == ax)) { if (sgn) return -st[j].rh - st[j].rl; commit 69fda28279b497bd405fdd442a6d8e4d3d5f681b Author: Siddhesh Poyarekar Date: Fri Jan 31 12:16:30 2025 -0500 assert: Add test for CVE-2025-0395 Use the __progname symbol to override the program name to induce the failure that CVE-2025-0395 describes. This is related to BZ #32582 Signed-off-by: Siddhesh Poyarekar Reviewed-by: Adhemerval Zanella (cherry picked from commit cdb9ba84191ce72e86346fb8b1d906e7cd930ea2) diff --git a/assert/Makefile b/assert/Makefile index 65b9d0768e..8d106d8752 100644 --- a/assert/Makefile +++ b/assert/Makefile @@ -39,6 +39,7 @@ tests := \ test-assert-perr \ tst-assert-c++ \ tst-assert-g++ \ + tst-assert-sa-2025-0001 \ # tests ifeq ($(have-cxx-thread_local),yes) diff --git a/assert/tst-assert-sa-2025-0001.c b/assert/tst-assert-sa-2025-0001.c new file mode 100644 index 0000000000..102cb0078d --- /dev/null +++ b/assert/tst-assert-sa-2025-0001.c @@ -0,0 +1,92 @@ +/* Test for CVE-2025-0395. + Copyright The GNU Toolchain Authors. + 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 + . */ + +/* Test that a large enough __progname does not result in a buffer overflow + when printing an assertion failure. This was CVE-2025-0395. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern const char *__progname; + +int +do_test (int argc, char **argv) +{ + + support_need_proc ("Reads /proc/self/maps to add guards to writable maps."); + ignore_stderr (); + + /* XXX assumes that the assert is on a 2 digit line number. */ + const char *prompt = ": %s:99: do_test: Assertion `argc < 1' failed.\n"; + + int ret = fprintf (stderr, prompt, __FILE__); + if (ret < 0) + FAIL_EXIT1 ("fprintf failed: %m\n"); + + size_t pagesize = getpagesize (); + size_t namesize = pagesize - 1 - ret; + + /* Alter the progname so that the assert message fills the entire page. */ + char progname[namesize]; + memset (progname, 'A', namesize - 1); + progname[namesize - 1] = '\0'; + __progname = progname; + + FILE *f = xfopen ("/proc/self/maps", "r"); + char *line = NULL; + size_t len = 0; + uintptr_t prev_to = 0; + + /* Pad the beginning of every writable mapping with a PROT_NONE map. This + ensures that the mmap in the assert_fail path never ends up below a + writable map and will terminate immediately in case of a buffer + overflow. */ + while (xgetline (&line, &len, f)) + { + uintptr_t from, to; + char perm[4]; + + sscanf (line, "%" SCNxPTR "-%" SCNxPTR " %c%c%c%c ", + &from, &to, + &perm[0], &perm[1], &perm[2], &perm[3]); + + bool writable = (memchr (perm, 'w', 4) != NULL); + + if (prev_to != 0 && from - prev_to > pagesize && writable) + xmmap ((void *) from - pagesize, pagesize, PROT_NONE, + MAP_ANONYMOUS | MAP_PRIVATE, 0); + + prev_to = to; + } + + xfclose (f); + + assert (argc < 1); + return 0; +} + +#define EXPECTED_SIGNAL SIGABRT +#define TEST_FUNCTION_ARGV do_test +#include commit 1e0e33e1b19a7634b364ac7b97c3c9612d5b776f Author: Aurelien Jarno Date: Sat Feb 15 11:08:33 2025 +0100 Fix tst-aarch64-pkey to handle ENOSPC as not supported The syscall pkey_alloc can return ENOSPC to indicate either that all keys are in use or that the system runs in a mode in which memory protection keys are disabled. In such case the test should not fail and just return unsupported. This matches the behaviour of the generic tst-pkey. Reviewed-by: Adhemerval Zanella Reviewed-by: Florian Weimer (cherry picked from commit 60f2d6be657aa8c663ee14bd266d343ae0f35afb) diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-aarch64-pkey.c b/sysdeps/unix/sysv/linux/aarch64/tst-aarch64-pkey.c index 3ff33ef72a..c884efc3b4 100644 --- a/sysdeps/unix/sysv/linux/aarch64/tst-aarch64-pkey.c +++ b/sysdeps/unix/sysv/linux/aarch64/tst-aarch64-pkey.c @@ -55,6 +55,10 @@ do_test (void) if (errno == ENOSYS || errno == EINVAL) FAIL_UNSUPPORTED ("kernel or CPU does not support memory protection keys"); + if (errno == ENOSPC) + FAIL_UNSUPPORTED + ("no keys available or kernel does not support memory" + " protection keys"); FAIL_EXIT1 ("pkey_alloc: %m"); } commit a900dbaf70f0a957f56b52caa69173592ad7596e Author: H.J. Lu Date: Thu Feb 20 07:08:26 2025 +0800 x86 (__HAVE_FLOAT128): Defined to 0 for Intel SYCL compiler [BZ #32723] Intel compiler always defines __INTEL_LLVM_COMPILER. When SYCL is enabled by -fsycl, it also defines SYCL_LANGUAGE_VERSION. Since Intel SYCL compiler doesn't support _Float128: https://github.com/intel/llvm/issues/16903 define __HAVE_FLOAT128 to 0 for Intel SYCL compiler. This fixes BZ #32723. Signed-off-by: H.J. Lu Reviewed-by: Sam James (cherry picked from commit 5a4573be6f96ff49111bb6cae767676b5aafa7a8) diff --git a/sysdeps/x86/bits/floatn.h b/sysdeps/x86/bits/floatn.h index d197cb10dd..adc7ed2e9e 100644 --- a/sysdeps/x86/bits/floatn.h +++ b/sysdeps/x86/bits/floatn.h @@ -25,11 +25,15 @@ floating-point type with the IEEE 754 binary128 format, and this glibc includes corresponding *f128 interfaces for it. The required libgcc support was added some time after the basic compiler - support, for x86_64 and x86. */ + support, for x86_64 and x86. Intel SYCL compiler doesn't support + _Float128: https://github.com/intel/llvm/issues/16903 + */ #if (defined __x86_64__ \ ? __GNUC_PREREQ (4, 3) \ : (defined __GNU__ ? __GNUC_PREREQ (4, 5) : __GNUC_PREREQ (4, 4))) \ - || __glibc_clang_prereq (3, 4) + || (__glibc_clang_prereq (3, 4) \ + && (!defined __INTEL_LLVM_COMPILER \ + || !defined SYCL_LANGUAGE_VERSION)) # define __HAVE_FLOAT128 1 #else # define __HAVE_FLOAT128 0 commit 2cb04444b934e000a4e36c1876ef2bf03dd80d66 Author: koraynilay Date: Sat Feb 22 15:55:59 2025 +0100 math: Fix `unknown type name '__float128'` for clang 3.4 to 3.8.1 (bug 32694) When compiling a program that includes using a clang version between 3.4 (included) and 3.8.1 (included), clang will fail with `unknown type name '__float128'; did you mean '__cfloat128'?`. This changes fixes the clang prerequirements macro call in floatn.h to check for clang 3.9 instead of 3.4, since support for __float128 was actually enabled in 3.9 by: commit 50f29e06a1b6a38f0bba9360cbff72c82d46cdd4 Author: Nemanja Ivanovic Date: Wed Apr 13 09:49:45 2016 +0000 Enable support for __float128 in Clang This fixes bug 32694. Signed-off-by: koraynilay Reviewed-by: H.J. Lu (cherry picked from commit 29803ed3ce420f01e7c567c97fc8945d5e5e5992) diff --git a/sysdeps/x86/bits/floatn.h b/sysdeps/x86/bits/floatn.h index adc7ed2e9e..4674165bd7 100644 --- a/sysdeps/x86/bits/floatn.h +++ b/sysdeps/x86/bits/floatn.h @@ -31,7 +31,7 @@ #if (defined __x86_64__ \ ? __GNUC_PREREQ (4, 3) \ : (defined __GNU__ ? __GNUC_PREREQ (4, 5) : __GNUC_PREREQ (4, 4))) \ - || (__glibc_clang_prereq (3, 4) \ + || (__glibc_clang_prereq (3, 9) \ && (!defined __INTEL_LLVM_COMPILER \ || !defined SYCL_LANGUAGE_VERSION)) # define __HAVE_FLOAT128 1 @@ -93,7 +93,7 @@ typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__))); /* The type _Float128 exists only since GCC 7.0. */ # if !__GNUC_PREREQ (7, 0) \ || (defined __cplusplus && !__GNUC_PREREQ (13, 0)) \ - || __glibc_clang_prereq (3, 4) + || __glibc_clang_prereq (3, 9) typedef __float128 _Float128; # endif commit 07288c7445bba747f65380066b1b5bdb2df5b630 Author: John David Anglin Date: Tue Feb 25 15:57:53 2025 -0500 math: Add optimization barrier to ensure a1 + u.d is not reused [BZ #30664] A number of fma tests started to fail on hppa when gcc was changed to use Ranger rather than EVRP. Eventually I found that the value of a1 + u.d in this is block of code was being computed in FE_TOWARDZERO mode and not the original rounding mode: if (TININESS_AFTER_ROUNDING) { w.d = a1 + u.d; if (w.ieee.exponent == 109) return w.d * 0x1p-108; } This caused the exponent value to be wrong and the wrong return path to be used. Here we add an optimization barrier after the rounding mode is reset to ensure that the previous value of a1 + u.d is not reused. Signed-off-by: John David Anglin diff --git a/sysdeps/ieee754/dbl-64/s_fma.c b/sysdeps/ieee754/dbl-64/s_fma.c index 20f617b996..42351c6b34 100644 --- a/sysdeps/ieee754/dbl-64/s_fma.c +++ b/sysdeps/ieee754/dbl-64/s_fma.c @@ -244,6 +244,9 @@ __fma (double x, double y, double z) /* Reset rounding mode and test for inexact simultaneously. */ int j = libc_feupdateenv_test (&env, FE_INEXACT) != 0; + /* Ensure value of a1 + u.d is not reused. */ + a1 = math_opt_barrier (a1); + if (__glibc_likely (adjust == 0)) { if ((u.ieee.mantissa1 & 1) == 0 && u.ieee.exponent != 0x7ff) commit 30992cb5e9d713ab0f4135dd8776a201f7a53f24 Author: Yangyu Chen Date: Tue Feb 25 01:12:19 2025 +0800 RISC-V: Fix IFUNC resolver cannot access gp pointer In some cases, an IFUNC resolver may need to access the gp pointer to access global variables. Such an object may have l_relocated == 0 at this time. In this case, an IFUNC resolver will fail to access a global variable and cause a SIGSEGV. This patch fixes this issue by relaxing the check of l_relocated in elf_machine_runtime_setup, but added a check for SHARED case to avoid using this code in static-linked executables. Such object have already set up the gp pointer in load_gp function and l->l_scope will be NULL if it is a pie object. So if we use these code to set up the gp pointer again for static-pie, it will causing a SIGSEGV in glibc as original bug on BZ #31317. I have also reproduced and checked BZ #31317 using the mold commit bed5b1731b ("illumos: Treat absolute symbols specially"), this patch can fix the issue. Also, we used the wrong gp pointer previously because ref->st_value is not the relocated address but just the offset from the base address of ELF. An edge case may happen if we reference gp pointer in a IFUNC resolver in a PIE object, but it will not happen in compiler-generated codes since -pie will disable relax to gp. In this case, the GP will be initialized incorrectly since the ref->st_value is not the address after relocation. This patch fixes this issue by adding the l->l_addr to ref->st_value to get the relocated address for the gp pointer. We don't use SYMBOL_ADDRESS macro here because __global_pointer$ is a special symbol that has SHN_ABS type, but it will use PC-relative addressing in the load_gp function using lla. Closes: BZ #32269 Fixes: 96d1b9ac23 ("RISC-V: Fix the static-PIE non-relocated object check") Co-authored-by: Vivian Wang Signed-off-by: Yangyu Chen (cherry picked from commit 3fd2ff7685e3ee85c8cd2896f28ad62f67d7c483) diff --git a/NEWS b/NEWS index cc98ab54c2..d819f5d896 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ Version 2.41.1 The following bugs were resolved with this release: + [32269] RISC-V IFUNC resolver cannot access gp pointer [32626] math: math: log10p1f is not correctly rounded [32627] math: math: sinhf is not correctly rounded [32630] math: math: tanf is not correctly rounded for all rounding diff --git a/sysdeps/riscv/dl-machine.h b/sysdeps/riscv/dl-machine.h index a30892f080..dcc3e0883b 100644 --- a/sysdeps/riscv/dl-machine.h +++ b/sysdeps/riscv/dl-machine.h @@ -348,7 +348,8 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[], gotplt[1] = (ElfW(Addr)) l; } - if (l->l_type == lt_executable && l->l_relocated) +#ifdef SHARED + if (l->l_type == lt_executable) { /* The __global_pointer$ may not be defined by the linker if the $gp register does not be used to access the global variable @@ -362,12 +363,16 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[], _dl_lookup_symbol_x ("__global_pointer$", l, &ref, l->l_scope, NULL, 0, 0, NULL); if (ref) - asm ( - "mv gp, %0\n" - : - : "r" (ref->st_value) - ); + asm ( + "mv gp, %0\n" + : + : "r" (ref->st_value + l->l_addr) + /* Don't use SYMBOL_ADDRESS here since __global_pointer$ + can be SHN_ABS type, but we need the address relative to + PC, not the absolute address. */ + ); } +#endif #endif return lazy; } commit 7c9a0868077c7e2cfed161ea47c40a96b269c773 Author: Luna Lamb Date: Thu Feb 13 17:52:09 2025 +0000 Aarch64: Improve codegen in SVE asinh Use unpredicated muls, use lanewise mla's and improve memory access. 1% regression in throughput microbenchmark on Neoverse V1. Reviewed-by: Wilco Dijkstra (cherry picked from commit 8f0e7fe61e0a2ad5ed777933703ce09053810ec4) diff --git a/sysdeps/aarch64/fpu/asinh_sve.c b/sysdeps/aarch64/fpu/asinh_sve.c index 0889f79dbb..ff6b71390c 100644 --- a/sysdeps/aarch64/fpu/asinh_sve.c +++ b/sysdeps/aarch64/fpu/asinh_sve.c @@ -18,36 +18,49 @@ . */ #include "sv_math.h" -#include "poly_sve_f64.h" #define SignMask (0x8000000000000000) #define One (0x3ff0000000000000) #define Thres (0x5fe0000000000000) /* asuint64 (0x1p511). */ +#define IndexMask (((1 << V_LOG_TABLE_BITS) - 1) << 1) static const struct data { - double poly[18]; - double ln2, p3, p1, p4, p0, p2; - uint64_t n; - uint64_t off; + double even_coeffs[9]; + double ln2, p3, p1, p4, p0, p2, c1, c3, c5, c7, c9, c11, c13, c15, c17; + uint64_t off, mask; } data = { - /* Polynomial generated using Remez on [2^-26, 1]. */ - .poly - = { -0x1.55555555554a7p-3, 0x1.3333333326c7p-4, -0x1.6db6db68332e6p-5, - 0x1.f1c71b26fb40dp-6, -0x1.6e8b8b654a621p-6, 0x1.1c4daa9e67871p-6, - -0x1.c9871d10885afp-7, 0x1.7a16e8d9d2ecfp-7, -0x1.3ddca533e9f54p-7, - 0x1.0becef748dafcp-7, -0x1.b90c7099dd397p-8, 0x1.541f2bb1ffe51p-8, - -0x1.d217026a669ecp-9, 0x1.0b5c7977aaf7p-9, -0x1.e0f37daef9127p-11, - 0x1.388b5fe542a6p-12, -0x1.021a48685e287p-14, 0x1.93d4ba83d34dap-18 }, + /* Polynomial generated using Remez on [2^-26, 1]. */ + .even_coeffs ={ + -0x1.55555555554a7p-3, + -0x1.6db6db68332e6p-5, + -0x1.6e8b8b654a621p-6, + -0x1.c9871d10885afp-7, + -0x1.3ddca533e9f54p-7, + -0x1.b90c7099dd397p-8, + -0x1.d217026a669ecp-9, + -0x1.e0f37daef9127p-11, + -0x1.021a48685e287p-14, }, + + .c1 = 0x1.3333333326c7p-4, + .c3 = 0x1.f1c71b26fb40dp-6, + .c5 = 0x1.1c4daa9e67871p-6, + .c7 = 0x1.7a16e8d9d2ecfp-7, + .c9 = 0x1.0becef748dafcp-7, + .c11 = 0x1.541f2bb1ffe51p-8, + .c13 = 0x1.0b5c7977aaf7p-9, + .c15 = 0x1.388b5fe542a6p-12, + .c17 = 0x1.93d4ba83d34dap-18, + .ln2 = 0x1.62e42fefa39efp-1, .p0 = -0x1.ffffffffffff7p-2, .p1 = 0x1.55555555170d4p-2, .p2 = -0x1.0000000399c27p-2, .p3 = 0x1.999b2e90e94cap-3, .p4 = -0x1.554e550bd501ep-3, - .n = 1 << V_LOG_TABLE_BITS, - .off = 0x3fe6900900000000 + .off = 0x3fe6900900000000, + .mask = 0xfffULL << 52, }; static svfloat64_t NOINLINE @@ -64,11 +77,10 @@ __sv_log_inline (svfloat64_t x, const struct data *d, const svbool_t pg) of the algorithm used. */ svuint64_t ix = svreinterpret_u64 (x); - svuint64_t tmp = svsub_x (pg, ix, d->off); - svuint64_t i = svand_x (pg, svlsr_x (pg, tmp, (51 - V_LOG_TABLE_BITS)), - (d->n - 1) << 1); - svint64_t k = svasr_x (pg, svreinterpret_s64 (tmp), 52); - svuint64_t iz = svsub_x (pg, ix, svand_x (pg, tmp, 0xfffULL << 52)); + svuint64_t i_off = svsub_x (pg, ix, d->off); + svuint64_t i + = svand_x (pg, svlsr_x (pg, i_off, (51 - V_LOG_TABLE_BITS)), IndexMask); + svuint64_t iz = svsub_x (pg, ix, svand_x (pg, i_off, d->mask)); svfloat64_t z = svreinterpret_f64 (iz); svfloat64_t invc = svld1_gather_index (pg, &__v_log_data.table[0].invc, i); @@ -78,14 +90,14 @@ __sv_log_inline (svfloat64_t x, const struct data *d, const svbool_t pg) svfloat64_t p1_p4 = svld1rq (svptrue_b64 (), &d->p1); svfloat64_t r = svmla_x (pg, sv_f64 (-1.0), invc, z); - svfloat64_t kd = svcvt_f64_x (pg, k); + svfloat64_t kd + = svcvt_f64_x (pg, svasr_x (pg, svreinterpret_s64 (i_off), 52)); svfloat64_t hi = svmla_lane (svadd_x (pg, logc, r), kd, ln2_p3, 0); - svfloat64_t r2 = svmul_x (pg, r, r); - + svfloat64_t r2 = svmul_x (svptrue_b64 (), r, r); svfloat64_t y = svmla_lane (sv_f64 (d->p2), r, ln2_p3, 1); - svfloat64_t p = svmla_lane (sv_f64 (d->p0), r, p1_p4, 0); + y = svmla_lane (y, r2, p1_p4, 1); y = svmla_x (pg, p, r2, y); y = svmla_x (pg, hi, r2, y); @@ -111,7 +123,6 @@ svfloat64_t SV_NAME_D1 (asinh) (svfloat64_t x, const svbool_t pg) svuint64_t iax = svbic_x (pg, ix, SignMask); svuint64_t sign = svand_x (pg, ix, SignMask); svfloat64_t ax = svreinterpret_f64 (iax); - svbool_t ge1 = svcmpge (pg, iax, One); svbool_t special = svcmpge (pg, iax, Thres); @@ -120,7 +131,7 @@ svfloat64_t SV_NAME_D1 (asinh) (svfloat64_t x, const svbool_t pg) svfloat64_t option_1 = sv_f64 (0); if (__glibc_likely (svptest_any (pg, ge1))) { - svfloat64_t x2 = svmul_x (pg, ax, ax); + svfloat64_t x2 = svmul_x (svptrue_b64 (), ax, ax); option_1 = __sv_log_inline ( svadd_x (pg, ax, svsqrt_x (pg, svadd_x (pg, x2, 1))), d, pg); } @@ -130,21 +141,53 @@ svfloat64_t SV_NAME_D1 (asinh) (svfloat64_t x, const svbool_t pg) The largest observed error in this region is 1.51 ULPs: _ZGVsMxv_asinh(0x1.fe12bf8c616a2p-1) got 0x1.c1e649ee2681bp-1 want 0x1.c1e649ee2681dp-1. */ + svfloat64_t option_2 = sv_f64 (0); if (__glibc_likely (svptest_any (pg, svnot_z (pg, ge1)))) { - svfloat64_t x2 = svmul_x (pg, ax, ax); - svfloat64_t x4 = svmul_x (pg, x2, x2); - svfloat64_t p = sv_pw_horner_17_f64_x (pg, x2, x4, d->poly); - option_2 = svmla_x (pg, ax, p, svmul_x (pg, x2, ax)); + svfloat64_t x2 = svmul_x (svptrue_b64 (), ax, ax); + svfloat64_t x4 = svmul_x (svptrue_b64 (), x2, x2); + /* Order-17 Pairwise Horner scheme. */ + svfloat64_t c13 = svld1rq (svptrue_b64 (), &d->c1); + svfloat64_t c57 = svld1rq (svptrue_b64 (), &d->c5); + svfloat64_t c911 = svld1rq (svptrue_b64 (), &d->c9); + svfloat64_t c1315 = svld1rq (svptrue_b64 (), &d->c13); + + svfloat64_t p01 = svmla_lane (sv_f64 (d->even_coeffs[0]), x2, c13, 0); + svfloat64_t p23 = svmla_lane (sv_f64 (d->even_coeffs[1]), x2, c13, 1); + svfloat64_t p45 = svmla_lane (sv_f64 (d->even_coeffs[2]), x2, c57, 0); + svfloat64_t p67 = svmla_lane (sv_f64 (d->even_coeffs[3]), x2, c57, 1); + svfloat64_t p89 = svmla_lane (sv_f64 (d->even_coeffs[4]), x2, c911, 0); + svfloat64_t p1011 = svmla_lane (sv_f64 (d->even_coeffs[5]), x2, c911, 1); + svfloat64_t p1213 + = svmla_lane (sv_f64 (d->even_coeffs[6]), x2, c1315, 0); + svfloat64_t p1415 + = svmla_lane (sv_f64 (d->even_coeffs[7]), x2, c1315, 1); + svfloat64_t p1617 = svmla_x (pg, sv_f64 (d->even_coeffs[8]), x2, d->c17); + + svfloat64_t p = svmla_x (pg, p1415, x4, p1617); + p = svmla_x (pg, p1213, x4, p); + p = svmla_x (pg, p1011, x4, p); + p = svmla_x (pg, p89, x4, p); + + p = svmla_x (pg, p67, x4, p); + p = svmla_x (pg, p45, x4, p); + + p = svmla_x (pg, p23, x4, p); + + p = svmla_x (pg, p01, x4, p); + + option_2 = svmla_x (pg, ax, p, svmul_x (svptrue_b64 (), x2, ax)); } - /* Choose the right option for each lane. */ - svfloat64_t y = svsel (ge1, option_1, option_2); - if (__glibc_unlikely (svptest_any (pg, special))) return special_case ( - x, svreinterpret_f64 (sveor_x (pg, svreinterpret_u64 (y), sign)), + x, + svreinterpret_f64 (sveor_x ( + pg, svreinterpret_u64 (svsel (ge1, option_1, option_2)), sign)), special); + + /* Choose the right option for each lane. */ + svfloat64_t y = svsel (ge1, option_1, option_2); return svreinterpret_f64 (sveor_x (pg, svreinterpret_u64 (y), sign)); } commit 94859e86807aff482f742ea650c32716f2780bdc Author: Luna Lamb Date: Thu Feb 13 17:54:46 2025 +0000 Aarch64: Improve codegen in SVE exp and users, and update expf_inline Use unpredicted muls, and improve memory access. 7%, 3% and 1% improvement in throughput microbenchmark on Neoverse V1, for exp, exp2 and cosh respectively. Reviewed-by: Wilco Dijkstra (cherry picked from commit c0ff447edf19bd4630fe79adf5e8b896405b059f) diff --git a/sysdeps/aarch64/fpu/cosh_sve.c b/sysdeps/aarch64/fpu/cosh_sve.c index ca44053535..77e58e123e 100644 --- a/sysdeps/aarch64/fpu/cosh_sve.c +++ b/sysdeps/aarch64/fpu/cosh_sve.c @@ -23,7 +23,7 @@ static const struct data { float64_t poly[3]; float64_t inv_ln2, ln2_hi, ln2_lo, shift, thres; - uint64_t index_mask, special_bound; + uint64_t special_bound; } data = { .poly = { 0x1.fffffffffffd4p-2, 0x1.5555571d6b68cp-3, 0x1.5555576a59599p-5, }, @@ -35,14 +35,16 @@ static const struct data .shift = 0x1.8p+52, .thres = 704.0, - .index_mask = 0xff, /* 0x1.6p9, above which exp overflows. */ .special_bound = 0x4086000000000000, }; static svfloat64_t NOINLINE -special_case (svfloat64_t x, svfloat64_t y, svbool_t special) +special_case (svfloat64_t x, svbool_t pg, svfloat64_t t, svbool_t special) { + svfloat64_t half_t = svmul_x (svptrue_b64 (), t, 0.5); + svfloat64_t half_over_t = svdivr_x (pg, t, 0.5); + svfloat64_t y = svadd_x (pg, half_t, half_over_t); return sv_call_f64 (cosh, x, y, special); } @@ -60,12 +62,12 @@ exp_inline (svfloat64_t x, const svbool_t pg, const struct data *d) svuint64_t u = svreinterpret_u64 (z); svuint64_t e = svlsl_x (pg, u, 52 - V_EXP_TAIL_TABLE_BITS); - svuint64_t i = svand_x (pg, u, d->index_mask); + svuint64_t i = svand_x (svptrue_b64 (), u, 0xff); svfloat64_t y = svmla_x (pg, sv_f64 (d->poly[1]), r, d->poly[2]); y = svmla_x (pg, sv_f64 (d->poly[0]), r, y); y = svmla_x (pg, sv_f64 (1.0), r, y); - y = svmul_x (pg, r, y); + y = svmul_x (svptrue_b64 (), r, y); /* s = 2^(n/N). */ u = svld1_gather_index (pg, __v_exp_tail_data, i); @@ -94,12 +96,12 @@ svfloat64_t SV_NAME_D1 (cosh) (svfloat64_t x, const svbool_t pg) /* Up to the point that exp overflows, we can use it to calculate cosh by exp(|x|) / 2 + 1 / (2 * exp(|x|)). */ svfloat64_t t = exp_inline (ax, pg, d); - svfloat64_t half_t = svmul_x (pg, t, 0.5); - svfloat64_t half_over_t = svdivr_x (pg, t, 0.5); /* Fall back to scalar for any special cases. */ if (__glibc_unlikely (svptest_any (pg, special))) - return special_case (x, svadd_x (pg, half_t, half_over_t), special); + return special_case (x, pg, t, special); + svfloat64_t half_t = svmul_x (svptrue_b64 (), t, 0.5); + svfloat64_t half_over_t = svdivr_x (pg, t, 0.5); return svadd_x (pg, half_t, half_over_t); } diff --git a/sysdeps/aarch64/fpu/exp10_sve.c b/sysdeps/aarch64/fpu/exp10_sve.c index f71bafdf0c..53b28934d9 100644 --- a/sysdeps/aarch64/fpu/exp10_sve.c +++ b/sysdeps/aarch64/fpu/exp10_sve.c @@ -18,21 +18,23 @@ . */ #include "sv_math.h" -#include "poly_sve_f64.h" #define SpecialBound 307.0 /* floor (log10 (2^1023)). */ static const struct data { - double poly[5]; + double c1, c3, c2, c4, c0; double shift, log10_2, log2_10_hi, log2_10_lo, scale_thres, special_bound; } data = { /* Coefficients generated using Remez algorithm. rel error: 0x1.9fcb9b3p-60 abs error: 0x1.a20d9598p-60 in [ -log10(2)/128, log10(2)/128 ] max ulp err 0.52 +0.5. */ - .poly = { 0x1.26bb1bbb55516p1, 0x1.53524c73cd32ap1, 0x1.0470591daeafbp1, - 0x1.2bd77b1361ef6p0, 0x1.142b5d54e9621p-1 }, + .c0 = 0x1.26bb1bbb55516p1, + .c1 = 0x1.53524c73cd32ap1, + .c2 = 0x1.0470591daeafbp1, + .c3 = 0x1.2bd77b1361ef6p0, + .c4 = 0x1.142b5d54e9621p-1, /* 1.5*2^46+1023. This value is further explained below. */ .shift = 0x1.800000000ffc0p+46, .log10_2 = 0x1.a934f0979a371p1, /* 1/log2(10). */ @@ -70,9 +72,9 @@ special_case (svbool_t pg, svfloat64_t s, svfloat64_t y, svfloat64_t n, /* |n| > 1280 => 2^(n) overflows. */ svbool_t p_cmp = svacgt (pg, n, d->scale_thres); - svfloat64_t r1 = svmul_x (pg, s1, s1); + svfloat64_t r1 = svmul_x (svptrue_b64 (), s1, s1); svfloat64_t r2 = svmla_x (pg, s2, s2, y); - svfloat64_t r0 = svmul_x (pg, r2, s1); + svfloat64_t r0 = svmul_x (svptrue_b64 (), r2, s1); return svsel (p_cmp, r1, r0); } @@ -103,11 +105,14 @@ svfloat64_t SV_NAME_D1 (exp10) (svfloat64_t x, svbool_t pg) comes at significant performance cost. */ svuint64_t u = svreinterpret_u64 (z); svfloat64_t scale = svexpa (u); - + svfloat64_t c24 = svld1rq (svptrue_b64 (), &d->c2); /* Approximate exp10(r) using polynomial. */ - svfloat64_t r2 = svmul_x (pg, r, r); - svfloat64_t y = svmla_x (pg, svmul_x (pg, r, d->poly[0]), r2, - sv_pairwise_poly_3_f64_x (pg, r, r2, d->poly + 1)); + svfloat64_t r2 = svmul_x (svptrue_b64 (), r, r); + svfloat64_t p12 = svmla_lane (sv_f64 (d->c1), r, c24, 0); + svfloat64_t p34 = svmla_lane (sv_f64 (d->c3), r, c24, 1); + svfloat64_t p14 = svmla_x (pg, p12, p34, r2); + + svfloat64_t y = svmla_x (pg, svmul_x (svptrue_b64 (), r, d->c0), r2, p14); /* Assemble result as exp10(x) = 2^n * exp10(r). If |x| > SpecialBound multiplication may overflow, so use special case routine. */ diff --git a/sysdeps/aarch64/fpu/exp2_sve.c b/sysdeps/aarch64/fpu/exp2_sve.c index a37c33092a..6db85266ca 100644 --- a/sysdeps/aarch64/fpu/exp2_sve.c +++ b/sysdeps/aarch64/fpu/exp2_sve.c @@ -18,7 +18,6 @@ . */ #include "sv_math.h" -#include "poly_sve_f64.h" #define N (1 << V_EXP_TABLE_BITS) @@ -27,15 +26,15 @@ static const struct data { - double poly[4]; + double c0, c2; + double c1, c3; double shift, big_bound, uoflow_bound; } data = { /* Coefficients are computed using Remez algorithm with minimisation of the absolute error. */ - .poly = { 0x1.62e42fefa3686p-1, 0x1.ebfbdff82c241p-3, 0x1.c6b09b16de99ap-5, - 0x1.3b2abf5571ad8p-7 }, - .shift = 0x1.8p52 / N, - .uoflow_bound = UOFlowBound, + .c0 = 0x1.62e42fefa3686p-1, .c1 = 0x1.ebfbdff82c241p-3, + .c2 = 0x1.c6b09b16de99ap-5, .c3 = 0x1.3b2abf5571ad8p-7, + .shift = 0x1.8p52 / N, .uoflow_bound = UOFlowBound, .big_bound = BigBound, }; @@ -67,9 +66,9 @@ special_case (svbool_t pg, svfloat64_t s, svfloat64_t y, svfloat64_t n, /* |n| > 1280 => 2^(n) overflows. */ svbool_t p_cmp = svacgt (pg, n, d->uoflow_bound); - svfloat64_t r1 = svmul_x (pg, s1, s1); + svfloat64_t r1 = svmul_x (svptrue_b64 (), s1, s1); svfloat64_t r2 = svmla_x (pg, s2, s2, y); - svfloat64_t r0 = svmul_x (pg, r2, s1); + svfloat64_t r0 = svmul_x (svptrue_b64 (), r2, s1); return svsel (p_cmp, r1, r0); } @@ -99,11 +98,14 @@ svfloat64_t SV_NAME_D1 (exp2) (svfloat64_t x, svbool_t pg) svuint64_t top = svlsl_x (pg, ki, 52 - V_EXP_TABLE_BITS); svfloat64_t scale = svreinterpret_f64 (svadd_x (pg, sbits, top)); + svfloat64_t c13 = svld1rq (svptrue_b64 (), &d->c1); /* Approximate exp2(r) using polynomial. */ - svfloat64_t r2 = svmul_x (pg, r, r); - svfloat64_t p = sv_pairwise_poly_3_f64_x (pg, r, r2, d->poly); - svfloat64_t y = svmul_x (pg, r, p); - + /* y = exp2(r) - 1 ~= C0 r + C1 r^2 + C2 r^3 + C3 r^4. */ + svfloat64_t r2 = svmul_x (svptrue_b64 (), r, r); + svfloat64_t p01 = svmla_lane (sv_f64 (d->c0), r, c13, 0); + svfloat64_t p23 = svmla_lane (sv_f64 (d->c2), r, c13, 1); + svfloat64_t p = svmla_x (pg, p01, p23, r2); + svfloat64_t y = svmul_x (svptrue_b64 (), r, p); /* Assemble exp2(x) = exp2(r) * scale. */ if (__glibc_unlikely (svptest_any (pg, special))) return special_case (pg, scale, y, kd, d); diff --git a/sysdeps/aarch64/fpu/exp_sve.c b/sysdeps/aarch64/fpu/exp_sve.c index 37de751f90..dc049482ed 100644 --- a/sysdeps/aarch64/fpu/exp_sve.c +++ b/sysdeps/aarch64/fpu/exp_sve.c @@ -21,12 +21,15 @@ static const struct data { - double poly[4]; + double c0, c2; + double c1, c3; double ln2_hi, ln2_lo, inv_ln2, shift, thres; + } data = { - .poly = { /* ulp error: 0.53. */ - 0x1.fffffffffdbcdp-2, 0x1.555555555444cp-3, 0x1.555573c6a9f7dp-5, - 0x1.1111266d28935p-7 }, + .c0 = 0x1.fffffffffdbcdp-2, + .c1 = 0x1.555555555444cp-3, + .c2 = 0x1.555573c6a9f7dp-5, + .c3 = 0x1.1111266d28935p-7, .ln2_hi = 0x1.62e42fefa3800p-1, .ln2_lo = 0x1.ef35793c76730p-45, /* 1/ln2. */ @@ -36,7 +39,6 @@ static const struct data .thres = 704.0, }; -#define C(i) sv_f64 (d->poly[i]) #define SpecialOffset 0x6000000000000000 /* 0x1p513. */ /* SpecialBias1 + SpecialBias1 = asuint(1.0). */ #define SpecialBias1 0x7000000000000000 /* 0x1p769. */ @@ -56,20 +58,20 @@ special_case (svbool_t pg, svfloat64_t s, svfloat64_t y, svfloat64_t n) svuint64_t b = svdup_u64_z (p_sign, SpecialOffset); /* Inactive lanes set to 0. */ - /* Set s1 to generate overflow depending on sign of exponent n. */ - svfloat64_t s1 = svreinterpret_f64 ( - svsubr_x (pg, b, SpecialBias1)); /* 0x70...0 - b. */ - /* Offset s to avoid overflow in final result if n is below threshold. */ + /* Set s1 to generate overflow depending on sign of exponent n, + ie. s1 = 0x70...0 - b. */ + svfloat64_t s1 = svreinterpret_f64 (svsubr_x (pg, b, SpecialBias1)); + /* Offset s to avoid overflow in final result if n is below threshold. + ie. s2 = as_u64 (s) - 0x3010...0 + b. */ svfloat64_t s2 = svreinterpret_f64 ( - svadd_x (pg, svsub_x (pg, svreinterpret_u64 (s), SpecialBias2), - b)); /* as_u64 (s) - 0x3010...0 + b. */ + svadd_x (pg, svsub_x (pg, svreinterpret_u64 (s), SpecialBias2), b)); /* |n| > 1280 => 2^(n) overflows. */ svbool_t p_cmp = svacgt (pg, n, 1280.0); - svfloat64_t r1 = svmul_x (pg, s1, s1); + svfloat64_t r1 = svmul_x (svptrue_b64 (), s1, s1); svfloat64_t r2 = svmla_x (pg, s2, s2, y); - svfloat64_t r0 = svmul_x (pg, r2, s1); + svfloat64_t r0 = svmul_x (svptrue_b64 (), r2, s1); return svsel (p_cmp, r1, r0); } @@ -103,16 +105,16 @@ svfloat64_t SV_NAME_D1 (exp) (svfloat64_t x, const svbool_t pg) svfloat64_t z = svmla_x (pg, sv_f64 (d->shift), x, d->inv_ln2); svuint64_t u = svreinterpret_u64 (z); svfloat64_t n = svsub_x (pg, z, d->shift); - + svfloat64_t c13 = svld1rq (svptrue_b64 (), &d->c1); /* r = x - n * ln2, r is in [-ln2/(2N), ln2/(2N)]. */ svfloat64_t ln2 = svld1rq (svptrue_b64 (), &d->ln2_hi); svfloat64_t r = svmls_lane (x, n, ln2, 0); r = svmls_lane (r, n, ln2, 1); /* y = exp(r) - 1 ~= r + C0 r^2 + C1 r^3 + C2 r^4 + C3 r^5. */ - svfloat64_t r2 = svmul_x (pg, r, r); - svfloat64_t p01 = svmla_x (pg, C (0), C (1), r); - svfloat64_t p23 = svmla_x (pg, C (2), C (3), r); + svfloat64_t r2 = svmul_x (svptrue_b64 (), r, r); + svfloat64_t p01 = svmla_lane (sv_f64 (d->c0), r, c13, 0); + svfloat64_t p23 = svmla_lane (sv_f64 (d->c2), r, c13, 1); svfloat64_t p04 = svmla_x (pg, p01, p23, r2); svfloat64_t y = svmla_x (pg, r, p04, r2); diff --git a/sysdeps/aarch64/fpu/sv_expf_inline.h b/sysdeps/aarch64/fpu/sv_expf_inline.h index f208d33896..16b81fc738 100644 --- a/sysdeps/aarch64/fpu/sv_expf_inline.h +++ b/sysdeps/aarch64/fpu/sv_expf_inline.h @@ -61,7 +61,7 @@ expf_inline (svfloat32_t x, const svbool_t pg, const struct sv_expf_data *d) /* scale = 2^(n/N). */ svfloat32_t scale = svexpa (svreinterpret_u32 (z)); - /* y = exp(r) - 1 ~= r + C0 r^2 + C1 r^3 + C2 r^4 + C3 r^5 + C4 r^6. */ + /* poly(r) = exp(r) - 1 ~= C0 r + C1 r^2 + C2 r^3 + C3 r^4 + C4 r^5. */ svfloat32_t p12 = svmla_lane (sv_f32 (d->c1), r, lane_consts, 2); svfloat32_t p34 = svmla_lane (sv_f32 (d->c3), r, lane_consts, 3); svfloat32_t r2 = svmul_x (svptrue_b32 (), r, r); @@ -71,5 +71,4 @@ expf_inline (svfloat32_t x, const svbool_t pg, const struct sv_expf_data *d) return svmla_x (pg, scale, scale, poly); } - #endif commit f3d9c116cb0a2efc3b7afafe2f966389526d5e70 Author: Yat Long Poon Date: Thu Feb 13 18:00:50 2025 +0000 AArch64: Improve codegen for SVE erfcf Reduce number of MOV/MOVPRFXs and use unpredicated FMUL. Replace MUL with LSL. Speedup on Neoverse V1: 6%. Reviewed-by: Wilco Dijkstra (cherry picked from commit f5ff34cb3c75ec1061c75bb9188b3c1176426947) diff --git a/sysdeps/aarch64/fpu/erfcf_sve.c b/sysdeps/aarch64/fpu/erfcf_sve.c index 2743f9dbb5..b57ab514b7 100644 --- a/sysdeps/aarch64/fpu/erfcf_sve.c +++ b/sysdeps/aarch64/fpu/erfcf_sve.c @@ -76,7 +76,7 @@ svfloat32_t SV_NAME_F1 (erfc) (svfloat32_t x, const svbool_t pg) svuint32_t i = svqadd (svreinterpret_u32 (z), dat->off_idx); /* Lookup erfc(r) and 2/sqrt(pi)*exp(-r^2) in tables. */ - i = svmul_x (pg, i, 2); + i = svlsl_x (svptrue_b32 (), i, 1); const float32_t *p = &__v_erfcf_data.tab[0].erfc - 2 * dat->off_arr; svfloat32_t erfcr = svld1_gather_index (pg, p, i); svfloat32_t scale = svld1_gather_index (pg, p + 1, i); @@ -84,15 +84,15 @@ svfloat32_t SV_NAME_F1 (erfc) (svfloat32_t x, const svbool_t pg) /* erfc(x) ~ erfc(r) - scale * d * poly(r, d). */ svfloat32_t r = svsub_x (pg, z, shift); svfloat32_t d = svsub_x (pg, a, r); - svfloat32_t d2 = svmul_x (pg, d, d); - svfloat32_t r2 = svmul_x (pg, r, r); + svfloat32_t d2 = svmul_x (svptrue_b32 (), d, d); + svfloat32_t r2 = svmul_x (svptrue_b32 (), r, r); svfloat32_t coeffs = svld1rq (svptrue_b32 (), &dat->third); - svfloat32_t third = svdup_lane (coeffs, 0); svfloat32_t p1 = r; - svfloat32_t p2 = svmls_lane (third, r2, coeffs, 1); - svfloat32_t p3 = svmul_x (pg, r, svmla_lane (sv_f32 (-0.5), r2, coeffs, 0)); + svfloat32_t p2 = svmls_lane (sv_f32 (dat->third), r2, coeffs, 1); + svfloat32_t p3 + = svmul_x (svptrue_b32 (), r, svmla_lane (sv_f32 (-0.5), r2, coeffs, 0)); svfloat32_t p4 = svmla_lane (sv_f32 (dat->two_over_five), r2, coeffs, 2); p4 = svmls_x (pg, sv_f32 (dat->tenth), r2, p4); commit 2025e27a817f99c64ddcd663b7861012893d7aab Author: Yat Long Poon Date: Thu Feb 13 18:02:01 2025 +0000 AArch64: Improve codegen for SVE pow Move constants to struct. Improve memory access with indexed/unpredicated instructions. Eliminate register spills. Speedup on Neoverse V1: 24%. Reviewed-by: Wilco Dijkstra (cherry picked from commit 0b195651db3ae793187c7dd6d78b5a7a8da9d5e6) diff --git a/sysdeps/aarch64/fpu/pow_sve.c b/sysdeps/aarch64/fpu/pow_sve.c index 42d551ca92..b8c1b39dca 100644 --- a/sysdeps/aarch64/fpu/pow_sve.c +++ b/sysdeps/aarch64/fpu/pow_sve.c @@ -44,19 +44,18 @@ /* Data is defined in v_pow_log_data.c. */ #define N_LOG (1 << V_POW_LOG_TABLE_BITS) -#define A __v_pow_log_data.poly #define Off 0x3fe6955500000000 /* Data is defined in v_pow_exp_data.c. */ #define N_EXP (1 << V_POW_EXP_TABLE_BITS) #define SignBias (0x800 << V_POW_EXP_TABLE_BITS) -#define C __v_pow_exp_data.poly #define SmallExp 0x3c9 /* top12(0x1p-54). */ #define BigExp 0x408 /* top12(512.). */ #define ThresExp 0x03f /* BigExp - SmallExp. */ #define HugeExp 0x409 /* top12(1024.). */ /* Constants associated with pow. */ +#define SmallBoundX 0x1p-126 #define SmallPowX 0x001 /* top12(0x1p-126). */ #define BigPowX 0x7ff /* top12(INFINITY). */ #define ThresPowX 0x7fe /* BigPowX - SmallPowX. */ @@ -64,6 +63,31 @@ #define BigPowY 0x43e /* top12(0x1.749p62). */ #define ThresPowY 0x080 /* BigPowY - SmallPowY. */ +static const struct data +{ + double log_c0, log_c2, log_c4, log_c6, ln2_hi, ln2_lo; + double log_c1, log_c3, log_c5, off; + double n_over_ln2, exp_c2, ln2_over_n_hi, ln2_over_n_lo; + double exp_c0, exp_c1; +} data = { + .log_c0 = -0x1p-1, + .log_c1 = -0x1.555555555556p-1, + .log_c2 = 0x1.0000000000006p-1, + .log_c3 = 0x1.999999959554ep-1, + .log_c4 = -0x1.555555529a47ap-1, + .log_c5 = -0x1.2495b9b4845e9p0, + .log_c6 = 0x1.0002b8b263fc3p0, + .off = Off, + .exp_c0 = 0x1.fffffffffffd4p-2, + .exp_c1 = 0x1.5555571d6ef9p-3, + .exp_c2 = 0x1.5555576a5adcep-5, + .ln2_hi = 0x1.62e42fefa3800p-1, + .ln2_lo = 0x1.ef35793c76730p-45, + .n_over_ln2 = 0x1.71547652b82fep0 * N_EXP, + .ln2_over_n_hi = 0x1.62e42fefc0000p-9, + .ln2_over_n_lo = -0x1.c610ca86c3899p-45, +}; + /* Check if x is an integer. */ static inline svbool_t sv_isint (svbool_t pg, svfloat64_t x) @@ -82,7 +106,7 @@ sv_isnotint (svbool_t pg, svfloat64_t x) static inline svbool_t sv_isodd (svbool_t pg, svfloat64_t x) { - svfloat64_t y = svmul_x (pg, x, 0.5); + svfloat64_t y = svmul_x (svptrue_b64 (), x, 0.5); return sv_isnotint (pg, y); } @@ -121,7 +145,7 @@ zeroinfnan (uint64_t i) static inline svbool_t sv_zeroinfnan (svbool_t pg, svuint64_t i) { - return svcmpge (pg, svsub_x (pg, svmul_x (pg, i, 2), 1), + return svcmpge (pg, svsub_x (pg, svadd_x (pg, i, i), 1), 2 * asuint64 (INFINITY) - 1); } @@ -174,16 +198,17 @@ sv_call_specialcase (svfloat64_t x1, svuint64_t u1, svuint64_t u2, additional 15 bits precision. IX is the bit representation of x, but normalized in the subnormal range using the sign bit for the exponent. */ static inline svfloat64_t -sv_log_inline (svbool_t pg, svuint64_t ix, svfloat64_t *tail) +sv_log_inline (svbool_t pg, svuint64_t ix, svfloat64_t *tail, + const struct data *d) { /* x = 2^k z; where z is in range [Off,2*Off) and exact. The range is split into N subintervals. The ith subinterval contains z and c is near its center. */ - svuint64_t tmp = svsub_x (pg, ix, Off); + svuint64_t tmp = svsub_x (pg, ix, d->off); svuint64_t i = svand_x (pg, svlsr_x (pg, tmp, 52 - V_POW_LOG_TABLE_BITS), sv_u64 (N_LOG - 1)); svint64_t k = svasr_x (pg, svreinterpret_s64 (tmp), 52); - svuint64_t iz = svsub_x (pg, ix, svand_x (pg, tmp, sv_u64 (0xfffULL << 52))); + svuint64_t iz = svsub_x (pg, ix, svlsl_x (pg, svreinterpret_u64 (k), 52)); svfloat64_t z = svreinterpret_f64 (iz); svfloat64_t kd = svcvt_f64_x (pg, k); @@ -199,40 +224,85 @@ sv_log_inline (svbool_t pg, svuint64_t ix, svfloat64_t *tail) |z/c - 1| < 1/N, so r = z/c - 1 is exactly representible. */ svfloat64_t r = svmad_x (pg, z, invc, -1.0); /* k*Ln2 + log(c) + r. */ - svfloat64_t t1 = svmla_x (pg, logc, kd, __v_pow_log_data.ln2_hi); + + svfloat64_t ln2_hilo = svld1rq_f64 (svptrue_b64 (), &d->ln2_hi); + svfloat64_t t1 = svmla_lane_f64 (logc, kd, ln2_hilo, 0); svfloat64_t t2 = svadd_x (pg, t1, r); - svfloat64_t lo1 = svmla_x (pg, logctail, kd, __v_pow_log_data.ln2_lo); + svfloat64_t lo1 = svmla_lane_f64 (logctail, kd, ln2_hilo, 1); svfloat64_t lo2 = svadd_x (pg, svsub_x (pg, t1, t2), r); /* Evaluation is optimized assuming superscalar pipelined execution. */ - svfloat64_t ar = svmul_x (pg, r, -0.5); /* A[0] = -0.5. */ - svfloat64_t ar2 = svmul_x (pg, r, ar); - svfloat64_t ar3 = svmul_x (pg, r, ar2); + + svfloat64_t log_c02 = svld1rq_f64 (svptrue_b64 (), &d->log_c0); + svfloat64_t ar = svmul_lane_f64 (r, log_c02, 0); + svfloat64_t ar2 = svmul_x (svptrue_b64 (), r, ar); + svfloat64_t ar3 = svmul_x (svptrue_b64 (), r, ar2); /* k*Ln2 + log(c) + r + A[0]*r*r. */ svfloat64_t hi = svadd_x (pg, t2, ar2); - svfloat64_t lo3 = svmla_x (pg, svneg_x (pg, ar2), ar, r); + svfloat64_t lo3 = svmls_x (pg, ar2, ar, r); svfloat64_t lo4 = svadd_x (pg, svsub_x (pg, t2, hi), ar2); /* p = log1p(r) - r - A[0]*r*r. */ /* p = (ar3 * (A[1] + r * A[2] + ar2 * (A[3] + r * A[4] + ar2 * (A[5] + r * A[6])))). */ - svfloat64_t a56 = svmla_x (pg, sv_f64 (A[5]), r, A[6]); - svfloat64_t a34 = svmla_x (pg, sv_f64 (A[3]), r, A[4]); - svfloat64_t a12 = svmla_x (pg, sv_f64 (A[1]), r, A[2]); + + svfloat64_t log_c46 = svld1rq_f64 (svptrue_b64 (), &d->log_c4); + svfloat64_t a56 = svmla_lane_f64 (sv_f64 (d->log_c5), r, log_c46, 1); + svfloat64_t a34 = svmla_lane_f64 (sv_f64 (d->log_c3), r, log_c46, 0); + svfloat64_t a12 = svmla_lane_f64 (sv_f64 (d->log_c1), r, log_c02, 1); svfloat64_t p = svmla_x (pg, a34, ar2, a56); p = svmla_x (pg, a12, ar2, p); - p = svmul_x (pg, ar3, p); + p = svmul_x (svptrue_b64 (), ar3, p); svfloat64_t lo = svadd_x ( - pg, svadd_x (pg, svadd_x (pg, svadd_x (pg, lo1, lo2), lo3), lo4), p); + pg, svadd_x (pg, svsub_x (pg, svadd_x (pg, lo1, lo2), lo3), lo4), p); svfloat64_t y = svadd_x (pg, hi, lo); *tail = svadd_x (pg, svsub_x (pg, hi, y), lo); return y; } +static inline svfloat64_t +sv_exp_core (svbool_t pg, svfloat64_t x, svfloat64_t xtail, + svuint64_t sign_bias, svfloat64_t *tmp, svuint64_t *sbits, + svuint64_t *ki, const struct data *d) +{ + /* exp(x) = 2^(k/N) * exp(r), with exp(r) in [2^(-1/2N),2^(1/2N)]. */ + /* x = ln2/N*k + r, with int k and r in [-ln2/2N, ln2/2N]. */ + svfloat64_t n_over_ln2_and_c2 = svld1rq_f64 (svptrue_b64 (), &d->n_over_ln2); + svfloat64_t z = svmul_lane_f64 (x, n_over_ln2_and_c2, 0); + /* z - kd is in [-1, 1] in non-nearest rounding modes. */ + svfloat64_t kd = svrinta_x (pg, z); + *ki = svreinterpret_u64 (svcvt_s64_x (pg, kd)); + + svfloat64_t ln2_over_n_hilo + = svld1rq_f64 (svptrue_b64 (), &d->ln2_over_n_hi); + svfloat64_t r = x; + r = svmls_lane_f64 (r, kd, ln2_over_n_hilo, 0); + r = svmls_lane_f64 (r, kd, ln2_over_n_hilo, 1); + /* The code assumes 2^-200 < |xtail| < 2^-8/N. */ + r = svadd_x (pg, r, xtail); + /* 2^(k/N) ~= scale. */ + svuint64_t idx = svand_x (pg, *ki, N_EXP - 1); + svuint64_t top + = svlsl_x (pg, svadd_x (pg, *ki, sign_bias), 52 - V_POW_EXP_TABLE_BITS); + /* This is only a valid scale when -1023*N < k < 1024*N. */ + *sbits = svld1_gather_index (pg, __v_pow_exp_data.sbits, idx); + *sbits = svadd_x (pg, *sbits, top); + /* exp(x) = 2^(k/N) * exp(r) ~= scale + scale * (exp(r) - 1). */ + svfloat64_t r2 = svmul_x (svptrue_b64 (), r, r); + *tmp = svmla_lane_f64 (sv_f64 (d->exp_c1), r, n_over_ln2_and_c2, 1); + *tmp = svmla_x (pg, sv_f64 (d->exp_c0), r, *tmp); + *tmp = svmla_x (pg, r, r2, *tmp); + svfloat64_t scale = svreinterpret_f64 (*sbits); + /* Note: tmp == 0 or |tmp| > 2^-200 and scale > 2^-739, so there + is no spurious underflow here even without fma. */ + z = svmla_x (pg, scale, scale, *tmp); + return z; +} + /* Computes sign*exp(x+xtail) where |xtail| < 2^-8/N and |xtail| <= |x|. The sign_bias argument is SignBias or 0 and sets the sign to -1 or 1. */ static inline svfloat64_t sv_exp_inline (svbool_t pg, svfloat64_t x, svfloat64_t xtail, - svuint64_t sign_bias) + svuint64_t sign_bias, const struct data *d) { /* 3 types of special cases: tiny (uflow and spurious uflow), huge (oflow) and other cases of large values of x (scale * (1 + TMP) oflow). */ @@ -240,73 +310,46 @@ sv_exp_inline (svbool_t pg, svfloat64_t x, svfloat64_t xtail, /* |x| is large (|x| >= 512) or tiny (|x| <= 0x1p-54). */ svbool_t uoflow = svcmpge (pg, svsub_x (pg, abstop, SmallExp), ThresExp); - /* Conditions special, uflow and oflow are all expressed as uoflow && - something, hence do not bother computing anything if no lane in uoflow is - true. */ - svbool_t special = svpfalse_b (); - svbool_t uflow = svpfalse_b (); - svbool_t oflow = svpfalse_b (); + svfloat64_t tmp; + svuint64_t sbits, ki; if (__glibc_unlikely (svptest_any (pg, uoflow))) { + svfloat64_t z + = sv_exp_core (pg, x, xtail, sign_bias, &tmp, &sbits, &ki, d); + /* |x| is tiny (|x| <= 0x1p-54). */ - uflow = svcmpge (pg, svsub_x (pg, abstop, SmallExp), 0x80000000); + svbool_t uflow + = svcmpge (pg, svsub_x (pg, abstop, SmallExp), 0x80000000); uflow = svand_z (pg, uoflow, uflow); /* |x| is huge (|x| >= 1024). */ - oflow = svcmpge (pg, abstop, HugeExp); + svbool_t oflow = svcmpge (pg, abstop, HugeExp); oflow = svand_z (pg, uoflow, svbic_z (pg, oflow, uflow)); + /* For large |x| values (512 < |x| < 1024) scale * (1 + TMP) can overflow - or underflow. */ - special = svbic_z (pg, uoflow, svorr_z (pg, uflow, oflow)); + or underflow. */ + svbool_t special = svbic_z (pg, uoflow, svorr_z (pg, uflow, oflow)); + + /* Update result with special and large cases. */ + z = sv_call_specialcase (tmp, sbits, ki, z, special); + + /* Handle underflow and overflow. */ + svbool_t x_is_neg = svcmplt (pg, x, 0); + svuint64_t sign_mask + = svlsl_x (pg, sign_bias, 52 - V_POW_EXP_TABLE_BITS); + svfloat64_t res_uoflow + = svsel (x_is_neg, sv_f64 (0.0), sv_f64 (INFINITY)); + res_uoflow = svreinterpret_f64 ( + svorr_x (pg, svreinterpret_u64 (res_uoflow), sign_mask)); + /* Avoid spurious underflow for tiny x. */ + svfloat64_t res_spurious_uflow + = svreinterpret_f64 (svorr_x (pg, sign_mask, 0x3ff0000000000000)); + + z = svsel (oflow, res_uoflow, z); + z = svsel (uflow, res_spurious_uflow, z); + return z; } - /* exp(x) = 2^(k/N) * exp(r), with exp(r) in [2^(-1/2N),2^(1/2N)]. */ - /* x = ln2/N*k + r, with int k and r in [-ln2/2N, ln2/2N]. */ - svfloat64_t z = svmul_x (pg, x, __v_pow_exp_data.n_over_ln2); - /* z - kd is in [-1, 1] in non-nearest rounding modes. */ - svfloat64_t shift = sv_f64 (__v_pow_exp_data.shift); - svfloat64_t kd = svadd_x (pg, z, shift); - svuint64_t ki = svreinterpret_u64 (kd); - kd = svsub_x (pg, kd, shift); - svfloat64_t r = x; - r = svmls_x (pg, r, kd, __v_pow_exp_data.ln2_over_n_hi); - r = svmls_x (pg, r, kd, __v_pow_exp_data.ln2_over_n_lo); - /* The code assumes 2^-200 < |xtail| < 2^-8/N. */ - r = svadd_x (pg, r, xtail); - /* 2^(k/N) ~= scale. */ - svuint64_t idx = svand_x (pg, ki, N_EXP - 1); - svuint64_t top - = svlsl_x (pg, svadd_x (pg, ki, sign_bias), 52 - V_POW_EXP_TABLE_BITS); - /* This is only a valid scale when -1023*N < k < 1024*N. */ - svuint64_t sbits = svld1_gather_index (pg, __v_pow_exp_data.sbits, idx); - sbits = svadd_x (pg, sbits, top); - /* exp(x) = 2^(k/N) * exp(r) ~= scale + scale * (exp(r) - 1). */ - svfloat64_t r2 = svmul_x (pg, r, r); - svfloat64_t tmp = svmla_x (pg, sv_f64 (C[1]), r, C[2]); - tmp = svmla_x (pg, sv_f64 (C[0]), r, tmp); - tmp = svmla_x (pg, r, r2, tmp); - svfloat64_t scale = svreinterpret_f64 (sbits); - /* Note: tmp == 0 or |tmp| > 2^-200 and scale > 2^-739, so there - is no spurious underflow here even without fma. */ - z = svmla_x (pg, scale, scale, tmp); - - /* Update result with special and large cases. */ - if (__glibc_unlikely (svptest_any (pg, special))) - z = sv_call_specialcase (tmp, sbits, ki, z, special); - - /* Handle underflow and overflow. */ - svuint64_t sign_bit = svlsr_x (pg, svreinterpret_u64 (x), 63); - svbool_t x_is_neg = svcmpne (pg, sign_bit, 0); - svuint64_t sign_mask = svlsl_x (pg, sign_bias, 52 - V_POW_EXP_TABLE_BITS); - svfloat64_t res_uoflow = svsel (x_is_neg, sv_f64 (0.0), sv_f64 (INFINITY)); - res_uoflow = svreinterpret_f64 ( - svorr_x (pg, svreinterpret_u64 (res_uoflow), sign_mask)); - z = svsel (oflow, res_uoflow, z); - /* Avoid spurious underflow for tiny x. */ - svfloat64_t res_spurious_uflow - = svreinterpret_f64 (svorr_x (pg, sign_mask, 0x3ff0000000000000)); - z = svsel (uflow, res_spurious_uflow, z); - - return z; + return sv_exp_core (pg, x, xtail, sign_bias, &tmp, &sbits, &ki, d); } static inline double @@ -341,47 +384,39 @@ pow_sc (double x, double y) svfloat64_t SV_NAME_D2 (pow) (svfloat64_t x, svfloat64_t y, const svbool_t pg) { + const struct data *d = ptr_barrier (&data); + /* This preamble handles special case conditions used in the final scalar fallbacks. It also updates ix and sign_bias, that are used in the core computation too, i.e., exp( y * log (x) ). */ svuint64_t vix0 = svreinterpret_u64 (x); svuint64_t viy0 = svreinterpret_u64 (y); - svuint64_t vtopx0 = svlsr_x (svptrue_b64 (), vix0, 52); /* Negative x cases. */ - svuint64_t sign_bit = svlsr_m (pg, vix0, 63); - svbool_t xisneg = svcmpeq (pg, sign_bit, 1); + svbool_t xisneg = svcmplt (pg, x, 0); /* Set sign_bias and ix depending on sign of x and nature of y. */ - svbool_t yisnotint_xisneg = svpfalse_b (); + svbool_t yint_or_xpos = pg; svuint64_t sign_bias = sv_u64 (0); svuint64_t vix = vix0; - svuint64_t vtopx1 = vtopx0; if (__glibc_unlikely (svptest_any (pg, xisneg))) { /* Determine nature of y. */ - yisnotint_xisneg = sv_isnotint (xisneg, y); - svbool_t yisint_xisneg = sv_isint (xisneg, y); + yint_or_xpos = sv_isint (xisneg, y); svbool_t yisodd_xisneg = sv_isodd (xisneg, y); /* ix set to abs(ix) if y is integer. */ - vix = svand_m (yisint_xisneg, vix0, 0x7fffffffffffffff); - vtopx1 = svand_m (yisint_xisneg, vtopx0, 0x7ff); + vix = svand_m (yint_or_xpos, vix0, 0x7fffffffffffffff); /* Set to SignBias if x is negative and y is odd. */ sign_bias = svsel (yisodd_xisneg, sv_u64 (SignBias), sv_u64 (0)); } - /* Special cases of x or y: zero, inf and nan. */ - svbool_t xspecial = sv_zeroinfnan (pg, vix0); - svbool_t yspecial = sv_zeroinfnan (pg, viy0); - svbool_t special = svorr_z (pg, xspecial, yspecial); - /* Small cases of x: |x| < 0x1p-126. */ - svuint64_t vabstopx0 = svand_x (pg, vtopx0, 0x7ff); - svbool_t xsmall = svcmplt (pg, vabstopx0, SmallPowX); - if (__glibc_unlikely (svptest_any (pg, xsmall))) + svbool_t xsmall = svaclt (yint_or_xpos, x, SmallBoundX); + if (__glibc_unlikely (svptest_any (yint_or_xpos, xsmall))) { /* Normalize subnormal x so exponent becomes negative. */ - svbool_t topx_is_null = svcmpeq (xsmall, vtopx1, 0); + svuint64_t vtopx = svlsr_x (svptrue_b64 (), vix, 52); + svbool_t topx_is_null = svcmpeq (xsmall, vtopx, 0); svuint64_t vix_norm = svreinterpret_u64 (svmul_m (xsmall, x, 0x1p52)); vix_norm = svand_m (xsmall, vix_norm, 0x7fffffffffffffff); @@ -391,20 +426,24 @@ svfloat64_t SV_NAME_D2 (pow) (svfloat64_t x, svfloat64_t y, const svbool_t pg) /* y_hi = log(ix, &y_lo). */ svfloat64_t vlo; - svfloat64_t vhi = sv_log_inline (pg, vix, &vlo); + svfloat64_t vhi = sv_log_inline (yint_or_xpos, vix, &vlo, d); /* z = exp(y_hi, y_lo, sign_bias). */ - svfloat64_t vehi = svmul_x (pg, y, vhi); - svfloat64_t velo = svmul_x (pg, y, vlo); - svfloat64_t vemi = svmls_x (pg, vehi, y, vhi); - velo = svsub_x (pg, velo, vemi); - svfloat64_t vz = sv_exp_inline (pg, vehi, velo, sign_bias); + svfloat64_t vehi = svmul_x (svptrue_b64 (), y, vhi); + svfloat64_t vemi = svmls_x (yint_or_xpos, vehi, y, vhi); + svfloat64_t velo = svnmls_x (yint_or_xpos, vemi, y, vlo); + svfloat64_t vz = sv_exp_inline (yint_or_xpos, vehi, velo, sign_bias, d); /* Cases of finite y and finite negative x. */ - vz = svsel (yisnotint_xisneg, sv_f64 (__builtin_nan ("")), vz); + vz = svsel (yint_or_xpos, vz, sv_f64 (__builtin_nan (""))); + + /* Special cases of x or y: zero, inf and nan. */ + svbool_t xspecial = sv_zeroinfnan (svptrue_b64 (), vix0); + svbool_t yspecial = sv_zeroinfnan (svptrue_b64 (), viy0); + svbool_t special = svorr_z (svptrue_b64 (), xspecial, yspecial); /* Cases of zero/inf/nan x or y. */ - if (__glibc_unlikely (svptest_any (pg, special))) + if (__glibc_unlikely (svptest_any (svptrue_b64 (), special))) vz = sv_call2_f64 (pow_sc, x, y, vz, special); return vz; commit 7774a9d07ab2fa3704deb0ffa60588017cf990e7 Author: Yat Long Poon Date: Thu Feb 13 18:03:04 2025 +0000 AArch64: Improve codegen for SVE powf Improve memory access with indexed/unpredicated instructions. Eliminate register spills. Speedup on Neoverse V1: 3%. Reviewed-by: Wilco Dijkstra (cherry picked from commit 95e807209b680257a9afe81a507754f1565dbb4d) diff --git a/sysdeps/aarch64/fpu/powf_sve.c b/sysdeps/aarch64/fpu/powf_sve.c index 29e9acb6fb..7046990aa1 100644 --- a/sysdeps/aarch64/fpu/powf_sve.c +++ b/sysdeps/aarch64/fpu/powf_sve.c @@ -26,7 +26,6 @@ #define Tlogc __v_powf_data.logc #define Texp __v_powf_data.scale #define SignBias (1 << (V_POWF_EXP2_TABLE_BITS + 11)) -#define Shift 0x1.8p52 #define Norm 0x1p23f /* 0x4b000000. */ /* Overall ULP error bound for pow is 2.6 ulp @@ -36,7 +35,7 @@ static const struct data double log_poly[4]; double exp_poly[3]; float uflow_bound, oflow_bound, small_bound; - uint32_t sign_bias, sign_mask, subnormal_bias, off; + uint32_t sign_bias, subnormal_bias, off; } data = { /* rel err: 1.5 * 2^-30. Each coefficients is multiplied the value of V_POWF_EXP2_N. */ @@ -53,7 +52,6 @@ static const struct data .small_bound = 0x1p-126f, .off = 0x3f35d000, .sign_bias = SignBias, - .sign_mask = 0x80000000, .subnormal_bias = 0x0b800000, /* 23 << 23. */ }; @@ -86,7 +84,7 @@ svisodd (svbool_t pg, svfloat32_t x) static inline svbool_t sv_zeroinfnan (svbool_t pg, svuint32_t i) { - return svcmpge (pg, svsub_x (pg, svmul_x (pg, i, 2u), 1), + return svcmpge (pg, svsub_x (pg, svadd_x (pg, i, i), 1), 2u * 0x7f800000 - 1); } @@ -150,9 +148,14 @@ powf_specialcase (float x, float y, float z) } /* Scalar fallback for special case routines with custom signature. */ -static inline svfloat32_t -sv_call_powf_sc (svfloat32_t x1, svfloat32_t x2, svfloat32_t y, svbool_t cmp) +static svfloat32_t NOINLINE +sv_call_powf_sc (svfloat32_t x1, svfloat32_t x2, svfloat32_t y) { + /* Special cases of x or y: zero, inf and nan. */ + svbool_t xspecial = sv_zeroinfnan (svptrue_b32 (), svreinterpret_u32 (x1)); + svbool_t yspecial = sv_zeroinfnan (svptrue_b32 (), svreinterpret_u32 (x2)); + svbool_t cmp = svorr_z (svptrue_b32 (), xspecial, yspecial); + svbool_t p = svpfirst (cmp, svpfalse ()); while (svptest_any (cmp, p)) { @@ -182,30 +185,30 @@ sv_powf_core_ext (const svbool_t pg, svuint64_t i, svfloat64_t z, svint64_t k, /* Polynomial to approximate log1p(r)/ln2. */ svfloat64_t logx = A (0); - logx = svmla_x (pg, A (1), r, logx); - logx = svmla_x (pg, A (2), r, logx); - logx = svmla_x (pg, A (3), r, logx); - logx = svmla_x (pg, y0, r, logx); + logx = svmad_x (pg, r, logx, A (1)); + logx = svmad_x (pg, r, logx, A (2)); + logx = svmad_x (pg, r, logx, A (3)); + logx = svmad_x (pg, r, logx, y0); *pylogx = svmul_x (pg, y, logx); /* z - kd is in [-1, 1] in non-nearest rounding modes. */ - svfloat64_t kd = svadd_x (pg, *pylogx, Shift); - svuint64_t ki = svreinterpret_u64 (kd); - kd = svsub_x (pg, kd, Shift); + svfloat64_t kd = svrinta_x (svptrue_b64 (), *pylogx); + svuint64_t ki = svreinterpret_u64 (svcvt_s64_x (svptrue_b64 (), kd)); r = svsub_x (pg, *pylogx, kd); /* exp2(x) = 2^(k/N) * 2^r ~= s * (C0*r^3 + C1*r^2 + C2*r + 1). */ - svuint64_t t - = svld1_gather_index (pg, Texp, svand_x (pg, ki, V_POWF_EXP2_N - 1)); - svuint64_t ski = svadd_x (pg, ki, sign_bias); - t = svadd_x (pg, t, svlsl_x (pg, ski, 52 - V_POWF_EXP2_TABLE_BITS)); + svuint64_t t = svld1_gather_index ( + svptrue_b64 (), Texp, svand_x (svptrue_b64 (), ki, V_POWF_EXP2_N - 1)); + svuint64_t ski = svadd_x (svptrue_b64 (), ki, sign_bias); + t = svadd_x (svptrue_b64 (), t, + svlsl_x (svptrue_b64 (), ski, 52 - V_POWF_EXP2_TABLE_BITS)); svfloat64_t s = svreinterpret_f64 (t); svfloat64_t p = C (0); p = svmla_x (pg, C (1), p, r); p = svmla_x (pg, C (2), p, r); - p = svmla_x (pg, s, p, svmul_x (pg, s, r)); + p = svmla_x (pg, s, p, svmul_x (svptrue_b64 (), s, r)); return p; } @@ -219,19 +222,16 @@ sv_powf_core (const svbool_t pg, svuint32_t i, svuint32_t iz, svint32_t k, { const svbool_t ptrue = svptrue_b64 (); - /* Unpack and promote input vectors (pg, y, z, i, k and sign_bias) into two in - order to perform core computation in double precision. */ + /* Unpack and promote input vectors (pg, y, z, i, k and sign_bias) into two + * in order to perform core computation in double precision. */ const svbool_t pg_lo = svunpklo (pg); const svbool_t pg_hi = svunpkhi (pg); - svfloat64_t y_lo = svcvt_f64_x ( - ptrue, svreinterpret_f32 (svunpklo (svreinterpret_u32 (y)))); - svfloat64_t y_hi = svcvt_f64_x ( - ptrue, svreinterpret_f32 (svunpkhi (svreinterpret_u32 (y)))); - svfloat32_t z = svreinterpret_f32 (iz); - svfloat64_t z_lo = svcvt_f64_x ( - ptrue, svreinterpret_f32 (svunpklo (svreinterpret_u32 (z)))); - svfloat64_t z_hi = svcvt_f64_x ( - ptrue, svreinterpret_f32 (svunpkhi (svreinterpret_u32 (z)))); + svfloat64_t y_lo + = svcvt_f64_x (pg, svreinterpret_f32 (svunpklo (svreinterpret_u32 (y)))); + svfloat64_t y_hi + = svcvt_f64_x (pg, svreinterpret_f32 (svunpkhi (svreinterpret_u32 (y)))); + svfloat64_t z_lo = svcvt_f64_x (pg, svreinterpret_f32 (svunpklo (iz))); + svfloat64_t z_hi = svcvt_f64_x (pg, svreinterpret_f32 (svunpkhi (iz))); svuint64_t i_lo = svunpklo (i); svuint64_t i_hi = svunpkhi (i); svint64_t k_lo = svunpklo (k); @@ -258,9 +258,9 @@ sv_powf_core (const svbool_t pg, svuint32_t i, svuint32_t iz, svint32_t k, /* Implementation of SVE powf. Provides the same accuracy as AdvSIMD powf, since it relies on the same algorithm. The theoretical maximum error is under 2.60 ULPs. - Maximum measured error is 2.56 ULPs: - SV_NAME_F2 (pow) (0x1.004118p+0, 0x1.5d14a4p+16) got 0x1.fd4bp+127 - want 0x1.fd4b06p+127. */ + Maximum measured error is 2.57 ULPs: + SV_NAME_F2 (pow) (0x1.031706p+0, 0x1.ce2ec2p+12) got 0x1.fff868p+127 + want 0x1.fff862p+127. */ svfloat32_t SV_NAME_F2 (pow) (svfloat32_t x, svfloat32_t y, const svbool_t pg) { const struct data *d = ptr_barrier (&data); @@ -269,21 +269,19 @@ svfloat32_t SV_NAME_F2 (pow) (svfloat32_t x, svfloat32_t y, const svbool_t pg) svuint32_t viy0 = svreinterpret_u32 (y); /* Negative x cases. */ - svuint32_t sign_bit = svand_m (pg, vix0, d->sign_mask); - svbool_t xisneg = svcmpeq (pg, sign_bit, d->sign_mask); + svbool_t xisneg = svcmplt (pg, x, sv_f32 (0)); /* Set sign_bias and ix depending on sign of x and nature of y. */ - svbool_t yisnotint_xisneg = svpfalse_b (); + svbool_t yint_or_xpos = pg; svuint32_t sign_bias = sv_u32 (0); svuint32_t vix = vix0; if (__glibc_unlikely (svptest_any (pg, xisneg))) { /* Determine nature of y. */ - yisnotint_xisneg = svisnotint (xisneg, y); - svbool_t yisint_xisneg = svisint (xisneg, y); + yint_or_xpos = svisint (xisneg, y); svbool_t yisodd_xisneg = svisodd (xisneg, y); /* ix set to abs(ix) if y is integer. */ - vix = svand_m (yisint_xisneg, vix0, 0x7fffffff); + vix = svand_m (yint_or_xpos, vix0, 0x7fffffff); /* Set to SignBias if x is negative and y is odd. */ sign_bias = svsel (yisodd_xisneg, sv_u32 (d->sign_bias), sv_u32 (0)); } @@ -294,8 +292,8 @@ svfloat32_t SV_NAME_F2 (pow) (svfloat32_t x, svfloat32_t y, const svbool_t pg) svbool_t cmp = svorr_z (pg, xspecial, yspecial); /* Small cases of x: |x| < 0x1p-126. */ - svbool_t xsmall = svaclt (pg, x, d->small_bound); - if (__glibc_unlikely (svptest_any (pg, xsmall))) + svbool_t xsmall = svaclt (yint_or_xpos, x, d->small_bound); + if (__glibc_unlikely (svptest_any (yint_or_xpos, xsmall))) { /* Normalize subnormal x so exponent becomes negative. */ svuint32_t vix_norm = svreinterpret_u32 (svmul_x (xsmall, x, Norm)); @@ -304,32 +302,35 @@ svfloat32_t SV_NAME_F2 (pow) (svfloat32_t x, svfloat32_t y, const svbool_t pg) vix = svsel (xsmall, vix_norm, vix); } /* Part of core computation carried in working precision. */ - svuint32_t tmp = svsub_x (pg, vix, d->off); - svuint32_t i = svand_x (pg, svlsr_x (pg, tmp, (23 - V_POWF_LOG2_TABLE_BITS)), - V_POWF_LOG2_N - 1); - svuint32_t top = svand_x (pg, tmp, 0xff800000); - svuint32_t iz = svsub_x (pg, vix, top); - svint32_t k - = svasr_x (pg, svreinterpret_s32 (top), (23 - V_POWF_EXP2_TABLE_BITS)); - - /* Compute core in extended precision and return intermediate ylogx results to - handle cases of underflow and underflow in exp. */ + svuint32_t tmp = svsub_x (yint_or_xpos, vix, d->off); + svuint32_t i = svand_x ( + yint_or_xpos, svlsr_x (yint_or_xpos, tmp, (23 - V_POWF_LOG2_TABLE_BITS)), + V_POWF_LOG2_N - 1); + svuint32_t top = svand_x (yint_or_xpos, tmp, 0xff800000); + svuint32_t iz = svsub_x (yint_or_xpos, vix, top); + svint32_t k = svasr_x (yint_or_xpos, svreinterpret_s32 (top), + (23 - V_POWF_EXP2_TABLE_BITS)); + + /* Compute core in extended precision and return intermediate ylogx results + * to handle cases of underflow and underflow in exp. */ svfloat32_t ylogx; - svfloat32_t ret = sv_powf_core (pg, i, iz, k, y, sign_bias, &ylogx, d); + svfloat32_t ret + = sv_powf_core (yint_or_xpos, i, iz, k, y, sign_bias, &ylogx, d); /* Handle exp special cases of underflow and overflow. */ - svuint32_t sign = svlsl_x (pg, sign_bias, 20 - V_POWF_EXP2_TABLE_BITS); + svuint32_t sign + = svlsl_x (yint_or_xpos, sign_bias, 20 - V_POWF_EXP2_TABLE_BITS); svfloat32_t ret_oflow - = svreinterpret_f32 (svorr_x (pg, sign, asuint (INFINITY))); + = svreinterpret_f32 (svorr_x (yint_or_xpos, sign, asuint (INFINITY))); svfloat32_t ret_uflow = svreinterpret_f32 (sign); - ret = svsel (svcmple (pg, ylogx, d->uflow_bound), ret_uflow, ret); - ret = svsel (svcmpgt (pg, ylogx, d->oflow_bound), ret_oflow, ret); + ret = svsel (svcmple (yint_or_xpos, ylogx, d->uflow_bound), ret_uflow, ret); + ret = svsel (svcmpgt (yint_or_xpos, ylogx, d->oflow_bound), ret_oflow, ret); /* Cases of finite y and finite negative x. */ - ret = svsel (yisnotint_xisneg, sv_f32 (__builtin_nanf ("")), ret); + ret = svsel (yint_or_xpos, ret, sv_f32 (__builtin_nanf (""))); - if (__glibc_unlikely (svptest_any (pg, cmp))) - return sv_call_powf_sc (x, y, ret, cmp); + if (__glibc_unlikely (svptest_any (cmp, cmp))) + return sv_call_powf_sc (x, y, ret); return ret; } commit 6d1f97bb0667e35cbb4e656516b0b5f48afcabde Author: Yury Khrustalev Date: Tue Jan 28 16:13:51 2025 +0000 aarch64: Add configure checks for GCS support - Add check that linker supports -z gcs=... - Add checks that main and test compiler support -mbranch-protection=gcs Reviewed-by: Adhemerval Zanella diff --git a/configure b/configure index eb8abd0054..8fd09c6d88 100755 --- a/configure +++ b/configure @@ -8908,6 +8908,105 @@ printf "%s\n" "$libc_linker_feature" >&6; } config_vars="$config_vars load-address-ldflag = $libc_cv_load_address_ldflag" +# Check if compilers support GCS in branch protection: + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports -mbranch-protection=gcs" >&5 +printf %s "checking if compiler supports -mbranch-protection=gcs... " >&6; } +if test ${libc_cv_cc_gcs+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) if { ac_try='${CC-cc} -Werror -mbranch-protection=gcs -xc /dev/null -S -o /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } +then : + libc_cv_cc_gcs=yes +else case e in #( + e) libc_cv_cc_gcs=no ;; +esac +fi ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_cc_gcs" >&5 +printf "%s\n" "$libc_cv_cc_gcs" >&6; } +if test "$TEST_CC" = "$CC"; then + libc_cv_test_cc_gcs=$libc_cv_cc_gcs +else + +saved_CC="$CC" +CC="$TEST_CC" +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports -mbranch-protection=gcs in testing" >&5 +printf %s "checking if compiler supports -mbranch-protection=gcs in testing... " >&6; } +if test ${libc_cv_test_cc_gcs+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) if { ac_try='${CC-cc} -Werror -mbranch-protection=gcs -xc /dev/null -S -o /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } +then : + libc_cv_test_cc_gcs=yes +else case e in #( + e) libc_cv_test_cc_gcs=no ;; +esac +fi ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_test_cc_gcs" >&5 +printf "%s\n" "$libc_cv_test_cc_gcs" >&6; } + +CC="$saved_CC" + +fi + +config_vars="$config_vars +have-cc-gcs = $libc_cv_cc_gcs" +config_vars="$config_vars +have-test-cc-gcs = $libc_cv_test_cc_gcs" + +# Check if linker supports GCS marking +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -z gcs=always" >&5 +printf %s "checking for linker that supports -z gcs=always... " >&6; } +libc_linker_feature=no +cat > conftest.c <&5 + (eval $ac_try) 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } +then + if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-z,gcs=always -nostdlib \ + -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \ + | grep "warning: -z gcs=always ignored" > /dev/null 2>&1; then + true + else + libc_linker_feature=yes + fi +fi +rm -f conftest* +if test $libc_linker_feature = yes; then + libc_cv_ld_gcs=yes +else + libc_cv_ld_gcs=no +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5 +printf "%s\n" "$libc_linker_feature" >&6; } +config_vars="$config_vars +have-ld-gcs = $libc_cv_ld_gcs" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build programs as PIE" >&5 printf %s "checking if we can build programs as PIE... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext diff --git a/configure.ac b/configure.ac index 050bfa65e3..d4ef0c4243 100644 --- a/configure.ac +++ b/configure.ac @@ -1992,6 +1992,23 @@ LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address], [libc_cv_load_address_ldflag=]) LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address_ldflag]) +# Check if compilers support GCS in branch protection: +LIBC_TRY_CC_AND_TEST_CC_OPTION([if compiler supports -mbranch-protection=gcs], + [-Werror -mbranch-protection=gcs], + libc_cv_cc_gcs, + [libc_cv_cc_gcs=yes], + [libc_cv_cc_gcs=no], + libc_cv_test_cc_gcs, + [libc_cv_test_cc_gcs=yes], + [libc_cv_test_cc_gcs=no]) +LIBC_CONFIG_VAR([have-cc-gcs], [$libc_cv_cc_gcs]) +LIBC_CONFIG_VAR([have-test-cc-gcs], [$libc_cv_test_cc_gcs]) + +# Check if linker supports GCS marking +LIBC_LINKER_FEATURE([-z gcs=always], [-Wl,-z,gcs=always], + [libc_cv_ld_gcs=yes], [libc_cv_ld_gcs=no]) +LIBC_CONFIG_VAR([have-ld-gcs], [$libc_cv_ld_gcs]) + AC_MSG_CHECKING(if we can build programs as PIE) AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED # error PIE is not supported commit fda5730898bc36d637bf32588c16ea06dde81d81 Author: Yury Khrustalev Date: Tue Jan 21 13:33:20 2025 +0000 aarch64: Add tests for Guarded Control Stack These tests validate that GCS tunable works as expected depending on the GCS markings in the test binaries. Tests validate both static and dynamically linked binaries. These new tests are AArch64 specific. Moreover, they are included only if linker supports the "-z gcs=" option. If built, these tests will run on systems with and without HWCAP_GCS. In the latter case the tests will be reported as UNSUPPORTED. Reviewed-by: Adhemerval Zanella diff --git a/sysdeps/unix/sysv/linux/aarch64/Makefile b/sysdeps/unix/sysv/linux/aarch64/Makefile index 1fdad67fae..e16799fedd 100644 --- a/sysdeps/unix/sysv/linux/aarch64/Makefile +++ b/sysdeps/unix/sysv/linux/aarch64/Makefile @@ -3,7 +3,77 @@ sysdep_headers += sys/elf.h tests += \ tst-aarch64-pkey \ # tests -endif + +ifneq (no,$(findstring no,$(have-cc-gcs) $(have-test-cc-gcs) $(have-ld-gcs))) + +gcs-tests-dynamic = \ + tst-gcs-disabled \ + tst-gcs-enforced \ + tst-gcs-enforced-abort \ + tst-gcs-optional-off \ + tst-gcs-optional-on \ + tst-gcs-override \ + # gcs-tests-dynamic + +gcs-tests-static = \ + tst-gcs-disabled-static \ + tst-gcs-enforced-static \ + tst-gcs-enforced-static-abort \ + tst-gcs-optional-static-off \ + tst-gcs-optional-static-on \ + tst-gcs-override-static \ + # gcs-tests-static + +tests += \ + $(gcs-tests-dynamic) \ + $(gcs-tests-static) \ + # tests + +tests-static += \ + $(gcs-tests-static) \ + # tests-static + +define run-gcs-abort-test + $(test-wrapper-env) $(run-program-env) \ + $(tst-gcs-$*-abort-ENV) $(host-test-program-cmd) +endef + +$(objpfx)tst-gcs-%-abort.out: $(..)sysdeps/unix/sysv/linux/aarch64/tst-gcs-abort.sh \ + $(objpfx)tst-gcs-%-abort + $(SHELL) $< $(common-objpfx) $(test-name) '$(run-gcs-abort-test)'; \ + $(evaluate-test) + +LDFLAGS-tst-gcs-disabled += -Wl,-z gcs=always +LDFLAGS-tst-gcs-enforced += -Wl,-z gcs=always +LDFLAGS-tst-gcs-enforced-abort += -Wl,-z gcs=never +LDFLAGS-tst-gcs-optional-on += -Wl,-z gcs=always +LDFLAGS-tst-gcs-optional-off += -Wl,-z gcs=never +LDFLAGS-tst-gcs-override += -Wl,-z gcs=never + +LDFLAGS-tst-gcs-disabled-static += -Wl,-z gcs=always +LDFLAGS-tst-gcs-enforced-static += -Wl,-z gcs=always +LDFLAGS-tst-gcs-enforced-static-abort += -Wl,-z gcs=never +LDFLAGS-tst-gcs-optional-static-on += -Wl,-z gcs=always +LDFLAGS-tst-gcs-optional-static-off += -Wl,-z gcs=never +LDFLAGS-tst-gcs-override-static += -Wl,-z gcs=never + +tst-gcs-disabled-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=0 +tst-gcs-enforced-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1 +tst-gcs-enforced-abort-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1 +tst-gcs-optional-on-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2 +tst-gcs-optional-off-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2 +tst-gcs-override-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=3 + +tst-gcs-disabled-static-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=0 +tst-gcs-enforced-static-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1 +tst-gcs-enforced-static-abort-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1 +tst-gcs-optional-static-on-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2 +tst-gcs-optional-static-off-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2 +tst-gcs-override-static-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=3 + +endif # ifeq ($(have-test-cc-gcs),yes) + +endif # ifeq ($(subdir),misc) ifeq ($(subdir),stdlib) gen-as-const-headers += ucontext_i.sym diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-abort.sh b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-abort.sh new file mode 100644 index 0000000000..9e2be2d5c5 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-abort.sh @@ -0,0 +1,39 @@ +#!/bin/sh +# Test wrapper for AArch64 tests for GCS that are expected to abort. +# 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 +# . + +objpfx=$1; shift +tstname=$1; shift +tstrun=$1; shift + +logfile=$objpfx/$tstname.out + +rm -vf $logfile +touch $logfile + +${tstrun} 2>> $logfile >> $logfile; status=$? + +if test $status -eq 127 \ + && grep -q -w "not GCS compatible" "$logfile" ; then + exit 0 +elif test $status -eq 77; then + exit 77 +else + echo "unexpected test output or exit status $status" + exit 1 +fi diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-disabled-static.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-disabled-static.c new file mode 100644 index 0000000000..c71d68cb86 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-disabled-static.c @@ -0,0 +1 @@ +#include "tst-gcs-disabled.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-disabled.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-disabled.c new file mode 100644 index 0000000000..bd688785bb --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-disabled.c @@ -0,0 +1,2 @@ +#define TEST_GCS_EXPECT_ENABLED 0 +#include "tst-gcs-skeleton.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-enforced-abort.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-enforced-abort.c new file mode 100644 index 0000000000..608318f26d --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-enforced-abort.c @@ -0,0 +1,2 @@ +#define TEST_GCS_EXPECT_ENABLED 1 +#include "tst-gcs-skeleton.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-enforced-static-abort.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-enforced-static-abort.c new file mode 100644 index 0000000000..c20a999f6b --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-enforced-static-abort.c @@ -0,0 +1 @@ +#include "tst-gcs-enforced-abort.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-enforced-static.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-enforced-static.c new file mode 100644 index 0000000000..bb39dada55 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-enforced-static.c @@ -0,0 +1 @@ +#include "tst-gcs-enforced.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-enforced.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-enforced.c new file mode 100644 index 0000000000..608318f26d --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-enforced.c @@ -0,0 +1,2 @@ +#define TEST_GCS_EXPECT_ENABLED 1 +#include "tst-gcs-skeleton.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-optional-off.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-optional-off.c new file mode 100644 index 0000000000..bd688785bb --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-optional-off.c @@ -0,0 +1,2 @@ +#define TEST_GCS_EXPECT_ENABLED 0 +#include "tst-gcs-skeleton.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-optional-on.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-optional-on.c new file mode 100644 index 0000000000..608318f26d --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-optional-on.c @@ -0,0 +1,2 @@ +#define TEST_GCS_EXPECT_ENABLED 1 +#include "tst-gcs-skeleton.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-optional-static-off.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-optional-static-off.c new file mode 100644 index 0000000000..54e3b9a0d5 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-optional-static-off.c @@ -0,0 +1 @@ +#include "tst-gcs-optional-off.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-optional-static-on.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-optional-static-on.c new file mode 100644 index 0000000000..11b884b429 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-optional-static-on.c @@ -0,0 +1 @@ +#include "tst-gcs-optional-on.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-override-static.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-override-static.c new file mode 100644 index 0000000000..09055dcdc4 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-override-static.c @@ -0,0 +1 @@ +#include "tst-gcs-override.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-override.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-override.c new file mode 100644 index 0000000000..608318f26d --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-override.c @@ -0,0 +1,2 @@ +#define TEST_GCS_EXPECT_ENABLED 1 +#include "tst-gcs-skeleton.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-skeleton.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-skeleton.c new file mode 100644 index 0000000000..37692c96d0 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-skeleton.c @@ -0,0 +1,58 @@ +/* AArch64 tests for GCS. + 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 + . */ + +#include +#include +#include + +#include +#include + +static bool __check_gcs_status (void) +{ + register unsigned long x16 asm ("x16"); + asm volatile ( + "mov x16, #1 /* _CHKFEAT_GCS */\n" + "hint 40 /* CHKFEAT_X16 */\n" + : "=r" (x16)); + return x16 ^ 1; +} + +static int +do_test (void) +{ + /* Check if GCS could possible by enabled. */ + if (!(getauxval (AT_HWCAP) & HWCAP_GCS)) + { + puts ("kernel or CPU does not support GCS"); + return EXIT_UNSUPPORTED; + } + bool gcs_enabled = __check_gcs_status (); + if (gcs_enabled) + puts ("GCS enabled"); + else + puts ("GCS not enabled"); +#if TEST_GCS_EXPECT_ENABLED + TEST_VERIFY (gcs_enabled); +#else + TEST_VERIFY (!gcs_enabled); +#endif + return 0; +} + +#include commit 61ba3cdfa9e946fc91b0113a7a569cbe57fb46c1 Author: Yury Khrustalev Date: Wed Jan 22 15:06:18 2025 +0000 aarch64: Add GCS tests for transitive dependencies Reviewed-by: Adhemerval Zanella diff --git a/sysdeps/unix/sysv/linux/aarch64/Makefile b/sysdeps/unix/sysv/linux/aarch64/Makefile index e16799fedd..19f2988dac 100644 --- a/sysdeps/unix/sysv/linux/aarch64/Makefile +++ b/sysdeps/unix/sysv/linux/aarch64/Makefile @@ -13,6 +13,10 @@ gcs-tests-dynamic = \ tst-gcs-optional-off \ tst-gcs-optional-on \ tst-gcs-override \ + tst-gcs-shared-disabled \ + tst-gcs-shared-enforced-abort \ + tst-gcs-shared-optional \ + tst-gcs-shared-override \ # gcs-tests-dynamic gcs-tests-static = \ @@ -71,6 +75,31 @@ tst-gcs-optional-static-on-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2 tst-gcs-optional-static-off-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2 tst-gcs-override-static-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=3 +# force one of the dependencies to be unmarked +LDFLAGS-tst-gcs-mod2.so += -Wl,-z gcs=never + +LDFLAGS-tst-gcs-shared-disabled = -Wl,-z gcs=always +LDFLAGS-tst-gcs-shared-enforced-abort = -Wl,-z gcs=always +LDFLAGS-tst-gcs-shared-optional = -Wl,-z gcs=always +LDFLAGS-tst-gcs-shared-override = -Wl,-z gcs=always + +modules-names += \ + tst-gcs-mod1 \ + tst-gcs-mod2 \ + tst-gcs-mod3 \ + # modules-names + +$(objpfx)tst-gcs-shared-disabled: $(objpfx)tst-gcs-mod1.so $(objpfx)tst-gcs-mod3.so +$(objpfx)tst-gcs-shared-enforced-abort: $(objpfx)tst-gcs-mod1.so $(objpfx)tst-gcs-mod3.so +$(objpfx)tst-gcs-shared-optional: $(objpfx)tst-gcs-mod1.so $(objpfx)tst-gcs-mod3.so +$(objpfx)tst-gcs-shared-override: $(objpfx)tst-gcs-mod1.so $(objpfx)tst-gcs-mod3.so +$(objpfx)tst-gcs-mod1.so: $(objpfx)tst-gcs-mod2.so + +tst-gcs-shared-disabled-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=0 +tst-gcs-shared-enforced-abort-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1 +tst-gcs-shared-optional-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2 +tst-gcs-shared-override-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=3 + endif # ifeq ($(have-test-cc-gcs),yes) endif # ifeq ($(subdir),misc) diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-helper.h b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-helper.h new file mode 100644 index 0000000000..d8a586d2d8 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-helper.h @@ -0,0 +1,39 @@ +/* AArch64 tests for GCS. + 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 + . */ + +#ifndef TST_GCS_HELPER_H +#define TST_GCS_HELPER_H + +#include +#include +#include + +#include +#include + +static bool __check_gcs_status (void) +{ + register unsigned long x16 asm ("x16"); + asm volatile ( + "mov x16, #1 /* _CHKFEAT_GCS */\n" + "hint 40 /* CHKFEAT_X16 */\n" + : "=r" (x16)); + return x16 ^ 1; +} + +#endif // POINTER_GUARD_H diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-mod1.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-mod1.c new file mode 100644 index 0000000000..931ff81797 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-mod1.c @@ -0,0 +1,27 @@ +/* DSO for testing GCS. + 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 + . */ + +#include + +int fun2 (void); // tst-gcs-mod2.c + +int fun1 (void) +{ + puts ("called function fun1"); + return fun2 (); +} diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-mod2.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-mod2.c new file mode 100644 index 0000000000..f9370eb8ff --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-mod2.c @@ -0,0 +1,25 @@ +/* DSO for testing GCS. + 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 + . */ + +#include + +int fun2 (void) +{ + puts ("called function fun2"); + return 0; +} diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-mod3.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-mod3.c new file mode 100644 index 0000000000..38bb357547 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-mod3.c @@ -0,0 +1,25 @@ +/* DSO for testing GCS. + 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 + . */ + +#include + +int fun3 (void) +{ + puts ("called function fun3"); + return 0; +} diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-shared-disabled.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-shared-disabled.c new file mode 100644 index 0000000000..8598dc44b5 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-shared-disabled.c @@ -0,0 +1,2 @@ +#define TEST_GCS_EXPECT_ENABLED 0 +#include "tst-gcs-shared.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-shared-enforced-abort.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-shared-enforced-abort.c new file mode 100644 index 0000000000..f1333cee9d --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-shared-enforced-abort.c @@ -0,0 +1,2 @@ +#define TEST_GCS_EXPECT_ENABLED 1 +#include "tst-gcs-shared.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-shared-optional.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-shared-optional.c new file mode 100644 index 0000000000..8598dc44b5 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-shared-optional.c @@ -0,0 +1,2 @@ +#define TEST_GCS_EXPECT_ENABLED 0 +#include "tst-gcs-shared.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-shared-override.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-shared-override.c new file mode 100644 index 0000000000..f1333cee9d --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-shared-override.c @@ -0,0 +1,2 @@ +#define TEST_GCS_EXPECT_ENABLED 1 +#include "tst-gcs-shared.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-shared.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-shared.c new file mode 100644 index 0000000000..1192de69fc --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-shared.c @@ -0,0 +1,41 @@ +/* AArch64 tests for GCS. + 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 + . */ + +#include "tst-gcs-helper.h" + +int fun1 (void); // tst-gcs-mod1.c +int fun3 (void); // tst-gcs-mod3.c + +static int +do_test (void) +{ + /* Check if GCS could possible by enabled. */ + if (!(getauxval (AT_HWCAP) & HWCAP_GCS)) + { + puts ("kernel or CPU does not support GCS"); + return EXIT_UNSUPPORTED; + } +#if TEST_GCS_EXPECT_ENABLED + TEST_VERIFY (__check_gcs_status ()); +#else + TEST_VERIFY (!__check_gcs_status ()); +#endif + return fun1 () + fun3 (); +} + +#include diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-skeleton.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-skeleton.c index 37692c96d0..feb5e33ebf 100644 --- a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-skeleton.c +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-skeleton.c @@ -16,22 +16,7 @@ License along with the GNU C Library; if not, see . */ -#include -#include -#include - -#include -#include - -static bool __check_gcs_status (void) -{ - register unsigned long x16 asm ("x16"); - asm volatile ( - "mov x16, #1 /* _CHKFEAT_GCS */\n" - "hint 40 /* CHKFEAT_X16 */\n" - : "=r" (x16)); - return x16 ^ 1; -} +#include "tst-gcs-helper.h" static int do_test (void) commit 8d98ee8d70cd4bbbb2e7d3292600c8719e24a255 Author: Yury Khrustalev Date: Wed Jan 22 17:21:26 2025 +0000 aarch64: Add GCS tests for dlopen Reviewed-by: Adhemerval Zanella diff --git a/Makeconfig b/Makeconfig index d0108d2caa..aa547a443f 100644 --- a/Makeconfig +++ b/Makeconfig @@ -633,7 +633,7 @@ link-libc-printers-tests = $(link-libc-rpath) \ $(link-libc-tests-after-rpath-link) # This is how to find at build-time things that will be installed there. -rpath-dirs = math elf dlfcn nss nis rt resolv mathvec support +rpath-dirs = math elf dlfcn nss nis rt resolv mathvec support misc rpath-link = \ $(common-objdir):$(subst $(empty) ,:,$(patsubst ../$(subdir),.,$(rpath-dirs:%=$(common-objpfx)%))) else # build-static diff --git a/sysdeps/unix/sysv/linux/aarch64/Makefile b/sysdeps/unix/sysv/linux/aarch64/Makefile index 19f2988dac..ce24f386a0 100644 --- a/sysdeps/unix/sysv/linux/aarch64/Makefile +++ b/sysdeps/unix/sysv/linux/aarch64/Makefile @@ -8,6 +8,11 @@ ifneq (no,$(findstring no,$(have-cc-gcs) $(have-test-cc-gcs) $(have-ld-gcs))) gcs-tests-dynamic = \ tst-gcs-disabled \ + tst-gcs-dlopen-disabled \ + tst-gcs-dlopen-enforced \ + tst-gcs-dlopen-optional-off \ + tst-gcs-dlopen-optional-on \ + tst-gcs-dlopen-override \ tst-gcs-enforced \ tst-gcs-enforced-abort \ tst-gcs-optional-off \ @@ -100,6 +105,24 @@ tst-gcs-shared-enforced-abort-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1 tst-gcs-shared-optional-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2 tst-gcs-shared-override-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=3 +LDFLAGS-tst-gcs-dlopen-disabled = -Wl,-z gcs=always +LDFLAGS-tst-gcs-dlopen-enforced = -Wl,-z gcs=always +LDFLAGS-tst-gcs-dlopen-optional-on = -Wl,-z gcs=always +LDFLAGS-tst-gcs-dlopen-optional-off = -Wl,-z gcs=never +LDFLAGS-tst-gcs-dlopen-override = -Wl,-z gcs=always + +tst-gcs-dlopen-disabled-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=0 +tst-gcs-dlopen-enforced-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1 +tst-gcs-dlopen-optional-on-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2 +tst-gcs-dlopen-optional-off-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2 +tst-gcs-dlopen-override-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=3 + +$(objpfx)tst-gcs-dlopen-disabled.out: $(objpfx)tst-gcs-mod2.so +$(objpfx)tst-gcs-dlopen-enforced.out: $(objpfx)tst-gcs-mod2.so +$(objpfx)tst-gcs-dlopen-optional-on.out: $(objpfx)tst-gcs-mod2.so +$(objpfx)tst-gcs-dlopen-optional-off.out: $(objpfx)tst-gcs-mod2.so +$(objpfx)tst-gcs-dlopen-override.out: $(objpfx)tst-gcs-mod2.so + endif # ifeq ($(have-test-cc-gcs),yes) endif # ifeq ($(subdir),misc) diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-dlopen-disabled.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-dlopen-disabled.c new file mode 100644 index 0000000000..34395280a3 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-dlopen-disabled.c @@ -0,0 +1,3 @@ +#define TEST_GCS_EXPECT_ENABLED 0 +#define TEST_GCS_EXPECT_DLOPEN 1 +#include "tst-gcs-dlopen.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-dlopen-enforced.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-dlopen-enforced.c new file mode 100644 index 0000000000..d8489ecd24 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-dlopen-enforced.c @@ -0,0 +1,3 @@ +#define TEST_GCS_EXPECT_ENABLED 1 +#define TEST_GCS_EXPECT_DLOPEN 0 +#include "tst-gcs-dlopen.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-dlopen-optional-off.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-dlopen-optional-off.c new file mode 100644 index 0000000000..34395280a3 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-dlopen-optional-off.c @@ -0,0 +1,3 @@ +#define TEST_GCS_EXPECT_ENABLED 0 +#define TEST_GCS_EXPECT_DLOPEN 1 +#include "tst-gcs-dlopen.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-dlopen-optional-on.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-dlopen-optional-on.c new file mode 100644 index 0000000000..d8489ecd24 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-dlopen-optional-on.c @@ -0,0 +1,3 @@ +#define TEST_GCS_EXPECT_ENABLED 1 +#define TEST_GCS_EXPECT_DLOPEN 0 +#include "tst-gcs-dlopen.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-dlopen-override.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-dlopen-override.c new file mode 100644 index 0000000000..152ffcf207 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-dlopen-override.c @@ -0,0 +1,3 @@ +#define TEST_GCS_EXPECT_ENABLED 1 +#define TEST_GCS_EXPECT_DLOPEN 1 +#include "tst-gcs-dlopen.c" diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-dlopen.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-dlopen.c new file mode 100644 index 0000000000..6e0801c63a --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-dlopen.c @@ -0,0 +1,62 @@ +/* AArch64 tests for GCS for dlopen use case. + 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 + . */ + +#include "tst-gcs-helper.h" + +#include +#include + +static int +do_test (void) +{ + /* Check if GCS could possible by enabled. */ + if (!(getauxval (AT_HWCAP) & HWCAP_GCS)) + { + puts ("kernel or CPU does not support GCS"); + return EXIT_UNSUPPORTED; + } + /* The tst-gcs-mod2.so test library does not have GCS marking. */ + void *h = dlopen ("tst-gcs-mod2.so", RTLD_NOW); + const char *err = dlerror (); + +#if TEST_GCS_EXPECT_DLOPEN + TEST_VERIFY (h != NULL); +#else + TEST_VERIFY (h == NULL); + /* Only accept expected GCS-related errors. */ + TEST_VERIFY (strstr (err, "not GCS compatible") != NULL); +#endif + +#if TEST_GCS_EXPECT_ENABLED + TEST_VERIFY (__check_gcs_status ()); +#else + TEST_VERIFY (!__check_gcs_status ()); +#endif + + if (h == NULL) + printf ("dlopen error: %s\n", err); + else + { + puts ("library loaded normally"); + dlclose (h); + } + + return 0; +} + +#include commit 009c5a2dca7cfc66b01b7217edb20996e25642da Author: Yury Khrustalev Date: Thu Jan 23 10:36:36 2025 +0000 aarch64: Add GCS test with signal handler Test that when we return from a function that enabled GCS at runtime we get SIGSEGV. Also test that ucontext contains GCS block with the GCS pointer. Reviewed-by: Adhemerval Zanella diff --git a/sysdeps/unix/sysv/linux/aarch64/Makefile b/sysdeps/unix/sysv/linux/aarch64/Makefile index ce24f386a0..0839f0b08c 100644 --- a/sysdeps/unix/sysv/linux/aarch64/Makefile +++ b/sysdeps/unix/sysv/linux/aarch64/Makefile @@ -15,6 +15,7 @@ gcs-tests-dynamic = \ tst-gcs-dlopen-override \ tst-gcs-enforced \ tst-gcs-enforced-abort \ + tst-gcs-noreturn \ tst-gcs-optional-off \ tst-gcs-optional-on \ tst-gcs-override \ @@ -123,6 +124,10 @@ $(objpfx)tst-gcs-dlopen-optional-on.out: $(objpfx)tst-gcs-mod2.so $(objpfx)tst-gcs-dlopen-optional-off.out: $(objpfx)tst-gcs-mod2.so $(objpfx)tst-gcs-dlopen-override.out: $(objpfx)tst-gcs-mod2.so +LDFLAGS-tst-gcs-noreturn = -Wl,-z gcs=always + +tst-gcs-noreturn-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=0 + endif # ifeq ($(have-test-cc-gcs),yes) endif # ifeq ($(subdir),misc) diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-noreturn.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-noreturn.c new file mode 100644 index 0000000000..f55057924f --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-noreturn.c @@ -0,0 +1,101 @@ +/* AArch64 test for GCS abort when returning to non-GCS address. + 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 + . */ + +#include "tst-gcs-helper.h" + +#include +#include + +#include + +# ifndef PR_SET_SHADOW_STACK_STATUS +# define PR_SET_SHADOW_STACK_STATUS 75 +# define PR_SHADOW_STACK_ENABLE (1UL << 0) +# endif + +static void +run_with_gcs (void) +{ + int r = prctl (PR_SET_SHADOW_STACK_STATUS, PR_SHADOW_STACK_ENABLE, 0, 0, 0); + /* Syscall should succeed. */ + TEST_VERIFY (r == 0); + bool gcs_enabled = __check_gcs_status (); + /* Now GCS should be enabled. */ + TEST_VERIFY (gcs_enabled); + printf ("GCS is %s\n", gcs_enabled ? "enabled" : "disabled"); +} + +static struct _aarch64_ctx * +extension (void *p) +{ + return p; +} + +#ifndef GCS_MAGIC +#define GCS_MAGIC 0x47435300 +#endif + +static void +handler (int sig, siginfo_t *si, void *ctx) +{ + TEST_VERIFY (sig == SIGSEGV); + ucontext_t *uc = ctx; + void *p = uc->uc_mcontext.__reserved; + if (extension (p)->magic == FPSIMD_MAGIC) + p = (char *)p + extension (p)->size; + if (extension (p)->magic == GCS_MAGIC) + { + struct { uint64_t x, gcspr, y, z; } *q = p; + printf ("GCS pointer: %016lx\n", q->gcspr); + exit (0); + } + else + exit (3); +} + +static int +do_test (void) +{ + /* Check if GCS could possible by enabled. */ + if (!(getauxval (AT_HWCAP) & HWCAP_GCS)) + { + puts ("kernel or CPU does not support GCS"); + return EXIT_UNSUPPORTED; + } + bool gcs_enabled = __check_gcs_status (); + /* This test should be rung with GCS initially disabled. */ + TEST_VERIFY (!gcs_enabled); + + /* We can't use EXPECTED_SIGNAL because of cases when + this test runs on a system that does not support GCS + which is being detected at runtime. */ + struct sigaction sigact; + sigemptyset (&sigact.sa_mask); + sigact.sa_flags = 0; + sigact.sa_flags = sigact.sa_flags | SA_SIGINFO; + sigact.sa_sigaction = handler; + xsigaction (SIGSEGV, &sigact, NULL); + + run_with_gcs (); + /* If we reached this point, then something went wrong. + Returning from a function that enabled GCS should result in + SIGSEGV that we catch with the handler set up above. */ + return 2; +} + +#include commit e0bc5f64eaf75764db0f7972ac1763315f5eab81 Author: Wilco Dijkstra Date: Fri Dec 13 15:43:07 2024 +0000 math: Improve layout of exp/exp10 data GCC aligns global data to 16 bytes if their size is >= 16 bytes. This patch changes the exp_data struct slightly so that the fields are better aligned and without gaps. As a result on targets that support them, more load-pair instructions are used in exp. Exp10 is improved by moving invlog10_2N later so that neglog10_2hiN and neglog10_2loN can be loaded using load-pair. The exp benchmark improves 2.5%, "144bits" by 7.2%, "768bits" by 12.7% on Neoverse V2. Exp10 improves by 1.5%. Reviewed-by: Adhemerval Zanella (cherry picked from commit 5afaf99edb326fd9f36eb306a828d129a3a1d7f7) diff --git a/sysdeps/ieee754/dbl-64/math_config.h b/sysdeps/ieee754/dbl-64/math_config.h index 299a2ff8c1..3382e385f9 100644 --- a/sysdeps/ieee754/dbl-64/math_config.h +++ b/sysdeps/ieee754/dbl-64/math_config.h @@ -195,16 +195,18 @@ check_uflow (double x) extern const struct exp_data { double invln2N; - double shift; double negln2hiN; double negln2loN; double poly[4]; /* Last four coefficients. */ + double shift; + double exp2_shift; double exp2_poly[EXP2_POLY_ORDER]; - double invlog10_2N; + double neglog10_2hiN; double neglog10_2loN; double exp10_poly[5]; + double invlog10_2N; uint64_t tab[2*(1 << EXP_TABLE_BITS)]; } __exp_data attribute_hidden; commit c47c3890f15e82954a502cab7f7f1672ff3d7715 Author: Wilco Dijkstra Date: Tue Dec 24 18:01:59 2024 +0000 AArch64: Add SVE memset Add SVE memset based on the generic memset with predicated load for sizes < 16. Unaligned memsets of 128-1024 are improved by ~20% on average by using aligned stores for the last 64 bytes. Performance of random memset benchmark improves by ~2% on Neoverse V1. Reviewed-by: Yury Khrustalev (cherry picked from commit 163b1bbb76caba4d9673c07940c5930a1afa7548) diff --git a/sysdeps/aarch64/multiarch/Makefile b/sysdeps/aarch64/multiarch/Makefile index 772b16a358..1c3c392513 100644 --- a/sysdeps/aarch64/multiarch/Makefile +++ b/sysdeps/aarch64/multiarch/Makefile @@ -14,6 +14,7 @@ sysdep_routines += \ memset_kunpeng \ memset_mops \ memset_oryon1 \ + memset_sve_zva64 \ memset_zva64 \ strlen_asimd \ strlen_generic \ diff --git a/sysdeps/aarch64/multiarch/ifunc-impl-list.c b/sysdeps/aarch64/multiarch/ifunc-impl-list.c index 0481e450be..8dc314b67d 100644 --- a/sysdeps/aarch64/multiarch/ifunc-impl-list.c +++ b/sysdeps/aarch64/multiarch/ifunc-impl-list.c @@ -57,6 +57,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, IFUNC_IMPL_ADD (array, i, memset, 1, __memset_kunpeng) #if HAVE_AARCH64_SVE_ASM IFUNC_IMPL_ADD (array, i, memset, sve && !bti && zva_size == 256, __memset_a64fx) + IFUNC_IMPL_ADD (array, i, memset, sve && zva_size == 64, __memset_sve_zva64) #endif IFUNC_IMPL_ADD (array, i, memset, mops, __memset_mops) IFUNC_IMPL_ADD (array, i, memset, 1, __memset_generic)) diff --git a/sysdeps/aarch64/multiarch/memset.c b/sysdeps/aarch64/multiarch/memset.c index f6194e4a93..183c334988 100644 --- a/sysdeps/aarch64/multiarch/memset.c +++ b/sysdeps/aarch64/multiarch/memset.c @@ -36,6 +36,7 @@ extern __typeof (__redirect_memset) __memset_a64fx attribute_hidden; extern __typeof (__redirect_memset) __memset_generic attribute_hidden; extern __typeof (__redirect_memset) __memset_mops attribute_hidden; extern __typeof (__redirect_memset) __memset_oryon1 attribute_hidden; +extern __typeof (__redirect_memset) __memset_sve_zva64 attribute_hidden; static inline __typeof (__redirect_memset) * select_memset_ifunc (void) @@ -49,6 +50,9 @@ select_memset_ifunc (void) { if (IS_A64FX (midr) && zva_size == 256) return __memset_a64fx; + + if (zva_size == 64) + return __memset_sve_zva64; } if (IS_ORYON1 (midr) && zva_size == 64) diff --git a/sysdeps/aarch64/multiarch/memset_sve_zva64.S b/sysdeps/aarch64/multiarch/memset_sve_zva64.S new file mode 100644 index 0000000000..7fb40fdd9e --- /dev/null +++ b/sysdeps/aarch64/multiarch/memset_sve_zva64.S @@ -0,0 +1,123 @@ +/* Optimized memset for SVE. + 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 + . */ + +#include + +/* Assumptions: + * + * ARMv8-a, AArch64, Advanced SIMD, SVE, unaligned accesses. + * ZVA size is 64. + */ + +#if HAVE_AARCH64_SVE_ASM + +.arch armv8.2-a+sve + +#define dstin x0 +#define val x1 +#define valw w1 +#define count x2 +#define dst x3 +#define dstend x4 +#define zva_val x5 +#define vlen x5 +#define off x3 +#define dstend2 x5 + +ENTRY (__memset_sve_zva64) + dup v0.16B, valw + cmp count, 16 + b.lo L(set_16) + + add dstend, dstin, count + cmp count, 64 + b.hs L(set_128) + + /* Set 16..63 bytes. */ + mov off, 16 + and off, off, count, lsr 1 + sub dstend2, dstend, off + str q0, [dstin] + str q0, [dstin, off] + str q0, [dstend2, -16] + str q0, [dstend, -16] + ret + + .p2align 4 +L(set_16): + whilelo p0.b, xzr, count + st1b z0.b, p0, [dstin] + ret + + .p2align 4 +L(set_128): + bic dst, dstin, 15 + cmp count, 128 + b.hi L(set_long) + stp q0, q0, [dstin] + stp q0, q0, [dstin, 32] + stp q0, q0, [dstend, -64] + stp q0, q0, [dstend, -32] + ret + + .p2align 4 +L(set_long): + cmp count, 256 + b.lo L(no_zva) + tst valw, 255 + b.ne L(no_zva) + + str q0, [dstin] + str q0, [dst, 16] + bic dst, dstin, 31 + stp q0, q0, [dst, 32] + bic dst, dstin, 63 + sub count, dstend, dst /* Count is now 64 too large. */ + sub count, count, 128 /* Adjust count and bias for loop. */ + + sub x8, dstend, 1 /* Write last bytes before ZVA loop. */ + bic x8, x8, 15 + stp q0, q0, [x8, -48] + str q0, [x8, -16] + str q0, [dstend, -16] + + .p2align 4 +L(zva64_loop): + add dst, dst, 64 + dc zva, dst + subs count, count, 64 + b.hi L(zva64_loop) + ret + +L(no_zva): + str q0, [dstin] + sub count, dstend, dst /* Count is 16 too large. */ + sub count, count, 64 + 16 /* Adjust count and bias for loop. */ +L(no_zva_loop): + stp q0, q0, [dst, 16] + stp q0, q0, [dst, 48] + add dst, dst, 64 + subs count, count, 64 + b.hi L(no_zva_loop) + stp q0, q0, [dstend, -64] + stp q0, q0, [dstend, -32] + ret + +END (__memset_sve_zva64) +#endif commit 89be78704ed8d8159c20f7cdbc5f461a322ab884 Author: Wilco Dijkstra Date: Thu Feb 27 16:28:52 2025 +0000 AArch64: Use prefer_sve_ifuncs for SVE memset Use prefer_sve_ifuncs for SVE memset just like memcpy. Reviewed-by: Yury Khrustalev (cherry picked from commit 0f044be1dae5169d0e57f8d487b427863aeadab4) diff --git a/sysdeps/aarch64/multiarch/memset.c b/sysdeps/aarch64/multiarch/memset.c index 183c334988..872f39f00f 100644 --- a/sysdeps/aarch64/multiarch/memset.c +++ b/sysdeps/aarch64/multiarch/memset.c @@ -51,7 +51,7 @@ select_memset_ifunc (void) if (IS_A64FX (midr) && zva_size == 256) return __memset_a64fx; - if (zva_size == 64) + if (prefer_sve_ifuncs && zva_size == 64) return __memset_sve_zva64; } commit 56609f8df1fa05c3af13dbe8c84bf5ce62192cd2 Author: Sam James Date: Tue Feb 18 18:49:09 2025 +0000 Pass -Wl,--no-error-execstack for tests where -Wl,-z,execstack is used [PR32717] When GNU Binutils is configured with --enable-error-execstack=yes, a handful of our tests which rely on -Wl,-z,execstack fail. Pass --Wl,--no-error-execstack to override the behaviour and get a warning instead. Bug: https://sourceware.org/PR32717 Reviewed-by: Adhemerval Zanella (cherry picked from commit a2bd5008a99032830add3e4005c25b61e3207112) diff --git a/config.make.in b/config.make.in index 36096881b7..59897eaec2 100644 --- a/config.make.in +++ b/config.make.in @@ -53,6 +53,7 @@ c++-bits-std_abs-h = @CXX_BITS_STD_ABS_H@ enable-werror = @enable_werror@ have-z-execstack = @libc_cv_z_execstack@ +have-no-error-execstack = @libc_cv_no_error_execstack@ have-protected-data = @libc_cv_protected_data@ have-insert = @libc_cv_insert@ have-glob-dat-reloc = @libc_cv_has_glob_dat@ diff --git a/configure b/configure index 8fd09c6d88..80b4a63f1b 100755 --- a/configure +++ b/configure @@ -659,6 +659,7 @@ libc_cv_has_glob_dat libc_cv_fpie libc_cv_test_static_pie libc_cv_z_execstack +libc_cv_no_error_execstack ASFLAGS_config libc_cv_cc_with_libunwind libc_cv_insert @@ -7114,6 +7115,40 @@ if test $libc_cv_as_noexecstack = yes; then fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports --no-error-execstack" >&5 +printf %s "checking for linker that supports --no-error-execstack... " >&6; } +libc_linker_feature=no +cat > conftest.c <&5 + (eval $ac_try) 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } +then + if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-no-error-execstack -nostdlib \ + -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \ + | grep "warning: --no-error-execstack ignored" > /dev/null 2>&1; then + true + else + libc_linker_feature=yes + fi +fi +rm -f conftest* +if test $libc_linker_feature = yes; then + libc_cv_no_error_execstack=yes +else + libc_cv_no_error_execstack=no +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5 +printf "%s\n" "$libc_linker_feature" >&6; } + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -z execstack" >&5 printf %s "checking for linker that supports -z execstack... " >&6; } libc_linker_feature=no diff --git a/configure.ac b/configure.ac index d4ef0c4243..7d04b54c98 100644 --- a/configure.ac +++ b/configure.ac @@ -1318,6 +1318,10 @@ if test $libc_cv_as_noexecstack = yes; then fi AC_SUBST(ASFLAGS_config) +LIBC_LINKER_FEATURE([--no-error-execstack], [-Wl,-no-error-execstack], + [libc_cv_no_error_execstack=yes], [libc_cv_no_error_execstack=no]) +AC_SUBST(libc_cv_no_error_execstack) + LIBC_LINKER_FEATURE([-z execstack], [-Wl,-z,execstack], [libc_cv_z_execstack=yes], [libc_cv_z_execstack=no]) AC_SUBST(libc_cv_z_execstack) diff --git a/elf/Makefile b/elf/Makefile index 4b1d0d8741..75fc517248 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -1988,6 +1988,9 @@ $(objpfx)tst-execstack.out: $(objpfx)tst-execstack-mod.so CPPFLAGS-tst-execstack.c += -DUSE_PTHREADS=0 LDFLAGS-tst-execstack = -Wl,-z,noexecstack LDFLAGS-tst-execstack-mod.so = -Wl,-z,execstack +ifeq ($(have-no-error-execstack),yes) +LDFLAGS-tst-execstack-mod.so += -Wl,--no-error-execstack +endif $(objpfx)tst-execstack-needed: $(objpfx)tst-execstack-mod.so LDFLAGS-tst-execstack-needed = -Wl,-z,noexecstack @@ -1997,6 +2000,9 @@ CFLAGS-tst-execstack-prog.c += -Wno-trampolines CFLAGS-tst-execstack-mod.c += -Wno-trampolines LDFLAGS-tst-execstack-prog-static = -Wl,-z,execstack +ifeq ($(have-no-error-execstack),yes) +LDFLAGS-tst-execstack-prog-static += -Wl,--no-error-execstack +endif CFLAGS-tst-execstack-prog-static.c += -Wno-trampolines ifeq (yes,$(build-hardcoded-path-in-tests)) diff --git a/nptl/Makefile b/nptl/Makefile index 82621c7954..4be778ad65 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -701,6 +701,9 @@ $(objpfx)tst-execstack-threads.out: $(objpfx)tst-execstack-threads-mod.so LDFLAGS-tst-execstack-threads = -Wl,-z,noexecstack LDFLAGS-tst-execstack-threads-mod.so = -Wl,-z,execstack CFLAGS-tst-execstack-threads-mod.c += -Wno-trampolines +ifeq ($(have-no-error-execstack),yes) +LDFLAGS-tst-execstack-threads-mod.so += -Wl,--no-error-execstack +endif tst-stackguard1-ARGS = --command "$(host-test-program-cmd) --child" tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child" commit 746ef8e93964a99db3e3fa4b8a7aba179185ef0a Author: H.J. Lu Date: Wed Mar 5 10:19:59 2025 +0800 static-pie: Skip the empty PT_LOAD segment at offset 0 [BZ #32763] As shown in https://sourceware.org/bugzilla/show_bug.cgi?id=25237 linker may generate an empty PT_LOAD segments at offset 0: Elf file type is EXEC (Executable file) Entry point 0x4000e8 There are 3 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 0x00000000000000f0 0x00000000000000f0 R E 0x1000 LOAD 0x0000000000000000 0x0000000000410000 0x0000000000410000 0x0000000000000000 0x0000000000b5dce8 RW 0x10000 GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 0x10 Section to Segment mapping: Segment Sections... 00 .text 01 .bss 02 Skip the empty PT_LOAD segment at offset 0 to support such binaries. This fixes BZ #32763. Signed-off-by: H.J. Lu Reviewed-by: Sam James (cherry picked from commit 596130591ae4b058a529cc1318b95e624559054c) diff --git a/elf/Makefile b/elf/Makefile index 75fc517248..848a8c3077 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -1135,12 +1135,14 @@ tests += \ tst-dlopen-pie \ tst-dlopen-self-pie \ tst-dlopen-tlsmodid-pie \ + tst-pie-bss \ tst-pie1 \ tst-pie2 \ # tests tests-pie += \ tst-dlopen-self-pie \ tst-dlopen-tlsmodid-pie \ + tst-pie-bss \ tst-pie1 \ tst-pie2 \ # tests-pie @@ -1155,9 +1157,11 @@ LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address) ifeq (yes,$(enable-static-pie)) tests += \ tst-pie-address-static \ + tst-pie-bss-static \ # tests tests-static += \ tst-pie-address-static \ + tst-pie-bss-static \ # tests-static LDFLAGS-tst-pie-address-static += \ $(load-address-ldflag)=$(pde-load-address) @@ -2080,6 +2084,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \ CFLAGS-tst-pie1.c += $(pie-ccflag) CFLAGS-tst-pie2.c += $(pie-ccflag) +CFLAGS-tst-pie-bss.c += $(pie-ccflag) CFLAGS-tst-pie-address.c += $(pie-ccflag) $(objpfx)tst-piemod1.so: $(libsupport) 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 +++ b/elf/dl-reloc-static-pie.c @@ -51,7 +51,8 @@ _dl_relocate_static_pie (void) switch (ph->p_type) { case PT_LOAD: - if (ph->p_offset == 0) + /* Skip the empty PT_LOAD segment at offset 0. */ + if (ph->p_filesz != 0 && ph->p_offset == 0) file_p_vaddr = ph->p_vaddr; break; case PT_DYNAMIC: diff --git a/elf/tst-pie-bss-static.c b/elf/tst-pie-bss-static.c new file mode 100644 index 0000000000..5df542f9ee --- /dev/null +++ b/elf/tst-pie-bss-static.c @@ -0,0 +1,19 @@ +/* Test static PIE with an empty PT_LOAD segment at offset 0. + 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 + . */ + +#include "tst-pie-bss.c" diff --git a/elf/tst-pie-bss.c b/elf/tst-pie-bss.c new file mode 100644 index 0000000000..ee92754249 --- /dev/null +++ b/elf/tst-pie-bss.c @@ -0,0 +1,30 @@ +/* Test PIE with an empty PT_LOAD segment at offset 0. + 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 + . */ + +#include + +char bss[0xb5dce8] __attribute__ ((aligned (65536))); + +static int +do_test (void) +{ + printf ("Hello\n"); + return 0; +} + +#include commit fd202462c5f8ffa4dfb6b7c0c4cec2bce4bec408 Author: H.J. Lu Date: Fri Mar 7 08:58:47 2025 +0800 elf: Check if __attribute__ ((aligned (65536))) is supported The BZ #32763 tests fail to build for MicroBlaze (which defines MAX_OFILE_ALIGNMENT to (32768*8) in GCC, so __attribute__ ((aligned (65536))) is unsupported). Add a configure-time check to enable BZ #32763 tests only if __attribute__ ((aligned (65536))) is supported. Signed-off-by: H.J. Lu Reviewed-by: Sam James (cherry picked from commit 9b91484bee8f6f1bf1e2d26a8df461b553784528) diff --git a/configure b/configure index 80b4a63f1b..2a996cb0d9 100755 --- a/configure +++ b/configure @@ -8678,6 +8678,35 @@ if test $libc_cv_builtin_trap = yes; then fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports __attribute__ ((aligned (65536)))" >&5 +printf %s "checking whether the compiler supports __attribute__ ((aligned (65536)))... " >&6; } +if test ${libc_cv_aligned_65536+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +char bss0xb5dce8 __attribute__ ((aligned (65536))); + +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + libc_cv_aligned_65536=yes +else case e in #( + e) libc_cv_aligned_65536=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_aligned_65536" >&5 +printf "%s\n" "$libc_cv_aligned_65536" >&6; } +config_vars="$config_vars +aligned-65536 = $libc_cv_aligned_65536" + ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -8945,7 +8974,6 @@ load-address-ldflag = $libc_cv_load_address_ldflag" # Check if compilers support GCS in branch protection: - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports -mbranch-protection=gcs" >&5 printf %s "checking if compiler supports -mbranch-protection=gcs... " >&6; } if test ${libc_cv_cc_gcs+y} diff --git a/configure.ac b/configure.ac index 7d04b54c98..5f6f0b72bc 100644 --- a/configure.ac +++ b/configure.ac @@ -1824,6 +1824,17 @@ if test $libc_cv_builtin_trap = yes; then AC_DEFINE([HAVE_BUILTIN_TRAP]) fi +dnl Check if +AC_CACHE_CHECK([whether the compiler supports __attribute__ ((aligned (65536)))], + libc_cv_aligned_65536, [ +AC_COMPILE_IFELSE([AC_LANG_SOURCE([ +char bss[0xb5dce8] __attribute__ ((aligned (65536))); +])], + [libc_cv_aligned_65536=yes], + [libc_cv_aligned_65536=no]) +]) +LIBC_CONFIG_VAR([aligned-65536], [$libc_cv_aligned_65536]) + dnl C++ feature tests. AC_LANG_PUSH([C++]) diff --git a/elf/Makefile b/elf/Makefile index 848a8c3077..d6bba4b0ec 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -1135,17 +1135,19 @@ tests += \ tst-dlopen-pie \ tst-dlopen-self-pie \ tst-dlopen-tlsmodid-pie \ - tst-pie-bss \ tst-pie1 \ tst-pie2 \ # tests tests-pie += \ tst-dlopen-self-pie \ tst-dlopen-tlsmodid-pie \ - tst-pie-bss \ tst-pie1 \ tst-pie2 \ # tests-pie +ifeq (yes,$(aligned-65536)) +tests += tst-pie-bss +tests-pie += tst-pie-bss +endif ifneq (,$(load-address-ldflag)) tests += \ tst-pie-address \ @@ -1157,12 +1159,14 @@ LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address) ifeq (yes,$(enable-static-pie)) tests += \ tst-pie-address-static \ - tst-pie-bss-static \ # tests tests-static += \ tst-pie-address-static \ - tst-pie-bss-static \ # tests-static +ifeq (yes,$(aligned-65536)) +tests += tst-pie-bss-static +tests-static += tst-pie-bss-static +endif LDFLAGS-tst-pie-address-static += \ $(load-address-ldflag)=$(pde-load-address) endif commit 91f8cff2c48f678d4ba7ed3b3845290c45a672b3 Author: Florian Weimer Date: Fri Mar 7 07:52:11 2025 +0100 configure: Fix spelling of -Wl,--no-error-execstack option BFD ld recognizes all -no-* options (with a single leading dash) unconditionally. Fixes commit a2bd5008a99032830add3e4005c25b61e3207112 ("Pass -Wl,--no-error-execstack for tests where -Wl,-z,execstack is used [PR32717]"). (cherry picked from commit 59dc232df277c21239c357e3519682c26e182cd7) diff --git a/configure b/configure index 2a996cb0d9..674d1d7e4a 100755 --- a/configure +++ b/configure @@ -7122,7 +7122,7 @@ cat > conftest.c <&5 @@ -7131,7 +7131,7 @@ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; } then - if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-no-error-execstack -nostdlib \ + if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,--no-error-execstack -nostdlib \ -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \ | grep "warning: --no-error-execstack ignored" > /dev/null 2>&1; then true diff --git a/configure.ac b/configure.ac index 5f6f0b72bc..57cd24c87d 100644 --- a/configure.ac +++ b/configure.ac @@ -1318,7 +1318,7 @@ if test $libc_cv_as_noexecstack = yes; then fi AC_SUBST(ASFLAGS_config) -LIBC_LINKER_FEATURE([--no-error-execstack], [-Wl,-no-error-execstack], +LIBC_LINKER_FEATURE([--no-error-execstack], [-Wl,--no-error-execstack], [libc_cv_no_error_execstack=yes], [libc_cv_no_error_execstack=no]) AC_SUBST(libc_cv_no_error_execstack) commit 1a3083b999928d70b4889c889e38b1df32232fd2 Author: Florian Weimer Date: Fri Mar 7 21:40:55 2025 +0100 posix: Move environ helper variables next to environ definition (bug 32541) This helps with statically interposing getenv. Updates commit 7a61e7f557a97ab597d6fca5e2d1f13f65685c61 ("stdlib: Make getenv thread-safe in more cases"). Reviewed-by: H.J. Lu (cherry picked from commit 6ef0bd02dbe34aab8b956ffa2db5679341d520f5) diff --git a/posix/environ.c b/posix/environ.c index a0ed0d80ea..924effe3cd 100644 --- a/posix/environ.c +++ b/posix/environ.c @@ -2,6 +2,7 @@ #include #include +#include /* This must be initialized; we cannot have a weak alias into bss. */ char **__environ = NULL; @@ -10,3 +11,6 @@ weak_alias (__environ, environ) /* The SVR4 ABI says `_environ' will be the name to use in case the user overrides the weak alias `environ'. */ weak_alias (__environ, _environ) + +struct environ_array *__environ_array_list; +environ_counter __environ_counter; diff --git a/stdlib/Makefile b/stdlib/Makefile index 1c4fa2382f..c9c8f702a2 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -282,6 +282,7 @@ tests := \ tst-environ-change-3 \ tst-environ-change-4 \ tst-getenv-signal \ + tst-getenv-static \ tst-getenv-thread \ tst-getenv-unsetenv \ tst-getrandom \ @@ -377,6 +378,7 @@ tests-internal := \ # tests-internal tests-static := \ + tst-getenv-static \ tst-secure-getenv \ # tests-static diff --git a/stdlib/getenv.c b/stdlib/getenv.c index 5e7212cca6..1a7b0bfc06 100644 --- a/stdlib/getenv.c +++ b/stdlib/getenv.c @@ -20,9 +20,6 @@ #include #include -struct environ_array *__environ_array_list; -environ_counter __environ_counter; - char * getenv (const char *name) { diff --git a/stdlib/tst-getenv-static.c b/stdlib/tst-getenv-static.c new file mode 100644 index 0000000000..f5f484c83a --- /dev/null +++ b/stdlib/tst-getenv-static.c @@ -0,0 +1,38 @@ +/* Static interposition of getenv (bug 32541). + 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 + . */ + +#include +#include + +/* Some programs try to interpose getenv for their own use (not + glibc's internal use). Make sure that this is possible without + introducing linker failures due to duplicate symbols. */ + +char * +getenv (const char *ignored) +{ + return NULL; +} + +static int +do_test (void) +{ + TEST_COMPARE_STRING (getenv ("PATH"), NULL); + return 0; +} + +#include commit 66fc3bd75871d7239245c767abf44fb96d772f66 Author: Aurelien Jarno Date: Thu Mar 6 19:34:15 2025 +0100 math: Remove an extra semicolon in math function declarations Commit 6bc301672bfbd ("math: Remove __XXX math functions from installed math.h [BZ #32418]") left an extra semicolon after macro expansion. For instance the ceil declaration after expansion is: extern double ceil (double __x) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__));; This chokes very naive parsers like gauche c-wrapper. Fix that by removing that extra semicolon in the macro. Reviewed-by: Adhemerval Zanella (cherry picked from commit 443cb0b5f25129dd0f1e9f9101299d31c4700b7f) diff --git a/math/bits/mathcalls-macros.h b/math/bits/mathcalls-macros.h index 1ef07f1f58..321ae00ec8 100644 --- a/math/bits/mathcalls-macros.h +++ b/math/bits/mathcalls-macros.h @@ -34,7 +34,7 @@ #define __MATHCALLX(function,suffix, args, attrib) \ __MATHDECLX (_Mdouble_,function,suffix, args, attrib) #define __MATHDECLX(type, function,suffix, args, attrib) \ - __MATHDECL_1(type, function,suffix, args) __attribute__ (attrib); + __MATHDECL_1(type, function,suffix, args) __attribute__ (attrib) #define __MATHDECL_1_IMPL(type, function, suffix, args) \ extern type __MATH_PRECNAME(function,suffix) args __THROW #define __MATHDECL_1(type, function, suffix, args) \ commit 33bfd9020fdad925297c9e133055bd8804028f32 Author: Florian Weimer Date: Wed Mar 12 10:23:47 2025 +0100 Linux: Remove attribute access from sched_getattr (bug 32781) The GCC attribute expects an element count, not bytes. (cherry picked from commit 74c68fa61b5ebf4c64605a3cc5e47154a66671ce) diff --git a/NEWS b/NEWS index d819f5d896..983f8c6404 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,7 @@ The following bugs were resolved with this release: [32627] math: math: sinhf is not correctly rounded [32630] math: math: tanf is not correctly rounded for all rounding modes + [32781] Linux: Remove attribute access from sched_getattr Version 2.41 diff --git a/sysdeps/unix/sysv/linux/bits/sched.h b/sysdeps/unix/sysv/linux/bits/sched.h index 3656e98eda..39b0b3d19c 100644 --- a/sysdeps/unix/sysv/linux/bits/sched.h +++ b/sysdeps/unix/sysv/linux/bits/sched.h @@ -152,7 +152,7 @@ int sched_setattr (pid_t tid, struct sched_attr *attr, unsigned int flags) store it in *ATTR. */ int sched_getattr (pid_t tid, struct sched_attr *attr, unsigned int size, unsigned int flags) - __THROW __nonnull ((2)) __attr_access ((__write_only__, 2, 3)); + __THROW __nonnull ((2)); #endif commit e22c132484ea49be0478e4dcbd108d433d70f64c Author: Michael Jeanson Date: Fri Feb 14 13:54:22 2025 -0500 nptl: clear the whole rseq area before registration Due to the extensible nature of the rseq area we can't explictly initialize fields that are not part of the ABI yet. It was agreed with upstream that all new fields will be documented as zero initialized by userspace. Future kernels configured with CONFIG_DEBUG_RSEQ will validate the content of all fields during registration. Replace the explicit field initialization with a memset of the whole rseq area which will cover fields as they are added to future kernels. Signed-off-by: Michael Jeanson Reviewed-by: Florian Weimer (cherry picked from commit 689a62a4217fae78b9ce0db781dc2a421f2b1ab4) diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c index f487bfb66e..8629b5d41b 100644 --- a/sysdeps/nptl/dl-tls_init_tp.c +++ b/sysdeps/nptl/dl-tls_init_tp.c @@ -23,6 +23,7 @@ #include #include #include +#include #define TUNABLE_NAMESPACE pthread #include 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 +++ b/sysdeps/unix/sysv/linux/rseq-internal.h @@ -108,13 +108,12 @@ rseq_register_current_thread (struct pthread *self, bool do_rseq) if (size < RSEQ_AREA_SIZE_INITIAL) size = RSEQ_AREA_SIZE_INITIAL; - /* Initialize the rseq fields that are read by the kernel on - registration, there is no guarantee that struct pthread is - cleared on all architectures. */ + /* Initialize the whole rseq area to zero prior to registration. */ + memset (RSEQ_SELF (), 0, size); + + /* Set the cpu_id field to RSEQ_CPU_ID_UNINITIALIZED, this is checked by + the kernel at registration when CONFIG_DEBUG_RSEQ is enabled. */ RSEQ_SETMEM (cpu_id, RSEQ_CPU_ID_UNINITIALIZED); - RSEQ_SETMEM (cpu_id_start, 0); - RSEQ_SETMEM (rseq_cs, 0); - RSEQ_SETMEM (flags, 0); int ret = INTERNAL_SYSCALL_CALL (rseq, RSEQ_SELF (), size, 0, RSEQ_SIG); if (!INTERNAL_SYSCALL_ERROR_P (ret)) commit 98c712855d6606d078aaabaa7ef24b695c3f0349 Author: Florian Weimer Date: Thu Mar 13 06:07:07 2025 +0100 nptl: PTHREAD_COND_INITIALIZER compatibility with pre-2.41 versions (bug 32786) The new initializer and struct layout does not initialize the __g_signals field in the old struct layout before the change in commit c36fc50781995e6758cae2b6927839d0157f213c ("nptl: Remove g_refs from condition variables"). Bring back fields at the end of struct __pthread_cond_s, so that they are again zero-initialized. Reviewed-by: Sam James (cherry picked from commit dbc5a50d12eff4cb3f782129029d04b8a76f58e7) diff --git a/NEWS b/NEWS index 983f8c6404..6b34aa31f8 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,7 @@ The following bugs were resolved with this release: [32630] math: math: tanf is not correctly rounded for all rounding modes [32781] Linux: Remove attribute access from sched_getattr + [32786] nptl: PTHREAD_COND_INITIALIZER compatibility with pre-2.41 versions Version 2.41 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 +++ b/sysdeps/nptl/bits/thread-shared-types.h @@ -99,6 +99,8 @@ struct __pthread_cond_s unsigned int __g1_orig_size; unsigned int __wrefs; unsigned int __g_signals[2]; + unsigned int __unused_initialized_1; + unsigned int __unused_initialized_2; }; typedef unsigned int __tss_t; diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h index 050b4ab8d1..9ad36cabe9 100644 --- a/sysdeps/nptl/pthread.h +++ b/sysdeps/nptl/pthread.h @@ -152,7 +152,7 @@ enum /* Conditional variable handling. */ -#define PTHREAD_COND_INITIALIZER { { {0}, {0}, {0, 0}, 0, 0, {0, 0} } } +#define PTHREAD_COND_INITIALIZER { { {0}, {0}, {0, 0}, 0, 0, {0, 0}, 0, 0 } } /* Cleanup buffers */ commit ce9b765522f014daa0392099dd9ba1f7ddcc511d Author: Adhemerval Zanella Date: Wed Mar 12 10:59:17 2025 -0300 nptl: Check if thread is already terminated in sigcancel_handler (BZ 32782) The SIGCANCEL signal handler should not issue __syscall_do_cancel, which calls __do_cancel and __pthread_unwind, if the cancellation is already in proces (and libgcc unwind is not reentrant). Any cancellation signal received after is ignored. Checked on x86_64-linux-gnu and aarch64-linux-gnu. Tested-by: Aurelien Jarno Reviewed-by: Florian Weimer (cherry picked from commit 360cce0b066f34e85e473c04cdc16e6fa426021b) diff --git a/NEWS b/NEWS index 6b34aa31f8..6912162e01 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,7 @@ The following bugs were resolved with this release: [32630] math: math: tanf is not correctly rounded for all rounding modes [32781] Linux: Remove attribute access from sched_getattr + [32782] nptl: Race conditions in pthread cancellation causing crash [32786] nptl: PTHREAD_COND_INITIALIZER compatibility with pre-2.41 versions Version 2.41 diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c index f7ce3ec51b..b838273881 100644 --- a/nptl/pthread_cancel.c +++ b/nptl/pthread_cancel.c @@ -41,15 +41,17 @@ sigcancel_handler (int sig, siginfo_t *si, void *ctx) || si->si_code != SI_TKILL) return; - /* Check if asynchronous cancellation mode is set or if interrupted - instruction pointer falls within the cancellable syscall bridge. For - interruptable syscalls with external side-effects (i.e. partial reads), - the kernel will set the IP to after __syscall_cancel_arch_end, thus - disabling the cancellation and allowing the process to handle such + /* Check if asynchronous cancellation mode is set and cancellation is not + already in progress, or if interrupted instruction pointer falls within + the cancellable syscall bridge. + For interruptable syscalls with external side-effects (i.e. partial + reads), the kernel will set the IP to after __syscall_cancel_arch_end, + thus disabling the cancellation and allowing the process to handle such conditions. */ struct pthread *self = THREAD_SELF; int oldval = atomic_load_relaxed (&self->cancelhandling); - if (cancel_async_enabled (oldval) || cancellation_pc_check (ctx)) + if (cancel_enabled_and_canceled_and_async (oldval) + || cancellation_pc_check (ctx)) __syscall_do_cancel (); } diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile index a123e28a57..2e0ce773a0 100644 --- a/sysdeps/pthread/Makefile +++ b/sysdeps/pthread/Makefile @@ -106,6 +106,7 @@ tests += \ tst-cancel28 \ tst-cancel29 \ tst-cancel30 \ + tst-cancel32 \ tst-cleanup0 \ tst-cleanup1 \ tst-cleanup2 \ diff --git a/sysdeps/pthread/tst-cancel32.c b/sysdeps/pthread/tst-cancel32.c new file mode 100644 index 0000000000..ab550c16bf --- /dev/null +++ b/sysdeps/pthread/tst-cancel32.c @@ -0,0 +1,73 @@ +/* Check if pthread_setcanceltype disables asynchronous cancellation + once cancellation happens (BZ 32782) + + 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 + . */ + +/* The pthread_setcanceltype is a cancellation entrypoint, and if + asynchronous is enabled and the cancellation starts (on the second + pthread_setcanceltype call), the asynchronous should not restart + the process. */ + +#include + +#define NITER 1000 +#define NTHREADS 8 + +static void +tf_cleanup (void *arg) +{ +} + +static void * +tf (void *closure) +{ + pthread_cleanup_push (tf_cleanup, NULL); + for (;;) + { + /* The only possible failure for pthread_setcanceltype is an + invalid state type. */ + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL); + } + pthread_cleanup_pop (1); + + return NULL; +} + +static void +poll_threads (int nthreads) +{ + pthread_t thr[nthreads]; + for (int i = 0; i < nthreads; i++) + thr[i] = xpthread_create (NULL, tf, NULL); + for (int i = 0; i < nthreads; i++) + xpthread_cancel (thr[i]); + for (int i = 0; i < nthreads; i++) + xpthread_join (thr[i]); +} + +static int +do_test (void) +{ + for (int k = 0; k < NITER; k++) + poll_threads (NTHREADS); + + return 0; +} + +#include