summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2022-03-04 20:49:06 (GMT)
committerThomas Haller <thaller@redhat.com>2022-03-04 21:07:54 (GMT)
commitc027e54ffed247358b152f5330b5dc62c821024f (patch)
tree53aa74bf84d737f392c67df97219105cb6395f1b /lib
parent47c04fbfbd0a867773bf2a8f9f81e5338ee31e30 (diff)
downloadlibnl-c027e54ffed247358b152f5330b5dc62c821024f.zip
libnl-c027e54ffed247358b152f5330b5dc62c821024f.tar.gz
libnl-c027e54ffed247358b152f5330b5dc62c821024f.tar.bz2
route:cls: fix dangling pointers in to_clone() implementations
rtnl_tc_clone() first does a shallow-copy (nl_data_clone()), and then calls the to_clone() implementation. We need the shallow-copy, because we want that by default all simple fields get cloned automatically. But it means, we *must* take care of all pointers in the to_clone() implementation, and must never return without fixing them. Otherwise we will do a double free. An early "return -NLE_NOMEM;" leaves the pointer unchanged, and two objects own the same data (double free and use-after-free says hello).
Diffstat (limited to 'lib')
-rw-r--r--lib/route/cls/cgroup.c2
-rw-r--r--lib/route/cls/fw.c5
-rw-r--r--lib/route/cls/mall.c2
-rw-r--r--lib/route/cls/u32.c6
4 files changed, 14 insertions, 1 deletions
diff --git a/lib/route/cls/cgroup.c b/lib/route/cls/cgroup.c
index ba72fe2..ff993d1 100644
--- a/lib/route/cls/cgroup.c
+++ b/lib/route/cls/cgroup.c
@@ -32,6 +32,8 @@ static int cgroup_clone(void *_dst, void *_src)
{
struct rtnl_cgroup *dst = _dst, *src = _src;
+ dst->cg_ematch = NULL;
+
if (src->cg_ematch) {
dst->cg_ematch = rtnl_ematch_tree_clone(src->cg_ematch);
if (!dst->cg_ematch)
diff --git a/lib/route/cls/fw.c b/lib/route/cls/fw.c
index f35f659..2952efc 100644
--- a/lib/route/cls/fw.c
+++ b/lib/route/cls/fw.c
@@ -88,9 +88,12 @@ static int fw_clone(void *_dst, void *_src)
{
struct rtnl_fw *dst = _dst, *src = _src;
+ dst->cf_act = NULL;
+ dst->cf_police = NULL;
+
if (src->cf_act && !(dst->cf_act = nl_data_clone(src->cf_act)))
return -NLE_NOMEM;
-
+
if (src->cf_police && !(dst->cf_police = nl_data_clone(src->cf_police)))
return -NLE_NOMEM;
diff --git a/lib/route/cls/mall.c b/lib/route/cls/mall.c
index ba9bc0d..ded08c6 100644
--- a/lib/route/cls/mall.c
+++ b/lib/route/cls/mall.c
@@ -222,6 +222,8 @@ static int mall_clone(void *_dst, void *_src)
struct rtnl_act *next, *new;
int err;
+ dst->m_act = NULL;
+
if (src->m_act) {
if (!(dst->m_act = rtnl_act_alloc()))
return -NLE_NOMEM;
diff --git a/lib/route/cls/u32.c b/lib/route/cls/u32.c
index 7eb2e52..55163d1 100644
--- a/lib/route/cls/u32.c
+++ b/lib/route/cls/u32.c
@@ -178,6 +178,12 @@ static int u32_clone(void *_dst, void *_src)
{
struct rtnl_u32 *dst = _dst, *src = _src;
+ dst->cu_pcnt = NULL;
+ dst->cu_selector = NULL;
+ dst->cu_mark = NULL;
+ dst->cu_act = NULL;
+ dst->cu_police = NULL;
+
if (src->cu_selector &&
!(dst->cu_selector = nl_data_clone(src->cu_selector)))
return -NLE_NOMEM;