server/transaction: Fix message hash

Our message hashes used to generate transaction id's for dbus services
have been relying on an invalid cookie when messages don't have cookies
present. This was exposed by 20adbc2d459123772ecd2d17009e1db0dd6314f2
which enabled error handling for message.get_cookie().

In order to generate a hash of the message, we need to consider the type
of message we have. In the context of an sdbusplus server, METHOD_CALL
type messages will always be incoming and sealed. They will always
provide a valid .get_cookie(). Messages of METHOD_RETURN or METHOD_ERROR
will not be sealed, but will always be generated from an incoming
METHOD_CALL. Therefore they will always have a valid
.get_reply_cookie(). SIGNAL type messages will always be outgoing so
they will not have a cookie yet. We will just use a monotonic source for
generating a transaction id for those.

Tested:
    Run through the unit test suite and booted in a romulus virtual
    machine. Ensured that none of the daemons were ABRTing like they
    were with just 20adbc2d459123772ecd2d17009e1db0dd6314f2 applied.

Change-Id: Ic54ae3b3cfa75d2f419579e1cb02f57eacb87c57
Signed-off-by: William A. Kennington III <wak@google.com>
1 file changed
tree: 5b0342a1bdd2a26fc2ad45c3d53873398a95676b
  1. docs/
  2. example/
  3. mapbox/
  4. sdbusplus/
  5. test/
  6. tools/
  7. .clang-format
  8. .gitignore
  9. bootstrap.sh
  10. configure.ac
  11. LICENSE
  12. MAINTAINERS
  13. Makefile.am
  14. README.md
  15. sdbusplus.pc.in
README.md

sdbusplus

sdbusplus contains two parts:

  1. A C++ library (libsdbusplus) for interacting with D-Bus, built on top of the sd-bus library from systemd.
  2. A tool (sdbus++) to generate C++ bindings to simplify the development of D-Bus-based applications.

Dependencies

The sdbusplus library requires sd-bus, which is contained in libsystemd.

The sdbus++ application requires python and the python libraries mako and py-inflection.

C++ library

The sdbusplus library builds on top of the sd-bus library to create a modern C++ API for D-Bus. The library attempts to be as lightweight as possible, usually compiling to exactly the sd-bus API calls that would have been necessary, while also providing compile-time type-safety and memory leak protection afforded by modern C++ practices.

Consider the following code:

auto b = bus::new_system();
auto m = b.new_method_call("org.freedesktop.login1",
                           "/org/freedesktop/login1",
                           "org.freedesktop.login1.Manager",
                           "ListUsers");
auto reply = b.call(m);

std::vector<std::tuple<uint32_t, std::string, message::object_path>> users;
reply.read(users);

In a few, relatively succinct, C++ lines this snippet will create a D-Bus connection to the system bus, and call the systemd login manager to get a list of active users. The message and bus objects are automatically freed when they leave scope and the message format strings are generated at compile time based on the types being read. Compare this to the corresponding server code within logind.

In general, the library attempts to mimic the naming conventions of the sd-bus library: ex. sd_bus_call becomes sdbusplus::bus::call, sd_bus_get_unique_name becomes sdbusplus::bus::get_unique_name, sd_bus_message_get_signature becomes sdbusplus::message::get_signature, etc. This allows a relatively straight-forward translation back to the sd-bus functions for looking up the manpage details.

Binding generation tool

sdbusplus also contains a bindings generator tool: sdbus++. The purpose of a bindings generator is to reduce the boilerplate associated with creating D-Bus server or client applications. When creating a server application, rather than creating sd-bus vtables and writing C-style functions to handle each vtable callback, you can create a small YAML file to define your D-Bus interface and the sdbus++ tool will create a C++ class that implements your D-Bus interface. This class has a set of virtual functions for each method and property, which you can overload to create your own customized behavior for the interface.

There are currently two types of YAML files: interface and error. Interfaces are used to create server and client D-Bus interfaces. Errors are used to define C++ exceptions which can be thrown and will automatically turn into D-Bus error responses.

[[ D-Bus client bindings are not yet implemented. See openbmc/openbmc#851. ]]

Generating bindings

How to use tools/sdbus++

The path of your file will be the interface name. For example, for an interface org.freedesktop.Example, you would create the files org/freedesktop/Example.interface.yaml and org/freedesktop/Example.errors.yaml] for interfaces and errors respectively. These can then be used to generate the server and error bindings:

sdbus++ interface server-header org.freedesktop.Example > \
    org/freedesktop/Example/server.hpp
sdbus++ interface server-cpp org.freedesktop.Example > \
    org/freedesktop/Example/server.cpp
sdbus++ error exception-header org.freedesktop.Example > \
    org/freedesktop/Example/error.hpp \
sdbus++ error exception-cpp org.freedesktop.Example > \
    org/freedesktop/Example/error.cpp

Markdown-based documentation can also be generated from the interface and exception files:

sdbus++ interface markdown org.freedesktop.Example > \
    org/freedesktop/Example.md
sdbus++ error markdown org.freedesktop.Example >> \
    org/freedesktop/Example.md

See the example/Makefile.am for more details.

Installing sdbusplus on custom distributions

Installation of sdbusplus bindings on a custom distribution requires a few packages to be installed prior. Although these packages are the same for several distributions the names of these packages do differ. Below are the packages needed for Ubuntu and Fedora.

Installation on Ubuntu

sudo apt install git autoconf libtool pkg-config g++ autoconf-archive libsystemd-dev python python-yaml python-mako python-inflection

Installation on Fedora

sudo dnf install git autoconf libtool gcc-c++ pkgconfig autoconf-archive systemd-devel python python-pip python-yaml python-mako

Install the inflection package using the pip utility (on Fedora)

pip install inflection