Skip to content

Commit

Permalink
libsepol: use reallocarray wrapper to avoid overflows
Browse files Browse the repository at this point in the history
Use a wrapper to guard `realloc(p, a * b)` type allocations, to detect
multiplication overflows, which result in too few memory being
allocated.

Use a custom implementation if the used C library does not offer one.

Also use temporary variables for realloc(3) results in add_i_to_a() and
fp_to_buffer().

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
  • Loading branch information
cgzones authored and fishilico committed Nov 11, 2021
1 parent db0be56 commit 7ae1cca
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 23 deletions.
6 changes: 6 additions & 0 deletions libsepol/src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ LOBJS += $(sort $(patsubst %.c,%.lo,$(sort $(wildcard $(CILDIR)/src/*.c)) $(CIL_
override CFLAGS += -I$(CILDIR)/include
endif

# check for reallocarray(3) availability
H := \#
ifeq (yes,$(shell printf '${H}define _GNU_SOURCE\n${H}include <stdlib.h>\nint main(void){void*p=reallocarray(NULL, 1, sizeof(char));return 0;}' | $(CC) -x c -o /dev/null - >/dev/null 2>&1 && echo yes))
override CFLAGS += -DHAVE_REALLOCARRAY
endif

LD_SONAME_FLAGS=-soname,$(LIBSO),--version-script=$(LIBMAP),-z,defs

LN=ln
Expand Down
4 changes: 2 additions & 2 deletions libsepol/src/kernel_to_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ int strs_add(struct strs *strs, char *s)
char **new;
unsigned i = strs->size;
strs->size *= 2;
new = realloc(strs->list, sizeof(char *)*strs->size);
new = reallocarray(strs->list, strs->size, sizeof(char *));
if (!new) {
sepol_log_err("Out of memory");
return -1;
Expand Down Expand Up @@ -220,7 +220,7 @@ int strs_add_at_index(struct strs *strs, char *s, unsigned index)
while (index >= strs->size) {
strs->size *= 2;
}
new = realloc(strs->list, sizeof(char *)*strs->size);
new = reallocarray(strs->list, strs->size, sizeof(char *));
if (!new) {
sepol_log_err("Out of memory");
return -1;
Expand Down
9 changes: 5 additions & 4 deletions libsepol/src/module_to_cil.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ static int stack_push(struct stack *stack, void *ptr)
void *new_stack;

if (stack->pos + 1 == stack->size) {
new_stack = realloc(stack->stack, sizeof(*stack->stack) * (stack->size * 2));
new_stack = reallocarray(stack->stack, stack->size * 2, sizeof(*stack->stack));
if (new_stack == NULL) {
goto exit;
}
Expand Down Expand Up @@ -4148,7 +4148,7 @@ int sepol_module_package_to_cil(FILE *fp, struct sepol_module_package *mod_pkg)
static int fp_to_buffer(FILE *fp, char **data, size_t *data_len)
{
int rc = -1;
char *d = NULL;
char *d = NULL, *d_tmp;
size_t d_len = 0;
size_t read_len = 0;
size_t max_len = 1 << 17; // start at 128KB, this is enough to hold about half of all the existing pp files
Expand All @@ -4164,12 +4164,13 @@ static int fp_to_buffer(FILE *fp, char **data, size_t *data_len)
d_len += read_len;
if (d_len == max_len) {
max_len *= 2;
d = realloc(d, max_len);
if (d == NULL) {
d_tmp = realloc(d, max_len);
if (d_tmp == NULL) {
log_err("Out of memory");
rc = -1;
goto exit;
}
d = d_tmp;
}
}

Expand Down
5 changes: 3 additions & 2 deletions libsepol/src/optimize.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ static int type_vec_append(struct type_vec *v, uint32_t type)
{
if (v->capacity == v->count) {
unsigned int new_capacity = v->capacity * 2;
uint32_t *new_types = realloc(v->types,
new_capacity * sizeof(*v->types));
uint32_t *new_types = reallocarray(v->types,
new_capacity,
sizeof(*v->types));
if (!new_types)
return -1;

Expand Down
11 changes: 11 additions & 0 deletions libsepol/src/private.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,14 @@ static inline void* mallocarray(size_t nmemb, size_t size) {

return malloc(nmemb * size);
}

#ifndef HAVE_REALLOCARRAY
static inline void* reallocarray(void *ptr, size_t nmemb, size_t size) {
if (size && nmemb > (size_t)-1 / size) {
errno = ENOMEM;
return NULL;
}

return realloc(ptr, nmemb * size);
}
#endif
6 changes: 3 additions & 3 deletions libsepol/src/services.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ static void push(char *expr_ptr)
else
new_stack_len = stack_len * 2;

new_stack = realloc(stack, new_stack_len * sizeof(*stack));
new_stack = reallocarray(stack, new_stack_len, sizeof(*stack));
if (!new_stack) {
ERR(NULL, "unable to allocate stack space");
return;
Expand Down Expand Up @@ -449,8 +449,8 @@ static int constraint_expr_eval_reason(context_struct_t *scontext,
else
new_expr_list_len = expr_list_len * 2;

new_expr_list = realloc(expr_list,
new_expr_list_len * sizeof(*expr_list));
new_expr_list = reallocarray(expr_list,
new_expr_list_len, sizeof(*expr_list));
if (!new_expr_list) {
ERR(NULL, "failed to allocate expr buffer stack");
rc = -ENOMEM;
Expand Down
5 changes: 3 additions & 2 deletions libsepol/src/user_record.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,9 @@ int sepol_user_add_role(sepol_handle_t * handle,
if (!role_cp)
goto omem;

roles_realloc = realloc(user->roles,
sizeof(char *) * (user->num_roles + 1));
roles_realloc = reallocarray(user->roles,
user->num_roles + 1,
sizeof(char *));
if (!roles_realloc)
goto omem;

Expand Down
12 changes: 6 additions & 6 deletions libsepol/src/users.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,17 +226,17 @@ int sepol_user_modify(sepol_handle_t * handle,
void *tmp_ptr;

/* Ensure reverse lookup array has enough space */
tmp_ptr = realloc(policydb->user_val_to_struct,
(policydb->p_users.nprim +
1) * sizeof(user_datum_t *));
tmp_ptr = reallocarray(policydb->user_val_to_struct,
policydb->p_users.nprim + 1,
sizeof(user_datum_t *));
if (!tmp_ptr)
goto omem;
policydb->user_val_to_struct = tmp_ptr;
policydb->user_val_to_struct[policydb->p_users.nprim] = NULL;

tmp_ptr = realloc(policydb->sym_val_to_name[SYM_USERS],
(policydb->p_users.nprim +
1) * sizeof(char *));
tmp_ptr = reallocarray(policydb->sym_val_to_name[SYM_USERS],
policydb->p_users.nprim + 1,
sizeof(char *));
if (!tmp_ptr)
goto omem;
policydb->sym_val_to_name[SYM_USERS] = tmp_ptr;
Expand Down
11 changes: 7 additions & 4 deletions libsepol/src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ struct val_to_name {
* 0). Return 0 on success, -1 on out of memory. */
int add_i_to_a(uint32_t i, uint32_t * cnt, uint32_t ** a)
{
uint32_t *new;

if (cnt == NULL || a == NULL)
return -1;

Expand All @@ -48,17 +50,18 @@ int add_i_to_a(uint32_t i, uint32_t * cnt, uint32_t ** a)
* than be smart about it, for now we realloc() the array each
* time a new uint32_t is added! */
if (*a != NULL)
*a = (uint32_t *) realloc(*a, (*cnt + 1) * sizeof(uint32_t));
new = (uint32_t *) reallocarray(*a, *cnt + 1, sizeof(uint32_t));
else { /* empty list */

*cnt = 0;
*a = (uint32_t *) malloc(sizeof(uint32_t));
new = (uint32_t *) malloc(sizeof(uint32_t));
}
if (*a == NULL) {
if (new == NULL) {
return -1;
}
(*a)[*cnt] = i;
new[*cnt] = i;
(*cnt)++;
*a = new;
return 0;
}

Expand Down

0 comments on commit 7ae1cca

Please sign in to comment.