diff options
author | Thomas Haller <thaller@redhat.com> | 2022-03-15 10:35:02 (GMT) |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2022-03-16 23:11:14 (GMT) |
commit | d23fb814998f7afd26e2eb678919b0e3a796a91f (patch) | |
tree | 28f95d689f2cf70d5aa3923a0fa99100532123b8 /lib/xfrm/sa.c | |
parent | 7f7452c973a4f55f4d8ab6f8b36493a3b00a9397 (diff) | |
download | libnl-d23fb814998f7afd26e2eb678919b0e3a796a91f.zip libnl-d23fb814998f7afd26e2eb678919b0e3a796a91f.tar.gz libnl-d23fb814998f7afd26e2eb678919b0e3a796a91f.tar.bz2 |
lib: make nl_object_clone() out-of-memory safe
nl_object_clone() first does a shallow copy using memcpy().
That is useful, because it can correctly copy simple fields
(like numbers). For pointer values, we need to implement
oo_clone() to fixup the pointers and get the deep-copy correct.
Now, oo_clone() must always follow through, to un-alias the copied
pointer. In particular also in the error case. The oo_clone()
implementations sometimes fail (with ENOMEM) and just return.
In those cases, we must make sure that we don't leave the wrong pointers
there. The pointers must be cleared first.
Otherwise, any failure (which basically are ENOMEM) leave the object
in an inconsistent state, and we double-free/use-after-free the
pointers.
Diffstat (limited to 'lib/xfrm/sa.c')
-rw-r--r-- | lib/xfrm/sa.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/lib/xfrm/sa.c b/lib/xfrm/sa.c index d453c26..3b657bf 100644 --- a/lib/xfrm/sa.c +++ b/lib/xfrm/sa.c @@ -136,6 +136,20 @@ static int xfrm_sa_clone(struct nl_object *_dst, struct nl_object *_src) struct xfrmnl_sa* src = nl_object_priv(_src); uint32_t len = 0; + dst->sel = NULL; + dst->id.daddr = NULL; + dst->saddr = NULL; + dst->lft = NULL; + dst->aead = NULL; + dst->auth = NULL; + dst->crypt = NULL; + dst->comp = NULL; + dst->encap = NULL; + dst->coaddr = NULL; + dst->sec_ctx = NULL; + dst->replay_state_esn = NULL; + dst->user_offload = NULL; + if (src->sel) if ((dst->sel = xfrmnl_sel_clone (src->sel)) == NULL) return -NLE_NOMEM; |