Fatal warnings in client code

Thomas Kluyver thomas at kluyver.me.uk
Mon Mar 6 16:53:41 UTC 2023


Thanks Simon - I understand from what you wrote that this is the intended behaviour.

On Mon, 6 Mar 2023, at 13:16, Simon McVittie wrote:
> On Mon, 06 Mar 2023 at 12:20:05 +0000, Thomas Kluyver wrote:
>> I helped someone work around VLC crashing when it tried to create a
>> D-Bus message with a string that was not UTF-8 (probably loaded from
>> a file without checking the encoding). The workaround was to set the
>> environment variable DBUS_FATAL_WARNINGS=0 when running VLC.
>
> Any time that DBUS_FATAL_WARNINGS=0 is helpful, it means there is a
> programming error in client code, for which the only solution is to fix
> some aspect of the client code.
>
> libdbus doesn't use GLib, but its general philosophy for handling
> errors is based on the design of GLib: there's a distinction between
> recoverable runtime errors which might be caused by some external
> situation and can potentially be fixed by rectifying that external
> situation (these are usually reported via DBusError), and programming
> errors for which the only solution is a code change (these are undefined
> behaviour, but as a courtesy to developers they are often reported via
> "checks" like _dbus_return_val_if_fail() if they can be detected easily).
>
>> In terms of implementation, the public function
>> calls _dbus_return_val_if_fail, which is a macro wrapping
>> _dbus_warn_return_if_fail, which calls _dbus_warn_check_failed. The
>> comment for that last function mentions 'Calling this means "there is
>> a bug"' - should that mean only bugs in dbus itself, or also bugs in
>> application code using it?
>
> That means bugs in anything. These "checks" are primarily for detecting
> bugs in application code, but libdbus does not have enough context to know
> whether the bug it has detected is in application code, libdbus itself,
> or a different library in the same process: all it knows is that there
> is a bug.
>
> In contexts where the bug that was detected is known (or at least
> strongly believed) to be in libdbus, it should be using _dbus_assert,
> which is unaffected by DBUS_FATAL_WARNINGS=0 but is normally disabled
> in production builds.
>
> C/C++ are not memory-safe languages, so any library in the same process
> space can cause memory corruption that triggers a "check" failure.
>
>> I disagree with his reasoning (he says that the sender shouldn't
>> validate messages), but it seems drastic for library code to call abort()
>> and crash the entire application. Is this the intended behaviour, or has
>> the application or the distro misconfigured something somewhere along
>> the way?
>
> Attempting to send non-UTF-8 in a D-Bus STRING is a programming error,
> because the spec for the D-Bus STRING type says it is a sequence of
> Unicode codepoints encoded in UTF-8, without any U+0000. If the caller has
> a string that might or might not be valid UTF-8, then they are responsible
> for checking whether it's valid before passing it into libdbus.
>
> At the protocol design level, D-Bus APIs that want to accept or return
> non-UTF-8 in a message need to use a byte array instead, like the 
> standard
> org.freedesktop.DBus.GetConnectionSELinuxSecurityContext method does
> <https://dbus.freedesktop.org/doc/dbus-specification.html#bus-messages-get-connection-selinux-security-context>.
>
> Other common failure modes for building a D-Bus message include trying to
> send BOOLEANs with value greater than 1, STRINGs that are null pointers,
> any dangling pointer (use-after-free, memory corruption or similar), and
> stack overruns caused by a missing varargs termination.
>
> The result of a programming error is undefined behaviour, after
> which literally anything can happen, including a crash or a security
> vulnerability. The default build-time configuration for libdbus is to
> include "checks" that diagnose these programming errors when it is
> straightforward to do so, by causing a deterministic crash that can
> be investigated like any other. Typically these "checks" will detect
> non-Unicode STRINGs, out-of-range BOOLEANs and null pointers, because
> those are easy to detect, but will not detect use-after-free or memory
> corruption, because it's not generally possible to detect those reliably
> or efficiently.
>
> With DBUS_FATAL_WARNINGS=0 or if "checks" were disabled at build time,
> the typical result of attempting to send invalid D-Bus messages is that
> message validation will fail in the message bus instead of in the client,
> resulting in the client being unceremoniously disconnected.
>
>> The docs for the function in question say that it can return false if
>> there's not enough memory, but don't mention any other failure conditions:
>> 
>> https://dbus.freedesktop.org/doc/api/html/group__DBusMessage.html#ga17491f3b75b3203f6fc47dcc2e3b221b
>
> The general philosophy is that the documentation describes the behaviour
> when the API is used correctly. When the API is used incorrectly,
> undefined behaviour occurs and there are no longer any guarantees.
>
> In principle the API documentation could say things like:
>
>     DBUS_EXPORT dbus_bool_t dbus_message_iter_append_basic (... etc. ...)
>
>     Appends a basic-typed value to the message.
>
>     ...
>
>     If @type is not a basic type, the behaviour is undefined.
>
>     If @value is NULL or does not point to a valid object of type @type,
>     the behaviour is undefined.
>
>     If a DBUS_TYPE_STRING parameter is not valid UTF-8, the behaviour is
>     undefined.
>
>     If a DBUS_TYPE_BOOLEAN parameter is neither 0 nor 1, the behaviour is
>     undefined.
>
>     If a DBUS_TYPE_SIGNATURE parameter is not a syntactically valid
>     signature, the behaviour is undefined.
>
>     Returns: TRUE on success, FALSE if not enough memory, an unspecified
>         value if undefined behaviour was caused.
>
> but that would make the API documentation much larger, and would probably
> still not be comprehensive.
>
> Strictly speaking, the documentation for dbus_message_iter_append_basic()
> doesn't actually say that there aren't other situations where FALSE can
> be returned, it only says that OOM causes FALSE to be returned. It also
> doesn't explicitly say that TRUE is returned on success (I think that's
> probably a bug, merge requests welcome).
>
>     smcv


More information about the dbus mailing list