Fix race for X509 store found by thread sanitizer
[openssl.git] / crypto / conf / conf_def.c
index 5ada0fe056852764466d9df3ceeb9d53cedbdd0c..e047746f67642632ebc5e8c7bfa57023c9633da0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -226,6 +226,9 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
     char *dirpath = NULL;
     OPENSSL_DIR_CTX *dirctx = NULL;
 #endif
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    int numincludes = 0;
+#endif
 
     if ((buff = BUF_MEM_new()) == NULL) {
         ERR_raise(ERR_LIB_CONF, ERR_R_BUF_LIB);
@@ -233,13 +236,11 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
     }
 
     section = OPENSSL_strdup("default");
-    if (section == NULL) {
-        ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
+    if (section == NULL)
         goto err;
-    }
 
     if (_CONF_new_data(conf) == 0) {
-        ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_CONF, ERR_R_CONF_LIB);
         goto err;
     }
 
@@ -425,10 +426,8 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
                         goto err;
                 } else if (strcmp(p, "includedir") == 0) {
                     OPENSSL_free(conf->includedir);
-                    if ((conf->includedir = OPENSSL_strdup(pval)) == NULL) {
-                        ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
+                    if ((conf->includedir = OPENSSL_strdup(pval)) == NULL)
                         goto err;
-                    }
                 }
 
                 /*
@@ -442,6 +441,20 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
                 const char *include_dir = ossl_safe_getenv("OPENSSL_CONF_INCLUDE");
                 char *include_path = NULL;
 
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+                /*
+                 * The include processing below can cause the "conf" fuzzer to
+                 * timeout due to the fuzzer inserting large and complicated
+                 * includes - with a large amount of time spent in
+                 * OPENSSL_strlcat/OPENSSL_strcpy. This is not a security
+                 * concern because config files should never come from untrusted
+                 * sources. We just set an arbitrary limit on the allowed
+                 * number of includes when fuzzing to prevent this timeout.
+                 */
+                if (numincludes++ > 10)
+                    goto err;
+#endif
+
                 if (include_dir == NULL)
                     include_dir = conf->includedir;
 
@@ -458,7 +471,6 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
 
                     include_path = OPENSSL_malloc(newlen);
                     if (include_path == NULL) {
-                        ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
                         OPENSSL_free(include);
                         goto err;
                     }
@@ -495,13 +507,13 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
                     /* push the currently processing BIO onto stack */
                     if (biosk == NULL) {
                         if ((biosk = sk_BIO_new_null()) == NULL) {
-                            ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
+                            ERR_raise(ERR_LIB_CONF, ERR_R_CRYPTO_LIB);
                             BIO_free(next);
                             goto err;
                         }
                     }
                     if (!sk_BIO_push(biosk, in)) {
-                        ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
+                        ERR_raise(ERR_LIB_CONF, ERR_R_CRYPTO_LIB);
                         BIO_free(next);
                         goto err;
                     }
@@ -519,16 +531,12 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
             start = eat_ws(conf, p);
             trim_ws(conf, start);
 
-            if ((v = OPENSSL_malloc(sizeof(*v))) == NULL) {
-                ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
+            if ((v = OPENSSL_malloc(sizeof(*v))) == NULL)
                 goto err;
-            }
             v->name = OPENSSL_strdup(pname);
             v->value = NULL;
-            if (v->name == NULL) {
-                ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
+            if (v->name == NULL)
                 goto err;
-            }
             if (!str_copy(conf, psection, &(v->value), start))
                 goto err;
 
@@ -544,7 +552,7 @@ static int def_load_bio(CONF *conf, BIO *in, long *line)
             } else
                 tv = sv;
             if (_CONF_add_string(conf, tv, v) == 0) {
-                ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
+                ERR_raise(ERR_LIB_CONF, ERR_R_CONF_LIB);
                 goto err;
             }
             v = NULL;
@@ -757,7 +765,7 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from)
                 goto err;
             }
             if (!BUF_MEM_grow_clean(buf, newsize)) {
-                ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
+                ERR_raise(ERR_LIB_CONF, ERR_R_BUF_LIB);
                 goto err;
             }
             while (*p)
@@ -849,10 +857,8 @@ static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx)
 
             newlen = pathlen + namelen + 2;
             newpath = OPENSSL_zalloc(newlen);
-            if (newpath == NULL) {
-                ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
+            if (newpath == NULL)
                 break;
-            }
 #ifdef OPENSSL_SYS_VMS
             /*
              * If the given path isn't clear VMS syntax,
@@ -886,7 +892,7 @@ static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx)
 
 static int is_keytype(const CONF *conf, char c, unsigned short type)
 {
-    const unsigned short * keytypes = (const unsigned short *) conf->meth_data;
+    const unsigned short *keytypes = (const unsigned short *) conf->meth_data;
     unsigned char key = (unsigned char)c;
 
 #ifdef CHARSET_EBCDIC