Re: [DTrace-devel] [PATCH v3] dvar: ensure dynamic variables cannot overwrite eachother

Eugene Loh <[email protected]>
Newsgroups dev.linux.lists.dtrace
Message-ID <[email protected]>
Reviewed-by: Eugene Loh <[email protected]>

On 8/11/25 16:22, Kris Van Hees via DTrace-devel wrote:
> As Eugene discovered, it was possible for dynamic variables (elements
> of associative arrays and TLS variables) to overwrite eachother.  The

eachother

> problem turns out to be due to the implementation of the BPF helper
> bpf_map_update_elem().  In order for the update to be seen as an atomic
> operation, it does not update the value of the map element in-place but
> instead allocates a new element and places it in front of the old one
> before it removes the old one.  The result is that the address of the
> map element changes as a result of the bpf_map_update_elem() call.
>
> Fortunately, we can just assign the address of the map element in the
> value that we obtained using bpf_map_lookup_elem() because that gives
> us a pointer to the map value, and we can assign directly into it.
>
> In other words, we do not need the 2nd bpf_map_update_elem() anyway,
> and since that was the culprit, removing it resolves the issue.
>
> Test included.
>
> Signed-off-by: Kris Van Hees <[email protected]>
> Signed-off-by: Eugene Loh <[email protected]>
> ---
>   bpf/get_dvar.c                       |  5 +----
>   test/unittest/assocs/tst.collision.d | 22 ++++++++++++++++++++++
>   2 files changed, 23 insertions(+), 4 deletions(-)
>   create mode 100644 test/unittest/assocs/tst.collision.d
>
> diff --git a/bpf/get_dvar.c b/bpf/get_dvar.c
> index 1bb5eb002..073cca57c 100644
> --- a/bpf/get_dvar.c
> +++ b/bpf/get_dvar.c
> @@ -1,6 +1,6 @@
>   // SPDX-License-Identifier: GPL-2.0
>   /*
> - * Copyright (c) 2019, 2024, Oracle and/or its affiliates.
> + * Copyright (c) 2019, 2025, Oracle and/or its affiliates.
>    */
>   #include <linux/bpf.h>
>   #include <stdint.h>
> @@ -150,9 +150,6 @@ noinline void *dt_get_assoc(uint32_t id, const char *tuple, uint64_t store,
>   		if (valp == 0)
>   			return dt_no_dvar();
>   		*valp = (uint64_t)valp;
> -		if (bpf_map_update_elem(&tuples, tuple, valp, BPF_ANY) < 0)
> -			return dt_no_dvar();
> -
>   		val = *valp;
>   	} else {
>   		/*
> diff --git a/test/unittest/assocs/tst.collision.d b/test/unittest/assocs/tst.collision.d
> new file mode 100644
> index 000000000..11a4363ca
> --- /dev/null
> +++ b/test/unittest/assocs/tst.collision.d
> @@ -0,0 +1,22 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + */
> +
> +/*
> + * ASSERTION: Dynamic variables do not overwrite eachother.
> + */
> +
> +BEGIN
> +{
> +	assoc[0x1234] = 1;
> +	self->tls_assoc[1] = 0x1111;
> +	self->tls_assoc[1] = 0;
> +	self->tls_assoc[1] = 0x2222;
> +
> +	printf("%x / %x\n", assoc[0x1234], self->tls_assoc[1]);
> +
> +	exit(assoc[0x1234] == 1 && self->tls_assoc[1] == 0x2222 ? 0 : 1);
> +}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.