Fix: sessiond: instance uuid is not sufficiently unique
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 3 Jan 2023 23:41:23 +0000 (18:41 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 5 Jan 2023 21:33:35 +0000 (16:33 -0500)
commitbff8215ae6ade578ab842a75108e517da1789ae6
tree11e8ed04382af9dbff108bfa33bc1084528ebb3e
parentc7a4f82e187f16400a8f1894651c2f92a3592f5b
Fix: sessiond: instance uuid is not sufficiently unique

Observed issue
==============

Tracing a cluster of machines -- all launched simultaneously -- to the
same relay daemon occasionally produces corrupted traces.

The size of packets received (as seen from the relay daemon logs) and
that of those present in the on-disk stream occasionally didn't match.

The traces were observed to all relate to the same trace UUID, but
present packet begin timestamps that were not monotonic for a given
stream.

This causes both Babeltrace 1.x and 2.x to fail to open the traces with
different error messages related to clocks.

Cause
=====

On start, the session daemon generates a UUID to uniquely identify the
sessiond instance. Since the UUID generation utils use time() to seed
the random number generator, two session daemons launched within the
same second can end up with the same instance UUID.

Since the relay daemon relies on this UUID to uniquely identify a
session daemon accross its various connections, identifier clashes can
cause streams from the same `uid` or `pid` to become scrambled resulting
in corrupted traces.

Solution
========

The UUID utils now initializes its random seed using the getrandom() API
in non-blocking mode. If that fails -- most likely because the random
pool is depleted or the syscall is not available on the platform -- it
falls back to using a hash of two time readings (with nanosecond
precision), of the hostname, and the PID.

Known drawbacks
===============

This fix implements many fallbacks, each with their own caveats and we
don't have full test coverage for all of those for the moment.

This article presents the different drawbacks of using /dev/urandom vs
getrandom().

https://lwn.net/Articles/884875/

As for the pseudo-random time and configuration based fallback, it is
meant as a last resort for platforms or configurations where both
getrandom() (old kernels or non-Linux platforms) and /dev/urandom (e.g.
locked-down container) are not be available. I haven't done a formal
analysis of the entropy of this home-grown method. The practical
use-case we want to enable is launching multiple virtual machines (or
containers) at roughly the same time and ensure that they don't end up
using the same sessiond UUID.

In that respect, having a different host name and minute timing changes
seem enough to prevent a UUID clash.

Using the PID as part of the hash also helps when launching multiple
session daemons simultaneously for different users.

Change-Id: I320fff7bc52752ff504643569e49fa3c02472ec2
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
configure.ac
src/common/Makefile.am
src/common/random.c [new file with mode: 0644]
src/common/random.h [new file with mode: 0644]
src/common/uuid.c
tests/unit/test_uuid.c
This page took 0.02661 seconds and 4 git commands to generate.