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/fib_lookup | |
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/fib_lookup')
-rw-r--r-- | lib/fib_lookup/lookup.c | 10 | ||||
-rw-r--r-- | lib/fib_lookup/request.c | 5 |
2 files changed, 10 insertions, 5 deletions
diff --git a/lib/fib_lookup/lookup.c b/lib/fib_lookup/lookup.c index 6c5635d..e258546 100644 --- a/lib/fib_lookup/lookup.c +++ b/lib/fib_lookup/lookup.c @@ -55,11 +55,13 @@ static int result_clone(struct nl_object *_dst, struct nl_object *_src) struct flnl_result *dst = nl_object_priv(_dst); struct flnl_result *src = nl_object_priv(_src); - if (src->fr_req) - if (!(dst->fr_req = (struct flnl_request *) - nl_object_clone(OBJ_CAST(src->fr_req)))) + dst->fr_req = NULL; + + if (src->fr_req) { + if (!(dst->fr_req = (struct flnl_request *) nl_object_clone(OBJ_CAST(src->fr_req)))) return -NLE_NOMEM; - + } + return 0; } diff --git a/lib/fib_lookup/request.c b/lib/fib_lookup/request.c index 6b70fe4..0773c3b 100644 --- a/lib/fib_lookup/request.c +++ b/lib/fib_lookup/request.c @@ -40,9 +40,12 @@ static int request_clone(struct nl_object *_dst, struct nl_object *_src) struct flnl_request *dst = nl_object_priv(_dst); struct flnl_request *src = nl_object_priv(_src); - if (src->lr_addr) + dst->lr_addr = NULL; + + if (src->lr_addr) { if (!(dst->lr_addr = nl_addr_clone(src->lr_addr))) return -NLE_NOMEM; + } return 0; } |