diff mbox series

[bpf-next,v2,10/11] selftests/bpf: Add UAF tests for arena atomics

Message ID 20240701133432.3883-11-iii@linux.ibm.com (mailing list archive)
State Superseded
Delegated to: BPF
Headers show
Series s390/bpf: Implement arena | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-VM_Test-6 success Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-4 success Logs for aarch64-gcc / build / build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-9 success Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-11 fail Logs for s390x-gcc / build / build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-12 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-13 success Logs for s390x-gcc / test
bpf/vmtest-bpf-next-VM_Test-14 success Logs for s390x-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-15 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-16 success Logs for x86_64-gcc / build / build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-17 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-18 success Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-19 success Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-20 success Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-21 success Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-22 success Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-23 success Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-24 fail Logs for x86_64-gcc / veristat / veristat on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-25 success Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-26 success Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17-O2
bpf/vmtest-bpf-next-VM_Test-27 success Logs for x86_64-llvm-17 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-28 success Logs for x86_64-llvm-17 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-29 success Logs for x86_64-llvm-17 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-30 success Logs for x86_64-llvm-17 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-31 success Logs for x86_64-llvm-17 / veristat
bpf/vmtest-bpf-next-VM_Test-32 success Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-33 success Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18-O2
bpf/vmtest-bpf-next-VM_Test-34 success Logs for x86_64-llvm-18 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-35 success Logs for x86_64-llvm-18 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-36 success Logs for x86_64-llvm-18 / test (test_progs_cpuv4, false, 360) / test_progs_cpuv4 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-37 success Logs for x86_64-llvm-18 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-38 success Logs for x86_64-llvm-18 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-39 success Logs for x86_64-llvm-18 / veristat
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for bpf-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 8 this patch: 8
netdev/build_tools success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers warning 12 maintainers not CCed: yonghong.song@linux.dev mykolal@fb.com haoluo@google.com jolsa@kernel.org shuah@kernel.org song@kernel.org john.fastabend@gmail.com eddyz87@gmail.com kpsingh@kernel.org linux-kselftest@vger.kernel.org martin.lau@linux.dev sdf@google.com
netdev/build_clang success Errors and warnings before: 8 this patch: 8
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 8 this patch: 8
netdev/checkpatch warning WARNING: Use of volatile is usually wrong: see Documentation/process/volatile-considered-harmful.rst WARNING: please, no spaces at the start of a line
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-PR success PR summary
bpf/vmtest-bpf-next-VM_Test-8 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-0 success Logs for Lint
bpf/vmtest-bpf-next-VM_Test-10 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-2 success Logs for Unittests
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-5 success Logs for aarch64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-3 success Logs for Validate matrix.py
bpf/vmtest-bpf-next-VM_Test-7 success Logs for s390x-gcc / build-release

Commit Message

Ilya Leoshkevich July 1, 2024, 1:24 p.m. UTC
Check that __sync_*() functions don't cause kernel panics when handling
freed arena pages.

x86_64 does not support some arena atomics yet, and aarch64 may or may
not support them, based on the availability of LSE atomics at run time.
Do not enable this test for these architectures for simplicity.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
 .../selftests/bpf/prog_tests/arena_atomics.c  | 18 +++++
 .../selftests/bpf/progs/arena_atomics.c       | 76 +++++++++++++++++++
 2 files changed, 94 insertions(+)

Comments

Daniel Borkmann July 1, 2024, 3:22 p.m. UTC | #1
On 7/1/24 3:24 PM, Ilya Leoshkevich wrote:
> Check that __sync_*() functions don't cause kernel panics when handling
> freed arena pages.
> 
> x86_64 does not support some arena atomics yet, and aarch64 may or may
> not support them, based on the availability of LSE atomics at run time.
> Do not enable this test for these architectures for simplicity.
> 
> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
> ---
>   .../selftests/bpf/prog_tests/arena_atomics.c  | 18 +++++
>   .../selftests/bpf/progs/arena_atomics.c       | 76 +++++++++++++++++++
>   2 files changed, 94 insertions(+)
> 
> diff --git a/tools/testing/selftests/bpf/prog_tests/arena_atomics.c b/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
> index 0807a48a58ee..26e7c06c6cb4 100644
> --- a/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
> +++ b/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
> @@ -146,6 +146,22 @@ static void test_xchg(struct arena_atomics *skel)
>   	ASSERT_EQ(skel->arena->xchg32_result, 1, "xchg32_result");
>   }
>   
> +static void test_uaf(struct arena_atomics *skel)
> +{
> +	LIBBPF_OPTS(bpf_test_run_opts, topts);
> +	int err, prog_fd;
> +
> +	/* No need to attach it, just run it directly */
> +	prog_fd = bpf_program__fd(skel->progs.uaf);
> +	err = bpf_prog_test_run_opts(prog_fd, &topts);
> +	if (!ASSERT_OK(err, "test_run_opts err"))
> +		return;
> +	if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
> +		return;
> +
> +	ASSERT_EQ(skel->arena->uaf_recovery_fails, 0, "uaf_recovery_fails");
> +}
> +
>   void test_arena_atomics(void)
>   {
>   	struct arena_atomics *skel;
> @@ -180,6 +196,8 @@ void test_arena_atomics(void)
>   		test_cmpxchg(skel);
>   	if (test__start_subtest("xchg"))
>   		test_xchg(skel);
> +	if (test__start_subtest("uaf"))
> +		test_uaf(skel);
>   
>   cleanup:
>   	arena_atomics__destroy(skel);
> diff --git a/tools/testing/selftests/bpf/progs/arena_atomics.c b/tools/testing/selftests/bpf/progs/arena_atomics.c
> index 55f10563208d..0ea310713fe6 100644
> --- a/tools/testing/selftests/bpf/progs/arena_atomics.c
> +++ b/tools/testing/selftests/bpf/progs/arena_atomics.c
> @@ -176,3 +176,79 @@ int xchg(const void *ctx)
>   
>   	return 0;
>   }
> +
> +__u64 __arena uaf_sink;
> +volatile __u64 __arena uaf_recovery_fails;
> +
> +SEC("syscall")
> +int uaf(const void *ctx)
> +{
> +	if (pid != (bpf_get_current_pid_tgid() >> 32))
> +		return 0;
> +#if defined(ENABLE_ATOMICS_TESTS) && !defined(__TARGET_ARCH_arm64) && \
> +    !defined(__TARGET_ARCH_x86)
> +	__u32 __arena *page32;
> +	__u64 __arena *page64;
> +	void __arena *page;
> +

Looks like the selftest is failing s390x-gcc CI build, ptal :

   https://github.com/kernel-patches/bpf/actions/runs/9745362735/job/26893165998

   [...]
     CLNG-BPF [test_maps] btf__core_reloc_size.bpf.o
     CLNG-BPF [test_maps] bind6_prog.bpf.o
   progs/arena_atomics.c:190:8: error: 'section' attribute only applies to functions, global variables, Objective-C methods, and Objective-C properties
     190 |         __u32 __arena *page32;
         |               ^
   progs/arena_atomics.c:32:17: note: expanded from macro '__arena'
      32 | #define __arena SEC(".addr_space.1")
         |                 ^
   /tmp/work/bpf/bpf/tools/testing/selftests/bpf/tools/include/bpf/bpf_helpers.h:40:17: note: expanded from macro 'SEC'
      40 |         __attribute__((section(name), used))                                \
         |                        ^
   progs/arena_atomics.c:191:8: error: 'section' attribute only applies to functions, global variables, Objective-C methods, and Objective-C properties
     191 |         __u64 __arena *page64;
         |               ^
   progs/arena_atomics.c:32:17: note: expanded from macro '__arena'
      32 | #define __arena SEC(".addr_space.1")
         |                 ^
   /tmp/work/bpf/bpf/tools/testing/selftests/bpf/tools/include/bpf/bpf_helpers.h:40:17: note: expanded from macro 'SEC'
      40 |         __attribute__((section(name), used))                                \
         |                        ^
   progs/arena_atomics.c:192:7: error: 'section' attribute only applies to functions, global variables, Objective-C methods, and Objective-C properties
     192 |         void __arena *page;
         |              ^
   progs/arena_atomics.c:32:17: note: expanded from macro '__arena'
      32 | #define __arena SEC(".addr_space.1")
         |                 ^
   /tmp/work/bpf/bpf/tools/testing/selftests/bpf/tools/include/bpf/bpf_helpers.h:40:17: note: expanded from macro 'SEC'
      40 |         __attribute__((section(name), used))                                \
         |                        ^
   3 errors generated.
     CLNG-BPF [test_maps] cpumask_success.bpf.o
   make: *** [Makefile:654: /tmp/work/bpf/bpf/tools/testing/selftests/bpf/arena_atomics.bpf.o] Error 1
   make: *** Waiting for unfinished jobs....
     CLNG-BPF [test_maps] fib_lookup.bpf.o
   make: Leaving directory '/tmp/work/bpf/bpf/tools/testing/selftests/bpf'
   Error: Process completed with exit code 2.
Ilya Leoshkevich July 1, 2024, 5:02 p.m. UTC | #2
On Mon, 2024-07-01 at 17:22 +0200, Daniel Borkmann wrote:
> On 7/1/24 3:24 PM, Ilya Leoshkevich wrote:
> > Check that __sync_*() functions don't cause kernel panics when
> > handling
> > freed arena pages.
> > 
> > x86_64 does not support some arena atomics yet, and aarch64 may or
> > may
> > not support them, based on the availability of LSE atomics at run
> > time.
> > Do not enable this test for these architectures for simplicity.
> > 
> > Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
> > ---
> >   .../selftests/bpf/prog_tests/arena_atomics.c  | 18 +++++
> >   .../selftests/bpf/progs/arena_atomics.c       | 76
> > +++++++++++++++++++
> >   2 files changed, 94 insertions(+)
> > 
> > diff --git a/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
> > b/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
> > index 0807a48a58ee..26e7c06c6cb4 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
> > @@ -146,6 +146,22 @@ static void test_xchg(struct arena_atomics
> > *skel)
> >   	ASSERT_EQ(skel->arena->xchg32_result, 1, "xchg32_result");
> >   }
> >   
> > +static void test_uaf(struct arena_atomics *skel)
> > +{
> > +	LIBBPF_OPTS(bpf_test_run_opts, topts);
> > +	int err, prog_fd;
> > +
> > +	/* No need to attach it, just run it directly */
> > +	prog_fd = bpf_program__fd(skel->progs.uaf);
> > +	err = bpf_prog_test_run_opts(prog_fd, &topts);
> > +	if (!ASSERT_OK(err, "test_run_opts err"))
> > +		return;
> > +	if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
> > +		return;
> > +
> > +	ASSERT_EQ(skel->arena->uaf_recovery_fails, 0,
> > "uaf_recovery_fails");
> > +}
> > +
> >   void test_arena_atomics(void)
> >   {
> >   	struct arena_atomics *skel;
> > @@ -180,6 +196,8 @@ void test_arena_atomics(void)
> >   		test_cmpxchg(skel);
> >   	if (test__start_subtest("xchg"))
> >   		test_xchg(skel);
> > +	if (test__start_subtest("uaf"))
> > +		test_uaf(skel);
> >   
> >   cleanup:
> >   	arena_atomics__destroy(skel);
> > diff --git a/tools/testing/selftests/bpf/progs/arena_atomics.c
> > b/tools/testing/selftests/bpf/progs/arena_atomics.c
> > index 55f10563208d..0ea310713fe6 100644
> > --- a/tools/testing/selftests/bpf/progs/arena_atomics.c
> > +++ b/tools/testing/selftests/bpf/progs/arena_atomics.c
> > @@ -176,3 +176,79 @@ int xchg(const void *ctx)
> >   
> >   	return 0;
> >   }
> > +
> > +__u64 __arena uaf_sink;
> > +volatile __u64 __arena uaf_recovery_fails;
> > +
> > +SEC("syscall")
> > +int uaf(const void *ctx)
> > +{
> > +	if (pid != (bpf_get_current_pid_tgid() >> 32))
> > +		return 0;
> > +#if defined(ENABLE_ATOMICS_TESTS) && !defined(__TARGET_ARCH_arm64)
> > && \
> > +    !defined(__TARGET_ARCH_x86)
> > +	__u32 __arena *page32;
> > +	__u64 __arena *page64;
> > +	void __arena *page;
> > +
> 
> Looks like the selftest is failing s390x-gcc CI build, ptal :
> 
>   
> https://github.com/kernel-patches/bpf/actions/runs/9745362735/job/26893165998
> 
>    [...]
>      CLNG-BPF [test_maps] btf__core_reloc_size.bpf.o
>      CLNG-BPF [test_maps] bind6_prog.bpf.o
>    progs/arena_atomics.c:190:8: error: 'section' attribute only
> applies to functions, global variables, Objective-C methods, and
> Objective-C properties
>      190 |         __u32 __arena *page32;
>          |               ^
>    progs/arena_atomics.c:32:17: note: expanded from macro '__arena'
>       32 | #define __arena SEC(".addr_space.1")
>          |                 ^
>   
> /tmp/work/bpf/bpf/tools/testing/selftests/bpf/tools/include/bpf/bpf_h
> elpers.h:40:17: note: expanded from macro 'SEC'
>       40 |         __attribute__((section(name),
> used))                                \
>          |                        ^
>    progs/arena_atomics.c:191:8: error: 'section' attribute only
> applies to functions, global variables, Objective-C methods, and
> Objective-C properties
>      191 |         __u64 __arena *page64;
>          |               ^
>    progs/arena_atomics.c:32:17: note: expanded from macro '__arena'
>       32 | #define __arena SEC(".addr_space.1")
>          |                 ^
>   
> /tmp/work/bpf/bpf/tools/testing/selftests/bpf/tools/include/bpf/bpf_h
> elpers.h:40:17: note: expanded from macro 'SEC'
>       40 |         __attribute__((section(name),
> used))                                \
>          |                        ^
>    progs/arena_atomics.c:192:7: error: 'section' attribute only
> applies to functions, global variables, Objective-C methods, and
> Objective-C properties
>      192 |         void __arena *page;
>          |              ^
>    progs/arena_atomics.c:32:17: note: expanded from macro '__arena'
>       32 | #define __arena SEC(".addr_space.1")
>          |                 ^
>   
> /tmp/work/bpf/bpf/tools/testing/selftests/bpf/tools/include/bpf/bpf_h
> elpers.h:40:17: note: expanded from macro 'SEC'
>       40 |         __attribute__((section(name),
> used))                                \
>          |                        ^
>    3 errors generated.
>      CLNG-BPF [test_maps] cpumask_success.bpf.o
>    make: *** [Makefile:654:
> /tmp/work/bpf/bpf/tools/testing/selftests/bpf/arena_atomics.bpf.o]
> Error 1
>    make: *** Waiting for unfinished jobs....
>      CLNG-BPF [test_maps] fib_lookup.bpf.o
>    make: Leaving directory
> '/tmp/work/bpf/bpf/tools/testing/selftests/bpf'
>    Error: Process completed with exit code 2.

Apparently this particular test redefines the __arena macro.

The "common" definition is __attribute__((address_space(1))) for LLVM,
and nothing for GCC. I assume this doesn't work if one wants to have
globals inside the arena, hence the redefinition. Unfortunately the
redefinition breaks the usage of __arena in pointer types.

I think I will replace the redefinition with a separate __arena_global
macro.
diff mbox series

Patch

diff --git a/tools/testing/selftests/bpf/prog_tests/arena_atomics.c b/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
index 0807a48a58ee..26e7c06c6cb4 100644
--- a/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
+++ b/tools/testing/selftests/bpf/prog_tests/arena_atomics.c
@@ -146,6 +146,22 @@  static void test_xchg(struct arena_atomics *skel)
 	ASSERT_EQ(skel->arena->xchg32_result, 1, "xchg32_result");
 }
 
+static void test_uaf(struct arena_atomics *skel)
+{
+	LIBBPF_OPTS(bpf_test_run_opts, topts);
+	int err, prog_fd;
+
+	/* No need to attach it, just run it directly */
+	prog_fd = bpf_program__fd(skel->progs.uaf);
+	err = bpf_prog_test_run_opts(prog_fd, &topts);
+	if (!ASSERT_OK(err, "test_run_opts err"))
+		return;
+	if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
+		return;
+
+	ASSERT_EQ(skel->arena->uaf_recovery_fails, 0, "uaf_recovery_fails");
+}
+
 void test_arena_atomics(void)
 {
 	struct arena_atomics *skel;
@@ -180,6 +196,8 @@  void test_arena_atomics(void)
 		test_cmpxchg(skel);
 	if (test__start_subtest("xchg"))
 		test_xchg(skel);
+	if (test__start_subtest("uaf"))
+		test_uaf(skel);
 
 cleanup:
 	arena_atomics__destroy(skel);
diff --git a/tools/testing/selftests/bpf/progs/arena_atomics.c b/tools/testing/selftests/bpf/progs/arena_atomics.c
index 55f10563208d..0ea310713fe6 100644
--- a/tools/testing/selftests/bpf/progs/arena_atomics.c
+++ b/tools/testing/selftests/bpf/progs/arena_atomics.c
@@ -176,3 +176,79 @@  int xchg(const void *ctx)
 
 	return 0;
 }
+
+__u64 __arena uaf_sink;
+volatile __u64 __arena uaf_recovery_fails;
+
+SEC("syscall")
+int uaf(const void *ctx)
+{
+	if (pid != (bpf_get_current_pid_tgid() >> 32))
+		return 0;
+#if defined(ENABLE_ATOMICS_TESTS) && !defined(__TARGET_ARCH_arm64) && \
+    !defined(__TARGET_ARCH_x86)
+	__u32 __arena *page32;
+	__u64 __arena *page64;
+	void __arena *page;
+
+	page = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
+	bpf_arena_free_pages(&arena, page, 1);
+	uaf_recovery_fails = 24;
+
+	page32 = (__u32 __arena *)page;
+	uaf_sink += __sync_fetch_and_add(page32, 1);
+	uaf_recovery_fails -= 1;
+	__sync_add_and_fetch(page32, 1);
+	uaf_recovery_fails -= 1;
+	uaf_sink += __sync_fetch_and_sub(page32, 1);
+	uaf_recovery_fails -= 1;
+	__sync_sub_and_fetch(page32, 1);
+	uaf_recovery_fails -= 1;
+	uaf_sink += __sync_fetch_and_and(page32, 1);
+	uaf_recovery_fails -= 1;
+	__sync_and_and_fetch(page32, 1);
+	uaf_recovery_fails -= 1;
+	uaf_sink += __sync_fetch_and_or(page32, 1);
+	uaf_recovery_fails -= 1;
+	__sync_or_and_fetch(page32, 1);
+	uaf_recovery_fails -= 1;
+	uaf_sink += __sync_fetch_and_xor(page32, 1);
+	uaf_recovery_fails -= 1;
+	__sync_xor_and_fetch(page32, 1);
+	uaf_recovery_fails -= 1;
+	uaf_sink += __sync_val_compare_and_swap(page32, 0, 1);
+	uaf_recovery_fails -= 1;
+	uaf_sink += __sync_lock_test_and_set(page32, 1);
+	uaf_recovery_fails -= 1;
+
+	page64 = (__u64 __arena *)page;
+	uaf_sink += __sync_fetch_and_add(page64, 1);
+	uaf_recovery_fails -= 1;
+	__sync_add_and_fetch(page64, 1);
+	uaf_recovery_fails -= 1;
+	uaf_sink += __sync_fetch_and_sub(page64, 1);
+	uaf_recovery_fails -= 1;
+	__sync_sub_and_fetch(page64, 1);
+	uaf_recovery_fails -= 1;
+	uaf_sink += __sync_fetch_and_and(page64, 1);
+	uaf_recovery_fails -= 1;
+	__sync_and_and_fetch(page64, 1);
+	uaf_recovery_fails -= 1;
+	uaf_sink += __sync_fetch_and_or(page64, 1);
+	uaf_recovery_fails -= 1;
+	__sync_or_and_fetch(page64, 1);
+	uaf_recovery_fails -= 1;
+	uaf_sink += __sync_fetch_and_xor(page64, 1);
+	uaf_recovery_fails -= 1;
+	__sync_xor_and_fetch(page64, 1);
+	uaf_recovery_fails -= 1;
+	uaf_sink += __sync_val_compare_and_swap(page64, 0, 1);
+	uaf_recovery_fails -= 1;
+	uaf_sink += __sync_lock_test_and_set(page64, 1);
+	uaf_recovery_fails -= 1;
+#endif
+
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";