[prev in list] [next in list] [prev in thread] [next in thread]
List: elinks-dev
Subject: Re: [elinks-dev] festival command injection when PIPE_BUF < 1037
From: Kalle Olavi Niemitalo <kon () iki ! fi>
Date: 2007-03-09 19:50:42
Message-ID: 87lki6i4bx.fsf () Astalo ! kon ! iki ! fi
[Download RAW message or body]
[Attachment #2 (multipart/signed)]
Content-Transfer-Encoding: quoted-printable
Witek, I see you have fixed this bug in commit
1f09c740a8207b38a475ec1375fc859b90b3a625. Please consider
applying the patch at the end of this message to clarify the
assumptions being made.
I'm still worrying about these problems in the speech code:
- Does "festival -i" enable readline-like functionality that
could be used to erase the quote character before the parser
sees it, and thus inject arbitrary commands again? When ELinks
reads struct screen_char in order to generate a string that it
will send to the terminal, it filters out control characters;
doing the same here might be prudent. Of course, if festival
automatically disables such functionality when its stdin is not
a terminal, then such filtering is not needed, but this should
be documented.
- If struct screen_char contains UCS-4, write_to_festival uses
only the low 8 bits. I think this clashes with the intention
to make --enable-utf-8 the default in ELinks 0.12.0. The input
charsets of the speech synthesizer executables are very badly
documented but the espeak library apparently can autodetect
between UTF-8 and the language-specific ISO-8859-*, and for
festival and flite the appropriate charset depends on the voice
selected in configuration files. So ELinks should have a
configuration option for the speech charset, and recode to
that. Because the charset conversion can change the number of
bytes in the string, the MAX_LINE_LENGTH restriction may have
to be implemented in a different way.
After those issues have been resolved, I think the speech code
can be merged, and then the following less important problems
should also be fixed or at least added to bugzilla:
- The document.speech.system option is documented as "Default
speech system". This is wrong because ELinks never uses a
non-"default" speech system.
- If the speech synthesizer process dies for any reason, there
should be a way to make ELinks spawn a new one. Perhaps by
detecting EPIPE?
Perhaps there should also be a way to let the user specify the
file name of the speech synthesizer executable. I don't know
though how to best prevent kiosk users from specifying arbitrary
executables in an anonymous-mode ELinks.
festival: Assert that writes are not short. Add comments.
---
commit f6a8bcdd75e68f9153c7115edce7f3714f1a7225
tree f27156249ad0674b37bffbf2c889010032908237
parent 1f09c740a8207b38a475ec1375fc859b90b3a625
author Kalle Olavi Niemitalo <kon@iki.fi> Thu, 08 Mar 2007 00:33:50 +0200
committer Kalle Olavi Niemitalo <Kalle@Astalo.kon.iki.fi> Thu, 08 Mar 2007 00:33:50 +0200
src/viewer/text/festival.c | 29 +++++++++++++++++++++++++++++
1 files changed, 29 insertions(+), 0 deletions(-)
diff --git a/src/viewer/text/festival.c b/src/viewer/text/festival.c
index d67bba4..a4f83cd 100644
--- a/src/viewer/text/festival.c
+++ b/src/viewer/text/festival.c
@@ -50,10 +50,16 @@ read_from_festival(struct fest *fest)
NULL, NULL, fest);
}
+/* These numbers must match the documentation of the
+ * "document.speech.system" option. */
#define FESTIVAL_SYSTEM 0
#define FLITE_SYSTEM 1
#define ESPEAK_SYSTEM 2
+/* How many character cells to speak from each line. Because
+ * write_to_festival currently cannot recover from short writes, this
+ * must be set so low that the generated string cannot become more
+ * than PIPE_BUF bytes long. SUSv2 says PIPE_BUF >= 512. */
#define MAX_LINE_LENGTH 240
static void
@@ -86,6 +92,8 @@ write_to_festival(struct fest *fest)
data = doc->data[fest->line].chars;
if (festival.speech_system == FESTIVAL_SYSTEM) {
+ /* The string generated here will be at most
+ * 10+MAX_LINE_LENGTH*2+2+1 bytes long. */
add_to_string(&buf, "(SayText \"");
/* UTF-8 not supported yet. Does festival support UTF-8? */
for (i = 0; i < len; i++) {
@@ -105,8 +113,29 @@ write_to_festival(struct fest *fest)
}
add_char_to_string(&buf, '\n');
+ /* Cannot allow a short write here. It would probably cause
+ * an unpaired quote character to be sent to festival,
+ * enabling a command injection attack. If buf.length <=
+ * PIPE_BUF, then the write will occur either completely or
+ * not at all. Compare to _POSIX_PIPE_BUF instead, to ensure
+ * portability to systems with an unusually low PIPE_BUF.
+ * If this assertion fails, that means MAX_LINE_LENGTH was
+ * set too high. */
+ assert(buf.length <= _POSIX_PIPE_BUF);
+ if_assert_failed { buf.length = 0; }
w = safe_write(fest->out, buf.source, buf.length);
if (w >= 0) {
+ assert(w == buf.length);
+ if_assert_failed {
+ /* The input parser of the festival process is
+ * now in an unknown state. */
+ clear_handlers(fest->in);
+ close(fest->in);
+ fest->in = -1;
+ clear_handlers(fest->out);
+ close(fest->out);
+ fest->out = -1;
+ }
if (fest->line >= doc_view->vs->y + doc_view->box.height) {
move_page_down(doc_view->session, doc_view);
refresh_view(doc_view->session, doc_view, 0);
[Attachment #5 (application/pgp-signature)]
_______________________________________________
elinks-dev mailing list
elinks-dev@linuxfromscratch.org
http://linuxfromscratch.org/mailman/listinfo/elinks-dev
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic