summaryrefslogtreecommitdiffstats
path: root/lib/fib_lookup
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2022-03-15 10:35:02 (GMT)
committerThomas Haller <thaller@redhat.com>2022-03-16 23:11:14 (GMT)
commitd23fb814998f7afd26e2eb678919b0e3a796a91f (patch)
tree28f95d689f2cf70d5aa3923a0fa99100532123b8 /lib/fib_lookup
parent7f7452c973a4f55f4d8ab6f8b36493a3b00a9397 (diff)
downloadlibnl-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.c10
-rw-r--r--lib/fib_lookup/request.c5
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;
}