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