From: Markus Armbruster <armbru@redhat.com>
To: Peter Xu <peterx@redhat.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH RFC] qemu-error: introduce error_report_once
Date: Tue, 15 May 2018 17:56:34 +0200 [thread overview]
Message-ID: <87vaboud3h.fsf@dusky.pond.sub.org> (raw)
In-Reply-To: <20180515123827.GB9089@xz-mi> (Peter Xu's message of "Tue, 15 May 2018 20:38:27 +0800")
Peter Xu <peterx@redhat.com> writes:
> On Tue, May 15, 2018 at 02:02:55PM +0200, Markus Armbruster wrote:
>> Peter Xu <peterx@redhat.com> writes:
>>
>> > I stole the printk_once() macro.
>> >
>> > I always wanted to be able to print some error directly if there is a
>> > buffer to dump, however we can't use error_report() really quite often
>> > when there can be any DDOS attack.
>>
>> Got an example?
>
> There aren't much, but there are still some error_report()s that can
> be used in frequently called functions, especially on IO paths. For
> example:
>
>
> *** hw/usb/dev-storage.c:
> usb_msd_handle_data[422] error_report("usb-msd: Bad CBW size");
> usb_msd_handle_data[427] error_report("usb-msd: Bad signature %08x",
> usb_msd_handle_data[434] error_report("usb-msd: Bad LUN %d", cbw.lun);
>
> *** hw/usb/dev-uas.c:
> usb_uas_handle_control[656] error_report("%s: unhandled control request (req 0x%x, val 0x%x, idx 0x%x",
> usb_uas_handle_data[823] error_report("%s: unknown command iu: id 0x%x",
> usb_uas_handle_data[870] error_report("%s: no inflight request", __func__);
> usb_uas_handle_data[888] error_report("%s: invalid endpoint %d", __func__, p->ep->nr);
>
> *** hw/virtio/vhost-user.c:
> vhost_user_read[208] error_report("Failed to read msg header. Read %d instead of %d."
> vhost_user_read[215] error_report("Failed to read msg header."
> vhost_user_read[223] error_report("Failed to read msg header."
> vhost_user_read[234] error_report("Failed to read msg payload."
> process_message_reply[260] error_report("Received unexpected msg type."
> vhost_user_write[302] error_report("Failed to set msg fds.");
> vhost_user_write[308] error_report("Failed to write msg."
> ...
> slave_read[859] error_report("Failed to read from slave.");
> slave_read[864] error_report("Failed to read msg header."
> slave_read[873] error_report("Failed to read payload from slave.");
> slave_read[885] error_report("Received unexpected msg type.");
> slave_read[910] error_report("Failed to send msg reply to slave.");
> ...
>
> I only picked some of the callers, they might not all suite in this
> case, but just to show what I mean.
>
> Another example is in VT-d emulation code, we have trace_vtd_error()
> tracer. AFAIU all those places can be replaced by something like
> error_report() but trace points are mostly used to avoid DDOS attack,
> say, an evil guest might trigger this error tons of times to even use
> up a host's disk space (e.g., in libvirt qemu log, since libvirt might
> capture that). However using trace points mean that errors are not
> dumped if trace not enabled.
>
> So this print_once() thing will make sure (1) it's on by deffault, so
> we can even get something without turning the trace on and
> reproducing, and (2) it won't be affected by DDOS attack.
>
>>
>> > To avoid that, we can introduce a
>> > print-once function for it.
>> >
>> > CC: Markus Armbruster <armbru@redhat.com>
>> > Signed-off-by: Peter Xu <peterx@redhat.com>
>> > ---
>> > We can for sure introduce similar functions for the rest of the
>> > error_*() functions, it's just an idea to see whether we'd like it
>> > in general.
>> > ---
>> > include/qemu/error-report.h | 12 ++++++++++++
>> > 1 file changed, 12 insertions(+)
>> >
>> > diff --git a/include/qemu/error-report.h b/include/qemu/error-report.h
>> > index e1c8ae1a52..efebb80e2c 100644
>> > --- a/include/qemu/error-report.h
>> > +++ b/include/qemu/error-report.h
>> > @@ -44,6 +44,18 @@ void error_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
>> > void warn_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
>> > void info_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
>> >
>> > +#define error_report_once(fmt, ...) \
>> > + ({ \
>> > + static bool __print_once; \
>> > + bool __ret_print_once = !__print_once; \
>> > + \
>> > + if (!__print_once) { \
>> > + __print_once = true; \
>> > + error_report(fmt, ##__VA_ARGS__); \
>> > + } \
>> > + unlikely(__ret_print_once); \
>> > + })
>> > +
>> > const char *error_get_progname(void);
>> > extern bool enable_timestamp_msg;
>>
>> Ignorant question: what's the return value's intended use?
>
> For me I don't need it, I just didn't see a reason to remove it - it's
> quite cheap as a stack variable (comparing to the heap variable
> __print_once which will really consume some byte in the binaries) and
> basically it works just like we exported that __print_once when
> needed, so I kept it in case people might use it.
>
> One example I can think of is that we can keep some error environment
> when the first error happens:
>
> if (something_wrong_happened) {
> if (error_report_once("blablabla")) {
> /* only cache the first error */
> error_cmd = xxx;
> error_param = xxx;
> ...
> }
> }
I see.
Add a contract comment (suggest to start with the one next to
error_report()), expand the tabs, replace the reserved identifiers
(caught by patchew; you can use foo_ instead of __foo), throw in at
least one use to serve as a showcase (ideally one demonstrating the
difference to trace points), and consider working some of your
additional rationale into your commit message.
next prev parent reply other threads:[~2018-05-15 15:56 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-05-15 9:13 [Qemu-devel] [PATCH RFC] qemu-error: introduce error_report_once Peter Xu
2018-05-15 9:16 ` no-reply
2018-05-15 12:02 ` Markus Armbruster
2018-05-15 12:38 ` Peter Xu
2018-05-15 15:56 ` Markus Armbruster [this message]
2018-05-15 16:39 ` Eric Blake
2018-05-16 3:08 ` Peter Xu
2018-05-15 15:29 ` Eric Blake
2018-05-16 3:07 ` Peter Xu
2018-05-16 14:02 ` Eric Blake
2018-05-17 2:51 ` Peter Xu
2018-05-31 11:03 ` Stefan Hajnoczi
2018-06-01 3:17 ` Peter Xu
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=87vaboud3h.fsf@dusky.pond.sub.org \
--to=armbru@redhat.com \
--cc=peterx@redhat.com \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.