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