Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sudo-project
GitHub Repository: sudo-project/sudo
Path: blob/main/plugins/sudoers/gc.c
1532 views
1
/*
2
* SPDX-License-Identifier: ISC
3
*
4
* Copyright (c) 2016 Todd C. Miller <[email protected]>
5
*
6
* Permission to use, copy, modify, and distribute this software for any
7
* purpose with or without fee is hereby granted, provided that the above
8
* copyright notice and this permission notice appear in all copies.
9
*
10
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
*/
18
19
#include <config.h>
20
21
#include <stdlib.h>
22
#include <string.h>
23
24
#include <sudoers.h>
25
26
struct sudoers_gc_entry {
27
SLIST_ENTRY(sudoers_gc_entry) entries;
28
enum sudoers_gc_types type;
29
union {
30
char **vec;
31
void *ptr;
32
} u;
33
};
34
SLIST_HEAD(sudoers_gc_list, sudoers_gc_entry);
35
#ifdef NO_LEAKS
36
static struct sudoers_gc_list sudoers_gc_list =
37
SLIST_HEAD_INITIALIZER(sudoers_gc_list);
38
#endif
39
40
bool
41
sudoers_gc_add(enum sudoers_gc_types type, void *v)
42
{
43
#ifdef NO_LEAKS
44
struct sudoers_gc_entry *gc;
45
debug_decl(sudoers_gc_add, SUDOERS_DEBUG_UTIL);
46
47
if (v == NULL)
48
debug_return_bool(false);
49
50
gc = calloc(1, sizeof(*gc));
51
if (gc == NULL) {
52
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
53
debug_return_bool(false);
54
}
55
switch (type) {
56
case GC_PTR:
57
gc->u.ptr = v;
58
break;
59
case GC_VECTOR:
60
gc->u.vec = v;
61
break;
62
default:
63
free(gc);
64
sudo_warnx("unexpected garbage type %d", type);
65
debug_return_bool(false);
66
}
67
gc->type = type;
68
SLIST_INSERT_HEAD(&sudoers_gc_list, gc, entries);
69
debug_return_bool(true);
70
#else
71
return true;
72
#endif /* NO_LEAKS */
73
}
74
75
bool
76
sudoers_gc_remove(enum sudoers_gc_types type, void *v)
77
{
78
#ifdef NO_LEAKS
79
struct sudoers_gc_entry *gc, *prev = NULL;
80
debug_decl(sudoers_gc_remove, SUDOERS_DEBUG_UTIL);
81
82
if (v == NULL)
83
debug_return_bool(false);
84
85
SLIST_FOREACH(gc, &sudoers_gc_list, entries) {
86
switch (gc->type) {
87
case GC_PTR:
88
if (gc->u.ptr == v)
89
goto found;
90
break;
91
case GC_VECTOR:
92
if (gc->u.vec == v)
93
goto found;
94
break;
95
default:
96
sudo_warnx("unexpected garbage type %d in %p", gc->type, gc);
97
}
98
prev = gc;
99
}
100
/* If this happens, there is a bug in the g/c code. */
101
sudo_warnx("%s: unable to find %p, type %d", __func__, v, type);
102
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
103
abort();
104
#else
105
debug_return_bool(false);
106
#endif
107
found:
108
if (prev == NULL)
109
SLIST_REMOVE_HEAD(&sudoers_gc_list, entries);
110
else
111
SLIST_REMOVE_AFTER(prev, entries);
112
free(gc);
113
114
debug_return_bool(true);
115
#else
116
return true;
117
#endif /* NO_LEAKS */
118
}
119
120
void
121
sudoers_gc_run(void)
122
{
123
#ifdef NO_LEAKS
124
struct sudoers_gc_entry *gc;
125
char **cur;
126
debug_decl(sudoers_gc_run, SUDOERS_DEBUG_UTIL);
127
128
/* Collect garbage. */
129
while ((gc = SLIST_FIRST(&sudoers_gc_list)) != NULL) {
130
SLIST_REMOVE_HEAD(&sudoers_gc_list, entries);
131
switch (gc->type) {
132
case GC_PTR:
133
free(gc->u.ptr);
134
free(gc);
135
break;
136
case GC_VECTOR:
137
for (cur = gc->u.vec; *cur != NULL; cur++)
138
free(*cur);
139
free(gc->u.vec);
140
free(gc);
141
break;
142
default:
143
sudo_warnx("unexpected garbage type %d", gc->type);
144
}
145
}
146
147
debug_return;
148
#endif /* NO_LEAKS */
149
}
150
151