From: Max Reitz <mreitz@redhat.com>
To: Connor Kuehl <ckuehl@redhat.com>, qemu-block@nongnu.org
Cc: kwolf@redhat.com, dillaman@redhat.com, qemu-devel@nongnu.org
Subject: Re: [PATCH 2/2] block/rbd: Don't unescape in qemu_rbd_next_tok()
Date: Thu, 1 Apr 2021 19:24:34 +0200 [thread overview]
Message-ID: <c8a21743-6264-fe4e-294f-82f74766a5e7@redhat.com> (raw)
In-Reply-To: <20210401155211.2093139-3-ckuehl@redhat.com>
On 01.04.21 17:52, Connor Kuehl wrote:
> That's qemu_rbd_unescape()'s job! No need to duplicate the labor.
>
> Furthermore, this was causing some confusion in the parsing logic to
> where the caller might test for the presence of a character to split on
> like so:
>
> if (strchr(image_name, '/')) {
> found_str = qemu_rbd_next_tok(image_name, '/', &image_name);
> [..]
>
> When qemu_rbd_next_tok() performs unescaping as a side effect, the
> parser can get confused thinking that it can split this string, but
> really the delimiter '/' gets unescaped and so qemu_rbd_next_tok() never
> "finds" the delimiter and consumes the rest of the token input stream.
I don’t fully understand. I understand the strchr() problem and the
thing you explain next. But I would have thought that’s a problem of
using strchr(), i.e. that we’d need a custom function to do strchr() but
consider escaped characters. If it’s just about true/false like in your
example, it could be a new version of qemu_rbd_next_tok() that does not
modify the string.
Or, well, actually, in your example, one could unconditionally invoke
qemu_rbd_next_tok() and check whether *found_str is '\0' or not.
> This is problematic because qemu_rbd_next_tok() also steals the input
> pointer to the token stream and sets it to NULL. This causes a segfault
> where the parser expects to split one string into two.
I would say that’s a problem of the caller. It can pass a different
variable for the out-pointer, so the input pointer isn’t stolen.
> In this case, the parser is determining if a string is a
> namespace/image_name pair like so:
>
> "foo/bar"
>
> And clearly it's looking to split it like so:
>
> namespace: foo
> image_name: bar
>
> but if the input is "foo\/bar", it *should* split into
>
> namespace: foo\
> image_name: bar
Should it? I would have fully expected it to not be split and the
parser complains that the input is invalid. Or, let’s say,
"foo\/bar/baz” should be split into “foo\/bar” and “baz”.
Max
> and its subordinate parts can be unescaped after tokenization.
>
> So, instead of tokenizing *and* escaping all at once, do one before the
> other to avoid stumbling into a segfault by confusing the parsing logic.
>
> Reported-by: Han Han <hhan@redhat.com>
> Fixes: https://bugzilla.redhat.com/1873913
> Signed-off-by: Connor Kuehl <ckuehl@redhat.com>
> ---
> block/rbd.c | 3 ---
> tests/qemu-iotests/231 | 4 ++++
> tests/qemu-iotests/231.out | 3 +++
> 3 files changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/block/rbd.c b/block/rbd.c
> index 9071a00e3f..9bed0863e5 100644
> --- a/block/rbd.c
> +++ b/block/rbd.c
> @@ -123,9 +123,6 @@ static char *qemu_rbd_next_tok(char *src, char delim, char **p)
> if (*end == delim) {
> break;
> }
> - if (*end == '\\' && end[1] != '\0') {
> - end++;
> - }
> }
> if (*end == delim) {
> *p = end + 1;
> diff --git a/tests/qemu-iotests/231 b/tests/qemu-iotests/231
> index 0f66d0ca36..8e6c6447c1 100755
> --- a/tests/qemu-iotests/231
> +++ b/tests/qemu-iotests/231
> @@ -55,6 +55,10 @@ _filter_conf()
> $QEMU_IMG info "json:{'file.driver':'rbd','file.filename':'rbd:rbd/bogus:conf=${BOGUS_CONF}'}" 2>&1 | _filter_conf
> $QEMU_IMG info "json:{'file.driver':'rbd','file.pool':'rbd','file.image':'bogus','file.conf':'${BOGUS_CONF}'}" 2>&1 | _filter_conf
>
> +# Regression test: the qemu-img invocation is expected to fail, but it should
> +# not seg fault the parser.
> +$QEMU_IMG create "rbd:rbd/aa\/bb:conf=${BOGUS_CONF}" 1M 2>&1 | _filter_conf
> +
> # success, all done
> echo "*** done"
> rm -f $seq.full
> diff --git a/tests/qemu-iotests/231.out b/tests/qemu-iotests/231.out
> index 747dd221bb..a785a6e859 100644
> --- a/tests/qemu-iotests/231.out
> +++ b/tests/qemu-iotests/231.out
> @@ -4,4 +4,7 @@ unable to get monitor info from DNS SRV with service name: ceph-mon
> qemu-img: Could not open 'json:{'file.driver':'rbd','file.filename':'rbd:rbd/bogus:conf=BOGUS_CONF'}': error connecting: No such file or directory
> unable to get monitor info from DNS SRV with service name: ceph-mon
> qemu-img: Could not open 'json:{'file.driver':'rbd','file.pool':'rbd','file.image':'bogus','file.conf':'BOGUS_CONF'}': error connecting: No such file or directory
> +Formatting 'rbd:rbd/aa\/bb:conf=BOGUS_CONF', fmt=raw size=1048576
> +unable to get monitor info from DNS SRV with service name: ceph-mon
> +qemu-img: rbd:rbd/aa\/bb:conf=BOGUS_CONF: error connecting: No such file or directory
> *** done
>
next prev parent reply other threads:[~2021-04-01 17:26 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-01 15:52 [PATCH 0/2] Fix segfault in qemu_rbd_parse_filename Connor Kuehl
2021-04-01 15:52 ` [PATCH 1/2] iotests/231: Update expected deprecation message Connor Kuehl
2021-04-01 16:52 ` Max Reitz
2021-04-01 17:07 ` Max Reitz
2021-04-01 17:10 ` Connor Kuehl
2021-04-01 15:52 ` [PATCH 2/2] block/rbd: Don't unescape in qemu_rbd_next_tok() Connor Kuehl
2021-04-01 17:24 ` Max Reitz [this message]
2021-04-01 18:09 ` Connor Kuehl
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=c8a21743-6264-fe4e-294f-82f74766a5e7@redhat.com \
--to=mreitz@redhat.com \
--cc=ckuehl@redhat.com \
--cc=dillaman@redhat.com \
--cc=kwolf@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).