2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-30 13:58:34 +00:00

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 <ptikhomirov@virtuozzo.com>
This commit is contained in:
Pavel Tikhomirov
2022-03-09 13:52:00 +03:00
committed by Andrei Vagin
parent 7e9a9dc342
commit 09fa32a755

View File

@@ -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);
}