|
 |
c6b9e5 |
From cc0b8bdf124c47090d0b794c9b6e2e3852c860d9 Mon Sep 17 00:00:00 2001
|
|
 |
c6b9e5 |
From: Hanno Boeck <hanno@hboeck.de>
|
|
 |
c6b9e5 |
Date: Mon, 22 Feb 2016 07:46:17 -0500
|
|
 |
c6b9e5 |
Subject: [PATCH] GVariant text: fix scan of positional parameters
|
|
 |
c6b9e5 |
|
|
 |
c6b9e5 |
The scanning to find the end of a positional parameter designator in
|
|
 |
c6b9e5 |
GVariant text format (e.g. '%i') is currently broken in case the 'end'
|
|
 |
c6b9e5 |
pointer is not specified.
|
|
 |
c6b9e5 |
|
|
 |
c6b9e5 |
The scan is controlled by a somewhat complicated loop that needs to deal
|
|
 |
c6b9e5 |
properly with cases like (123, %(ii)) [where '%(ii)' is to be taken
|
|
 |
c6b9e5 |
together, but the final ')' not].
|
|
 |
c6b9e5 |
|
|
 |
c6b9e5 |
This loop missed the case where a format string passed to
|
|
 |
c6b9e5 |
g_variant_new_parsed() ended immediately after such a conversion, with a
|
|
 |
c6b9e5 |
nul character. In this case the 'end' pointer is NULL, so the only way
|
|
 |
c6b9e5 |
we can find the end is by scanning for nul in the string.
|
|
 |
c6b9e5 |
|
|
 |
c6b9e5 |
In case of g_variant_new_parsed() [which is what this code was designed
|
|
 |
c6b9e5 |
to be used for], the bug is somewhat unlikely in practice: the only way
|
|
 |
c6b9e5 |
that a valid text-form GVariant could ever contain a positional
|
|
 |
c6b9e5 |
parameter replacement at the end of the string is if this positional
|
|
 |
c6b9e5 |
parameter were the only thing being returned. In that case, the user
|
|
 |
c6b9e5 |
would likely have opted for a more direct approach.
|
|
 |
c6b9e5 |
|
|
 |
c6b9e5 |
Unfortunately, this code is also active in the tokenisation phase of
|
|
 |
c6b9e5 |
g_variant_parse(), before positional parameters are rejected as invalid
|
|
 |
c6b9e5 |
for that case. Anyone who calls this function with a nul-terminated
|
|
 |
c6b9e5 |
string (and no end pointer) is vulnerable to a crash from malicious user
|
|
 |
c6b9e5 |
input. This can be seen, at the very least with many commandline tools:
|
|
 |
c6b9e5 |
|
|
 |
c6b9e5 |
$ dconf write /x '%i'
|
|
 |
c6b9e5 |
Segmentation fault
|
|
 |
c6b9e5 |
|
|
 |
c6b9e5 |
We fix this problem by searching for the nul character in this case, in
|
|
 |
c6b9e5 |
addition to comparing the end pointer.
|
|
 |
c6b9e5 |
|
|
 |
c6b9e5 |
This problem is almost certainly limited to being able to cause crashes.
|
|
 |
c6b9e5 |
The loop in question only performs reads and, in the security-sensitive
|
|
 |
c6b9e5 |
case, the token will be quickly rejected after the loop is finished
|
|
 |
c6b9e5 |
(since it starts with '%' and the 'app' pointer is unset). This is
|
|
 |
c6b9e5 |
further mitigated by the fact that there are no known cases of GVariant
|
|
 |
c6b9e5 |
text format being used as part of a protocol at a privilege barrier.
|
|
 |
c6b9e5 |
---
|
|
 |
c6b9e5 |
glib/gvariant-parser.c | 2 +-
|
|
 |
c6b9e5 |
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
 |
c6b9e5 |
|
|
 |
c6b9e5 |
diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c
|
|
 |
c6b9e5 |
index e7dab85..9f4bcc5 100644
|
|
 |
c6b9e5 |
--- a/glib/gvariant-parser.c
|
|
 |
c6b9e5 |
+++ b/glib/gvariant-parser.c
|
|
 |
c6b9e5 |
@@ -237,7 +237,7 @@ token_stream_prepare (TokenStream *stream)
|
|
 |
c6b9e5 |
* Also: ] and > are never in format strings.
|
|
 |
c6b9e5 |
*/
|
|
 |
c6b9e5 |
for (end = stream->stream + 1;
|
|
 |
c6b9e5 |
- end != stream->end && *end != ',' &&
|
|
 |
c6b9e5 |
+ end != stream->end && *end != '\0' && *end != ',' &&
|
|
 |
c6b9e5 |
*end != ':' && *end != '>' && *end != ']' && !g_ascii_isspace (*end);
|
|
 |
c6b9e5 |
end++)
|
|
 |
c6b9e5 |
|
|
 |
c6b9e5 |
--
|
|
 |
c6b9e5 |
1.8.3.1
|
|
 |
c6b9e5 |
|