1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copyright (c) 2014, Google Inc.
2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Permission to use, copy, modify, and/or distribute this software for any
4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * purpose with or without fee is hereby granted, provided that the above
5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * copyright notice and this permission notice appear in all copies.
6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/base.h>
16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
17f4e427204234da139fd0585def4b4e22502e33f0Adam Langley#if defined(__GLIBC__) && !defined(__UCLIBC__)
18f4e427204234da139fd0585def4b4e22502e33f0Adam Langley#define OPENSSL_GLIBC
19f4e427204234da139fd0585def4b4e22502e33f0Adam Langley#endif
20f4e427204234da139fd0585def4b4e22502e33f0Adam Langley
21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley// This file isn't built on ARM or Aarch64 because we link statically in those
22f4e427204234da139fd0585def4b4e22502e33f0Adam Langley// builds and trying to override malloc in a static link doesn't work. It also
2395add82835138f09cf7bb4a51c04c6320c241674David Benjamin// requires glibc. It's also disabled on ASan builds as this interferes with
2495add82835138f09cf7bb4a51c04c6320c241674David Benjamin// ASan's malloc interceptor.
2595add82835138f09cf7bb4a51c04c6320c241674David Benjamin//
2695add82835138f09cf7bb4a51c04c6320c241674David Benjamin// TODO(davidben): See if this and ASan's and MSan's interceptors can be made to
2795add82835138f09cf7bb4a51c04c6320c241674David Benjamin// coexist.
28f4e427204234da139fd0585def4b4e22502e33f0Adam Langley#if defined(__linux__) && defined(OPENSSL_GLIBC) && !defined(OPENSSL_ARM) && \
298ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    !defined(OPENSSL_AARCH64) && !defined(OPENSSL_ASAN) &&                   \
308ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    !defined(OPENSSL_MSAN)
31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
32b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root#include <errno.h>
33b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root#include <signal.h>
34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <stdint.h>
35e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <stdio.h>
36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <stdlib.h>
37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <unistd.h>
38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <new>
40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
4295add82835138f09cf7bb4a51c04c6320c241674David Benjamin// This file defines overrides for the standard allocation functions that allow
4395add82835138f09cf7bb4a51c04c6320c241674David Benjamin// a given allocation to be made to fail for testing. If the program is run
4495add82835138f09cf7bb4a51c04c6320c241674David Benjamin// with MALLOC_NUMBER_TO_FAIL set to a base-10 number then that allocation will
4595add82835138f09cf7bb4a51c04c6320c241674David Benjamin// return NULL. If MALLOC_BREAK_ON_FAIL is also defined then the allocation
4695add82835138f09cf7bb4a51c04c6320c241674David Benjamin// will signal SIGTRAP rather than return NULL.
4795add82835138f09cf7bb4a51c04c6320c241674David Benjamin//
4895add82835138f09cf7bb4a51c04c6320c241674David Benjamin// This code is not thread safe.
49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
50d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic uint64_t current_malloc_count = 0;
51d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic uint64_t malloc_number_to_fail = 0;
5295add82835138f09cf7bb4a51c04c6320c241674David Benjaminstatic bool failure_enabled = false, break_on_fail = false, in_call = false;
53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
54d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyextern "C" {
5595add82835138f09cf7bb4a51c04c6320c241674David Benjamin// These are other names for the standard allocation functions.
5695add82835138f09cf7bb4a51c04c6320c241674David Benjaminextern void *__libc_malloc(size_t size);
5795add82835138f09cf7bb4a51c04c6320c241674David Benjaminextern void *__libc_calloc(size_t num_elems, size_t size);
5895add82835138f09cf7bb4a51c04c6320c241674David Benjaminextern void *__libc_realloc(void *ptr, size_t size);
59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
61d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic void exit_handler(void) {
62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (failure_enabled && current_malloc_count > malloc_number_to_fail) {
63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    _exit(88);
64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
67d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic void cpp_new_handler() {
68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  // Return to try again. It won't fail a second time.
69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return;
70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
7295add82835138f09cf7bb4a51c04c6320c241674David Benjamin// should_fail_allocation returns true if the current allocation should fail.
7395add82835138f09cf7bb4a51c04c6320c241674David Benjaminstatic bool should_fail_allocation() {
7495add82835138f09cf7bb4a51c04c6320c241674David Benjamin  static bool init = false;
75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (in_call) {
7795add82835138f09cf7bb4a51c04c6320c241674David Benjamin    return false;
78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
8095add82835138f09cf7bb4a51c04c6320c241674David Benjamin  in_call = true;
81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!init) {
83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    const char *env = getenv("MALLOC_NUMBER_TO_FAIL");
84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (env != NULL && env[0] != 0) {
85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      char *endptr;
86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      malloc_number_to_fail = strtoull(env, &endptr, 10);
87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      if (*endptr == 0) {
8895add82835138f09cf7bb4a51c04c6320c241674David Benjamin        failure_enabled = true;
89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        atexit(exit_handler);
90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        std::set_new_handler(cpp_new_handler);
91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      }
92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
93b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    break_on_fail = (NULL != getenv("MALLOC_BREAK_ON_FAIL"));
9495add82835138f09cf7bb4a51c04c6320c241674David Benjamin    init = true;
95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
9795add82835138f09cf7bb4a51c04c6320c241674David Benjamin  in_call = false;
98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!failure_enabled) {
10095add82835138f09cf7bb4a51c04c6320c241674David Benjamin    return false;
101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
10395add82835138f09cf7bb4a51c04c6320c241674David Benjamin  bool should_fail = (current_malloc_count == malloc_number_to_fail);
104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  current_malloc_count++;
105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
106b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (should_fail && break_on_fail) {
107b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    raise(SIGTRAP);
108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return should_fail;
110d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
112d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyextern "C" {
113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
114d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid *malloc(size_t size) {
115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (should_fail_allocation()) {
116b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    errno = ENOMEM;
117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
12095add82835138f09cf7bb4a51c04c6320c241674David Benjamin  return __libc_malloc(size);
121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
123d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid *calloc(size_t num_elems, size_t size) {
124d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (should_fail_allocation()) {
125b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    errno = ENOMEM;
126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
127d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
128d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
12995add82835138f09cf7bb4a51c04c6320c241674David Benjamin  return __libc_calloc(num_elems, size);
130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
132d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid *realloc(void *ptr, size_t size) {
133d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (should_fail_allocation()) {
134b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    errno = ENOMEM;
135d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
136d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
137d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
13895add82835138f09cf7bb4a51c04c6320c241674David Benjamin  return __libc_realloc(ptr, size);
139d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
140d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
141d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}  // extern "C"
142d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
143f4e427204234da139fd0585def4b4e22502e33f0Adam Langley#endif  /* defined(linux) && GLIBC && !ARM && !AARCH64 && !ASAN */
144