Merge pull request #32234 from poettering/dlopen-name-elf-note

Expose dlopen() dependencies in an ELF section, and add spec for it
This commit is contained in:
Luca Boccassi
2024-05-08 13:56:34 +02:00
committed by GitHub
20 changed files with 253 additions and 0 deletions
+15
View File
@@ -129,6 +129,11 @@ bool compression_supported(Compression c) {
#if HAVE_XZ
int dlopen_lzma(void) {
ELF_NOTE_DLOPEN("lzma",
"Support lzma compression in journal and coredump files",
COMPRESSION_PRIORITY_XZ,
"liblzma.so.5");
return dlopen_many_sym_or_warn(
&lzma_dl,
"liblzma.so.5", LOG_DEBUG,
@@ -186,6 +191,11 @@ int compress_blob_xz(const void *src, uint64_t src_size,
#if HAVE_LZ4
int dlopen_lz4(void) {
ELF_NOTE_DLOPEN("lz4",
"Support lz4 compression in journal and coredump files",
COMPRESSION_PRIORITY_LZ4,
"liblz4.so.1");
return dlopen_many_sym_or_warn(
&lz4_dl,
"liblz4.so.1", LOG_DEBUG,
@@ -242,6 +252,11 @@ int compress_blob_lz4(const void *src, uint64_t src_size,
#if HAVE_ZSTD
int dlopen_zstd(void) {
ELF_NOTE_DLOPEN("zstd",
"Support zstd compression in journal and coredump files",
COMPRESSION_PRIORITY_ZSTD,
"libzstd.so.1");
return dlopen_many_sym_or_warn(
&zstd_dl,
"libzstd.so.1", LOG_DEBUG,
+41
View File
@@ -39,3 +39,44 @@ int dlopen_many_sym_or_warn_sentinel(void **dlp, const char *filename, int log_l
/* libbpf is a bit confused about type-safety and API compatibility. Provide a macro that can tape over that mess. Sad. */
#define DLSYM_ARG_FORCE(arg) \
&sym_##arg, STRINGIFY(arg)
#define ELF_NOTE_DLOPEN_VENDOR "FDO"
#define ELF_NOTE_DLOPEN_TYPE UINT32_C(0x407c0c0a)
#define ELF_NOTE_DLOPEN_PRIORITY_REQUIRED "required"
#define ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED "recommended"
#define ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED "suggested"
/* Add an ".note.dlopen" ELF note to our binary that declares our weak dlopen() dependency. This
* information can be read from an ELF file via "readelf -p .note.dlopen" or an equivalent command. */
#define _ELF_NOTE_DLOPEN(json, variable_name) \
__attribute__((used, section(".note.dlopen"))) _Alignas(sizeof(uint32_t)) static const struct { \
struct { \
uint32_t n_namesz, n_descsz, n_type; \
} nhdr; \
char name[sizeof(ELF_NOTE_DLOPEN_VENDOR)]; \
_Alignas(sizeof(uint32_t)) char dlopen_json[sizeof(json)]; \
} variable_name = { \
.nhdr = { \
.n_namesz = sizeof(ELF_NOTE_DLOPEN_VENDOR), \
.n_descsz = sizeof(json), \
.n_type = ELF_NOTE_DLOPEN_TYPE, \
}, \
.name = ELF_NOTE_DLOPEN_VENDOR, \
.dlopen_json = json, \
}
#define _SONAME_ARRAY1(a) "[\""a"\"]"
#define _SONAME_ARRAY2(a, b) "[\""a"\",\""b"\"]"
#define _SONAME_ARRAY3(a, b, c) "[\""a"\",\""b"\",\""c"\"]"
#define _SONAME_ARRAY4(a, b, c, d) "[\""a"\",\""b"\",\""c"\"",\""d"\"]"
#define _SONAME_ARRAY5(a, b, c, d, e) "[\""a"\",\""b"\",\""c"\"",\""d"\",\""e"\"]"
#define _SONAME_ARRAY_GET(_1,_2,_3,_4,_5,NAME,...) NAME
#define _SONAME_ARRAY(...) _SONAME_ARRAY_GET(__VA_ARGS__, _SONAME_ARRAY5, _SONAME_ARRAY4, _SONAME_ARRAY3, _SONAME_ARRAY2, _SONAME_ARRAY1)(__VA_ARGS__)
/* The 'priority' must be one of 'required', 'recommended' or 'suggested' as per specification, use the
* macro defined above to specify it.
* Multiple sonames can be passed and they will be automatically contructed into a json array (but note that
* due to preprocessor language limitations if more than the limit defined above is used, a new
* _SONAME_ARRAY<X+1> will need to be added). */
#define ELF_NOTE_DLOPEN(feature, description, priority, ...) \
_ELF_NOTE_DLOPEN("[{\"feature\":\"" feature "\",\"description\":\"" description "\",\"priority\":\"" priority "\",\"soname\":" _SONAME_ARRAY(__VA_ARGS__) "}]", UNIQ_T(s, UNIQ))
+5
View File
@@ -41,6 +41,11 @@ DLSYM_FUNCTION(gcry_randomize);
DLSYM_FUNCTION(gcry_strerror);
static int dlopen_gcrypt(void) {
ELF_NOTE_DLOPEN("gcrypt",
"Support for journald forward-sealing",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libgcrypt.so.20");
return dlopen_many_sym_or_warn(
&gcrypt_dl,
"libgcrypt.so.20", LOG_DEBUG,
+4
View File
@@ -16,6 +16,10 @@ DLSYM_FUNCTION(xkb_keymap_new_from_names);
DLSYM_FUNCTION(xkb_keymap_unref);
static int dlopen_xkbcommon(void) {
ELF_NOTE_DLOPEN("xkbcommon",
"Support for keyboard locale descriptions",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED, "libxkbcommon.so.0");
return dlopen_many_sym_or_warn(
&xkbcommon_dl, "libxkbcommon.so.0", LOG_DEBUG,
DLSYM_ARG(xkb_context_new),
+5
View File
@@ -76,6 +76,11 @@ int dlopen_bpf(void) {
void *dl;
int r;
ELF_NOTE_DLOPEN("bpf",
"Support firewalling and sandboxing with BPF",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libbpf.so.1", "libbpf.so.0");
DISABLE_WARNING_DEPRECATED_DECLARATIONS;
dl = dlopen("libbpf.so.1", RTLD_LAZY);
+5
View File
@@ -252,6 +252,11 @@ int dlopen_cryptsetup(void) {
DISABLE_WARNING_DEPRECATED_DECLARATIONS;
ELF_NOTE_DLOPEN("cryptsetup",
"Support for disk encryption, integrity, and authentication",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libcryptsetup.so.12");
r = dlopen_many_sym_or_warn(
&cryptsetup_dl, "libcryptsetup.so.12", LOG_DEBUG,
DLSYM_ARG(crypt_activate_by_passphrase),
+10
View File
@@ -87,6 +87,11 @@ static DLSYM_FUNCTION(gelf_getnote);
int dlopen_dw(void) {
int r;
ELF_NOTE_DLOPEN("dw",
"Support for backtrace and ELF package metadata decoding from core files",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libdw.so.1");
r = dlopen_many_sym_or_warn(
&dw_dl, "libdw.so.1", LOG_DEBUG,
DLSYM_ARG(dwarf_getscopes),
@@ -130,6 +135,11 @@ int dlopen_dw(void) {
int dlopen_elf(void) {
int r;
ELF_NOTE_DLOPEN("elf",
"Support for backtraces and reading ELF package metadata from core files",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libelf.so.1");
r = dlopen_many_sym_or_warn(
&elf_dl, "libelf.so.1", LOG_DEBUG,
DLSYM_ARG(elf_begin),
+5
View File
@@ -354,6 +354,11 @@ int fw_iptables_add_local_dnat(
}
static int dlopen_iptc(void) {
ELF_NOTE_DLOPEN("ip4tc",
"Support for firewall rules",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libip4tc.so.2");
return dlopen_many_sym_or_warn(
&iptc_dl,
"libip4tc.so.2", LOG_DEBUG,
+10
View File
@@ -21,6 +21,11 @@ const char *(*sym_idn2_strerror)(int rc) _const_ = NULL;
DLSYM_FUNCTION(idn2_to_unicode_8z8z);
int dlopen_idn(void) {
ELF_NOTE_DLOPEN("idn",
"Support for internationalized domain names",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libidn2.so.0");
return dlopen_many_sym_or_warn(
&idn_dl, "libidn2.so.0", LOG_DEBUG,
DLSYM_ARG(idn2_lookup_u8),
@@ -39,6 +44,11 @@ int dlopen_idn(void) {
_cleanup_(dlclosep) void *dl = NULL;
int r;
ELF_NOTE_DLOPEN("idn",
"Support for internationalized domain names",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libidn.so.12", "libidn.so.11");
if (idn_dl)
return 0; /* Already loaded */
+5
View File
@@ -30,6 +30,11 @@ DLSYM_FUNCTION(archive_write_set_format_filter_by_ext);
DLSYM_FUNCTION(archive_write_set_format_gnutar);
int dlopen_libarchive(void) {
ELF_NOTE_DLOPEN("archive",
"Support for decompressing archive files",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libarchive.so.13");
return dlopen_many_sym_or_warn(
&libarchive_dl,
"libarchive.so.13",
+5
View File
@@ -72,6 +72,11 @@ static void fido_log_propagate_handler(const char *s) {
int dlopen_libfido2(void) {
int r;
ELF_NOTE_DLOPEN("fido2",
"Support fido2 for encryption and authentication",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libfido2.so.1");
r = dlopen_many_sym_or_warn(
&libfido2_dl, "libfido2.so.1", LOG_DEBUG,
DLSYM_ARG(fido_assert_allow_cred),
+5
View File
@@ -25,6 +25,11 @@ DLSYM_FUNCTION(kmod_unref);
DLSYM_FUNCTION(kmod_validate_resources);
int dlopen_libkmod(void) {
ELF_NOTE_DLOPEN("kmod",
"Support for loading kernel modules",
ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
"libkmod.so.2");
return dlopen_many_sym_or_warn(
&libkmod_dl,
"libkmod.so.2",
@@ -20,6 +20,11 @@ DLSYM_FUNCTION(passwdqc_check);
DLSYM_FUNCTION(passwdqc_random);
int dlopen_passwdqc(void) {
ELF_NOTE_DLOPEN("passwdqc",
"Support for password quality checks",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libpasswdqc.so.1");
return dlopen_many_sym_or_warn(
&passwdqc_dl, "libpasswdqc.so.1", LOG_DEBUG,
DLSYM_ARG(passwdqc_params_reset),
@@ -24,6 +24,11 @@ DLSYM_FUNCTION(pwquality_set_int_value);
DLSYM_FUNCTION(pwquality_strerror);
int dlopen_pwquality(void) {
ELF_NOTE_DLOPEN("pwquality",
"Support for password quality checks",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libpwquality.so.1");
return dlopen_many_sym_or_warn(
&pwquality_dl, "libpwquality.so.1", LOG_DEBUG,
DLSYM_ARG(pwquality_check),
+5
View File
@@ -27,6 +27,11 @@ const struct hash_ops pcre2_code_hash_ops_free = {};
int dlopen_pcre2(void) {
#if HAVE_PCRE2
ELF_NOTE_DLOPEN("pcre2",
"Support for regular expressions",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libpcre2-8.so.0");
/* So here's something weird: PCRE2 actually renames the symbols exported by the library via C
* macros, so that the exported symbols carry a suffix "_8" but when used from C the suffix is
* gone. In the argument list below we ignore this mangling. Surprisingly (at least to me), we
+5
View File
@@ -61,6 +61,11 @@ DLSYM_FUNCTION(p11_kit_uri_new);
DLSYM_FUNCTION(p11_kit_uri_parse);
int dlopen_p11kit(void) {
ELF_NOTE_DLOPEN("p11-kit",
"Support for PKCS11 hardware tokens",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libp11-kit.so.0");
return dlopen_many_sym_or_warn(
&p11kit_dl,
"libp11-kit.so.0", LOG_DEBUG,
+5
View File
@@ -24,6 +24,11 @@ static DLSYM_FUNCTION(QRcode_free);
int dlopen_qrencode(void) {
int r;
ELF_NOTE_DLOPEN("qrencode",
"Support for generating QR codes",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libqrencode.so.4", "libqrencode.so.3");
FOREACH_STRING(s, "libqrencode.so.4", "libqrencode.so.3") {
r = dlopen_many_sym_or_warn(
&qrcode_dl, s, LOG_DEBUG,
+15
View File
@@ -113,6 +113,11 @@ static DLSYM_FUNCTION(Tss2_RC_Decode);
int dlopen_tpm2(void) {
int r;
ELF_NOTE_DLOPEN("tpm",
"Support for TPM",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libtss2-esys.so.0");
r = dlopen_many_sym_or_warn(
&libtss2_esys_dl, "libtss2-esys.so.0", LOG_DEBUG,
DLSYM_ARG(Esys_Create),
@@ -164,12 +169,22 @@ int dlopen_tpm2(void) {
if (r < 0)
log_debug("libtss2-esys too old, does not include Esys_TR_GetTpmHandle.");
ELF_NOTE_DLOPEN("tpm",
"Support for TPM",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libtss2-rc.so.0");
r = dlopen_many_sym_or_warn(
&libtss2_rc_dl, "libtss2-rc.so.0", LOG_DEBUG,
DLSYM_ARG(Tss2_RC_Decode));
if (r < 0)
return r;
ELF_NOTE_DLOPEN("tpm",
"Support for TPM",
ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
"libtss2-mu.so.0");
return dlopen_many_sym_or_warn(
&libtss2_mu_dl, "libtss2-mu.so.0", LOG_DEBUG,
DLSYM_ARG(Tss2_MU_TPM2_CC_Marshal),