Bug Summary

File:conf.c
Location:line 270, column 8
Description:Dereference of null pointer (loaded from variable 'dst')

Annotated Source Code

1/*-
2 * Copyright (c) 2007 Aaron L. Meihm
3 * Copyright (c) 2007 Christian S.J. Peron
4 * All rights reserved.
5 *
6 * $Id: conf.c,v 1.15 2007/04/13 14:45:12 csjp Exp $
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30#include "includes.h"
31
32static const struct _settype_tab {
33 char *stt_str;
34 int stt_val;
35} settype_tab[] = {
36 { "auditclass", SET_TYPE_AUCLASS },
37 { "auditevent", SET_TYPE_AUEVENT },
38 { "auid", SET_TYPE_AUID },
39 { "egid", SET_TYPE_EGID },
40 { "euid", SET_TYPE_EUID },
41 { "path", SET_TYPE_PATH },
42#ifdef PCRE
43 { "pcre", SET_TYPE_PCRE },
44#endif
45 { "rgid", SET_TYPE_RGID },
46 { "ruid", SET_TYPE_RUID },
47 { "logchannel", SET_TYPE_LOGCHANNEL },
48 { NULL((void *)0), 0 }
49};
50
51extern FILE *yyin;
52extern char *yytext;
53extern int yyparse(void);
54bsm_set_head_t bsm_set_head;
55int lineno = 1;
56char *conffile;
57
58/*
59 * Return BSM set named str, or NULL if the set was not found in the BSM set
60 * queue.
61 */
62struct bsm_set *
63conf_get_bsm_set(char *str)
64{
65 struct bsm_set *ptr;
66
67 TAILQ_FOREACH(ptr, &bsm_set_head, bss_glue)for ((ptr) = (((&bsm_set_head))->tqh_first); (ptr); (ptr
) = (((ptr))->bss_glue.tqe_next))
{
68 if (strcmp(str, ptr->bss_name) == 0)
69 return (ptr);
70 }
71 return (NULL((void *)0));
72}
73
74/*
75 * Return sequence with name str from parent queue, or NULL if sequence is not
76 * found.
77 */
78struct bsm_sequence *
79conf_get_parent_sequence(char *str)
80{
81
82 return (NULL((void *)0));
83}
84
85/*
86 * Load configuration file from path.
87 */
88void
89conf_load(char *path)
90{
91 FILE *f;
92
93 f = fopen(path, "r");
94 if (f == NULL((void *)0))
95 bsmtrace_error(1, "%s: %s", path, strerror(errno(* __error())));
96 conffile = path;
97 yyin = f;
98 TAILQ_INIT(&bsm_set_head)do { (((&bsm_set_head))->tqh_first) = ((void *)0); (&
bsm_set_head)->tqh_last = &(((&bsm_set_head))->
tqh_first);; } while (0)
;
99 yyparse();
100 (void) fclose(f);
101}
102
103/*
104 * Configuration file error reporting, non-zero ln overrides lineno.
105 */
106void
107conf_detail(int ln, const char *fmt, ...)
108{
109 char buf[1024];
110 va_list ap;
111
112 if (ln == 0)
113 ln = lineno;
114 va_start(ap, fmt)__builtin_va_start(ap, fmt);
115 (void) vsnprintf(buf, sizeof(buf), fmt, ap);
116 va_end(ap)__builtin_va_end(ap);
117 bsmtrace_error(1, "%s:%d: %s", conffile, ln, buf);
118}
119
120/*
121 * Add value str to array a. We verify the value str points at is suitable for
122 * an insertion into an array of type.
123 */
124void
125conf_array_add(const char *str, struct array *a, int type)
126{
127 int e, value;
128 char *ptr, *r, *estring;
129 struct au_event_ent *aue;
130 struct au_class_ent *auc;
131 struct passwd *pwd;
132 struct group *gr;
133#ifdef PCRE
134 const char *error;
135 int erroffset;
136 pcre *re;
137#endif
138
139 e = 0;
140 switch (type) {
141 case SET_TYPE_AUCLASS:
142 auc = getauclassnam(str);
143 if (auc == NULL((void *)0)) {
144 estring = "audit class";
145 e++;
146 break;
147 }
148 value = auc->ac_class;
149 break;
150 case SET_TYPE_AUEVENT:
151 aue = getauevnam(str);
152 if (aue == NULL((void *)0)) {
153 estring = "audit event";
154 e++;
155 break;
156 }
157 value = aue->ae_number;
158 break;
159 case SET_TYPE_AUID:
160 case SET_TYPE_EUID:
161 case SET_TYPE_RUID:
162 pwd = getpwnam(str);
163 endpwent();
164 if (pwd == NULL((void *)0)) {
165 estring = "user";
166 e++;
167 break;
168 }
169 value = pwd->pw_uid;
170 break;
171 case SET_TYPE_EGID:
172 case SET_TYPE_RGID:
173 gr = getgrnam(str);
174 endgrent();
175 if (gr == NULL((void *)0)) {
176 estring = "group";
177 e++;
178 break;
179 }
180 value = gr->gr_gid;
181 break;
182#ifdef PCRE
183 case SET_TYPE_PCRE:
184 re = pcre_compile(str, 0, &error, &erroffset, NULL((void *)0));
185 if (error != 0)
186 bsmtrace_error(1, "%s: pcre_compile failed", __func__);
187 break;
188#endif
189 case SET_TYPE_PATH:
190 case SET_TYPE_LOGCHANNEL:
191 ptr = strdup(str);
192 if (ptr == NULL((void *)0))
193 bsmtrace_error(1, "%s: strdup failed", __func__);
194 break;
195 }
196 if (e != 0) {
197 value = strtoul(str, &r, 10);
198 /* XXX look for overflows */
199 if (*r != '\0')
200 conf_detail(0, "%s: invalid %s name\n", str, estring);
201 }
202 if (type == SET_TYPE_PATH || type == SET_TYPE_LOGCHANNEL) {
203 a->a_data.string[a->a_cnt++] = ptr;
204 a->a_type = STRING_ARRAY2;
205#ifdef PCRE
206 } else if (type == SET_TYPE_PCRE) {
207 a->a_data.pcre[a->a_cnt++] = re;
208 a->a_type = PCRE_ARRAY;
209#endif
210 } else {
211 a->a_data.value[a->a_cnt++] = value;
212 a->a_type = INTEGER_ARRAY1;
213 }
214}
215
216/*
217 * Set subject for parent sequence seq to subj.
218 */
219void
220conf_sequence_set_subj(struct bsm_sequence *seq, struct bsm_set *subj,
221 int negate)
222{
223 struct array *src, *dst;
224
225 /*
226 * Make sure the passed subj actually contains subject information.
227 */
228 if (subj->bss_type != SET_TYPE_AUID &&
229 subj->bss_type != SET_TYPE_RUID &&
230 subj->bss_type != SET_TYPE_EUID &&
231 subj->bss_type != SET_TYPE_RGID &&
232 subj->bss_type != SET_TYPE_EGID)
233 conf_detail(0, "supplied set does not contain subjects\n");
234 src = &subj->bss_data;
235 dst = &seq->bs_subj.bs_par_subj;
236 *dst = *src;
237 seq->bs_subj.bs_par_subj.a_negated = negate;
238 seq->bs_subj_type = subj->bss_type;
239}
240
241/*
242 * Return set type token from string str.
243 */
244int
245conf_set_type(char *str)
246{
247 const struct _settype_tab *setptr;
248
249 for (setptr = settype_tab; setptr->stt_str != NULL((void *)0); setptr++) {
250 if (strcmp(setptr->stt_str, str) == 0)
251 return (setptr->stt_val);
252 }
253 return (-1);
254}
255
256void
257conf_handle_multiplier(struct bsm_sequence *bs, struct bsm_state *bm)
258{
259 struct bsm_state *vec, *dst;
260 int i;
261
262 assert(bm != NULL)((bm != ((void *)0)) ? (void)0 : __assert(__func__, "conf.c",
262, "bm != NULL"))
;
263 if (bm->bm_multiplier == 0)
1
Taking false branch
264 bm->bm_multiplier = 1;
265 vec = calloc(bm->bm_multiplier, sizeof(*bm));
266 if (vec == NULL((void *)0))
2
Assuming 'vec' is equal to null
3
Taking true branch
267 bsmtrace_error(1, "%s: calloc failed", __func__);
268 for (i = 0; i < bm->bm_multiplier; i++) {
4
Loop condition is true. Entering loop body
269 dst = &vec[i];
5
Null pointer value stored to 'dst'
270 *dst = *bm;
6
Dereference of null pointer (loaded from variable 'dst')
271 TAILQ_INSERT_TAIL(&bs->bs_mhead, dst, bm_glue)do {; (((dst))->bm_glue.tqe_next) = ((void *)0); (dst)->
bm_glue.tqe_prev = (&bs->bs_mhead)->tqh_last; *(&
bs->bs_mhead)->tqh_last = (dst); (&bs->bs_mhead)
->tqh_last = &(((dst))->bm_glue.tqe_next);;; } while
(0)
;
272 }
273}
274
275void
276yyerror(const char *str)
277{
278
279 conf_detail(0, "syntax error near '%s'", yytext);
280}
281
282int
283yywrap()
284{
285
286 return (1);
287}
288
289void
290conf_set_log_channel(struct bsm_set *bss, struct bsm_sequence *bs)
291{
292 struct array *a;
293 int i;
294 struct logchannel *lc;
295
296 a = &bss->bss_data;
297 for (i = 0; i < a->a_cnt; i++) {
298 lc = log_lookup_channel(a->a_data.string[i]);
299 if (lc == NULL((void *)0))
300 conf_detail(0, "unable to lookup channel");
301 TAILQ_INSERT_HEAD(&bs->bs_log_channel, lc, log_glue)do {; if (((((lc))->log_glue.tqe_next) = (((&bs->bs_log_channel
))->tqh_first)) != ((void *)0)) (((&bs->bs_log_channel
))->tqh_first)->log_glue.tqe_prev = &(((lc))->log_glue
.tqe_next); else (&bs->bs_log_channel)->tqh_last = &
(((lc))->log_glue.tqe_next); (((&bs->bs_log_channel
))->tqh_first) = (lc); (lc)->log_glue.tqe_prev = &(
((&bs->bs_log_channel))->tqh_first);;; } while (0)
;
302 }
303}
304
305int
306conf_return_scope(char *scopestr)
307{
308
309 if (strcmp(scopestr, "global") == 0)
310 return (BSM_SCOPE_GLOBAL);
311 else if (strcmp(scopestr, "process") == 0)
312 return (BSM_SCOPE_PROCESS);
313 else if (strcmp(scopestr, "session") == 0)
314 return (BSM_SCOPE_SESSION);
315 else if (strcmp(scopestr, "thread") == 0)
316 return (BSM_SCOPE_THREAD);
317 return (-1);
318}