1e71b7053SJung-uk Kim /* 2b077aed3SPierre Pronchery * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. 3e71b7053SJung-uk Kim * 4b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use 5e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 6e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 7e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html 8e71b7053SJung-uk Kim */ 9e71b7053SJung-uk Kim 1017f01e99SJung-uk Kim #ifndef OSSL_CRYPTO_ASYNC_POSIX_H 1117f01e99SJung-uk Kim #define OSSL_CRYPTO_ASYNC_POSIX_H 12e71b7053SJung-uk Kim #include <openssl/e_os2.h> 13e71b7053SJung-uk Kim 14e71b7053SJung-uk Kim #if defined(OPENSSL_SYS_UNIX) \ 15e71b7053SJung-uk Kim && defined(OPENSSL_THREADS) && !defined(OPENSSL_NO_ASYNC) \ 16e71b7053SJung-uk Kim && !defined(__ANDROID__) && !defined(__OpenBSD__) 17e71b7053SJung-uk Kim 18e71b7053SJung-uk Kim # include <unistd.h> 19e71b7053SJung-uk Kim 20c9cf7b5cSJung-uk Kim # if _POSIX_VERSION >= 200112L \ 21*a8fe2d33SWarner Losh && (_POSIX_VERSION < 200809L || defined(__GLIBC__) || defined(__FreeBSD__)) 22e71b7053SJung-uk Kim 23e71b7053SJung-uk Kim # include <pthread.h> 24e71b7053SJung-uk Kim 25e71b7053SJung-uk Kim # define ASYNC_POSIX 26e71b7053SJung-uk Kim # define ASYNC_ARCH 27e71b7053SJung-uk Kim 28b077aed3SPierre Pronchery # if defined(__CET__) || defined(__ia64__) 29b077aed3SPierre Pronchery /* 30b077aed3SPierre Pronchery * When Intel CET is enabled, makecontext will create a different 31b077aed3SPierre Pronchery * shadow stack for each context. async_fibre_swapcontext cannot 32b077aed3SPierre Pronchery * use _longjmp. It must call swapcontext to swap shadow stack as 33b077aed3SPierre Pronchery * well as normal stack. 34b077aed3SPierre Pronchery * On IA64 the register stack engine is not saved across setjmp/longjmp. Here 35b077aed3SPierre Pronchery * swapcontext() performs correctly. 36b077aed3SPierre Pronchery */ 37b077aed3SPierre Pronchery # define USE_SWAPCONTEXT 38b077aed3SPierre Pronchery # endif 39b077aed3SPierre Pronchery # if defined(__aarch64__) && defined(__clang__) \ 40b077aed3SPierre Pronchery && defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT == 1 41b077aed3SPierre Pronchery /* 42b077aed3SPierre Pronchery * setjmp/longjmp don't currently work with BTI on all libc implementations 43b077aed3SPierre Pronchery * when compiled by clang. This is because clang doesn't put a BTI after the 44b077aed3SPierre Pronchery * call to setjmp where it returns the second time. This then fails on libc 45b077aed3SPierre Pronchery * implementations - notably glibc - which use an indirect jump to there. 46b077aed3SPierre Pronchery * So use the swapcontext implementation, which does work. 47b077aed3SPierre Pronchery * See https://github.com/llvm/llvm-project/issues/48888. 48b077aed3SPierre Pronchery */ 49b077aed3SPierre Pronchery # define USE_SWAPCONTEXT 50b077aed3SPierre Pronchery # endif 51e71b7053SJung-uk Kim # include <ucontext.h> 52b077aed3SPierre Pronchery # ifndef USE_SWAPCONTEXT 53e71b7053SJung-uk Kim # include <setjmp.h> 54b077aed3SPierre Pronchery # endif 55e71b7053SJung-uk Kim 56e71b7053SJung-uk Kim typedef struct async_fibre_st { 57e71b7053SJung-uk Kim ucontext_t fibre; 58b077aed3SPierre Pronchery # ifndef USE_SWAPCONTEXT 59e71b7053SJung-uk Kim jmp_buf env; 60e71b7053SJung-uk Kim int env_init; 61b077aed3SPierre Pronchery # endif 62e71b7053SJung-uk Kim } async_fibre; 63e71b7053SJung-uk Kim async_fibre_swapcontext(async_fibre * o,async_fibre * n,int r)64e71b7053SJung-uk Kimstatic ossl_inline int async_fibre_swapcontext(async_fibre *o, async_fibre *n, int r) 65e71b7053SJung-uk Kim { 66b077aed3SPierre Pronchery # ifdef USE_SWAPCONTEXT 67b077aed3SPierre Pronchery swapcontext(&o->fibre, &n->fibre); 68b077aed3SPierre Pronchery # else 69e71b7053SJung-uk Kim o->env_init = 1; 70e71b7053SJung-uk Kim 71e71b7053SJung-uk Kim if (!r || !_setjmp(o->env)) { 72e71b7053SJung-uk Kim if (n->env_init) 73e71b7053SJung-uk Kim _longjmp(n->env, 1); 74e71b7053SJung-uk Kim else 75e71b7053SJung-uk Kim setcontext(&n->fibre); 76e71b7053SJung-uk Kim } 77b077aed3SPierre Pronchery # endif 78e71b7053SJung-uk Kim 79e71b7053SJung-uk Kim return 1; 80e71b7053SJung-uk Kim } 81e71b7053SJung-uk Kim 82e71b7053SJung-uk Kim # define async_fibre_init_dispatcher(d) 83e71b7053SJung-uk Kim 84e71b7053SJung-uk Kim int async_fibre_makecontext(async_fibre *fibre); 85e71b7053SJung-uk Kim void async_fibre_free(async_fibre *fibre); 86e71b7053SJung-uk Kim 87e71b7053SJung-uk Kim # endif 88e71b7053SJung-uk Kim #endif 8917f01e99SJung-uk Kim #endif /* OSSL_CRYPTO_ASYNC_POSIX_H */ 90