Coverage Report

Created: 2025-06-13 06:56

/src/openssl/crypto/async/arch/async_posix.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
/* This must be the first #include file */
11
#include "../async_local.h"
12
13
#ifdef ASYNC_POSIX
14
15
# include <stddef.h>
16
# include <unistd.h>
17
# include <openssl/err.h>
18
# include <openssl/crypto.h>
19
20
0
#define STACKSIZE       32768
21
22
static CRYPTO_RWLOCK *async_mem_lock;
23
24
static void *async_stack_alloc(size_t *num);
25
static void async_stack_free(void *addr);
26
27
int async_local_init(void)
28
0
{
29
0
    async_mem_lock = CRYPTO_THREAD_lock_new();
30
0
    return async_mem_lock != NULL;
31
0
}
32
33
void async_local_deinit(void)
34
0
{
35
0
    CRYPTO_THREAD_lock_free(async_mem_lock);
36
0
}
37
38
static int allow_customize = 1;
39
static ASYNC_stack_alloc_fn stack_alloc_impl = async_stack_alloc;
40
static ASYNC_stack_free_fn stack_free_impl = async_stack_free;
41
42
int ASYNC_is_capable(void)
43
0
{
44
0
    ucontext_t ctx;
45
46
    /*
47
     * Some platforms provide getcontext() but it does not work (notably
48
     * MacOSX PPC64). Check for a working getcontext();
49
     */
50
0
    return getcontext(&ctx) == 0;
51
0
}
52
53
int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn,
54
                            ASYNC_stack_free_fn free_fn)
55
0
{
56
0
    OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL);
57
58
0
    if (!CRYPTO_THREAD_write_lock(async_mem_lock))
59
0
        return 0;
60
0
    if (!allow_customize) {
61
0
        CRYPTO_THREAD_unlock(async_mem_lock);
62
0
        return 0;
63
0
    }
64
0
    CRYPTO_THREAD_unlock(async_mem_lock);
65
66
0
    if (alloc_fn != NULL)
67
0
        stack_alloc_impl = alloc_fn;
68
0
    if (free_fn != NULL)
69
0
        stack_free_impl = free_fn;
70
0
    return 1;
71
0
}
72
73
void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn,
74
                             ASYNC_stack_free_fn *free_fn)
75
0
{
76
0
    if (alloc_fn != NULL)
77
0
        *alloc_fn = stack_alloc_impl;
78
0
    if (free_fn != NULL)
79
0
        *free_fn = stack_free_impl;
80
0
}
81
82
static void *async_stack_alloc(size_t *num)
83
0
{
84
0
    return OPENSSL_malloc(*num);
85
0
}
86
87
static void async_stack_free(void *addr)
88
0
{
89
0
    OPENSSL_free(addr);
90
0
}
91
92
void async_local_cleanup(void)
93
0
{
94
0
}
95
96
int async_fibre_makecontext(async_fibre *fibre)
97
0
{
98
0
#ifndef USE_SWAPCONTEXT
99
0
    fibre->env_init = 0;
100
0
#endif
101
0
    if (getcontext(&fibre->fibre) == 0) {
102
0
        size_t num = STACKSIZE;
103
104
        /*
105
         *  Disallow customisation after the first
106
         *  stack is allocated.
107
         */
108
0
        if (allow_customize) {
109
0
            if (!CRYPTO_THREAD_write_lock(async_mem_lock))
110
0
                return 0;
111
0
            allow_customize = 0;
112
0
            CRYPTO_THREAD_unlock(async_mem_lock);
113
0
        }
114
115
0
        fibre->fibre.uc_stack.ss_sp = stack_alloc_impl(&num);
116
0
        if (fibre->fibre.uc_stack.ss_sp != NULL) {
117
0
            fibre->fibre.uc_stack.ss_size = num;
118
0
            fibre->fibre.uc_link = NULL;
119
0
            makecontext(&fibre->fibre, async_start_func, 0);
120
0
            return 1;
121
0
        }
122
0
    } else {
123
0
        fibre->fibre.uc_stack.ss_sp = NULL;
124
0
    }
125
0
    return 0;
126
0
}
127
128
void async_fibre_free(async_fibre *fibre)
129
0
{
130
0
    stack_free_impl(fibre->fibre.uc_stack.ss_sp);
131
0
    fibre->fibre.uc_stack.ss_sp = NULL;
132
0
}
133
134
#endif