From ff5ccbd62e0e01a4e246b5b3c7b62a9703091bd6 Mon Sep 17 00:00:00 2001 From: jake Date: Fri, 15 Sep 2023 01:50:29 +0000 Subject: [PATCH 7/8] !262 Fix empty pointer and overflow * Fix empty pointer and overflow --- src/runtime/conf.c | 63 +++++++++-- src/runtime/lcrcontainer.c | 135 ++--------------------- src/runtime/lcrcontainer.h | 40 ------- src/runtime/lcrcontainer_execute.c | 30 ++++++ src/runtime/lcrcontainer_extend.c | 144 ++++--------------------- src/runtime/lcrcontainer_extend.h | 11 -- src/third_party/go_crc64.c | 6 +- src/third_party/libocispec/common_c.py | 116 +++++++++++++------- src/third_party/libocispec/common_h.py | 4 +- src/third_party/libocispec/sources.py | 51 +++++---- src/utils/utils_buffer.c | 4 + src/utils/utils_cgroup.c | 5 + tests/fuzz/log_fuzz.cc | 2 +- 13 files changed, 238 insertions(+), 373 deletions(-) diff --git a/src/runtime/conf.c b/src/runtime/conf.c index d505507..7739de6 100644 --- a/src/runtime/conf.c +++ b/src/runtime/conf.c @@ -642,6 +642,10 @@ static int trans_oci_process_prlimit(const defs_process *proc, struct lcr_list * for (i = 0; i < proc->rlimits_len; i++) { defs_process_rlimits_element *lr = proc->rlimits[i]; + if (lr == NULL) { + continue; + } + char buf_key[30] = { 0 }; char buf_value[60] = { 0 }; size_t j; @@ -754,6 +758,10 @@ struct lcr_list *trans_oci_process(const defs_process *proc) { struct lcr_list *conf = NULL; + if (proc == NULL) { + return NULL; + } + conf = lcr_util_common_calloc_s(sizeof(struct lcr_list)); if (conf == NULL) { return NULL; @@ -1097,7 +1105,8 @@ bool is_system_container(const oci_runtime_spec *container) { size_t i = 0; for (i = 0; container->annotations != NULL && i < container->annotations->len; i++) { - if (strcmp(container->annotations->keys[i], "system.container") == 0) { + if (container->annotations->keys[i] != NULL && + strcmp(container->annotations->keys[i], "system.container") == 0) { return true; } } @@ -1108,7 +1117,8 @@ static bool is_external_rootfs(const oci_runtime_spec *container) { size_t i = 0; for (i = 0; container->annotations != NULL && i < container->annotations->len; i++) { - if (strcmp(container->annotations->keys[i], "external.rootfs") == 0) { + if (container->annotations->keys[i] != NULL && + strcmp(container->annotations->keys[i], "external.rootfs") == 0) { return true; } } @@ -1170,8 +1180,14 @@ struct lcr_list *trans_oci_mounts(const oci_runtime_spec *c) struct lcr_list *node = NULL; defs_mount *tmp = NULL; size_t i; - bool system_container = is_system_container(c); - bool external_rootfs = is_external_rootfs(c); + bool system_container = false; + bool external_rootfs = false; + + if (c == NULL) { + return NULL; + } + system_container = is_system_container(c); + external_rootfs = is_external_rootfs(c); conf = lcr_util_common_calloc_s(sizeof(*conf)); if (conf == NULL) { @@ -1181,7 +1197,7 @@ struct lcr_list *trans_oci_mounts(const oci_runtime_spec *c) for (i = 0; i < c->mounts_len; i++) { tmp = c->mounts[i]; - if (tmp->type == NULL) { + if (tmp == NULL || tmp->type == NULL) { goto out_free; } @@ -1210,6 +1226,10 @@ static int trans_one_oci_id_mapping(struct lcr_list *conf, const char *typ, cons char buf_value[DEFAULT_BUF_LEN] = { 0 }; char subid[ID_MAP_LEN] = { 0 }; + if (id == NULL) { + return -1; + } + nret = snprintf(buf_value, sizeof(buf_value), "%s %u %u %u", typ, id->container_id, id->host_id, id->size); if (nret < 0 || (size_t)nret >= sizeof(buf_value)) { return -1; @@ -1573,6 +1593,10 @@ static int trans_resources_devices_v1(const defs_resources *res, struct lcr_list for (i = 0; i < res->devices_len; i++) { defs_device_cgroup *lrd = res->devices[i]; + if (lrd == NULL) { + continue; + } + if (trans_resources_devices_ret(lrd, buf_value, sizeof(buf_value)) < 0) { goto out; } @@ -2009,6 +2033,10 @@ static int trans_resources_devices_v2(const defs_resources *res, struct lcr_list for (i = 0; i < res->devices_len; i++) { defs_device_cgroup *lrd = res->devices[i]; + if (lrd == NULL) { + continue; + } + if (trans_resources_devices_ret(lrd, buf_value, sizeof(buf_value)) < 0) { goto out; } @@ -2491,7 +2519,7 @@ static struct lcr_list *trans_oci_namespaces(const oci_runtime_config_linux *l) char *ns_name = NULL; ns = l->namespaces[i]; - if (ns->type == NULL || ns->path == NULL) { + if (ns == NULL || ns->type == NULL || ns->path == NULL) { continue; } @@ -2808,6 +2836,12 @@ static int seccomp_append_rule(const defs_syscall *syscall, size_t i, isula_buff ret = -1; goto out; } + + if (strlen(syscall->names[i]) > SIZE_MAX - strlen(action) - 2) { + ERROR("Out of range"); + ret = -1; + goto out; + } if (buffer->nappend(buffer, strlen(syscall->names[i]) + strlen(action) + 2, "%s %s", syscall->names[i], action)) { ERROR("Failed to append syscall name and action\n"); ret = -1; @@ -2820,6 +2854,15 @@ static int seccomp_append_rule(const defs_syscall *syscall, size_t i, isula_buff ret = -1; goto out; } + + /* Appending content is syscall->args[j]->op plus + * three unsigned numbers(which length is no more than 20 * 3) + */ + if (strlen(syscall->args[j]->op) > SIZE_MAX - 20 * 3) { + ERROR("Out of range"); + ret = -1; + goto out; + } if (buffer->nappend(buffer, 20 * 3 + strlen(syscall->args[j]->op), " [%u,%llu,%s,%llu]", syscall->args[j]->index, syscall->args[j]->value, syscall->args[j]->op, syscall->args[j]->value_two)) { @@ -3033,6 +3076,10 @@ struct lcr_list *trans_oci_linux(const oci_runtime_config_linux *l, char **secco int ret = 0; struct lcr_list *tmp = NULL; + if (l == NULL) { + return NULL; + } + struct lcr_list *conf = lcr_util_common_calloc_s(sizeof(*conf)); if (conf == NULL) { return NULL; @@ -3115,6 +3162,10 @@ struct lcr_list *trans_annotations(const json_map_string_string *anno) size_t len; int ret = 0; + if (anno == NULL) { + return NULL; + } + struct lcr_list *conf = lcr_util_common_calloc_s(sizeof(*conf)); if (conf == NULL) { return NULL; diff --git a/src/runtime/lcrcontainer.c b/src/runtime/lcrcontainer.c index ae5fe5b..4270902 100644 --- a/src/runtime/lcrcontainer.c +++ b/src/runtime/lcrcontainer.c @@ -43,52 +43,6 @@ #include "utils.h" #include "oci_runtime_spec.h" -/* - * Free lcr_container_info array returned by lcr_list_{active,all}_containers - */ -void lcr_containers_info_free(struct lcr_container_info **info_arr, size_t size) -{ - size_t i = 0; - struct lcr_container_info *in = NULL; - - if (info_arr == NULL) { - return; - } - if (size == 0) { - return; - } - for (i = 0, in = *info_arr; i < size; i++, in++) { - free(in->interface); - free(in->ipv4); - free(in->ipv6); - free(in->name); - free(in->state); - } - free(*info_arr); - *info_arr = NULL; -} - -/* - * Free lcr_container_info returned lcr_container_info_get - */ -void lcr_container_info_free(struct lcr_container_info *info) -{ - if (info == NULL) { - return; - } - free(info->interface); - info->interface = NULL; - free(info->ipv4); - info->ipv4 = NULL; - free(info->ipv6); - info->ipv6 = NULL; - free(info->name); - info->name = NULL; - free(info->state); - info->state = NULL; - free(info); -} - static inline bool is_container_exists(struct lxc_container *c) { return c->is_defined(c); @@ -99,85 +53,6 @@ static inline bool is_container_can_control(struct lxc_container *c) return c->may_control(c); } -/* - * Get one container info for a given name and lcrpath. - * return struct of container info, or NULL on error. - */ -struct lcr_container_info *lcr_container_info_get(const char *name, const char *lcrpath) -{ - int nret = -1; - struct lcr_container_info *info = NULL; - const char *st = NULL; - bool run_flag = false; - - struct lxc_container *c = lxc_container_without_config_new(name, lcrpath); - if (c == NULL) { - return NULL; - } - - if (!is_container_exists(c)) { - goto put_and_finish; - } - - st = c->state(c); - if (st == NULL) { - st = "UNKNOWN"; - } - run_flag = (strcmp(st, "STOPPED") != 0); - - /* Now it makes sense to allocate memory */ - info = lcr_util_common_calloc_s(sizeof(*info)); - if (info == NULL) { - nret = -1; - goto put_and_finish; - } - info->init = -1; - info->running = run_flag; - info->name = lcr_util_strdup_s(name); - info->state = lcr_util_strdup_s(st); - if (run_flag) { - info->init = c->init_pid(c); - } - - nret = 0; -put_and_finish: - lxc_container_put(c); - if (nret != 0) { - lcr_container_info_free(info); - info = NULL; - } - return info; -} - -/* - * Get a complete list of all containers for a given lcrpath. - * return Number of containers, or -1 on error. - **/ -int lcr_list_all_containers(const char *lcrpath, struct lcr_container_info **info_arr) -{ - char **container = NULL; - int n = 0; - int nret = -1; - size_t info_size = 0; - const char *path = lcrpath ? lcrpath : LCRPATH; - - clear_error_message(&g_lcr_error); - n = list_all_containers(path, &container, NULL); - if (n == -1) { - n = 0; - } - - nret = lcr_containers_info_get(path, info_arr, &info_size, container, n); - if (info_arr == NULL && nret == 0) { - return -1; - } else if (info_arr == NULL || nret == -1) { - lcr_containers_info_free(info_arr, info_size); - return -1; - } - - return (int)info_size; -} - static int create_partial(const struct lxc_container *c) { int fd = 0; @@ -275,6 +150,16 @@ bool lcr_create(const char *name, const char *lcrpath, void *oci_config) const char *tmp_path = lcrpath ? lcrpath : LCRPATH; oci_runtime_spec *oci_spec = (oci_runtime_spec *)oci_config; + if (name == NULL) { + ERROR("Missing container name"); + return false; + } + + if (oci_spec == NULL) { + ERROR("Empty oci config"); + return false; + } + clear_error_message(&g_lcr_error); isula_libutils_set_log_prefix(name); diff --git a/src/runtime/lcrcontainer.h b/src/runtime/lcrcontainer.h index 6add8c4..d4cef39 100644 --- a/src/runtime/lcrcontainer.h +++ b/src/runtime/lcrcontainer.h @@ -46,24 +46,6 @@ __EXPORT__ struct lcr_console_config { char *log_file_size; }; -/* -* Store lcr container info -*/ -__EXPORT__ struct lcr_container_info { - /* Name of container. */ - char *name; - /* State of container. */ - char *state; - /* Interface of container. */ - char *interface; - char *ipv4; - char *ipv6; - pid_t init; - double ram; - double swap; - bool running; -}; - __EXPORT__ struct blkio_stats { uint64_t read; uint64_t write; @@ -132,28 +114,6 @@ __EXPORT__ struct lcr_cgroup_resources { int64_t cpurt_runtime; }; -/* -* Get one container info for a given lcrpath. -* return struct of container info, or NULL on error. -*/ -__EXPORT__ struct lcr_container_info *lcr_container_info_get(const char *name, const char *lcrpath); - -/* -* Free lcr_container_info returned lcr_container_info_get -*/ -__EXPORT__ void lcr_container_info_free(struct lcr_container_info *info); - -/* -* Get a complete list of all containers for a given lcrpath. -* return Number of containers, or -1 on error. -*/ -__EXPORT__ int lcr_list_all_containers(const char *lcrpath, struct lcr_container_info **info_arr); - -/* -* Free lcr_container_info array returned by lcr_list_{active,all}_containers -*/ -__EXPORT__ void lcr_containers_info_free(struct lcr_container_info **info_arr, size_t size); - /* * Create a container * param name : container name diff --git a/src/runtime/lcrcontainer_execute.c b/src/runtime/lcrcontainer_execute.c index e91ff27..61bcd84 100644 --- a/src/runtime/lcrcontainer_execute.c +++ b/src/runtime/lcrcontainer_execute.c @@ -736,6 +736,11 @@ bool do_update(struct lxc_container *c, const char *name, const char *lcrpath, s { bool bret = false; + if (c == NULL) { + ERROR("Invalid arg c"); + return bret; + } + // If container is not running, update config file is enough, // resources will be updated when the container is started again. // If container is running (including paused), we need to update configs @@ -760,6 +765,16 @@ void do_lcr_state(struct lxc_container *c, struct lcr_container_state *lcs) { struct lxc_container_metrics lxc_metrics = { 0 }; + if (c == NULL) { + ERROR("Invalid argument c"); + return; + } + + if (lcs == NULL) { + ERROR("Invalid argument lcs"); + return; + } + clear_error_message(&g_lcr_error); (void)memset(lcs, 0x00, sizeof(struct lcr_container_state)); @@ -915,6 +930,16 @@ bool do_attach(const char *name, const char *path, const struct lcr_exec_request int pipefd[2] = {-1, -1}; int status = 0; + if (request == NULL) { + ERROR("Invalid request"); + return false; + } + + if (exit_code == NULL) { + ERROR("Invalid exit code"); + return false; + } + if (pipe(pipefd) != 0) { ERROR("Failed to create pipe\n"); return false; @@ -978,6 +1003,11 @@ void execute_lxc_start(const char *name, const char *path, const struct lcr_star size_t i = 0; int nret = 0; + if (request == NULL) { + COMMAND_ERROR("Invalid request"); + exit(EXIT_FAILURE); + } + if (lcr_util_check_inherited(true, -1) != 0) { COMMAND_ERROR("Close inherited fds failed"); } diff --git a/src/runtime/lcrcontainer_extend.c b/src/runtime/lcrcontainer_extend.c index 8b5a85c..d6b44d1 100644 --- a/src/runtime/lcrcontainer_extend.c +++ b/src/runtime/lcrcontainer_extend.c @@ -425,74 +425,6 @@ cleanup: return NULL; } -static struct lcr_container_info *info_new(struct lcr_container_info **info, size_t *size) -{ - struct lcr_container_info *m = NULL; - struct lcr_container_info *n = NULL; - size_t length = 0; - int nret = 0; - - if (*size > SIZE_MAX / sizeof(struct lcr_container_info) - 1) { - return NULL; - } - - length = (*size + 1) * sizeof(struct lcr_container_info); - - nret = lcr_mem_realloc((void **)&n, length, (void *)(*info), (*size) * sizeof(struct lcr_container_info)); - if (nret < 0) { - return NULL; - } - - *info = n; - m = *info + *size; - (*size)++; - - // *INDENT-OFF* - *m = (struct lcr_container_info) { - .name = NULL, .state = NULL, .interface = NULL, .ipv4 = NULL, .ipv6 = NULL, .ram = 0.0, .swap = 0.0, .init = -1 - }; - // *INDENT-ON* - return m; -} - -static void free_arr(char **array, size_t size) -{ - size_t i; - for (i = 0; i < size; i++) { - free(array[i]); - array[i] = NULL; - } - free(array); -} - -/* - * Get a complete list of active containers for a given lcrpath. - * return Number of containers, or -1 on error. - **/ -int lcr_list_active_containers(const char *lcrpath, struct lcr_container_info **info_arr) -{ - char **c = NULL; - int n = 0; - int nret = -1; - size_t info_size = 0; - const char *path = lcrpath ? lcrpath : LCRPATH; - - n = list_active_containers(path, &c, NULL); - if (n == -1) { - n = 0; - } - - nret = lcr_containers_info_get(path, info_arr, &info_size, c, n); - if ((info_arr == NULL) && nret == 0) { - return -1; - } else if ((info_arr == NULL) || nret == -1) { - lcr_containers_info_free(info_arr, info_size); - return -1; - } - - return (int)info_size; -} - bool lcr_delete_with_force(const char *name, const char *lcrpath, bool force) { struct lxc_container *c = NULL; @@ -563,61 +495,6 @@ void lcr_free_config(struct lcr_list *lcr_conf) } } -int lcr_containers_info_get(const char *lcrpath, struct lcr_container_info **info, size_t *size, char **containers, - int num) -{ - struct lcr_container_info *in = NULL; - struct lxc_container *c = NULL; - int i; - int nret = -1; - - if ((lcrpath == NULL) || num == 0) { - goto err_out; - } - - for (i = 0; i < num; i++) { - const char *st = NULL; - const char *name = containers[i]; - bool run_flag = true; - if (name == NULL) { - continue; - } - - c = lxc_container_without_config_new(name, lcrpath); - if (c == NULL) { - continue; - } - - if (!c->is_defined(c)) { - goto put_container; - } - - st = c->state(c); - if (st == NULL) { - st = "UNKNOWN"; - } - run_flag = (strcmp(st, "STOPPED") != 0); - - /* Now it makes sense to allocate memory */ - in = info_new(info, size); - if (in == NULL) { - goto put_container; - } - in->running = run_flag; - in->name = lcr_util_strdup_s(name); - in->state = lcr_util_strdup_s(st); - if (run_flag) { - in->init = c->init_pid(c); - } -put_container: - lxc_container_put(c); - } - nret = 0; -err_out: - free_arr(containers, (size_t)num); - return nret; -} - /* * Transform container JSON into oci_runtime_spec struct */ @@ -627,6 +504,11 @@ bool container_parse(const char *oci_filename, const char *oci_json_data, oci_ru parser_error err = NULL; bool ret = true; + if (container == NULL) { + ERROR("Invalid container arg"); + return false; + } + if (oci_json_data == NULL) { *container = oci_runtime_spec_parse_file(oci_filename, &ctx, &err); } else { @@ -683,6 +565,11 @@ struct lcr_list *lcr_oci2lcr(const struct lxc_container *c, oci_runtime_spec *co { struct lcr_list *lcr_conf = NULL; + if (container == NULL) { + ERROR("Invalid arguments"); + return NULL; + } + lcr_conf = lcr_util_common_calloc_s(sizeof(*lcr_conf)); if (lcr_conf == NULL) { goto out_free; @@ -776,6 +663,10 @@ static char *escape_string_encode(const char *src) return NULL; } + if (len > (SIZE_MAX - 1) / 2) { + return NULL; + } + dst = lcr_util_common_calloc_s(2 * len + 1); if (dst == NULL) { ERROR("Out of memory"); @@ -874,7 +765,7 @@ cleanup: return ret; } -char *lcr_get_bundle(const char *lcrpath, const char *name) +static char *lcr_get_bundle(const char *lcrpath, const char *name) { size_t len = 0; int nret = 0; @@ -932,6 +823,11 @@ bool lcr_save_spec(const char *name, const char *lcrpath, const struct lcr_list return bret; } + if (lcr_conf == NULL) { + ERROR("Empty lcr conf"); + return bret; + } + bundle = lcr_get_bundle(path, name); if (bundle == NULL) { goto out_free; diff --git a/src/runtime/lcrcontainer_extend.h b/src/runtime/lcrcontainer_extend.h index 981a2bb..f524a4a 100644 --- a/src/runtime/lcrcontainer_extend.h +++ b/src/runtime/lcrcontainer_extend.h @@ -44,12 +44,6 @@ struct lcr_list; } \ } while (0); -/* - * Get a complete list of active containers for a given lcrpath. - * return Number of containers, or -1 on error. - */ -int lcr_list_active_containers(const char *lcrpath, struct lcr_container_info **info_arr); - /* * Delete a container * param name : container name, required. @@ -82,11 +76,6 @@ struct lcr_list *lcr_oci2lcr(const struct lxc_container *c, oci_runtime_spec *co */ bool lcr_save_spec(const char *name, const char *lcrpath, const struct lcr_list *lcr_conf, const char *seccomp_conf); -int lcr_containers_info_get(const char *lcrpath, struct lcr_container_info **info, size_t *size, char **containers, - int num); - -char *lcr_get_bundle(const char *lcrpath, const char *name); - bool translate_spec(const struct lxc_container *c, oci_runtime_spec *container); #ifdef __cplusplus diff --git a/src/third_party/go_crc64.c b/src/third_party/go_crc64.c index a08e07c..d680815 100644 --- a/src/third_party/go_crc64.c +++ b/src/third_party/go_crc64.c @@ -32,10 +32,9 @@ isula_crc_table_t g_iso_crc_table; static void make_table(isula_crc_table_t *tab, uint64_t poly) { uint64_t i, j; - uint64_t t; for (i = 0; i < CRC_COL_LEN; i++) { - t = i; + uint64_t t = i; for (j = 0; j < CRC_ROW_LEN; j++) { if ((t & 1) == 1) { t = (t >> 1) ^ poly; @@ -50,10 +49,9 @@ static void make_table(isula_crc_table_t *tab, uint64_t poly) static void make_crc_table(isula_crc_table_t *tab) { uint64_t i, j; - uint64_t crc; for (i = 0; i < CRC_COL_LEN; i++) { - crc = tab->table[0][i]; + uint64_t crc = tab->table[0][i]; for (j = 1; j < CRC_ROW_LEN; j++) { crc = tab->table[0][(crc&0xff)] ^ (crc >> 8); tab->table[j][i] = crc; diff --git a/src/third_party/libocispec/common_c.py b/src/third_party/libocispec/common_c.py index 8c4f92f..5d6ed70 100644 --- a/src/third_party/libocispec/common_c.py +++ b/src/third_party/libocispec/common_c.py @@ -54,6 +54,14 @@ def generate_json_common_c(out): # define MAX_NUM_STR_LEN 21 +#if __WORDSIZE == 64 +// current max user memory for 64-machine is 2^47 B +#define MAX_MEMORY_SIZE ((size_t)1 << 47) +#else +// current max user memory for 32-machine is 2^31 B +#define MAX_MEMORY_SIZE ((size_t)1 << 31) +#endif + static yajl_gen_status gen_yajl_val (yajl_val obj, yajl_gen g, parser_error *err); static yajl_gen_status gen_yajl_val_obj (yajl_val obj, yajl_gen g, parser_error *err) @@ -227,15 +235,24 @@ safe_strdup(const char *src) return dst; } -void * -safe_malloc(size_t size) -{ +void *smart_calloc(size_t count, size_t extra, size_t unit_size) { void *ret = NULL; - if (size == 0) - abort(); - ret = calloc(1, size); - if (ret == NULL) - abort(); + if (unit_size == 0) { + return NULL; + } + + if (extra > MAX_MEMORY_SIZE || count > MAX_MEMORY_SIZE - extra) { + return NULL; + } + + if (count + extra == 0 || count + extra > (MAX_MEMORY_SIZE / unit_size)) { + return NULL; + } + + ret = calloc(count + extra, unit_size); + if (ret == NULL) { + return NULL; + } return ret; } @@ -572,18 +589,18 @@ make_json_map_int_int (yajl_val src, const struct parser_context *ctx, return NULL; len = YAJL_GET_OBJECT_NO_CHECK (src)->len; - ret = calloc (1, sizeof (*ret)); + ret = smart_calloc (1, 0, sizeof (*ret)); if (ret == NULL) return NULL; ret->len = 0; - ret->keys = calloc (len + 1, sizeof (int)); + ret->keys = smart_calloc (len, 1, sizeof (int)); if (ret->keys == NULL) { return NULL; } - ret->values = calloc (len + 1, sizeof (int)); + ret->values = smart_calloc (len, 1, sizeof (int)); if (ret->values == NULL) { return NULL; @@ -653,10 +670,10 @@ append_json_map_int_int (json_map_int_int * map, int key, int val) return -1; len = map->len + 1; - keys = calloc (1, len * sizeof (int)); + keys = smart_calloc (len, 0, sizeof (int)); if (keys == NULL) return -1; - vals = calloc (1, len * sizeof (int)); + vals = smart_calloc (len, 0, sizeof (int)); if (vals == NULL) { return -1; @@ -760,16 +777,16 @@ make_json_map_int_bool (yajl_val src, const struct parser_context *ctx, return NULL; len = YAJL_GET_OBJECT_NO_CHECK (src)->len; - ret = calloc (1, sizeof (*ret)); + ret = smart_calloc (1, 0, sizeof (*ret)); if (ret == NULL) return NULL; ret->len = 0; - ret->keys = calloc (len + 1, sizeof (int)); + ret->keys = smart_calloc (len, 1, sizeof (int)); if (ret->keys == NULL) { return NULL; } - ret->values = calloc (len + 1, sizeof (bool)); + ret->values = smart_calloc (len, 1, sizeof (bool)); if (ret->values == NULL) { return NULL; @@ -832,10 +849,10 @@ append_json_map_int_bool (json_map_int_bool * map, int key, bool val) return -1; len = map->len + 1; - keys = calloc (len, sizeof (int)); + keys = smart_calloc (len, 0, sizeof (int)); if (keys == NULL) return -1; - vals = calloc (len, sizeof (bool)); + vals = smart_calloc (len, 0, sizeof (bool)); if (vals == NULL) { return -1; @@ -945,18 +962,18 @@ make_json_map_int_string (yajl_val src, const struct parser_context *ctx, len = YAJL_GET_OBJECT_NO_CHECK (src)->len; - ret = calloc (1, sizeof (*ret)); + ret = smart_calloc (1, 0, sizeof (*ret)); if (ret == NULL) return NULL; ret->len = 0; - ret->keys = calloc (len + 1, sizeof (int)); + ret->keys = smart_calloc (len, 1, sizeof (int)); if (ret->keys == NULL) { return NULL; } - ret->values = calloc (len + 1, sizeof (char *)); + ret->values = smart_calloc (len, 1, sizeof (char *)); if (ret->values == NULL) { return NULL; @@ -1111,20 +1128,20 @@ make_json_map_string_int (yajl_val src, const struct parser_context *ctx, return NULL; len = YAJL_GET_OBJECT_NO_CHECK (src)->len; - ret = calloc (1, sizeof (*ret)); + ret = smart_calloc (1, 0, sizeof (*ret)); if (ret == NULL) { *(err) = strdup ("error allocating memory"); return NULL; } ret->len = 0; - ret->keys = calloc (len + 1, sizeof (char *)); + ret->keys = smart_calloc (len, 1, sizeof (char *)); if (ret->keys == NULL) { *(err) = strdup ("error allocating memory"); return NULL; } - ret->values = calloc (len + 1, sizeof (int)); + ret->values = smart_calloc (len, 1, sizeof (int)); if (ret->values == NULL) { *(err) = strdup ("error allocating memory"); @@ -1271,10 +1288,24 @@ make_json_map_string_int64 (yajl_val src, const struct parser_context *ctx, pars { size_t i; size_t len = YAJL_GET_OBJECT (src)->len; - ret = safe_malloc (sizeof(*ret)); + char **keys = NULL; + int64_t *vals = NULL; + ret = smart_calloc (1, 0, sizeof(*ret)); + if (ret == NULL) { + return NULL; + } + keys = smart_calloc (len, 1, sizeof (char *)); + if (keys == NULL) { + return NULL; + } + vals = smart_calloc (len, 1, sizeof (int64_t)); + if (vals == NULL) { + free(keys); + return NULL; + } ret->len = len; - ret->keys = safe_malloc ((len + 1) * sizeof (char *)); - ret->values = safe_malloc ((len + 1) * sizeof (int64_t)); + ret->keys = keys; + ret->values = vals; for (i = 0; i < len; i++) { const char *srckey = YAJL_GET_OBJECT (src)->keys[i]; @@ -1320,8 +1351,15 @@ append_json_map_string_int64 (json_map_string_int64 *map, const char *key, int64 return -1; len = map->len + 1; - keys = safe_malloc (len * sizeof(char *)); - vals = safe_malloc (len * sizeof(int64_t)); + keys = smart_calloc (len, 0, sizeof(char *)); + if (keys == NULL) { + return -1; + } + vals = smart_calloc (len, 0, sizeof(int64_t)); + if (vals == NULL) { + free(keys); + return -1; + } if (map->len) { @@ -1411,17 +1449,17 @@ make_json_map_string_bool (yajl_val src, const struct parser_context *ctx, if (src == NULL || YAJL_GET_OBJECT (src) == NULL) return NULL; - ret = calloc (1, sizeof (*ret)); + ret = smart_calloc (1, 0, sizeof (*ret)); if (ret == NULL) return NULL; ret->len = 0; - ret->keys = calloc (len + 1, sizeof (char *)); + ret->keys = smart_calloc (len, 1, sizeof (char *)); if (ret->keys == NULL) { return NULL; } - ret->values = calloc (len + 1, sizeof (bool)); + ret->values = smart_calloc (len, 1, sizeof (bool)); if (ret->values == NULL) { return NULL; @@ -1478,10 +1516,10 @@ append_json_map_string_bool (json_map_string_bool * map, const char *key, return -1; len = map->len + 1; - keys = calloc (len, sizeof (char *)); + keys = smart_calloc (len, 0, sizeof (char *)); if (keys == NULL) return -1; - vals = calloc (len, sizeof (bool)); + vals = smart_calloc (len, 0, sizeof (bool)); if (vals == NULL) { return -1; @@ -1599,14 +1637,14 @@ make_json_map_string_string (yajl_val src, const struct parser_context *ctx, ret->len = 0; - ret->keys = calloc (len + 1, sizeof (char *)); + ret->keys = smart_calloc (len, 1, sizeof (char *)); if (ret->keys == NULL) { *(err) = strdup ("error allocating memory"); return NULL; } - ret->values = calloc (len + 1, sizeof (char *)); + ret->values = smart_calloc (len, 1, sizeof (char *)); if (ret->values == NULL) { *(err) = strdup ("error allocating memory"); @@ -1731,12 +1769,12 @@ dup_json_map_string_string(const json_map_string_string *src, json_map_string_st goto out; } - dest->keys = safe_malloc(src->len * sizeof(char *)); + dest->keys = smart_calloc(src->len, 0, sizeof(char *)); if (dest->keys == NULL) { ret = -1; goto out; } - dest->values = safe_malloc(src->len * sizeof(char *)); + dest->values = smart_calloc(src->len, 0, sizeof(char *)); if (dest->values == NULL) { free(dest->keys); dest->keys = NULL; @@ -1800,7 +1838,7 @@ json_marshal_string (const char *str, size_t length, return json_buf; } - json_buf = calloc (1, gen_len + 1); + json_buf = smart_calloc (gen_len, 1, 1); if (json_buf == NULL) { *err = strdup ("error allocating memory"); diff --git a/src/third_party/libocispec/common_h.py b/src/third_party/libocispec/common_h.py index cefe117..af31013 100644 --- a/src/third_party/libocispec/common_h.py +++ b/src/third_party/libocispec/common_h.py @@ -110,6 +110,8 @@ static inline void ptr_free_function(void *p) { return stat; \\ } +#define JSON_MAX_SIZE (10LL * 1024LL * 1024LL) + typedef char *parser_error; struct parser_context @@ -130,7 +132,7 @@ yajl_val get_val (yajl_val tree, const char *name, yajl_type type); char *safe_strdup(const char *src); -void *safe_malloc(size_t size); +void *smart_calloc(size_t count, size_t extra, size_t unit_size); int common_safe_double (const char *numstr, double *converted); diff --git a/src/third_party/libocispec/sources.py b/src/third_party/libocispec/sources.py index a85d030..c69cb74 100644 --- a/src/third_party/libocispec/sources.py +++ b/src/third_party/libocispec/sources.py @@ -63,10 +63,10 @@ def parse_map_string_obj(obj, c_file, prefix, obj_typename): c_file.write(' const char **keys = YAJL_GET_OBJECT_NO_CHECK (tree)->keys;\n') c_file.write(' yajl_val *values = YAJL_GET_OBJECT_NO_CHECK (tree)->values;\n') c_file.write(' ret->len = len;\n') - c_file.write(' ret->keys = calloc (len + 1, sizeof (*ret->keys));\n') + c_file.write(' ret->keys = smart_calloc (len, 1, sizeof (*ret->keys));\n') c_file.write(' if (ret->keys == NULL)\n') c_file.write(' return NULL;\n') - c_file.write(' ret->%s = calloc (len + 1, sizeof (*ret->%s));\n' % \ + c_file.write(' ret->%s = smart_calloc (len, 1, sizeof (*ret->%s));\n' % \ (child.fixname, child.fixname)) c_file.write(' if (ret->%s == NULL)\n' % child.fixname) c_file.write(' {\n') @@ -109,14 +109,14 @@ def parse_obj_type_array(obj, c_file, prefix, obj_typename): c_file.write(' size_t len = YAJL_GET_ARRAY_NO_CHECK (tmp)->len;\n') c_file.write(' yajl_val *values = YAJL_GET_ARRAY_NO_CHECK (tmp)->values;\n') c_file.write(' ret->%s_len = len;\n' % (obj.fixname)) - c_file.write(' ret->%s = calloc (len + 1, sizeof (*ret->%s));\n' % \ + c_file.write(' ret->%s = smart_calloc (len, 1, sizeof (*ret->%s));\n' % \ (obj.fixname, obj.fixname)) c_file.write(' if (ret->%s == NULL)\n' % obj.fixname) c_file.write(' {\n') c_file.write(' return NULL;\n') c_file.write(' }\n') if obj.doublearray: - c_file.write(' ret->%s_item_lens = calloc ( len + 1, sizeof (size_t));\n' + c_file.write(' ret->%s_item_lens = smart_calloc ( len, 1, sizeof (size_t));\n' % (obj.fixname)) c_file.write(' if (ret->%s_item_lens == NULL)\n' % (obj.fixname)) c_file.write(' return NULL;\n') @@ -125,7 +125,7 @@ def parse_obj_type_array(obj, c_file, prefix, obj_typename): c_file.write(' yajl_val val = values[i];\n') if obj.doublearray: c_file.write(' size_t j;\n') - c_file.write(' ret->%s[i] = calloc ( YAJL_GET_ARRAY_NO_CHECK(val)->len + 1, sizeof (**ret->%s));\n' + c_file.write(' ret->%s[i] = smart_calloc ( YAJL_GET_ARRAY_NO_CHECK(val)->len, 1, sizeof (**ret->%s));\n' % (obj.fixname, obj.fixname)) c_file.write(' if (ret->%s[i] == NULL)\n' % obj.fixname) c_file.write(' return NULL;\n') @@ -158,7 +158,7 @@ def parse_obj_type_array(obj, c_file, prefix, obj_typename): c_file.write(' {\n') if obj.doublearray: c_file.write(' yajl_val *items = YAJL_GET_ARRAY_NO_CHECK(tmp)->values;\n') - c_file.write(' ret->%s = calloc ( YAJL_GET_ARRAY_NO_CHECK(tmp)->len + 1, sizeof (*ret->%s));\n' + c_file.write(' ret->%s = smart_calloc ( YAJL_GET_ARRAY_NO_CHECK(tmp)->len, 1, sizeof (*ret->%s));\n' % (obj.fixname, obj.fixname)) c_file.write(' if (ret->%s[i] == NULL)\n' % obj.fixname) c_file.write(' return NULL;\n') @@ -194,14 +194,14 @@ def parse_obj_type_array(obj, c_file, prefix, obj_typename): c_file.write(' size_t len = YAJL_GET_ARRAY_NO_CHECK (tmp)->len;\n') c_file.write(' yajl_val *values = YAJL_GET_ARRAY_NO_CHECK (tmp)->values;\n') c_file.write(' ret->%s_len = len;\n' % (obj.fixname)) - c_file.write(' ret->%s = calloc (len + 1, sizeof (*ret->%s));\n' \ + c_file.write(' ret->%s = smart_calloc (len, 1, sizeof (*ret->%s));\n' \ % (obj.fixname, obj.fixname)) c_file.write(' if (ret->%s == NULL)\n' % obj.fixname) c_file.write(' {\n') c_file.write(' return NULL;\n') c_file.write(' }\n') if obj.doublearray: - c_file.write(' ret->%s_item_lens = calloc ( len + 1, sizeof (size_t));\n' + c_file.write(' ret->%s_item_lens = smart_calloc ( len, 1, sizeof (size_t));\n' % (obj.fixname)) c_file.write(' if (ret->%s_item_lens == NULL)\n' % (obj.fixname)) c_file.write(' return NULL;\n') @@ -209,7 +209,7 @@ def parse_obj_type_array(obj, c_file, prefix, obj_typename): c_file.write(' {\n') if obj.doublearray: c_file.write(' yajl_val *items = YAJL_GET_ARRAY_NO_CHECK(values[i])->values;\n') - c_file.write(' ret->%s[i] = calloc ( YAJL_GET_ARRAY_NO_CHECK(values[i])->len + 1, sizeof (**ret->%s));\n' + c_file.write(' ret->%s[i] = smart_calloc ( YAJL_GET_ARRAY_NO_CHECK(values[i])->len, 1, sizeof (**ret->%s));\n' % (obj.fixname, obj.fixname)) c_file.write(' if (ret->%s[i] == NULL)\n' % obj.fixname) c_file.write(' return NULL;\n') @@ -344,19 +344,19 @@ def parse_obj_arr_obj(obj, c_file, prefix, obj_typename): if (ctx->options & OPT_PARSE_FULLKEY) { - resi = calloc (1, sizeof(*tree)); + resi = smart_calloc (1, 0, sizeof(*tree)); if (resi == NULL) { return NULL; } resi->type = yajl_t_object; - resi->u.object.keys = calloc (cnt, sizeof (const char *)); + resi->u.object.keys = smart_calloc (cnt, 0, sizeof (const char *)); if (resi->u.object.keys == NULL) { yajl_tree_free (resi); return NULL; } - resi->u.object.values = calloc (cnt, sizeof (yajl_val)); + resi->u.object.values = smart_calloc (cnt, 0, sizeof (yajl_val)); if (resi->u.object.values == NULL) { yajl_tree_free (resi); @@ -416,7 +416,7 @@ def parse_json_to_c(obj, c_file, prefix): c_file.write(" (void) ctx; /* Silence compiler warning. */\n") c_file.write(" if (tree == NULL)\n") c_file.write(" return NULL;\n") - c_file.write(" ret = calloc (1, sizeof (*ret));\n") + c_file.write(" ret = smart_calloc (1, 0, sizeof (*ret));\n") c_file.write(" if (ret == NULL)\n") c_file.write(" return NULL;\n") if obj.typ == 'mapStringObject': @@ -832,7 +832,7 @@ def read_val_generator(c_file, level, src, dest, typ, keyname, obj_typename): c_file.write('%syajl_val val = %s;\n' % (' ' * (level), src)) c_file.write('%sif (val != NULL)\n' % (' ' * (level))) c_file.write('%s {\n' % (' ' * (level))) - c_file.write('%s%s = calloc (1, sizeof (%s));\n' % + c_file.write('%s%s = smart_calloc (1, 0, sizeof (%s));\n' % (' ' * (level + 1), dest, helpers.get_map_c_types(num_type))) c_file.write('%sif (%s == NULL)\n' % (' ' * (level + 1), dest)) c_file.write('%s return NULL;\n' % (' ' * (level + 1))) @@ -867,7 +867,7 @@ def read_val_generator(c_file, level, src, dest, typ, keyname, obj_typename): c_file.write('%syajl_val val = %s;\n' % (' ' * (level), src)) c_file.write('%sif (val != NULL)\n' % (' ' * (level))) c_file.write('%s {\n' % (' ' * (level))) - c_file.write('%s%s = calloc (1, sizeof (bool));\n' % (' ' * (level + 1), dest)) + c_file.write('%s%s = smart_calloc (1, 0, sizeof (bool));\n' % (' ' * (level + 1), dest)) c_file.write('%sif (%s == NULL)\n' % (' ' * (level + 1), dest)) c_file.write('%s return NULL;\n' % (' ' * (level + 1))) c_file.write('%s*(%s) = YAJL_IS_TRUE(val);\n' % (' ' * (level + 1), dest)) @@ -878,7 +878,7 @@ def read_val_generator(c_file, level, src, dest, typ, keyname, obj_typename): % (' ' * (level + 1), keyname)) c_file.write('%sif (val != NULL)\n' % (' ' * (level + 1))) c_file.write('%s {\n' % (' ' * (level + 1))) - c_file.write('%s%s = calloc (1, sizeof (bool));\n' % (' ' * (level + 2), dest)) + c_file.write('%s%s = smart_calloc (1, 0, sizeof (bool));\n' % (' ' * (level + 2), dest)) c_file.write('%sif (%s == NULL)\n' % (' ' * (level + 2), dest)) c_file.write('%s return NULL;\n' % (' ' * (level + 2))) c_file.write('%s*(%s) = YAJL_IS_TRUE(val);\n' % (' ' * (level + 2), dest)) @@ -1163,17 +1163,17 @@ define_cleaner_function (%s *, free_%s)\n alen = YAJL_GET_ARRAY_NO_CHECK (tree)->len; if (alen == 0) return NULL; - ptr = calloc (1, sizeof (%s)); + ptr = smart_calloc (1, 0, sizeof (%s)); if (ptr == NULL) return NULL; - ptr->items = calloc (alen + 1, sizeof(*ptr->items)); + ptr->items = smart_calloc (alen, 1, sizeof(*ptr->items)); if (ptr->items == NULL) return NULL; ptr->len = alen; """ % (typename, typename, typename, typename, typename, typename, typename)) if obj.doublearray: - c_file.write(' ptr->subitem_lens = calloc ( alen + 1, sizeof (size_t));\n') + c_file.write(' ptr->subitem_lens = smart_calloc ( alen, 1, sizeof (size_t));\n') c_file.write(' if (ptr->subitem_lens == NULL)\n') c_file.write(' return NULL;') @@ -1191,7 +1191,7 @@ define_cleaner_function (%s *, free_%s)\n if obj.doublearray: c_file.write(' size_t j;\n') - c_file.write(' ptr->items[i] = calloc ( YAJL_GET_ARRAY_NO_CHECK(work)->len + 1, sizeof (**ptr->items));\n') + c_file.write(' ptr->items[i] = smart_calloc ( YAJL_GET_ARRAY_NO_CHECK(work)->len, 1, sizeof (**ptr->items));\n') c_file.write(' if (ptr->items[i] == NULL)\n') c_file.write(' return NULL;\n') c_file.write(' yajl_val *tmps = YAJL_GET_ARRAY_NO_CHECK(work)->values;\n') @@ -1220,7 +1220,7 @@ define_cleaner_function (%s *, free_%s)\n c_file.write(' break;\n') else: if obj.doublearray: - c_file.write(' ptr->items[i] = calloc ( YAJL_GET_ARRAY_NO_CHECK(work)->len + 1, sizeof (**ptr->items));\n') + c_file.write(' ptr->items[i] = smart_calloc ( YAJL_GET_ARRAY_NO_CHECK(work)->len, 1, sizeof (**ptr->items));\n') c_file.write(' if (ptr->items[i] == NULL)\n') c_file.write(' return NULL;\n') c_file.write(' size_t j;\n') @@ -1537,6 +1537,13 @@ define_cleaner_function (yajl_val, yajl_tree_free) return NULL; *err = NULL; + if (strlen(jsondata) >= JSON_MAX_SIZE) { + if (asprintf(err, "cannot parse the data with length exceeding %%llu", JSON_MAX_SIZE) < 0) { + *err = safe_strdup("error allocating memory"); + } + return NULL; + } + if (ctx == NULL) ctx = (const struct parser_context *)(&tmp_ctx); @@ -1601,7 +1608,7 @@ char * return json_buf; } - json_buf = calloc (1, gen_len + 1); + json_buf = smart_calloc (gen_len, 1, 1); if (json_buf == NULL) { *err = strdup ("Cannot allocate memory"); diff --git a/src/utils/utils_buffer.c b/src/utils/utils_buffer.c index da34991..05253ad 100644 --- a/src/utils/utils_buffer.c +++ b/src/utils/utils_buffer.c @@ -104,6 +104,10 @@ static int buffer_append(isula_buffer *buf, const char *append, size_t length) return 0; } + if (length == SIZE_MAX) { + return -1; + } + desired_length = length + 1; if (!buffer_has_space(buf, desired_length)) { if (buffer_grow(buf, desired_length) != 0) { diff --git a/src/utils/utils_cgroup.c b/src/utils/utils_cgroup.c index e4dde72..bd3bc42 100644 --- a/src/utils/utils_cgroup.c +++ b/src/utils/utils_cgroup.c @@ -29,6 +29,11 @@ /* swap in oci is memoy+swap, so here we need to get real swap */ int lcr_util_get_real_swap(int64_t memory, int64_t memory_swap, int64_t *swap) { + if (swap == NULL) { + ERROR("empty swap pointer"); + return -1; + } + if (memory == -1 && memory_swap == 0) { *swap = -1; // -1 is max return 0; diff --git a/tests/fuzz/log_fuzz.cc b/tests/fuzz/log_fuzz.cc index a8f80d4..4128ff6 100644 --- a/tests/fuzz/log_fuzz.cc +++ b/tests/fuzz/log_fuzz.cc @@ -40,7 +40,6 @@ extern "C" void testLog(struct isula_libutils_log_config *conf) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - const char *default_name = "iSula"; struct isula_libutils_log_config tconf = {0}; std::string testData(reinterpret_cast(data), size); std::vector ret_vec; @@ -67,6 +66,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) tconf.driver = ret_vec[4].c_str(); } } else { + const char *default_name = "iSula"; isula_libutils_default_log_config(default_name, &tconf); } -- 2.34.1