[CRIU] [PATCH] net: Relax xmalloc-ing (and fix NULL deref)

Pavel Emelyanov xemul at virtuozzo.com
Fri Jun 16 18:19:04 MSK 2017


There's potential NULL-derefernece in dump_netns_con() -- two xmalloc
results are not checked. However, since there's a huge set of these
xmallocs, I propose to relax the whole thing with one big xmalloc and
xptr_pull() helper.

Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
 criu/net.c | 55 +++++++++++++++++++++----------------------------------
 1 file changed, 21 insertions(+), 34 deletions(-)

diff --git a/criu/net.c b/criu/net.c
index 6849cd2..90aa947 100644
--- a/criu/net.c
+++ b/criu/net.c
@@ -1564,6 +1564,7 @@ static inline int dump_iptables(struct cr_imgset *fds)
 
 static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
 {
+	void *buf, *o_buf;
 	int ret = -1;
 	int i;
 	NetnsEntry netns = NETNS_ENTRY__INIT;
@@ -1580,8 +1581,16 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
 	list_for_each_entry(p, &ns->net.ids, node)
 		i++;
 
-	netns.nsids = xmalloc(sizeof(NetnsId *) * i);
-	ids = xmalloc(sizeof(NetnsId) * i);
+	o_buf = buf = xmalloc(
+			i * (sizeof(NetnsId*) + sizeof(NetnsId)) +
+			size4 * (sizeof(SysctlEntry*) + sizeof(SysctlEntry)) * 2 +
+			size6 * (sizeof(SysctlEntry*) + sizeof(SysctlEntry)) * 2
+		     );
+	if (!buf)
+		goto out;
+
+	netns.nsids = xptr_pull_s(&buf, i * sizeof(NetnsId*));
+	ids = xptr_pull_s(&buf, i * sizeof(NetnsId));
 	i = 0;
 	list_for_each_entry(p, &ns->net.ids, node) {
 		netns_id__init(&ids[i]);
@@ -1594,18 +1603,10 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
 
 	netns.n_def_conf4 = size4;
 	netns.n_all_conf4 = size4;
-	netns.def_conf4 = xmalloc(sizeof(SysctlEntry *) * size4);
-	if (!netns.def_conf4)
-		goto err_free;
-	netns.all_conf4 = xmalloc(sizeof(SysctlEntry *) * size4);
-	if (!netns.all_conf4)
-		goto err_free;
-	def_confs4 = xmalloc(sizeof(SysctlEntry) * size4);
-	if (!def_confs4)
-		goto err_free;
-	all_confs4 = xmalloc(sizeof(SysctlEntry) * size4);
-	if (!all_confs4)
-		goto err_free;
+	netns.def_conf4 = xptr_pull_s(&buf, size4 * sizeof(SysctlEntry*));
+	netns.all_conf4 = xptr_pull_s(&buf, size4 * sizeof(SysctlEntry*));
+	def_confs4 = xptr_pull_s(&buf, size4 * sizeof(SysctlEntry));
+	all_confs4 = xptr_pull_s(&buf, size4 * sizeof(SysctlEntry));
 
 	for (i = 0; i < size4; i++) {
 		sysctl_entry__init(&def_confs4[i]);
@@ -1618,18 +1619,10 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
 
 	netns.n_def_conf6 = size6;
 	netns.n_all_conf6 = size6;
-	netns.def_conf6 = xmalloc(sizeof(SysctlEntry *) * size6);
-	if (!netns.def_conf6)
-		goto err_free;
-	netns.all_conf6 = xmalloc(sizeof(SysctlEntry *) * size6);
-	if (!netns.all_conf6)
-		goto err_free;
-	def_confs6 = xmalloc(sizeof(SysctlEntry) * size6);
-	if (!def_confs6)
-		goto err_free;
-	all_confs6 = xmalloc(sizeof(SysctlEntry) * size6);
-	if (!all_confs6)
-		goto err_free;
+	netns.def_conf6 = xptr_pull_s(&buf, size6 * sizeof(SysctlEntry*));
+	netns.all_conf6 = xptr_pull_s(&buf, size6 * sizeof(SysctlEntry*));
+	def_confs6 = xptr_pull_s(&buf, size6 * sizeof(SysctlEntry));
+	all_confs6 = xptr_pull_s(&buf, size6 * sizeof(SysctlEntry));
 
 	for (i = 0; i < size6; i++) {
 		sysctl_entry__init(&def_confs6[i]);
@@ -1663,14 +1656,8 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
 
 	ret = pb_write_one(img_from_set(fds, CR_FD_NETNS), &netns, PB_NETNS);
 err_free:
-	xfree(netns.def_conf4);
-	xfree(netns.all_conf4);
-	xfree(def_confs4);
-	xfree(all_confs4);
-	xfree(netns.def_conf6);
-	xfree(netns.all_conf6);
-	xfree(def_confs6);
-	xfree(all_confs6);
+	xfree(o_buf);
+out:
 	return ret;
 }
 
-- 
2.1.4


More information about the CRIU mailing list