From 09fa32a755070d29f8501875d42ea4baf2b7da01 Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Wed, 9 Mar 2022 13:52:00 +0300 Subject: [PATCH] tun: fix tun_link leak in dump_tun_link coverity CID 389205: 452int dump_tun_link(NetDeviceEntry *nde, struct cr_imgset *fds, struct nlattr **info) 453{ ... 458 struct tun_link *tl; ... 2. alloc_fn: Storage is returned from allocation function get_tun_link_fd. [show details] 3. var_assign: Assigning: tl = storage returned from get_tun_link_fd(nde->name, nde->peer_nsid, tle.flags). 475 tl = get_tun_link_fd(nde->name, nde->peer_nsid, tle.flags); 4. Condition !tl, taking false branch. 476 if (!tl) 477 return ret; 478 479 tle.vnethdr = tl->dmp.vnethdr; 480 tle.sndbuf = tl->dmp.sndbuf; 481 482 nde->tun = &tle; CID 389205 (#1 of 1): Resource leak (RESOURCE_LEAK)5. leaked_storage: Variable tl going out of scope leaks the storage it points to. 483 return write_netdev_img(nde, fds, info); 484} Function get_tun_link_fd() can both return tun_link entry from tun_links list and a newly allocated one. So we should not free entry if it is from list and should free it when it is a new one to fix leak. Signed-off-by: Pavel Tikhomirov --- criu/tun.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/criu/tun.c b/criu/tun.c index 2a2f950da..bc84604b3 100644 --- a/criu/tun.c +++ b/criu/tun.c @@ -155,6 +155,7 @@ static struct tun_link *__dump_tun_link_fd(int fd, char *name, unsigned ns_id, u goto err; strlcpy(tl->name, name, sizeof(tl->name)); tl->ns_id = ns_id; + INIT_LIST_HEAD(&tl->l); if (ioctl(fd, TUNGETVNETHDRSZ, &tl->dmp.vnethdr) < 0) { pr_perror("Can't dump vnethdr size for %s", name); @@ -479,6 +480,14 @@ int dump_tun_link(NetDeviceEntry *nde, struct cr_imgset *fds, struct nlattr **in tle.vnethdr = tl->dmp.vnethdr; tle.sndbuf = tl->dmp.sndbuf; + /* + * Function get_tun_link_fd() can return either entry + * from tun_links list or a newly allocated one, need to + * free it only if not in list. + */ + if (list_empty(&tl->l)) + xfree(tl); + nde->tun = &tle; return write_netdev_img(nde, fds, info); }