]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/dso/dso_lib.c
Stop raising ERR_R_MALLOC_FAILURE in most places
[thirdparty/openssl.git] / crypto / dso / dso_lib.c
CommitLineData
0f113f3e 1/*
454afd98 2 * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
8f4fac7f 3 *
b6a34e9a 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
d2e9e320
RS
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
8f4fac7f
GT
8 */
9
706457b7 10#include "dso_local.h"
cd420b0b 11#include "internal/refcount.h"
8f4fac7f 12
3d8b2ec4 13static DSO *DSO_new_method(DSO_METHOD *meth)
0f113f3e
MC
14{
15 DSO *ret;
16
b51bce94 17 ret = OPENSSL_zalloc(sizeof(*ret));
e077455e 18 if (ret == NULL)
26a7d938 19 return NULL;
0f113f3e
MC
20 ret->meth_data = sk_void_new_null();
21 if (ret->meth_data == NULL) {
22 /* sk_new doesn't generate any errors so we do */
e077455e 23 ERR_raise(ERR_LIB_DSO, ERR_R_CRYPTO_LIB);
0f113f3e 24 OPENSSL_free(ret);
26a7d938 25 return NULL;
0f113f3e 26 }
e6a10b07 27 ret->meth = DSO_METHOD_openssl();
0f113f3e 28 ret->references = 1;
c74471d2
AG
29 ret->lock = CRYPTO_THREAD_lock_new();
30 if (ret->lock == NULL) {
e077455e 31 ERR_raise(ERR_LIB_DSO, ERR_R_CRYPTO_LIB);
98637bd3 32 sk_void_free(ret->meth_data);
0f113f3e 33 OPENSSL_free(ret);
c74471d2
AG
34 return NULL;
35 }
36
37 if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
38 DSO_free(ret);
0f113f3e
MC
39 ret = NULL;
40 }
c74471d2
AG
41
42 return ret;
0f113f3e 43}
8f4fac7f 44
3d8b2ec4
RS
45DSO *DSO_new(void)
46{
47 return DSO_new_method(NULL);
48}
49
8f4fac7f 50int DSO_free(DSO *dso)
0f113f3e
MC
51{
52 int i;
53
efa7dd64 54 if (dso == NULL)
208fb891 55 return 1;
0f113f3e 56
2f545ae4 57 if (CRYPTO_DOWN_REF(&dso->references, &i, dso->lock) <= 0)
c74471d2
AG
58 return 0;
59
f3f1cf84 60 REF_PRINT_COUNT("DSO", dso);
0f113f3e 61 if (i > 0)
c74471d2 62 return 1;
f3f1cf84 63 REF_ASSERT_ISNT(i < 0);
8f4fac7f 64
b39eda7e
MC
65 if ((dso->flags & DSO_FLAG_NO_UNLOAD_ON_FREE) == 0) {
66 if ((dso->meth->dso_unload != NULL) && !dso->meth->dso_unload(dso)) {
9311d0c4 67 ERR_raise(ERR_LIB_DSO, DSO_R_UNLOAD_FAILED);
b39eda7e
MC
68 return 0;
69 }
0f113f3e 70 }
8f4fac7f 71
0f113f3e 72 if ((dso->meth->finish != NULL) && !dso->meth->finish(dso)) {
9311d0c4 73 ERR_raise(ERR_LIB_DSO, DSO_R_FINISH_FAILED);
c74471d2 74 return 0;
0f113f3e
MC
75 }
76
77 sk_void_free(dso->meth_data);
b548a1f1
RS
78 OPENSSL_free(dso->filename);
79 OPENSSL_free(dso->loaded_filename);
c74471d2 80 CRYPTO_THREAD_lock_free(dso->lock);
0f113f3e 81 OPENSSL_free(dso);
c74471d2 82 return 1;
0f113f3e
MC
83}
84
85int DSO_flags(DSO *dso)
86{
87 return ((dso == NULL) ? 0 : dso->flags);
88}
8f4fac7f 89
d9ff8890 90int DSO_up_ref(DSO *dso)
0f113f3e 91{
c74471d2
AG
92 int i;
93
0f113f3e 94 if (dso == NULL) {
9311d0c4 95 ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
c74471d2 96 return 0;
0f113f3e 97 }
8f4fac7f 98
2f545ae4 99 if (CRYPTO_UP_REF(&dso->references, &i, dso->lock) <= 0)
c74471d2
AG
100 return 0;
101
e26f653d 102 REF_PRINT_COUNT("DSO", dso);
c74471d2
AG
103 REF_ASSERT_ISNT(i < 2);
104 return ((i > 1) ? 1 : 0);
0f113f3e 105}
8f4fac7f 106
b9e63915 107DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags)
0f113f3e
MC
108{
109 DSO *ret;
110 int allocated = 0;
111
112 if (dso == NULL) {
113 ret = DSO_new_method(meth);
114 if (ret == NULL) {
e077455e 115 ERR_raise(ERR_LIB_DSO, ERR_R_DSO_LIB);
0f113f3e
MC
116 goto err;
117 }
118 allocated = 1;
119 /* Pass the provided flags to the new DSO object */
120 if (DSO_ctrl(ret, DSO_CTRL_SET_FLAGS, flags, NULL) < 0) {
9311d0c4 121 ERR_raise(ERR_LIB_DSO, DSO_R_CTRL_FAILED);
0f113f3e
MC
122 goto err;
123 }
124 } else
125 ret = dso;
126 /* Don't load if we're currently already loaded */
127 if (ret->filename != NULL) {
9311d0c4 128 ERR_raise(ERR_LIB_DSO, DSO_R_DSO_ALREADY_LOADED);
0f113f3e
MC
129 goto err;
130 }
131 /*
132 * filename can only be NULL if we were passed a dso that already has one
133 * set.
134 */
135 if (filename != NULL)
136 if (!DSO_set_filename(ret, filename)) {
9311d0c4 137 ERR_raise(ERR_LIB_DSO, DSO_R_SET_FILENAME_FAILED);
0f113f3e
MC
138 goto err;
139 }
140 filename = ret->filename;
141 if (filename == NULL) {
9311d0c4 142 ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
0f113f3e
MC
143 goto err;
144 }
145 if (ret->meth->dso_load == NULL) {
9311d0c4 146 ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
0f113f3e
MC
147 goto err;
148 }
149 if (!ret->meth->dso_load(ret)) {
9311d0c4 150 ERR_raise(ERR_LIB_DSO, DSO_R_LOAD_FAILED);
0f113f3e
MC
151 goto err;
152 }
153 /* Load succeeded */
26a7d938 154 return ret;
0f113f3e
MC
155 err:
156 if (allocated)
157 DSO_free(ret);
26a7d938 158 return NULL;
0f113f3e 159}
8f4fac7f 160
e9a68cfb 161DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname)
0f113f3e
MC
162{
163 DSO_FUNC_TYPE ret = NULL;
164
165 if ((dso == NULL) || (symname == NULL)) {
9311d0c4 166 ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
26a7d938 167 return NULL;
0f113f3e
MC
168 }
169 if (dso->meth->dso_bind_func == NULL) {
9311d0c4 170 ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
26a7d938 171 return NULL;
0f113f3e
MC
172 }
173 if ((ret = dso->meth->dso_bind_func(dso, symname)) == NULL) {
9311d0c4 174 ERR_raise(ERR_LIB_DSO, DSO_R_SYM_FAILURE);
26a7d938 175 return NULL;
0f113f3e
MC
176 }
177 /* Success */
26a7d938 178 return ret;
0f113f3e
MC
179}
180
181/*
182 * I don't really like these *_ctrl functions very much to be perfectly
183 * honest. For one thing, I think I have to return a negative value for any
184 * error because possible DSO_ctrl() commands may return values such as
185 * "size"s that can legitimately be zero (making the standard
61986d32 186 * "if (DSO_cmd(...))" form that works almost everywhere else fail at odd
0f113f3e
MC
187 * times. I'd prefer "output" values to be passed by reference and the return
188 * value as success/failure like usual ... but we conform when we must... :-)
189 */
b9e63915 190long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg)
0f113f3e
MC
191{
192 if (dso == NULL) {
9311d0c4 193 ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
26a7d938 194 return -1;
0f113f3e
MC
195 }
196 /*
197 * We should intercept certain generic commands and only pass control to
198 * the method-specific ctrl() function if it's something we don't handle.
199 */
200 switch (cmd) {
201 case DSO_CTRL_GET_FLAGS:
202 return dso->flags;
203 case DSO_CTRL_SET_FLAGS:
204 dso->flags = (int)larg;
26a7d938 205 return 0;
0f113f3e
MC
206 case DSO_CTRL_OR_FLAGS:
207 dso->flags |= (int)larg;
26a7d938 208 return 0;
0f113f3e
MC
209 default:
210 break;
211 }
212 if ((dso->meth == NULL) || (dso->meth->dso_ctrl == NULL)) {
9311d0c4 213 ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
26a7d938 214 return -1;
0f113f3e 215 }
26a7d938 216 return dso->meth->dso_ctrl(dso, cmd, larg, parg);
0f113f3e 217}
51c8dc37 218
51c8dc37 219const char *DSO_get_filename(DSO *dso)
0f113f3e
MC
220{
221 if (dso == NULL) {
9311d0c4 222 ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
26a7d938 223 return NULL;
0f113f3e 224 }
26a7d938 225 return dso->filename;
0f113f3e 226}
51c8dc37
GT
227
228int DSO_set_filename(DSO *dso, const char *filename)
0f113f3e
MC
229{
230 char *copied;
231
232 if ((dso == NULL) || (filename == NULL)) {
9311d0c4 233 ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
26a7d938 234 return 0;
0f113f3e
MC
235 }
236 if (dso->loaded_filename) {
9311d0c4 237 ERR_raise(ERR_LIB_DSO, DSO_R_DSO_ALREADY_LOADED);
26a7d938 238 return 0;
0f113f3e
MC
239 }
240 /* We'll duplicate filename */
edae9834 241 copied = OPENSSL_strdup(filename);
e077455e 242 if (copied == NULL)
26a7d938 243 return 0;
b548a1f1 244 OPENSSL_free(dso->filename);
0f113f3e 245 dso->filename = copied;
208fb891 246 return 1;
0f113f3e 247}
51c8dc37 248
cbecb3ac 249char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2)
0f113f3e
MC
250{
251 char *result = NULL;
252
253 if (dso == NULL || filespec1 == NULL) {
9311d0c4 254 ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
26a7d938 255 return NULL;
0f113f3e
MC
256 }
257 if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
258 if (dso->merger != NULL)
259 result = dso->merger(dso, filespec1, filespec2);
260 else if (dso->meth->dso_merger != NULL)
261 result = dso->meth->dso_merger(dso, filespec1, filespec2);
262 }
26a7d938 263 return result;
0f113f3e 264}
cbecb3ac 265
51c8dc37 266char *DSO_convert_filename(DSO *dso, const char *filename)
0f113f3e
MC
267{
268 char *result = NULL;
269
270 if (dso == NULL) {
9311d0c4 271 ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
26a7d938 272 return NULL;
0f113f3e
MC
273 }
274 if (filename == NULL)
275 filename = dso->filename;
276 if (filename == NULL) {
9311d0c4 277 ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
26a7d938 278 return NULL;
0f113f3e
MC
279 }
280 if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
281 if (dso->name_converter != NULL)
282 result = dso->name_converter(dso, filename);
283 else if (dso->meth->dso_name_converter != NULL)
284 result = dso->meth->dso_name_converter(dso, filename);
285 }
286 if (result == NULL) {
edae9834 287 result = OPENSSL_strdup(filename);
e077455e 288 if (result == NULL)
26a7d938 289 return NULL;
0f113f3e 290 }
26a7d938 291 return result;
0f113f3e 292}
51c8dc37 293
cb6ea61c
MC
294int DSO_pathbyaddr(void *addr, char *path, int sz)
295{
e6a10b07
P
296 DSO_METHOD *meth = DSO_METHOD_openssl();
297
cb6ea61c 298 if (meth->pathbyaddr == NULL) {
9311d0c4 299 ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
cb6ea61c
MC
300 return -1;
301 }
302 return (*meth->pathbyaddr) (addr, path, sz);
303}
304
b39eda7e
MC
305DSO *DSO_dsobyaddr(void *addr, int flags)
306{
307 DSO *ret = NULL;
308 char *filename = NULL;
309 int len = DSO_pathbyaddr(addr, NULL, 0);
310
210fe4ed
DG
311 if (len < 0)
312 return NULL;
313
b39eda7e
MC
314 filename = OPENSSL_malloc(len);
315 if (filename != NULL
316 && DSO_pathbyaddr(addr, filename, len) == len)
317 ret = DSO_load(NULL, filename, NULL, flags);
318
319 OPENSSL_free(filename);
320 return ret;
321}
322
c6cb42e4 323void *DSO_global_lookup(const char *name)
0f113f3e 324{
e6a10b07
P
325 DSO_METHOD *meth = DSO_METHOD_openssl();
326
0f113f3e 327 if (meth->globallookup == NULL) {
9311d0c4 328 ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
0f113f3e
MC
329 return NULL;
330 }
331 return (*meth->globallookup) (name);
332}