Skip to content

Commit 51e8983

Browse files
committed
Fix release static analysis findings
safe_exec under-allocated argv by not reserving a slot for execve's terminating NULL, and several call sites omitted the required NULL sentinel, letting the varargs reader run past the provided arguments. The argv array now has a terminator slot and every safe_exec call passes an explicit sentinel. GSS ACK handling in auditd-listen allocated utok.value and copied into it without checking for allocation failure. The GSS path now logs and drops the ACK on ENOMEM before touching the buffer. auparse file source setup allocated source_list entries without checking the list or filename strdup allocations, leaving partial lists on failure. The setup now calloc's NULL-terminated lists, frees partial lists through a shared helper, and reuses that helper during destroy and init failure cleanup. audisp-remote's GSS connection setup left the connected socket open if credential negotiation failed after connect. The failure path now calls stop_sock() before returning the permanent error so the socket and GSS/KRB state are torn down consistently. The IDS session model treated the account string as transferred to new_session even though new_session could fail before taking ownership, and it could duplicate a NULL interpreted field. The caller now only duplicates non-NULL fields and always frees its local copy, while new_session makes its own stored copy and frees it if insertion fails.
1 parent 13ac2de commit 51e8983

6 files changed

Lines changed: 90 additions & 39 deletions

File tree

audisp/plugins/ids/model_bad_event.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,16 @@ static void start_session(auparse_state_t *au, struct ids_conf *config)
4444
a = -1;
4545

4646
int service_acct = 0;
47-
const char *acct = NULL;
47+
char *acct = NULL;
4848
const char *atype = auparse_normalize_subject_kind(au);
4949
if (atype && strncmp(atype, "service", 7) == 0)
5050
service_acct = 1;
51-
if (auparse_normalize_subject_primary(au) == 1)
52-
acct = strdup(auparse_interpret_field(au));
51+
if (auparse_normalize_subject_primary(au) == 1) {
52+
const char *field = auparse_interpret_field(au);
53+
54+
if (field)
55+
acct = strdup(field);
56+
}
5357

5458
// Have we seen this endpoint before?
5559
origin_data_t *o = find_origin(a);
@@ -60,7 +64,8 @@ static void start_session(auparse_state_t *au, struct ids_conf *config)
6064

6165
// Is this login a service account?
6266
if (service_acct && !config->option_service_login_allowed) {
63-
my_printf("bad_service_login_origin: %s", acct);
67+
my_printf("bad_service_login_origin: %s",
68+
acct ? acct : "?");
6469
bad_service_login_origin(o, config, acct);
6570
}
6671

@@ -88,15 +93,14 @@ static void start_session(auparse_state_t *au, struct ids_conf *config)
8893
if (auparse_normalize_session(au) == 1) {
8994
unsigned int s = auparse_get_field_int(au);
9095
if (s != UNSET) {
91-
// new_session takes custody of acct
96+
// new_session copies acct before storing it.
9297
new_session(s, a, acct);
93-
acct = NULL;
9498
// otherwise we have a strange daemon login
9599
} else if (debug)
96100
my_printf("start_session: can't find session in serial %s",
97101
auparse_get_type_name(au));
98102
}
99-
free((void *)acct);
103+
free(acct);
100104
}
101105

102106
static void end_session(auparse_state_t *au)
@@ -110,6 +114,7 @@ static void end_session(auparse_state_t *au)
110114
}
111115
}
112116

117+
113118
/* This function receives a single complete event from the auparse library. */
114119
void process_bad_event_model(auparse_state_t *au,
115120
struct ids_conf *config)
@@ -165,4 +170,3 @@ void process_bad_event_model(auparse_state_t *au,
165170
}
166171
}
167172
}
168-

audisp/plugins/ids/reactions.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,15 @@ static int safe_exec(const char *exe, ...)
9292
va_start(ap, exe);
9393
for (i = 1; va_arg(ap, char *) != NULL; i++);
9494
va_end(ap);
95-
argv = alloca(i * sizeof(char *));
95+
argv = alloca((i + 1) * sizeof(char *));
9696

9797
va_start(ap, exe);
9898
argv[0] = (char *) exe;
9999
for (i = 1; (argv[i] = (char *) va_arg(ap, char *)) != NULL; i++);
100100
va_end(ap);
101-
argv[i] = NULL;
102101

103102
execve(exe, argv, NULL);
104-
syslog(LOG_ALERT, "Audit IDS failed to exec %s", exe);
103+
syslog(LOG_ALERT, "Audit IDS failed to exec %s", exe);
105104
exit(1);
106105
}
107106

@@ -205,36 +204,36 @@ int restricted_role(const char *acct)
205204

206205
// Restrict to guest user
207206
rc = safe_exec("/usr/sbin/semanage", "login", "-m", "-s",
208-
"guest_u", acct);
207+
"guest_u", acct, NULL);
209208
if (rc)
210209
return rc;
211210

212211
// Need to force a logout of all sessions for the user
213-
return safe_exec("/usr/bin/killall", "--user", acct);
212+
return safe_exec("/usr/bin/killall", "--user", acct, NULL);
214213
}
215214

216215
int force_password_reset(const char *acct)
217216
{
218217
if (verify_acct(acct))
219218
return 1;
220219

221-
return safe_exec("/usr/bin/chage", "-d", "0", acct);
220+
return safe_exec("/usr/bin/chage", "-d", "0", acct, NULL);
222221
}
223222

224223
int lock_account(const char *acct)
225224
{
226225
if (verify_acct(acct))
227226
return 1;
228227

229-
return safe_exec("/usr/bin/passwd", "-l", acct);
228+
return safe_exec("/usr/bin/passwd", "-l", acct, NULL);
230229
}
231230

232231
int unlock_account(const char *acct)
233232
{
234233
if (verify_acct(acct))
235234
return 1;
236235

237-
return safe_exec("/usr/bin/passwd", "-u", acct);
236+
return safe_exec("/usr/bin/passwd", "-u", acct, NULL);
238237
}
239238

240239
int lock_account_timed(const char *acct, unsigned long length)
@@ -327,17 +326,17 @@ int unblock_ip_address(const char *addr)
327326

328327
int system_reboot(void)
329328
{
330-
return safe_exec("/sbin/init", "6");
329+
return safe_exec("/sbin/init", "6", NULL);
331330
}
332331

333332
int system_single_user(void)
334333
{
335-
return safe_exec("/sbin/init", "1");
334+
return safe_exec("/sbin/init", "1", NULL);
336335
}
337336

338337
int system_halt(void)
339338
{
340-
return safe_exec("/sbin/init", "0");
339+
return safe_exec("/sbin/init", "0", NULL);
341340
}
342341

343342
/*

audisp/plugins/ids/session.c

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,17 +85,36 @@ static void destroy_session(void)
8585
cur = NULL;
8686
}
8787

88+
/*
89+
* new_session - create a session
90+
* Args:
91+
* s - session id
92+
* o - origin address
93+
* acct - account string to copy into the session
94+
* Rtns:
95+
* void
96+
*/
8897
void new_session(unsigned int s, unsigned int o, const char *acct)
8998
{
9099
session_data_t *tmp = malloc(sizeof(session_data_t));
91-
if (tmp) {
92-
tmp->session = s;
93-
tmp->score = 0;
94-
tmp->killed = 0;
95-
tmp->origin = o;
96-
tmp->acct = acct ? acct : strdup("");
97-
add_session(tmp);
100+
101+
if (tmp == NULL)
102+
return;
103+
104+
tmp->acct = acct ? strdup(acct) : strdup("");
105+
if (tmp->acct == NULL) {
106+
free(tmp);
107+
return;
98108
}
109+
110+
tmp->session = s;
111+
tmp->score = 0;
112+
tmp->killed = 0;
113+
tmp->origin = o;
114+
if (add_session(tmp))
115+
return;
116+
117+
free_session(tmp);
99118
}
100119

101120
void destroy_sessions(void)
@@ -194,4 +213,3 @@ void add_to_score_session(session_data_t *s, unsigned int adj)
194213
if (debug)
195214
my_printf("session score: %u", s->score);
196215
}
197-

audisp/plugins/remote/audisp-remote.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2074,6 +2074,7 @@ static int init_sock(void)
20742074
#ifdef USE_GSSAPI
20752075
if (USE_GSS) {
20762076
if (negotiate_credentials()) {
2077+
stop_sock();
20772078
rc = ET_PERMANENT;
20782079
goto out;
20792080
}

auparse/auparse.c

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,25 @@ static int access_ok(const char *filename)
7373
#endif
7474
}
7575

76+
/*
77+
* free_source_list - release a NULL-terminated source file list
78+
* Args:
79+
* list - array of allocated file names
80+
* Rtns:
81+
* void
82+
*/
83+
static void free_source_list(char **list)
84+
{
85+
int n = 0;
86+
87+
if (list == NULL)
88+
return;
89+
90+
while (list[n])
91+
free(list[n++]);
92+
free(list);
93+
}
94+
7695
static int setup_log_file_array(auparse_state_t *au)
7796
{
7897
struct daemon_conf config;
@@ -490,11 +509,14 @@ auparse_state_t *auparse_init(ausource_t source, const void *b)
490509
goto bad_exit;
491510
if (access_ok(b))
492511
goto bad_exit;
493-
tmp = malloc(2*sizeof(char *));
512+
tmp = calloc(2, sizeof(char *));
494513
if (tmp == NULL)
495514
goto bad_exit;
496515
tmp[0] = strdup(b);
497-
tmp[1] = NULL;
516+
if (tmp[0] == NULL) {
517+
free_source_list(tmp);
518+
goto bad_exit;
519+
}
498520
au->source_list = tmp;
499521
break;
500522
case AUSOURCE_FILE_ARRAY:
@@ -506,10 +528,16 @@ auparse_state_t *auparse_init(ausource_t source, const void *b)
506528
goto bad_exit;
507529
n++;
508530
}
509-
tmp = malloc((n+1)*sizeof(char *));
510-
for (i=0; i<n; i++)
531+
tmp = calloc(n+1, sizeof(char *));
532+
if (tmp == NULL)
533+
goto bad_exit;
534+
for (i=0; i<n; i++) {
511535
tmp[i] = strdup(bb[i]);
512-
tmp[n] = NULL;
536+
if (tmp[i] == NULL) {
537+
free_source_list(tmp);
538+
goto bad_exit;
539+
}
540+
}
513541
au->source_list = tmp;
514542
break;
515543
case AUSOURCE_BUFFER:
@@ -578,6 +606,7 @@ auparse_state_t *auparse_init(ausource_t source, const void *b)
578606

579607
return au;
580608
bad_exit:
609+
free_source_list(au->source_list);
581610
databuf_free(&au->databuf);
582611
/* Free list of events list (au_lo) structure */
583612
au_lol_clear(au->au_lo, 0);
@@ -1103,13 +1132,8 @@ static void auparse_destroy_common(auparse_state_t *au)
11031132
if (au == NULL)
11041133
return;
11051134

1106-
if (au->source_list) {
1107-
int n = 0;
1108-
while (au->source_list[n])
1109-
free(au->source_list[n++]);
1110-
free(au->source_list);
1111-
au->source_list = NULL;
1112-
}
1135+
free_source_list(au->source_list);
1136+
au->source_list = NULL;
11131137

11141138
au->next_buf = NULL;
11151139
free(au->cur_buf);

src/auditd-listen.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,11 @@ static void client_ack(void *ack_data, const unsigned char *header,
10831083
mlen = strlen(msg);
10841084
utok.length = AUDIT_RMW_HEADER_SIZE + mlen;
10851085
utok.value = malloc(utok.length + 1);
1086+
if (utok.value == NULL) {
1087+
audit_msg(LOG_ERR, "GSS-API ACK to %s lost: "
1088+
"out of memory", sockaddr_to_addr(&io->addr));
1089+
return;
1090+
}
10861091

10871092
memcpy(utok.value, header, AUDIT_RMW_HEADER_SIZE);
10881093
memcpy(utok.value+AUDIT_RMW_HEADER_SIZE, msg, mlen);

0 commit comments

Comments
 (0)