> On 1 Dec 2022, at 21:19, Andrew Cooper <andrew.coop...@citrix.com> wrote:
> 
> fallback_exception_handler feeds a string with embedded newlines directly into
> syslog().  While this is an improvement on getting nothing, syslogd escapes
> all control characters it gets, and emits one (long) line into the log.
> 
> Fix the problem generally in the syslog stub.  As we already have a local copy
> of the string, split it in place and emit one syslog() call per line.
> 
> Also tweak Logging.msg_of to avoid putting an extra newline on a string which
> already ends with one.
> 
> Fixes: ee7815f49faf ("tools/oxenstored: Set uncaught exception handler")
> Signed-off-by: Andrew Cooper <andrew.coop...@citrix.com>
> ---
> CC: Christian Lindig <christian.lin...@citrix.com>
> CC: David Scott <d...@recoil.org>
> CC: Edwin Torok <edvin.to...@citrix.com>
> CC: Rob Hoes <rob.h...@citrix.com>

Acked-by: Christian Lindig <christian.lin...@citrix.com>

> ---
> tools/ocaml/xenstored/logging.ml     |  2 +-
> tools/ocaml/xenstored/syslog_stubs.c | 26 +++++++++++++++++++++++---
> 2 files changed, 24 insertions(+), 4 deletions(-)
> 
> diff --git a/tools/ocaml/xenstored/logging.ml 
> b/tools/ocaml/xenstored/logging.ml
> index 255051437d60..f233bc9a3956 100644
> --- a/tools/ocaml/xenstored/logging.ml
> +++ b/tools/ocaml/xenstored/logging.ml
> @@ -344,7 +344,7 @@ let watch_not_fired ~con perms path =
>       access_logging ~tid:0 ~con ~data Watch_not_fired ~level:Info
> 
> let msg_of exn bt =
> -     Printf.sprintf "Fatal exception: %s\n%s\n" (Printexc.to_string exn)
> +     Printf.sprintf "Fatal exception: %s\n%s" (Printexc.to_string exn)
>               (Printexc.raw_backtrace_to_string bt)
> 
> let fallback_exception_handler exn bt =
> diff --git a/tools/ocaml/xenstored/syslog_stubs.c 
> b/tools/ocaml/xenstored/syslog_stubs.c
> index e16c3a9491d0..760e78ff73dc 100644
> --- a/tools/ocaml/xenstored/syslog_stubs.c
> +++ b/tools/ocaml/xenstored/syslog_stubs.c
> @@ -37,14 +37,34 @@ value stub_syslog(value facility, value level, value msg)
> {
>       CAMLparam3(facility, level, msg);
>       char *c_msg = strdup(String_val(msg));

Is this working as expected? An OCaml string may contain embedded null bytes.

> +     char *s = c_msg, *ss;
>       int c_facility = __syslog_facility_table[Int_val(facility)]
>                      | __syslog_level_table[Int_val(level)];
> 
>       if ( !c_msg )
>               caml_raise_out_of_memory();
> -     caml_enter_blocking_section();
> -     syslog(c_facility, "%s", c_msg);
> -     caml_leave_blocking_section();
> +
> +     /*
> +      * syslog() doesn't like embedded newlines, and c_msg generally
> +      * contains them.
> +      *
> +      * Split the message in place by converting \n to \0, and issue one
> +      * syslog() call per line, skipping the final iteration if c_msg ends
> +      * with a newline anyway.
> +      */
> +     do {
> +             ss = strchr(s, '\n');
> +             if ( ss )
> +                     *ss = '\0';
> +             else if ( *s == '\0' )
> +                     break;
> +
> +             caml_enter_blocking_section();
> +             syslog(c_facility, "%s", s);
> +             caml_leave_blocking_section();
> +
> +             s = ss + 1;
> +     } while ( ss );
> 
>       free(c_msg);
>       CAMLreturn(Val_unit);
> -- 
> 2.11.0
> 


Reply via email to