diff options
author | Thomas Haller <thaller@redhat.com> | 2022-03-04 20:49:06 (GMT) |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2022-03-04 21:07:54 (GMT) |
commit | c027e54ffed247358b152f5330b5dc62c821024f (patch) | |
tree | 53aa74bf84d737f392c67df97219105cb6395f1b /lib | |
parent | 47c04fbfbd0a867773bf2a8f9f81e5338ee31e30 (diff) | |
download | libnl-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.c | 2 | ||||
-rw-r--r-- | lib/route/cls/fw.c | 5 | ||||
-rw-r--r-- | lib/route/cls/mall.c | 2 | ||||
-rw-r--r-- | lib/route/cls/u32.c | 6 |
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; |