From 3ee13066884acb4ac16cb41ed4ac01bb94fab4f6 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 23 May 2023 09:55:17 +0200
Subject: [PATCH] json: correctly handle magic strings when parsing variant
 strv

We can't dereference the variant object directly, as it might be
a magic object (which has an address on a faulting page); use
json_variant_is_sensitive() instead that handles this case.

For example, with an empty array:

==1547789==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000023 (pc 0x7fd616ca9a18 bp 0x7ffcba1dc7c0 sp 0x7ffcba1dc6d0 T0)
==1547789==The signal is caused by a READ memory access.
==1547789==Hint: address points to the zero page.
SCARINESS: 10 (null-deref)
    #0 0x7fd616ca9a18 in json_variant_strv ../src/shared/json.c:2190
    #1 0x408332 in oci_args ../src/nspawn/nspawn-oci.c:173
    #2 0x7fd616cc09ce in json_dispatch ../src/shared/json.c:4400
    #3 0x40addf in oci_process ../src/nspawn/nspawn-oci.c:428
    #4 0x7fd616cc09ce in json_dispatch ../src/shared/json.c:4400
    #5 0x41fef5 in oci_load ../src/nspawn/nspawn-oci.c:2187
    #6 0x4061e4 in LLVMFuzzerTestOneInput ../src/nspawn/fuzz-nspawn-oci.c:23
    #7 0x40691c in main ../src/fuzz/fuzz-main.c:50
    #8 0x7fd61564a50f in __libc_start_call_main (/lib64/libc.so.6+0x2750f)
    #9 0x7fd61564a5c8 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x275c8)
    #10 0x405da4 in _start (/home/fsumsal/repos/@systemd/systemd/build-san/fuzz-nspawn-oci+0x405da4)

DEDUP_TOKEN: json_variant_strv--oci_args--json_dispatch
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ../src/shared/json.c:2190 in json_variant_strv
==1547789==ABORTING

Or with an empty string in an array:

../src/shared/json.c:2202:39: runtime error: member access within misaligned address 0x000000000007 for type 'struct JsonVariant', which requires 8 byte alignment
0x000000000007: note: pointer points here
<memory cannot be printed>
    #0 0x7f35f4ca9bcf in json_variant_strv ../src/shared/json.c:2202
    #1 0x408332 in oci_args ../src/nspawn/nspawn-oci.c:173
    #2 0x7f35f4cc09ce in json_dispatch ../src/shared/json.c:4400
    #3 0x40addf in oci_process ../src/nspawn/nspawn-oci.c:428
    #4 0x7f35f4cc09ce in json_dispatch ../src/shared/json.c:4400
    #5 0x41fef5 in oci_load ../src/nspawn/nspawn-oci.c:2187
    #6 0x4061e4 in LLVMFuzzerTestOneInput ../src/nspawn/fuzz-nspawn-oci.c:23
    #7 0x40691c in main ../src/fuzz/fuzz-main.c:50
    #8 0x7f35f364a50f in __libc_start_call_main (/lib64/libc.so.6+0x2750f)
    #9 0x7f35f364a5c8 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x275c8)
    #10 0x405da4 in _start (/home/fsumsal/repos/@systemd/systemd/build-san/fuzz-nspawn-oci+0x405da4)

SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../src/shared/json.c:2202:39 in

Note: this happens only if json_variant_copy() in json_variant_set_source() fails.

Found by Nallocfuzz.

(cherry picked from commit 909eb4c01de03a32c915a2267166501dca5b78f6)
(cherry picked from commit 58c1816aa43b96b5ce0953bc8ff78c37c4226216)
(cherry picked from commit 89ab32d166a6920a14c19b90fe528c02ed5f4142)

Conflict:code context adaptation
Reference:https://github.com/systemd/systemd-stable/commit/3ee13066884acb4ac16cb41ed4ac01bb94fab4f6
---
 src/shared/json.c                                    | 4 ++--
 test/fuzz/fuzz-nspawn-oci/invalid-read-magic-string  | 1 +
 test/fuzz/fuzz-nspawn-oci/invalid-read-magic-string2 | 1 +
 3 files changed, 4 insertions(+), 2 deletions(-)
 create mode 100644 test/fuzz/fuzz-nspawn-oci/invalid-read-magic-string
 create mode 100644 test/fuzz/fuzz-nspawn-oci/invalid-read-magic-string2

diff --git a/src/shared/json.c b/src/shared/json.c
index 3ab562e219..6748dbcf8d 100644
--- a/src/shared/json.c
+++ b/src/shared/json.c
@@ -2103,7 +2103,7 @@ int json_variant_strv(JsonVariant *v, char ***ret) {
         if (!json_variant_is_array(v))
                 return -EINVAL;
 
-        sensitive = v->sensitive;
+        sensitive = json_variant_is_sensitive(v);
 
         n = json_variant_elements(v);
         l = new(char*, n+1);
@@ -2114,7 +2114,7 @@ int json_variant_strv(JsonVariant *v, char ***ret) {
                 JsonVariant *e;
 
                 assert_se(e = json_variant_by_index(v, i));
-                sensitive = sensitive || e->sensitive;
+                sensitive = sensitive || json_variant_is_sensitive(e);
 
                 if (!json_variant_is_string(e)) {
                         l[i] = NULL;
diff --git a/test/fuzz/fuzz-nspawn-oci/invalid-read-magic-string b/test/fuzz/fuzz-nspawn-oci/invalid-read-magic-string
new file mode 100644
index 0000000000..675bed0505
--- /dev/null
+++ b/test/fuzz/fuzz-nspawn-oci/invalid-read-magic-string
@@ -0,0 +1 @@
+{"ociVersion":"1.0.0","process":{"args":[]}}
diff --git a/test/fuzz/fuzz-nspawn-oci/invalid-read-magic-string2 b/test/fuzz/fuzz-nspawn-oci/invalid-read-magic-string2
new file mode 100644
index 0000000000..fb1269b9c8
--- /dev/null
+++ b/test/fuzz/fuzz-nspawn-oci/invalid-read-magic-string2
@@ -0,0 +1 @@
+{"ociVersion":"1.0.0","process":{"args":[""]}}
\ No newline at end of file
-- 
2.33.0

