[libc-commits] [libc] [libc] Fix sigaltstack with SS_DISABLE (PR #230053)
Jeff Bailey via libc-commits
libc-commits at lists.llvm.org
Thu Oct 8 13:46:54 PDT 2026
https://github.com/kaladron updated https://github.com/llvm/llvm-project/pull/230053
>From 5adffa983622b6fe9bd03250717de607f83b5feb Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jbailey at raspberryginger.com>
Date: Thu, 8 Oct 2026 10:41:49 +0100
Subject: [PATCH 1/2] [libc] Fix sigaltstack with SS_DISABLE
POSIX.1-2024 (IEEE Std 1003.1-2024) states in the DESCRIPTION section
for sigaltstack: "If it is set to SS_DISABLE, the stack is disabled and
ss_sp and ss_size are ignored."
Previously, sigaltstack unconditionally checked that ss_size was at
least MINSIGSTKSZ. This caused valid calls that disable an alternate
signal stack with ss_size = 0 and ss_sp = nullptr to erroneously fail
with ENOMEM.
Only validate ss_size against MINSIGSTKSZ when SS_DISABLE is not set.
Added SigaltstackDisableStack unit tests and verified invalid stack
combinations. Also updated file headers in the touched files.
Assisted-by: Automated tooling, human reviewed.
---
libc/src/signal/linux/CMakeLists.txt | 6 +--
libc/src/signal/linux/sigaltstack.cpp | 24 +++++-----
libc/test/src/signal/CMakeLists.txt | 2 +-
libc/test/src/signal/sigaltstack_test.cpp | 54 ++++++++++++++++++++---
4 files changed, 67 insertions(+), 19 deletions(-)
diff --git a/libc/src/signal/linux/CMakeLists.txt b/libc/src/signal/linux/CMakeLists.txt
index e585aa1a01fce1..663e00fbf249a5 100644
--- a/libc/src/signal/linux/CMakeLists.txt
+++ b/libc/src/signal/linux/CMakeLists.txt
@@ -74,11 +74,11 @@ add_entrypoint_object(
HDRS
../sigaltstack.h
DEPENDS
- libc.include.signal
+ libc.hdr.signal_macros
+ libc.hdr.types.stack_t
libc.include.sys_syscall
+ libc.src.__support.libc_errno
libc.src.__support.OSUtil.osutil
- libc.src.errno.errno
- libc.hdr.types.stack_t
)
add_entrypoint_object(
diff --git a/libc/src/signal/linux/sigaltstack.cpp b/libc/src/signal/linux/sigaltstack.cpp
index 990b841c6d9047..a874cd1064e0bc 100644
--- a/libc/src/signal/linux/sigaltstack.cpp
+++ b/libc/src/signal/linux/sigaltstack.cpp
@@ -1,18 +1,24 @@
-//===-- Linux implementation of sigaltstack -------------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Linux implementation of sigaltstack.
+///
+//===----------------------------------------------------------------------===//
#include "src/signal/sigaltstack.h"
+
+#include "hdr/signal_macros.h"
#include "hdr/types/stack_t.h"
+#include "src/__support/OSUtil/syscall.h"
+#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
-#include "src/signal/linux/signal_utils.h"
-
-#include "src/__support/common.h"
#include <sys/syscall.h>
@@ -21,15 +27,13 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, sigaltstack,
(const stack_t *__restrict ss, stack_t *__restrict oss)) {
if (ss != nullptr) {
- unsigned not_ss_disable = ~unsigned(SS_DISABLE);
- if ((unsigned(ss->ss_flags) & not_ss_disable) != 0) {
- // Flags cannot have anything other than SS_DISABLE set.
- // We do the type-casting to unsigned because the |ss_flags|
- // field of stack_t is of type "int".
+ if (ss->ss_flags != 0 && ss->ss_flags != SS_DISABLE) {
libc_errno = EINVAL;
return -1;
}
- if (ss->ss_size < MINSIGSTKSZ) {
+ // ss_size is only validated if the alternate stack is being enabled.
+ // When disabling (SS_DISABLE), ss_size and ss_sp are ignored.
+ if (ss->ss_flags != SS_DISABLE && ss->ss_size < MINSIGSTKSZ) {
libc_errno = ENOMEM;
return -1;
}
diff --git a/libc/test/src/signal/CMakeLists.txt b/libc/test/src/signal/CMakeLists.txt
index ac394ea6b7ab75..f22a8a8f0a092c 100644
--- a/libc/test/src/signal/CMakeLists.txt
+++ b/libc/test/src/signal/CMakeLists.txt
@@ -135,9 +135,9 @@ add_libc_test(
SRCS
sigaltstack_test.cpp
DEPENDS
+ libc.hdr.errno_macros
libc.hdr.signal_macros
libc.hdr.stdint_proxy
- libc.src.errno.errno
libc.src.signal.raise
libc.src.signal.sigaltstack
libc.src.signal.sigaction
diff --git a/libc/test/src/signal/sigaltstack_test.cpp b/libc/test/src/signal/sigaltstack_test.cpp
index 43c679b23bb299..200122c0d997f1 100644
--- a/libc/test/src/signal/sigaltstack_test.cpp
+++ b/libc/test/src/signal/sigaltstack_test.cpp
@@ -1,15 +1,19 @@
-//===-- Unittests for sigaltstack -----------------------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Unittests for sigaltstack.
+///
+//===----------------------------------------------------------------------===//
+#include "hdr/errno_macros.h"
#include "hdr/signal_macros.h"
#include "hdr/stdint_proxy.h"
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
-#include "src/signal/linux/signal_utils.h"
#include "src/signal/raise.h"
#include "src/signal/sigaction.h"
#include "src/signal/sigaltstack.h"
@@ -17,8 +21,6 @@
#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/Test.h"
-#include <sys/syscall.h>
-
constexpr int LOCAL_VAR_SIZE = 512;
constexpr int ALT_STACK_SIZE = SIGSTKSZ + LOCAL_VAR_SIZE * 2;
static uint8_t alt_stack[ALT_STACK_SIZE];
@@ -77,4 +79,46 @@ TEST_F(LlvmLibcSigaltstackTest, SigaltstackInvalidStack) {
ss.ss_flags = 0;
ASSERT_THAT(LIBC_NAMESPACE::sigaltstack(&ss, nullptr), Fails(ENOMEM));
+
+ // Sub-minimum size without SS_DISABLE should fail with ENOMEM.
+ ss.ss_size = MINSIGSTKSZ - 1;
+ ASSERT_THAT(LIBC_NAMESPACE::sigaltstack(&ss, nullptr), Fails(ENOMEM));
+
+ // SS_DISABLE combined with unsupported flags should fail with EINVAL.
+ ss.ss_flags = SS_DISABLE | SS_ONSTACK;
+ ASSERT_THAT(LIBC_NAMESPACE::sigaltstack(&ss, nullptr), Fails(EINVAL));
+}
+
+TEST_F(LlvmLibcSigaltstackTest, SigaltstackDisableStack) {
+ // First, set up a valid alternate stack.
+ stack_t ss;
+ ss.ss_sp = alt_stack;
+ ss.ss_size = ALT_STACK_SIZE;
+ ss.ss_flags = 0;
+ ASSERT_THAT(LIBC_NAMESPACE::sigaltstack(&ss, nullptr), Succeeds(0));
+
+ // Disable the alternate stack with ss_size = 0 and ss_sp = nullptr.
+ stack_t disable_ss;
+ disable_ss.ss_sp = nullptr;
+ disable_ss.ss_size = 0;
+ disable_ss.ss_flags = SS_DISABLE;
+ stack_t old_ss;
+ ASSERT_THAT(LIBC_NAMESPACE::sigaltstack(&disable_ss, &old_ss), Succeeds(0));
+ EXPECT_EQ(old_ss.ss_sp, static_cast<void *>(alt_stack));
+ EXPECT_EQ(old_ss.ss_size, static_cast<size_t>(ALT_STACK_SIZE));
+ EXPECT_EQ(old_ss.ss_flags, 0);
+
+ // Verify that subsequent query reports SS_DISABLE and zeroed stack info.
+ stack_t current_ss;
+ ASSERT_THAT(LIBC_NAMESPACE::sigaltstack(nullptr, ¤t_ss), Succeeds(0));
+ EXPECT_EQ(current_ss.ss_flags & SS_DISABLE, SS_DISABLE);
+ EXPECT_EQ(current_ss.ss_sp, nullptr);
+ EXPECT_EQ(current_ss.ss_size, size_t(0));
+
+ // Verify disabling when ss_size is non-zero sub-minimum and ss_sp is non-null
+ // (both should be ignored when SS_DISABLE is set).
+ disable_ss.ss_sp = alt_stack;
+ disable_ss.ss_size = MINSIGSTKSZ - 1;
+ disable_ss.ss_flags = SS_DISABLE;
+ EXPECT_THAT(LIBC_NAMESPACE::sigaltstack(&disable_ss, nullptr), Succeeds(0));
}
>From eb6caafacffb846637b29f4c59349b5cbfb25036 Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jbailey at raspberryginger.com>
Date: Thu, 8 Oct 2026 21:46:31 +0100
Subject: [PATCH 2/2] [libc] Add libc.src.errno.errno to sigaltstack DEPENDS
Add libc.src.errno.errno to the DEPENDS list for sigaltstack to satisfy
the link-time requirement for runtime errno storage.
Assisted-by: Automated tooling, human reviewed.
---
libc/src/signal/linux/CMakeLists.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/libc/src/signal/linux/CMakeLists.txt b/libc/src/signal/linux/CMakeLists.txt
index 663e00fbf249a5..8360ce21364766 100644
--- a/libc/src/signal/linux/CMakeLists.txt
+++ b/libc/src/signal/linux/CMakeLists.txt
@@ -79,6 +79,7 @@ add_entrypoint_object(
libc.include.sys_syscall
libc.src.__support.libc_errno
libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
)
add_entrypoint_object(
More information about the libc-commits
mailing list