xref: /linux/tools/lib/perf/include/internal/rc_check.h (revision de047c1091854f0c0561f3d199c2ea2e344f10a5)
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