This is unfortunately harder to implement than it sounds. The user's bus
is bound a to the user's lifecycle after all (i.e. only exists as long
as the user has at least one PAM session), and the path dynamically (at
least theoretically, in practice it's going to be the same always)
generated via $XDG_RUNTIME_DIR in /run/.
To fix this properly, we'll thus go through PAM before connecting to a
user bus. Which is hard since we cannot just link against libpam in the
container, since the container might have been compiled entirely
differently. So our way out is to use systemd-run from outside, which
invokes a transient unit that does PAM from outside, doing so via D-Bus.
Inside the transient unit we then invoke systemd-stdio-bridge which
forwards D-Bus from the user bus to us. The systemd-stdio-bridge makes
up the PAM session and thus we can sure tht the bus exists at least as
long as the bus connection is kept.
Or so say this differently: if you use "systemctl -M lennart@foobar"
now, the bus connection works like this:
1. sd-bus on the host forks off:
systemd-run -M foobar -PGq --wait -pUser=lennart -pPAMName=login systemd-stdio-bridge
2. systemd-run gets a connection to the "foobar" container's
system bus, and invokes the "systemd-stdio-bridge" binary as
transient service inside a PAM session for the user "lennart"
3. The systemd-stdio-bridge then proxies our D-Bus traffic to
the user bus.
sd-bus (on host) → systemd-run (on host) → systemd-stdio-bridge (in container)
Complicated? Well, to some point yes, but otoh it's actually nice in
various other ways, primarily as it makes the -H and -M codepaths more
alike. In the -H case (i.e. connect to remote host via SSH) a very
similar three steps are used. The only difference is that instead of
"systemd-run" the "ssh" binary is used to invoke the stdio bridge in a
PAM session of some other system. Thus we get similar implementation and
isolation for similar operations.
Fixes: #14580
Those are fairly trivial to reimplement, but any non-trivial user of sd-bus
is likely to need them. So let's expose them to save everyone the trouble.
I'm keeping the internal functions and making the public ones thin wrappers,
because for the internal uses we don't need the additional asserts, and also we
can't expose _pure_ annotation easily, and dropping it would likely make the
compiled code a bit less efficient.
This tweaks match installation a bit: the match callbacks are now only
called for messages read after the AddMatch() reply was received and
never anything already read before. Thus, installing a match gives you a
time guarantee: only messages received after it will be matched.
This is useful when listening to PropertiesChanged signals as an example
to ensure that only changes after the point the match was installed are
honoured, nothing before.
Let's count incoming messages and attach the current counter when we
first read them to the message objects. This allows us to nicely order
messages later on.
Apparently by the C standard "int" bitfields can have any signedness
(unlike non-bitfield declarations which are "signed" if the signedness
is not specified).
Let's fix the LGTM warning about this hence and be explicit that we mean
"signed" here.
We had atomic counters, but all other operations were non-serialized. This
means that concurrent access to the bus object was only safe if _all_ threads
were doing read-only access. Even sending of messages from threads would not be
possible, because after sending of the message we usually want to remove it
from the send queue in the bus object, which would race. Let's just kill this.
Let's do this like we usually do and size arrays with size_t.
We already do this for the "allocated" counter correctly, and externally
we expose the queue sizes as uint64_t anyway, hence there's really no
point in usigned "unsigned" internally.
Even though the dbus specification does not enforce any length limit on the
path of a dbus message, having to analyze too long strings in PID1 may be
time-consuming and it may have security impacts.
In any case, the limit is set so high that real-life applications should not
have a problem with it.
From WordNet (r) 3.0 (2006) [wn]:
time-out
n 1: a brief suspension of play; "each team has two time-outs left"
From The Free On-line Dictionary of Computing (18 March 2015) [foldoc]:
timeout
A period of time after which an error condition is raised if
some event has not occured. A common example is sending a
message. If the receiver does not acknowledge the message
within some preset timeout period, a transmission error is
assumed to have occured.
This adds a new pair of API calls sd_bus_set_close_on_exit() and
sd_bus_get_close_on_exit(). They control whether an sd_bus object
attached to a an sd-event loop shall automatically be flushed/closed
when the event loop goes down. Usually that's a good thing, except for
very few cases where the bus connection is longer living than the event
loop it is attached on. Specifically, this is the case for nspawn, where
we run the event loop only while the container is up, but afterwards
still want to be able to use the bus connection.
This adds sd_bus_{get,set}_method_call_timeout().
If the timeout is not set or set to 0, then the timeout value is
parsed from $SYSTEMD_BUS_TIMEOUT= environment variable. If the
environment variable is not set, then built-in timeout is used.
This makes OBJECT_PATH_FOREACH_PREFIX consistent with PATH_FOREACH_PREFIX
and also fixes 7 alerts reported by LGTM at
ac0a087003/files/src/libsystemd/sd-bus/bus-objects.c?sort=name&dir=ASC&mode=heatmap&showExcluded=true#V1383
These lines are generally out-of-date, incomplete and unnecessary. With
SPDX and git repository much more accurate and fine grained information
about licensing and authorship is available, hence let's drop the
per-file copyright notice. Of course, removing copyright lines of others
is problematic, hence this commit only removes my own lines and leaves
all others untouched. It might be nicer if sooner or later those could
go away too, making git the only and accurate source of authorship
information.
This part of the copyright blurb stems from the GPL use recommendations:
https://www.gnu.org/licenses/gpl-howto.en.html
The concept appears to originate in times where version control was per
file, instead of per tree, and was a way to glue the files together.
Ultimately, we nowadays don't live in that world anymore, and this
information is entirely useless anyway, as people are very welcome to
copy these files into any projects they like, and they shouldn't have to
change bits that are part of our copyright header for that.
hence, let's just get rid of this old cruft, and shorten our codebase a
bit.
This adds a function sd_bus_slot_set_destroy_callback() to set a function
which can free userdata or perform other cleanups.
sd_bus_slot_get_destory_callback() queries the callback, and is included
for completeness.
Without something like this, for floating asynchronous callbacks, which might
be called or not, depending on the sequence of events, it's hard to perform
resource cleanup. The alternative would be to always perform the cleanup from
the caller too, but that requires more coordination and keeping of some shared
state. It's nicer to keep the cleanup contained between the callback and the
function that requests the callback.
This new call allows explicit control of the "floating" state of a bus
slot object. This is useful for creating a bus slot object first,
retaining a reference to it, using it for making changes to the slot
object (for example, set a description) and then handing it over to
sd-bus for lifecycle management.
It's also useful to fix#8551.
Previously we were a bit sloppy with the index and size types of arrays,
we'd regularly use unsigned. While I don't think this ever resulted in
real issues I think we should be more careful there and follow a
stricter regime: unless there's a strong reason not to use size_t for
array sizes and indexes, size_t it should be. Any allocations we do
ultimately will use size_t anyway, and converting forth and back between
unsigned and size_t will always be a source of problems.
Note that on 32bit machines "unsigned" and "size_t" are equivalent, and
on 64bit machines our arrays shouldn't grow that large anyway, and if
they do we have a problem, however that kind of overly large allocation
we have protections for usually, but for overflows we do not have that
so much, hence let's add it.
So yeah, it's a story of the current code being already "good enough",
but I think some extra type hygiene is better.
This patch tries to be comprehensive, but it probably isn't and I missed
a few cases. But I guess we can cover that later as we notice it. Among
smaller fixes, this changes:
1. strv_length()' return type becomes size_t
2. the unit file changes array size becomes size_t
3. DNS answer and query array sizes become size_t
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=76745
Files which are installed as-is (any .service and other unit files, .conf
files, .policy files, etc), are left as is. My assumption is that SPDX
identifiers are not yet that well known, so it's better to retain the
extended header to avoid any doubt.
I also kept any copyright lines. We can probably remove them, but it'd nice to
obtain explicit acks from all involved authors before doing that.
we still invoke ssh unnecessarily when there in incompatible or erreneous input
The fallow-up to finish that would make the code a bit more verbose,
as it would require repeating this bit:
```
r = bus_connect_transport(arg_transport, arg_host, false, &bus);
if (r < 0) {
log_error_errno(r, "Failed to create bus connection: %m");
goto finish;
}
sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
```
in every verb, after parsing.
v2: add waitpid() to avoid a zombie process, switch to SIGTERM from SIGKILL
v3: refactor, wait in bus_start_address()
Currently, sd-bus supports the ability to have thread-local default busses.
However, this is less useful than it can be since all functions which
require an sd_bus* as input require the caller to pass it. This patch adds
a new macro which allows the developer to pass a constant SD_BUS_DEFAULT,
SD_BUS_DEFAULT_USER or SD_BUS_DEFAULT_SYSTEM instead. This reduces work for
the caller.
For example:
r = sd_bus_default(&bus);
r = sd_bus_call_method(bus, ...);
sd_bus_unref(bus);
Becomes:
r = sd_bus_call_method(SD_BUS_DEFAULT, ...);
If the specified thread-local default bus does not exist, the function
calls will return -ENOPKG. No bus will ever be implicitly created.
This is useful on direct connections to generate messages with valid
sender fields.
This is particularly useful for services that are accessible both
through direct connections and the broker, as it allows clients to
install matches on the sender service name, and they work the same in
both cases.
With this new API sd-bus can synthesize a local "Connected" signal when
the connection is fully established. It mirrors the local "Disconnected"
signal that is already generated when the connection is terminated. This
is useful to be notified when connection setup is done, in order to
start method calls then, in particular when using "slow" connection
methods (for example slow TCP, or most importantly the "watch_bind"
inotify logic).
Note that one could also use hook into the initial NameAcquired signal
received from the bus broker, but that scheme works only if we actually
connect to a bus. The benefit of "Connected" OTOH is that it works with
any kind of connection.
Ideally, we'd just generate this message unconditionally, but in order
not to break clients that do not expect this message it is opt-in.
We usually enqueue a number of these calls on each service
initialization. Let's do this asynchronously, and thus remove
synchronization points. This improves both performance behaviour and
reduces the chances to deadlock.
They do the same thing as their synchronous counterparts, but only
enqueue the operation, thus removing synchronization points during
service initialization.
If the callback function is passed as NULL we'll fallback to generic
implementations of the reply handlers, that terminate the connection if
the requested name cannot be acquired, under the assumption that not
being able to acquire the name is a technical problem.
Currently, reply callback timeouts are started the instant the method
calls are enqueued, which can be very early on. For example, the Hello()
method call is enqueued right when sd_bus_start() is called, i.e. before
the socket connection and everything is established.
With this change we instead start the method timeout the moment we
actually leave the authentication phase of the connection. This way, the
timeout the kernel applies on socket connecting, and we apply on the
authentication phase no longer runs in parallel to the Hello() method
call, but all three run serially one after the other, which is
definitely a cleaner approach.
Moreover, this makes the "watch bind" feature a lot more useful, as it
allows enqueuing method calls while we are still waiting for inotify
events, without them timeouting until the connection is actually
established, i.e. when the method call actually has a chance of being
actually run.
This is a change of behaviour of course, but I think the new behaviour
is much better than the old one, since we don't race timeouts against
each other anymore...
This adds a "watch-bind" feature to sd-bus connections. If set and the
AF_UNIX socket we are connecting to doesn't exist yet, we'll establish
an inotify watch instead, and wait for the socket to appear. In other
words, a missing AF_UNIX just makes connecting slower.
This is useful for daemons such as networkd or resolved that shall be
able to run during early-boot, before dbus-daemon is up, and want to
connect to dbus-daemon as soon as it becomes ready.
THe match cookie was used by kdbus to identify matches we install
uniquely. But given that kdbus is gone, the cookie serves no process
anymore, let's kill it.
As it turns out the authentication phase times out too often than is
good, mostly due to PRNG pools not being populated during boot. Hence,
let's increase the authentication timeout from 25s to 90s, to cover for
that.
(Note that we leave the D-Bus method call timeout at 25s, matching the
reference implementation's value. And if the auth phase managed to
complete then the pools should be populated enough and mehtod calls
shouldn't take needlessly long anymore).
Fixes: #6418
Some kdbus_flag and memfd related parts are left behind, because they
are entangled with the "legacy" dbus support.
test-bus-benchmark is switched to "manual". It was already broken before
(in the non-kdbus mode) but apparently nobody noticed. Hopefully it can
be fixed later.
Let's bump it further, as this the current limit turns out to be problematic
IRL. Let's bump it to more than twice what we know of is needed.
Fixes: #4068
Old libdbus has a feature that the process is terminated whenever the the bus
connection receives a disconnect. This is pretty useful on desktop apps (where
a disconnect indicates session termination), as well as on command line apps
(where we really shouldn't stay hanging in most cases if dbus daemon goes
down).
Add a similar feature to sd-bus, but make it opt-in rather than opt-out, like
it is on libdbus. Also, if the bus is attached to an event loop just exit the
event loop rather than the the whole process.
If the server side kicks us from the bus, from our view no names are on the bus
anymore, hence let's make sure to dispatch all tracking objects immediately.