Skip to content

Commit bfc585c

Browse files
committed
fix freebsd sysctl segfault
1 parent 56232e8 commit bfc585c

1 file changed

Lines changed: 44 additions & 10 deletions

File tree

src/OVAL/probes/unix/sysctl_probe.c

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,25 @@
4141
#include <stdlib.h>
4242
#include <limits.h>
4343
#include <string.h>
44+
#include <sys/types.h>
4445

4546
#include "common/debug_priv.h"
4647

4748
#define SYSCTL_CMD "/sbin/sysctl -ae"
49+
#define SYSCTL_VALUE_MAX (64 * 1024)
4850
#elif defined(OS_APPLE)
4951
#include <ctype.h>
5052
#include <stdio.h>
5153
#include <stdlib.h>
5254
#include <limits.h>
5355
#include <string.h>
56+
#include <sys/types.h>
5457

5558
#include "common/debug_priv.h"
5659

5760
/* On macOS sysctl(8) lives under /usr/sbin */
5861
#define SYSCTL_CMD "/usr/sbin/sysctl -ae"
62+
#define SYSCTL_VALUE_MAX (64 * 1024)
5963
#endif
6064

6165
#if defined(OS_LINUX)
@@ -349,13 +353,25 @@ static int sysctl_parse_line(char *line, char **mib, char **sysval)
349353
return 1;
350354
}
351355

352-
static int sysctl_append_value(char **value, size_t *value_len, const char *line)
356+
static int sysctl_append_value(char **value, size_t *value_len, const char *line, int *truncated)
353357
{
354-
size_t line_len, new_len;
358+
size_t line_len, append_len, new_len;
355359
char *new_value;
356360

361+
if (*truncated)
362+
return 0;
363+
357364
line_len = strlen(line);
358-
new_len = *value_len + line_len + (*value_len > 0 ? 1 : 0) + 1;
365+
if (*value_len >= SYSCTL_VALUE_MAX) {
366+
*truncated = 1;
367+
return 0;
368+
}
369+
370+
append_len = line_len;
371+
if (*value_len + append_len > SYSCTL_VALUE_MAX)
372+
append_len = SYSCTL_VALUE_MAX - *value_len;
373+
374+
new_len = *value_len + append_len + (*value_len > 0 ? 1 : 0) + 1;
359375
new_value = realloc(*value, new_len);
360376
if (new_value == NULL)
361377
return -1;
@@ -364,8 +380,13 @@ static int sysctl_append_value(char **value, size_t *value_len, const char *line
364380
if (*value_len > 0)
365381
new_value[(*value_len)++] = '\n';
366382

367-
memcpy(new_value + *value_len, line, line_len + 1);
368-
*value_len += line_len;
383+
memcpy(new_value + *value_len, line, append_len);
384+
*value_len += append_len;
385+
new_value[*value_len] = '\0';
386+
387+
if (append_len < line_len)
388+
*truncated = 1;
389+
369390
return 0;
370391
}
371392

@@ -526,14 +547,17 @@ int sysctl_probe_offline_mode_supported(void)
526547
int sysctl_probe_main(probe_ctx *ctx, void *probe_arg)
527548
{
528549
FILE *fp;
529-
char output[LINE_MAX];
550+
char *output = NULL;
551+
size_t output_cap = 0;
552+
ssize_t output_len;
530553
SEXP_t *name_entity, *probe_in;
531554
oval_schema_version_t over;
532555
int over_cmp;
533556
int ret = 0;
534557
char *current_mib = NULL;
535558
char *current_value = NULL;
536559
size_t current_value_len = 0;
560+
int current_value_truncated = 0;
537561

538562
probe_in = probe_ctx_getobject(ctx);
539563
name_entity = probe_obj_getent(probe_in, "name", 1);
@@ -558,7 +582,7 @@ int sysctl_probe_main(probe_ctx *ctx, void *probe_arg)
558582
return (PROBE_EFATAL);
559583
}
560584

561-
while (fgets(output, sizeof(output), fp)) {
585+
while ((output_len = getline(&output, &output_cap, fp)) != -1) {
562586
char *mib, *sysval, *newline;
563587

564588
newline = strchr(output, '\n');
@@ -579,37 +603,47 @@ int sysctl_probe_main(probe_ctx *ctx, void *probe_arg)
579603
current_mib = strdup(mib);
580604
current_value = NULL;
581605
current_value_len = 0;
606+
current_value_truncated = 0;
582607
if (current_mib == NULL) {
583608
dE("Failed to allocate new sysctl name buffer");
584609
ret = PROBE_ENOENT;
585610
goto cleanup;
586611
}
587612

588-
if (sysctl_append_value(&current_value, &current_value_len, sysval) != 0) {
613+
if (sysctl_append_value(&current_value, &current_value_len, sysval,
614+
&current_value_truncated) != 0) {
589615
dE("Failed to append sysctl value");
590616
ret = PROBE_ENOENT;
591617
goto cleanup;
592618
}
593619

620+
if (current_value_truncated)
621+
dD("Truncated sysctl value for %s to %d bytes", current_mib, SYSCTL_VALUE_MAX);
622+
594623
continue;
595624
}
596625

597626
if (current_mib == NULL)
598627
continue;
599628

600-
if (sysctl_append_value(&current_value, &current_value_len, output) != 0) {
629+
if (sysctl_append_value(&current_value, &current_value_len, output,
630+
&current_value_truncated) != 0) {
601631
dE("Failed to append sysctl continuation value");
602632
ret = PROBE_ENOENT;
603633
goto cleanup;
604634
}
605-
}
635+
636+
if (current_value_truncated)
637+
dD("Truncated sysctl value for %s to %d bytes", current_mib, SYSCTL_VALUE_MAX);
638+
}
606639

607640
if (current_mib != NULL)
608641
ret = sysctl_collect_item(ctx, name_entity, current_mib,
609642
current_value != NULL ? current_value : "",
610643
over_cmp);
611644

612645
cleanup:
646+
free(output);
613647
free(current_mib);
614648
free(current_value);
615649
pclose(fp);

0 commit comments

Comments
 (0)