qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH RFC] qemu-error: introduce error_report_once


From: Markus Armbruster
Subject: Re: [Qemu-devel] [PATCH RFC] qemu-error: introduce error_report_once
Date: Tue, 15 May 2018 17:56:34 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/25.3 (gnu/linux)

Peter Xu <address@hidden> writes:

> On Tue, May 15, 2018 at 02:02:55PM +0200, Markus Armbruster wrote:
>> Peter Xu <address@hidden> 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 <address@hidden>
>> > Signed-off-by: Peter Xu <address@hidden>
>> > ---
>> > 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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]