1 /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 #ifndef __LIBPERF_INTERNAL_RC_CHECK_H 3 #define __LIBPERF_INTERNAL_RC_CHECK_H 4 5 #include <stdlib.h> 6 #include <linux/zalloc.h> 7 8 /* 9 * Shared reference count checking macros. 10 * 11 * Reference count checking is an approach to sanitizing the use of reference 12 * counted structs. It leverages address and leak sanitizers to make sure gets 13 * are paired with a put. Reference count checking adds a malloc-ed layer of 14 * indirection on a get, and frees it on a put. A missed put will be reported as 15 * a memory leak. A double put will be reported as a double free. Accessing 16 * after a put will cause a use-after-free and/or a segfault. 17 */ 18 19 #ifndef REFCNT_CHECKING 20 /* Replaces "struct foo" so that the pointer may be interposed. */ 21 #define DECLARE_RC_STRUCT(struct_name) \ 22 struct struct_name 23 24 /* Declare a reference counted struct variable. */ 25 #define RC_STRUCT(struct_name) struct struct_name 26 27 /* 28 * Interpose the indirection. Result will hold the indirection and object is the 29 * reference counted struct. 30 */ 31 #define ADD_RC_CHK(result, object) (result = object, object) 32 33 /* Strip the indirection layer. */ 34 #define RC_CHK_ACCESS(object) object 35 36 /* Frees the object and the indirection layer. */ 37 #define RC_CHK_FREE(object) free(object) 38 39 /* A get operation adding the indirection layer. */ 40 #define RC_CHK_GET(result, object) ADD_RC_CHK(result, object) 41 42 /* A put operation removing the indirection layer. */ 43 #define RC_CHK_PUT(object) {} 44 45 #else 46 47 /* Replaces "struct foo" so that the pointer may be interposed. */ 48 #define DECLARE_RC_STRUCT(struct_name) \ 49 struct original_##struct_name; \ 50 struct struct_name { \ 51 struct original_##struct_name *orig; \ 52 }; \ 53 struct original_##struct_name 54 55 /* Declare a reference counted struct variable. */ 56 #define RC_STRUCT(struct_name) struct original_##struct_name 57 58 /* 59 * Interpose the indirection. Result will hold the indirection and object is the 60 * reference counted struct. 61 */ 62 #define ADD_RC_CHK(result, object) \ 63 ( \ 64 object ? (result = malloc(sizeof(*result)), \ 65 result ? (result->orig = object, result) \ 66 : (result = NULL, NULL)) \ 67 : (result = NULL, NULL) \ 68 ) 69 70 /* Strip the indirection layer. */ 71 #define RC_CHK_ACCESS(object) object->orig 72 73 /* Frees the object and the indirection layer. */ 74 #define RC_CHK_FREE(object) \ 75 do { \ 76 zfree(&object->orig); \ 77 free(object); \ 78 } while(0) 79 80 /* A get operation adding the indirection layer. */ 81 #define RC_CHK_GET(result, object) ADD_RC_CHK(result, (object ? object->orig : NULL)) 82 83 /* A put operation removing the indirection layer. */ 84 #define RC_CHK_PUT(object) \ 85 do { \ 86 if (object) { \ 87 object->orig = NULL; \ 88 free(object); \ 89 } \ 90 } while(0) 91 92 #endif 93 94 #endif /* __LIBPERF_INTERNAL_RC_CHECK_H */ 95