From patchwork Mon Mar 20 10:09:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yauheni Kaliuta X-Patchwork-Id: 9633665 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id E6F1F601E9 for ; Mon, 20 Mar 2017 10:09:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DA22127F95 for ; Mon, 20 Mar 2017 10:09:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CEE0327FA0; Mon, 20 Mar 2017 10:09:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6C0E727F95 for ; Mon, 20 Mar 2017 10:09:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753645AbdCTKId (ORCPT ); Mon, 20 Mar 2017 06:08:33 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50514 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753701AbdCTKHj (ORCPT ); Mon, 20 Mar 2017 06:07:39 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F11BD41A2F; Mon, 20 Mar 2017 10:07:38 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com F11BD41A2F Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=yauheni.kaliuta@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com F11BD41A2F Received: from astarta.redhat.com (ovpn-117-61.ams2.redhat.com [10.36.117.61]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 414E278DDF; Mon, 20 Mar 2017 10:07:38 +0000 (UTC) From: Yauheni Kaliuta To: linux-modules Cc: Lucas De Marchi Subject: [PATCH] depmod: fix errorpath memleaks in report cycles logic Date: Mon, 20 Mar 2017 12:09:51 +0200 Message-Id: <20170320100951.20884-1-yauheni.kaliuta@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Mon, 20 Mar 2017 10:07:39 +0000 (UTC) Sender: owner-linux-modules@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP From: Yauheni Kaliuta The c7ce9f0c80f3d561078a78205a14c5ba7663cfdd commit (depmod: handle nested loops) introduced a bunch of possible memory leaks in error path. In the real world scenario it is not a problem, since the utility quits if it detects any of the errors, but from the programming point of view, it is not nice. So, add the cleanups. Signed-off-by: Yauheni Kaliuta --- tools/depmod.c | 54 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/tools/depmod.c b/tools/depmod.c index 116adbeb14a0..7f9e9804787e 100644 --- a/tools/depmod.c +++ b/tools/depmod.c @@ -1481,10 +1481,10 @@ static void depmod_list_remove_data(struct kmod_list **list, void *data) *list = l; } -static void depmod_report_one_cycle(struct depmod *depmod, - struct vertex *vertex, - struct kmod_list **roots, - struct hash *loop_set) +static int depmod_report_one_cycle(struct depmod *depmod, + struct vertex *vertex, + struct kmod_list **roots, + struct hash *loop_set) { const char sep[] = " -> "; size_t sz; @@ -1493,6 +1493,7 @@ static void depmod_report_one_cycle(struct depmod *depmod, int i; int n; struct vertex *v; + int rc; array_init(&reverse, 3); @@ -1503,7 +1504,10 @@ static void depmod_report_one_cycle(struct depmod *depmod, sz += v->mod->modnamesz - 1; array_append(&reverse, v); - hash_add(loop_set, v->mod->modname, NULL); + rc = hash_add(loop_set, v->mod->modname, NULL); + if (rc != 0) + return rc; + /* the hash will be freed where created */ } sz += vertex->mod->modnamesz - 1; @@ -1528,6 +1532,8 @@ static void depmod_report_one_cycle(struct depmod *depmod, free(buf); array_free_array(&reverse); + + return 0; } static int depmod_report_cycles_from_root(struct depmod *depmod, @@ -1545,17 +1551,18 @@ static int depmod_report_cycles_from_root(struct depmod *depmod, struct mod *m; struct mod **itr, **itr_end; size_t is; + int ret = -ENOMEM; root = vertex_new(root_mod, NULL); if (root == NULL) { ERR("No memory to report cycles\n"); - return -ENOMEM; + goto out; } l = kmod_list_append(free_list, root); if (l == NULL) { ERR("No memory to report cycles\n"); - return -ENOMEM; + goto out; } free_list = l; @@ -1570,8 +1577,13 @@ static int depmod_report_cycles_from_root(struct depmod *depmod, * from part of a loop or from a branch after a loop */ if (m->visited && m == root->mod) { - depmod_report_one_cycle(depmod, vertex, - roots, loop_set); + int rc; + rc = depmod_report_one_cycle(depmod, vertex, + roots, loop_set); + if (rc != 0) { + ret = rc; + goto out; + } continue; } @@ -1598,7 +1610,7 @@ static int depmod_report_cycles_from_root(struct depmod *depmod, v = vertex_new(dep, vertex); if (v == NULL) { ERR("No memory to report cycles\n"); - return -ENOMEM; + goto out; } assert(is < stack_size); stack[is++] = v; @@ -1606,12 +1618,15 @@ static int depmod_report_cycles_from_root(struct depmod *depmod, l = kmod_list_append(free_list, v); if (l == NULL) { ERR("No memory to report cycles\n"); - return -ENOMEM; + goto out; } free_list = l; } } + ret = 0; + +out: while (free_list) { v = free_list->data; l = kmod_list_remove(free_list); @@ -1619,7 +1634,7 @@ static int depmod_report_cycles_from_root(struct depmod *depmod, free(v); } - return 0; + return ret; } static void depmod_report_cycles(struct depmod *depmod, uint16_t n_mods, @@ -1643,7 +1658,7 @@ static void depmod_report_cycles(struct depmod *depmod, uint16_t n_mods, l = kmod_list_append(roots, m); if (l == NULL) { ERR("No memory to report cycles\n"); - return; + goto out_list; } roots = l; n_r++; @@ -1652,13 +1667,13 @@ static void depmod_report_cycles(struct depmod *depmod, uint16_t n_mods, stack = malloc(n_r * sizeof(void *)); if (stack == NULL) { ERR("No memory to report cycles\n"); - return; + goto out_list; } loop_set = hash_new(16, NULL); if (loop_set == NULL) { ERR("No memory to report cycles\n"); - return; + goto out_list; } while (roots != NULL) { @@ -1670,14 +1685,19 @@ static void depmod_report_cycles(struct depmod *depmod, uint16_t n_mods, &roots, stack, n_r, loop_set); if (err < 0) - goto err; + goto out_hash; } num_cyclic = hash_get_count(loop_set); ERR("Found %d modules in dependency cycles!\n", num_cyclic); -err: +out_hash: hash_free(loop_set); +out_list: + while (roots != NULL) { + /* no need to free data, come from outside */ + roots = kmod_list_remove(roots); + } } static int depmod_calculate_dependencies(struct depmod *depmod)