Systemd/src/nss-systemd/nss-systemd.h

14 lines
316 B
C
Raw Normal View History

userdb: replace recursion lock Previously we'd used the existance of a specific AF_UNIX socket in the abstract namespace as lock for disabling lookup recursions. (for breaking out of the loop: userdb synthesized from nss → nss synthesized from userdb → userdb synthesized from nss → …) I did it like that because it promised to work the same both in static and in dynmically linked environments and is accessible easily from any programming language. However, it has a weakness regarding reuse attacks: the socket is securely hashed (siphash) from the thread ID in combination with the AT_RANDOM secret. Thus it should not be guessable from an attacker in advance. That's only true if a thread takes the lock only once and keeps it forever. However, if a thread takes and releases it multiple times an attacker might monitor that and quickly take the lock after the first iteration for follow-up iterations. It's not a big issue given that userdb (as the primary user for this) never released the lock and we never made the concept a public interface, and it was only included in one release so far, but it's something that deserves fixing. (moreover it's a local DoS only, only permitting to disable native userdb lookups) With this rework the libnss_systemd.so.2 module will now export two additional symbols. These symbols are not used by glibc, but can be used by arbitrary programs: one can be used to disable nss-systemd, the other to check if it is currently disabled. The lock is per-thread. It's slightly less pretty, since it requires people to manually link against C code via dlopen()/dlsym(), but it should work safely without the aforementioned weakness.
2020-06-04 11:46:36 +02:00
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <stdbool.h>
int _nss_systemd_block(bool b);
bool _nss_systemd_is_blocked(void);
/* For use with the _cleanup_() macro */
static inline void _nss_systemd_unblockp(bool *b) {
if (*b)
assert_se(_nss_systemd_block(false) >= 0);
}