=== modified file 'TODO' --- TODO 2020-02-08 14:01:38 +0000 +++ TODO 2020-02-09 03:38:33 +0000 @@ -14,7 +14,6 @@ ** TODO [#C] Make start_mandos_communication() take "struct server". ** TODO [#C] --interfaces=regex,eth*,noregex (bridge-utils-interfaces(5)) ** TODO [#A] Detect partial writes to stdout and exit with EX_TEMPFAIL -** TODO [#B] Use reallocarray() with GNU LibC 2.29 or later. * splashy ** TODO [#B] use scandir(3) instead of readdir(3) @@ -34,7 +33,6 @@ * plymouth ** TODO [#A] Detect partial writes to stdout and exit with EX_TEMPFAIL -** TODO [#B] Use reallocarray() with GNU LibC 2.29 or later. * TODO [#B] passdev === modified file 'dracut-module/password-agent.c' --- dracut-module/password-agent.c 2020-02-01 22:02:09 +0000 +++ dracut-module/password-agent.c 2020-02-09 03:38:33 +0000 @@ -49,7 +49,7 @@ #include /* EX_USAGE, EX_OSERR, EX_OSFILE */ #include /* errno, error_t, EACCES, ENAMETOOLONG, ENOENT, ENOTDIR, - EEXIST, ECHILD, EPERM, ENOMEM, + ENOMEM, EEXIST, ECHILD, EPERM, EAGAIN, EINTR, ENOBUFS, EADDRINUSE, ECONNREFUSED, ECONNRESET, ETOOMANYREFS, EMSGSIZE, EBADF, @@ -73,6 +73,7 @@ ARGP_ERR_UNKNOWN, ARGP_KEY_ARGS, struct argp, argp_parse(), ARGP_NO_EXIT */ +#include /* SIZE_MAX */ #include /* uid_t, gid_t, close(), pipe2(), fork(), _exit(), dup2(), STDOUT_FILENO, setresgid(), @@ -95,11 +96,10 @@ IN_EXCL_UNLINK, IN_ONLYDIR, struct inotify_event */ #include /* fnmatch(), FNM_FILE_NAME */ -#include /* asprintf(), FILE, fopen(), - getline(), sscanf(), feof(), - ferror(), fclose(), stderr, - rename(), fdopen(), fprintf(), - fscanf() */ +#include /* asprintf(), FILE, stderr, fopen(), + fclose(), getline(), sscanf(), + feof(), ferror(), rename(), + fdopen(), fprintf(), fscanf() */ #include /* GKeyFile, g_key_file_free(), g_key_file_new(), GError, g_key_file_load_from_file(), G_KEY_FILE_NONE, TRUE, G_FILE_ERROR_NOENT, @@ -651,6 +651,13 @@ __attribute__((nonnull, warn_unused_result)) bool add_to_queue(task_queue *const queue, const task_context task){ + if((queue->length + 1) > (SIZE_MAX / sizeof(task_context))){ + /* overflow */ + error(0, ENOMEM, "Failed to allocate %" PRIuMAX + " tasks for queue->tasks", (uintmax_t)(queue->length + 1)); + errno = ENOMEM; + return false; + } const size_t needed_size = sizeof(task_context)*(queue->length + 1); if(needed_size > (queue->allocated)){ task_context *const new_tasks = realloc(queue->tasks, @@ -1884,6 +1891,29 @@ g_assert_true(queue->tasks[0].func == dummy_func); } +static void test_add_to_queue_overflow(__attribute__((unused)) + test_fixture *fixture, + __attribute__((unused)) + gconstpointer user_data){ + __attribute__((cleanup(cleanup_queue))) + task_queue *queue = create_queue(); + g_assert_nonnull(queue); + g_assert_true(queue->length == 0); + queue->length = SIZE_MAX / sizeof(task_context); /* fake max size */ + + FILE *real_stderr = stderr; + FILE *devnull = fopen("/dev/null", "we"); + g_assert_nonnull(devnull); + stderr = devnull; + const bool ret = add_to_queue(queue, + (task_context){ .func=dummy_func }); + g_assert_true(errno == ENOMEM); + g_assert_false(ret); + stderr = real_stderr; + g_assert_cmpint(fclose(devnull), ==, 0); + queue->length = 0; /* Restore real size */ +} + static void dummy_func(__attribute__((unused)) const task_context task, __attribute__((unused)) @@ -7862,6 +7892,7 @@ test_add("/parse_arguments/mixed", test_parse_arguments_mixed); test_add("/queue/create", test_create_queue); test_add("/queue/add", test_add_to_queue); + test_add("/queue/add/overflow", test_add_to_queue_overflow); test_add("/queue/has_question/empty", test_queue_has_question_empty); test_add("/queue/has_question/false", === modified file 'plugin-runner.c' --- plugin-runner.c 2019-07-07 20:50:21 +0000 +++ plugin-runner.c 2020-02-09 03:38:33 +0000 @@ -26,8 +26,8 @@ #define _GNU_SOURCE /* TEMP_FAILURE_RETRY(), getline(), O_CLOEXEC, pipe2() */ #include /* size_t, NULL */ -#include /* malloc(), exit(), EXIT_SUCCESS, - realloc() */ +#include /* malloc(), reallocarray(), realloc(), + EXIT_SUCCESS, exit() */ #include /* bool, true, false */ #include /* fileno(), fprintf(), stderr, STDOUT_FILENO, fclose() */ @@ -179,8 +179,19 @@ /* Resize the pointed-to array to hold one more pointer */ char **new_array = NULL; do { - new_array = realloc(*array, sizeof(char *) - * (size_t) ((*len) + 2)); +#if defined(__GLIBC_PREREQ) and __GLIBC_PREREQ(2, 26) + new_array = reallocarray(*array, (size_t)((*len) + 2), + sizeof(char *)); +#else + if(((size_t)((*len) + 2)) > (SIZE_MAX / sizeof(char *))){ + /* overflow */ + new_array = NULL; + errno = ENOMEM; + } else { + new_array = realloc(*array, (size_t)((*len) + 2) + * sizeof(char *)); + } +#endif } while(new_array == NULL and errno == EINTR); /* Malloc check */ if(new_array == NULL){ @@ -708,10 +719,21 @@ custom_argc += 1; { - char **new_argv = realloc(custom_argv, sizeof(char *) - * ((size_t)custom_argc + 1)); +#if defined(__GLIBC_PREREQ) and __GLIBC_PREREQ(2, 26) + char **new_argv = reallocarray(custom_argv, (size_t)custom_argc + 1, + sizeof(char *)); +#else + char **new_argv = NULL; + if(((size_t)custom_argc + 1) > (SIZE_MAX / sizeof(char *))){ + /* overflow */ + errno = ENOMEM; + } else { + new_argv = realloc(custom_argv, ((size_t)custom_argc + 1) + * sizeof(char *)); + } +#endif if(new_argv == NULL){ - error(0, errno, "realloc"); + error(0, errno, "reallocarray"); exitstatus = EX_OSERR; free(new_arg); free(org_line); === modified file 'plugins.d/plymouth.c' --- plugins.d/plymouth.c 2019-07-27 10:11:45 +0000 +++ plugins.d/plymouth.c 2020-02-09 03:38:33 +0000 @@ -44,7 +44,7 @@ STDERR_FILENO, execv(), access() */ #include /* free(), EXIT_FAILURE, realloc(), EXIT_SUCCESS, malloc(), _exit(), - getenv() */ + getenv(), reallocarray() */ #include /* scandir(), alphasort() */ #include /* intmax_t, strtoumax(), SCNuMAX */ #include /* struct stat, lstat() */ @@ -204,9 +204,20 @@ char **tmp; int i = 0; for (; argv[i] != NULL; i++){ - tmp = realloc(new_argv, sizeof(const char *) * ((size_t)i + 2)); +#if defined(__GLIBC_PREREQ) and __GLIBC_PREREQ(2, 26) + tmp = reallocarray(new_argv, ((size_t)i + 2), + sizeof(const char *)); +#else + if(((size_t)i + 2) > (SIZE_MAX / sizeof(const char *))){ + /* overflow */ + tmp = NULL; + errno = ENOMEM; + } else { + tmp = realloc(new_argv, ((size_t)i + 2) * sizeof(const char *)); + } +#endif if(tmp == NULL){ - error_plus(0, errno, "realloc"); + error_plus(0, errno, "reallocarray"); free(new_argv); _exit(EX_OSERR); }