diff options
Diffstat (limited to 'meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32643.patch')
-rw-r--r-- | meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32643.patch | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32643.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32643.patch new file mode 100644 index 0000000000..9c0867bf5f --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32643.patch | |||
@@ -0,0 +1,154 @@ | |||
1 | From 78da5faccb3e065116b75b3ff87ff55381da6c76 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Thu, 17 Aug 2023 11:24:43 +0000 | ||
4 | Subject: [PATCH] gvariant: Check offset table doesn't fall outside variant | ||
5 | bounds | ||
6 | |||
7 | When dereferencing the first entry in the offset table for a tuple, | ||
8 | check that it doesn’t fall outside the bounds of the variant first. | ||
9 | |||
10 | This prevents an out-of-bounds read from some non-normal tuples. | ||
11 | |||
12 | This bug was introduced in commit 73d0aa81c2575a5c9ae77d. | ||
13 | |||
14 | Includes a unit test, although the test will likely only catch the | ||
15 | original bug if run with asan enabled. | ||
16 | |||
17 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
18 | |||
19 | Fixes: #2840 | ||
20 | oss-fuzz#54302 | ||
21 | |||
22 | CVE: CVE-2023-32643 | ||
23 | Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/78da5faccb3e065116b75b3ff87ff55381da6c76] | ||
24 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
25 | --- | ||
26 | glib/gvariant-serialiser.c | 12 ++++++-- | ||
27 | glib/tests/gvariant.c | 63 ++++++++++++++++++++++++++++++++++++++ | ||
28 | 2 files changed, 72 insertions(+), 3 deletions(-) | ||
29 | |||
30 | diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c | ||
31 | index 5aa2cbc..4e50ed7 100644 | ||
32 | --- a/glib/gvariant-serialiser.c | ||
33 | +++ b/glib/gvariant-serialiser.c | ||
34 | @@ -979,7 +979,8 @@ gvs_tuple_get_member_bounds (GVariantSerialised value, | ||
35 | |||
36 | member_info = g_variant_type_info_member_info (value.type_info, index_); | ||
37 | |||
38 | - if (member_info->i + 1) | ||
39 | + if (member_info->i + 1 && | ||
40 | + offset_size * (member_info->i + 1) <= value.size) | ||
41 | member_start = gvs_read_unaligned_le (value.data + value.size - | ||
42 | offset_size * (member_info->i + 1), | ||
43 | offset_size); | ||
44 | @@ -990,7 +991,8 @@ gvs_tuple_get_member_bounds (GVariantSerialised value, | ||
45 | member_start &= member_info->b; | ||
46 | member_start |= member_info->c; | ||
47 | |||
48 | - if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST) | ||
49 | + if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST && | ||
50 | + offset_size * (member_info->i + 1) <= value.size) | ||
51 | member_end = value.size - offset_size * (member_info->i + 1); | ||
52 | |||
53 | else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED) | ||
54 | @@ -1001,11 +1003,15 @@ gvs_tuple_get_member_bounds (GVariantSerialised value, | ||
55 | member_end = member_start + fixed_size; | ||
56 | } | ||
57 | |||
58 | - else /* G_VARIANT_MEMBER_ENDING_OFFSET */ | ||
59 | + else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET && | ||
60 | + offset_size * (member_info->i + 2) <= value.size) | ||
61 | member_end = gvs_read_unaligned_le (value.data + value.size - | ||
62 | offset_size * (member_info->i + 2), | ||
63 | offset_size); | ||
64 | |||
65 | + else /* invalid */ | ||
66 | + member_end = G_MAXSIZE; | ||
67 | + | ||
68 | if (out_member_start != NULL) | ||
69 | *out_member_start = member_start; | ||
70 | if (out_member_end != NULL) | ||
71 | diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c | ||
72 | index 679dd40..2eca8be 100644 | ||
73 | --- a/glib/tests/gvariant.c | ||
74 | +++ b/glib/tests/gvariant.c | ||
75 | @@ -5432,6 +5432,67 @@ test_normal_checking_tuple_offsets4 (void) | ||
76 | g_variant_unref (variant); | ||
77 | } | ||
78 | |||
79 | +/* This is a regression test that dereferencing the first element in the offset | ||
80 | + * table doesn’t dereference memory before the start of the GVariant. The first | ||
81 | + * element in the offset table gives the offset of the final member in the | ||
82 | + * tuple (the offset table is stored in reverse), and the position of this final | ||
83 | + * member is needed to check that none of the tuple members overlap with the | ||
84 | + * offset table | ||
85 | + * | ||
86 | + * See https://gitlab.gnome.org/GNOME/glib/-/issues/2840 */ | ||
87 | +static void | ||
88 | +test_normal_checking_tuple_offsets5 (void) | ||
89 | +{ | ||
90 | + /* A tuple of type (sss) in normal form would have an offset table with two | ||
91 | + * entries: | ||
92 | + * - The first entry (lowest index in the table) gives the offset of the | ||
93 | + * third `s` in the tuple, as the offset table is reversed compared to the | ||
94 | + * tuple members. | ||
95 | + * - The second entry (highest index in the table) gives the offset of the | ||
96 | + * second `s` in the tuple. | ||
97 | + * - The offset of the first `s` in the tuple is always 0. | ||
98 | + * | ||
99 | + * See §2.5.4 (Structures) of the GVariant specification for details, noting | ||
100 | + * that the table is only layed out this way because all three members of the | ||
101 | + * tuple have non-fixed sizes. | ||
102 | + * | ||
103 | + * It’s not clear whether the 0xaa data of this variant is part of the strings | ||
104 | + * in the tuple, or part of the offset table. It doesn’t really matter. This | ||
105 | + * is a regression test to check that the code to validate the offset table | ||
106 | + * doesn’t unconditionally try to access the first entry in the offset table | ||
107 | + * by subtracting the table size from the end of the GVariant data. | ||
108 | + * | ||
109 | + * In this non-normal case, that would result in an address off the start of | ||
110 | + * the GVariant data, and an out-of-bounds read, because the GVariant is one | ||
111 | + * byte long, but the offset table is calculated as two bytes long (with 1B | ||
112 | + * sized entries) from the tuple’s type. | ||
113 | + */ | ||
114 | + const GVariantType *data_type = G_VARIANT_TYPE ("(sss)"); | ||
115 | + const guint8 data[] = { 0xaa }; | ||
116 | + gsize size = sizeof (data); | ||
117 | + GVariant *variant = NULL; | ||
118 | + GVariant *normal_variant = NULL; | ||
119 | + GVariant *expected = NULL; | ||
120 | + | ||
121 | + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2840"); | ||
122 | + | ||
123 | + variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL); | ||
124 | + g_assert_nonnull (variant); | ||
125 | + | ||
126 | + g_assert_false (g_variant_is_normal_form (variant)); | ||
127 | + | ||
128 | + normal_variant = g_variant_get_normal_form (variant); | ||
129 | + g_assert_nonnull (normal_variant); | ||
130 | + | ||
131 | + expected = g_variant_new_parsed ("('', '', '')"); | ||
132 | + g_assert_cmpvariant (expected, variant); | ||
133 | + g_assert_cmpvariant (expected, normal_variant); | ||
134 | + | ||
135 | + g_variant_unref (expected); | ||
136 | + g_variant_unref (normal_variant); | ||
137 | + g_variant_unref (variant); | ||
138 | +} | ||
139 | + | ||
140 | /* Test that an otherwise-valid serialised GVariant is considered non-normal if | ||
141 | * its offset table entries are too wide. | ||
142 | * | ||
143 | @@ -5680,6 +5741,8 @@ main (int argc, char **argv) | ||
144 | test_normal_checking_tuple_offsets3); | ||
145 | g_test_add_func ("/gvariant/normal-checking/tuple-offsets4", | ||
146 | test_normal_checking_tuple_offsets4); | ||
147 | + g_test_add_func ("/gvariant/normal-checking/tuple-offsets5", | ||
148 | + test_normal_checking_tuple_offsets5); | ||
149 | g_test_add_func ("/gvariant/normal-checking/tuple-offsets/minimal-sized", | ||
150 | test_normal_checking_tuple_offsets_minimal_sized); | ||
151 | g_test_add_func ("/gvariant/normal-checking/empty-object-path", | ||
152 | -- | ||
153 | 2.24.4 | ||
154 | |||