xref: /llvm-project/libc/src/signal/linux/sigaltstack.cpp (revision 056a1676cbe43ce22b65a500a2dc9916fd575563)
167957368SSiva Chandra Reddy //===-- Linux implementation of sigaltstack -------------------------------===//
267957368SSiva Chandra Reddy //
367957368SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
467957368SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information.
567957368SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
667957368SSiva Chandra Reddy //
767957368SSiva Chandra Reddy //===----------------------------------------------------------------------===//
867957368SSiva Chandra Reddy 
967957368SSiva Chandra Reddy #include "src/signal/sigaltstack.h"
10*056a1676Swldfngrs #include "hdr/types/stack_t.h"
115ff3ff33SPetr Hosek #include "src/__support/macros/config.h"
127abf6c25SSiva Chandra Reddy #include "src/errno/libc_errno.h"
1367957368SSiva Chandra Reddy #include "src/signal/linux/signal_utils.h"
1467957368SSiva Chandra Reddy 
1567957368SSiva Chandra Reddy #include "src/__support/common.h"
1667957368SSiva Chandra Reddy 
1767957368SSiva Chandra Reddy #include <sys/syscall.h>
1867957368SSiva Chandra Reddy 
195ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL {
2067957368SSiva Chandra Reddy 
2167957368SSiva Chandra Reddy LLVM_LIBC_FUNCTION(int, sigaltstack,
2267957368SSiva Chandra Reddy                    (const stack_t *__restrict ss, stack_t *__restrict oss)) {
2367957368SSiva Chandra Reddy   if (ss != nullptr) {
2467957368SSiva Chandra Reddy     unsigned not_ss_disable = ~unsigned(SS_DISABLE);
2567957368SSiva Chandra Reddy     if ((unsigned(ss->ss_flags) & not_ss_disable) != 0) {
2667957368SSiva Chandra Reddy       // Flags cannot have anything other than SS_DISABLE set.
2767957368SSiva Chandra Reddy       // We do the type-casting to unsigned because the |ss_flags|
2867957368SSiva Chandra Reddy       // field of stack_t is of type "int".
297abf6c25SSiva Chandra Reddy       libc_errno = EINVAL;
3067957368SSiva Chandra Reddy       return -1;
3167957368SSiva Chandra Reddy     }
3267957368SSiva Chandra Reddy     if (ss->ss_size < MINSIGSTKSZ) {
337abf6c25SSiva Chandra Reddy       libc_errno = ENOMEM;
3467957368SSiva Chandra Reddy       return -1;
3567957368SSiva Chandra Reddy     }
3667957368SSiva Chandra Reddy   }
3767957368SSiva Chandra Reddy 
38b6bc9d72SGuillaume Chatelet   int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_sigaltstack, ss, oss);
3967957368SSiva Chandra Reddy   if (ret < 0) {
407abf6c25SSiva Chandra Reddy     libc_errno = -ret;
4167957368SSiva Chandra Reddy     return -1;
4267957368SSiva Chandra Reddy   }
4367957368SSiva Chandra Reddy   return 0;
4467957368SSiva Chandra Reddy }
4567957368SSiva Chandra Reddy 
465ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL
47