From: Roman Penyaev <r.peniaev@gmail.com>
With bitset management now it becomes feasible to implement
the logic of detaching frontends from multiplexer.
Signed-off-by: Roman Penyaev <r.peniaev@gmail.com>
Cc: "Marc-André Lureau" <marcandre.lureau@redhat.com>
Cc: qemu-devel@nongnu.org
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20241014152408.427700-8-r.peniaev@gmail.com>
---
chardev/chardev-internal.h | 1 +
chardev/char-fe.c | 2 +-
chardev/char-mux.c | 21 ++++++++++++++++++---
3 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/chardev/chardev-internal.h b/chardev/chardev-internal.h
index b89aada541..853807f3cb 100644
--- a/chardev/chardev-internal.h
+++ b/chardev/chardev-internal.h
@@ -61,6 +61,7 @@ DECLARE_INSTANCE_CHECKER(MuxChardev, MUX_CHARDEV,
bool mux_chr_attach_frontend(MuxChardev *d, CharBackend *b,
unsigned int *tag, Error **errp);
+bool mux_chr_detach_frontend(MuxChardev *d, unsigned int tag);
void mux_set_focus(Chardev *chr, unsigned int focus);
void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event);
diff --git a/chardev/char-fe.c b/chardev/char-fe.c
index 3b8771ca2a..8ac6bebb6f 100644
--- a/chardev/char-fe.c
+++ b/chardev/char-fe.c
@@ -225,7 +225,7 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del)
}
if (CHARDEV_IS_MUX(b->chr)) {
MuxChardev *d = MUX_CHARDEV(b->chr);
- d->backends[b->tag] = NULL;
+ mux_chr_detach_frontend(d, b->tag);
}
if (del) {
Object *obj = OBJECT(b->chr);
diff --git a/chardev/char-mux.c b/chardev/char-mux.c
index 4fc619b2da..bda5c45e60 100644
--- a/chardev/char-mux.c
+++ b/chardev/char-mux.c
@@ -290,10 +290,10 @@ static void char_mux_finalize(Object *obj)
bit = -1;
while ((bit = find_next_bit(&d->mux_bitset, MAX_MUX, bit + 1)) < MAX_MUX) {
CharBackend *be = d->backends[bit];
- if (be) {
- be->chr = NULL;
- }
+ be->chr = NULL;
+ d->backends[bit] = NULL;
}
+ d->mux_bitset = 0;
qemu_chr_fe_deinit(&d->chr, false);
}
@@ -332,6 +332,21 @@ bool mux_chr_attach_frontend(MuxChardev *d, CharBackend *b,
return true;
}
+bool mux_chr_detach_frontend(MuxChardev *d, unsigned int tag)
+{
+ unsigned int bit;
+
+ bit = find_next_bit(&d->mux_bitset, MAX_MUX, tag);
+ if (bit != tag) {
+ return false;
+ }
+
+ d->mux_bitset &= ~(1 << bit);
+ d->backends[bit] = NULL;
+
+ return true;
+}
+
void mux_set_focus(Chardev *chr, unsigned int focus)
{
MuxChardev *d = MUX_CHARDEV(chr);
--
2.47.0
On Tue, 15 Oct 2024 at 09:52, <marcandre.lureau@redhat.com> wrote:
>
> From: Roman Penyaev <r.peniaev@gmail.com>
>
> With bitset management now it becomes feasible to implement
> the logic of detaching frontends from multiplexer.
>
> Signed-off-by: Roman Penyaev <r.peniaev@gmail.com>
> Cc: "Marc-André Lureau" <marcandre.lureau@redhat.com>
> Cc: qemu-devel@nongnu.org
> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> Message-ID: <20241014152408.427700-8-r.peniaev@gmail.com>
Hi; Coverity reports an issue with this patch. I think
it's probably a bit confused, but on the other hand
I read the code and am also a bit confused so we could
probably adjust it to be clearer...
> +bool mux_chr_detach_frontend(MuxChardev *d, unsigned int tag)
> +{
> + unsigned int bit;
> +
> + bit = find_next_bit(&d->mux_bitset, MAX_MUX, tag);
Why are we calling find_next_bit() here? Coverity
points out that it can return MAX_MUX, which means that
if the caller passed in MAX_MUX then we will try to
dereference d->backends[MAX_MUX] which is off the
end of the array.
What I was expecting this code to do was to check
"is the bit actually currently set?", which would be
if (!(d->mux_bitset & (1 << bit))) {
...
}
Why do we want to find the next bit set after the
'tag' bit ?
> + if (bit != tag) {
> + return false;
> + }
> +
> + d->mux_bitset &= ~(1 << bit);
> + d->backends[bit] = NULL;
> +
> + return true;
> +}
(This is CID 1563776.)
thanks
-- PMM
Hi Peter,
On Fri, Nov 1, 2024 at 4:25 PM Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Tue, 15 Oct 2024 at 09:52, <marcandre.lureau@redhat.com> wrote:
> >
> > From: Roman Penyaev <r.peniaev@gmail.com>
> >
> > With bitset management now it becomes feasible to implement
> > the logic of detaching frontends from multiplexer.
> >
> > Signed-off-by: Roman Penyaev <r.peniaev@gmail.com>
> > Cc: "Marc-André Lureau" <marcandre.lureau@redhat.com>
> > Cc: qemu-devel@nongnu.org
> > Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > Message-ID: <20241014152408.427700-8-r.peniaev@gmail.com>
>
> Hi; Coverity reports an issue with this patch. I think
> it's probably a bit confused, but on the other hand
> I read the code and am also a bit confused so we could
> probably adjust it to be clearer...
>
> > +bool mux_chr_detach_frontend(MuxChardev *d, unsigned int tag)
> > +{
> > + unsigned int bit;
> > +
> > + bit = find_next_bit(&d->mux_bitset, MAX_MUX, tag);
>
> Why are we calling find_next_bit() here? Coverity
> points out that it can return MAX_MUX, which means that
> if the caller passed in MAX_MUX then we will try to
> dereference d->backends[MAX_MUX] which is off the
> end of the array.
>
> What I was expecting this code to do was to check
> "is the bit actually currently set?", which would be
> if (!(d->mux_bitset & (1 << bit))) {
> ...
> }
Yep, that looks less confusing. I'll send a follow up commit
on that.
Thanks.
--
Roman
Hi
On Fri, Nov 1, 2024 at 7:26 PM Peter Maydell <peter.maydell@linaro.org>
wrote:
> On Tue, 15 Oct 2024 at 09:52, <marcandre.lureau@redhat.com> wrote:
> >
> > From: Roman Penyaev <r.peniaev@gmail.com>
> >
> > With bitset management now it becomes feasible to implement
> > the logic of detaching frontends from multiplexer.
> >
> > Signed-off-by: Roman Penyaev <r.peniaev@gmail.com>
> > Cc: "Marc-André Lureau" <marcandre.lureau@redhat.com>
> > Cc: qemu-devel@nongnu.org
> > Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > Message-ID: <20241014152408.427700-8-r.peniaev@gmail.com>
>
> Hi; Coverity reports an issue with this patch. I think
> it's probably a bit confused, but on the other hand
> I read the code and am also a bit confused so we could
> probably adjust it to be clearer...
>
> > +bool mux_chr_detach_frontend(MuxChardev *d, unsigned int tag)
> > +{
> > + unsigned int bit;
> > +
> > + bit = find_next_bit(&d->mux_bitset, MAX_MUX, tag);
>
> Why are we calling find_next_bit() here? Coverity
> points out that it can return MAX_MUX, which means that
> if the caller passed in MAX_MUX then we will try to
> dereference d->backends[MAX_MUX] which is off the
> end of the array.
>
> What I was expecting this code to do was to check
> "is the bit actually currently set?", which would be
> if (!(d->mux_bitset & (1 << bit))) {
> ...
> }
>
It's actually sort of checking the tag bit is set:
bit = find_next_bit(&d->mux_bitset, MAX_MUX, tag);
if (bit != tag) { // <- here
return false;
The function should probably assert(tag < MAX_MUX) though, that will help
coverity I guess
> Why do we want to find the next bit set after the
> 'tag' bit ?
>
> > + if (bit != tag) {
> > + return false;
> > + }
> > +
> > + d->mux_bitset &= ~(1 << bit);
> > + d->backends[bit] = NULL;
> > +
> > + return true;
> > +}
>
> (This is CID 1563776.)
>
> thanks
> -- PMM
>
>
--
Marc-André Lureau
© 2016 - 2026 Red Hat, Inc.