From: Lennart Poettering Date: Sat, 11 May 2024 14:57:51 +0000 (+0200) Subject: core: split out smbios type 11 reader into src/shared/smbios11.[ch] X-Git-Tag: v257-rc1~1184^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bfb374e014b954371ff0964be8b7ecf78faf5c3e;p=thirdparty%2Fsystemd.git core: split out smbios type 11 reader into src/shared/smbios11.[ch] --- diff --git a/src/core/import-creds.c b/src/core/import-creds.c index f27ffed4a0d..4008ea43e9e 100644 --- a/src/core/import-creds.c +++ b/src/core/import-creds.c @@ -20,6 +20,7 @@ #include "path-util.h" #include "proc-cmdline.h" #include "recurse-dir.h" +#include "smbios11.h" #include "strv.h" #include "virt.h" @@ -578,38 +579,17 @@ static int import_credentials_smbios(ImportCredentialContext *c) { return 0; for (unsigned i = 0;; i++) { - struct dmi_field_header { - uint8_t type; - uint8_t length; - uint16_t handle; - uint8_t count; - char contents[]; - } _packed_ *dmi_field_header; - _cleanup_free_ char *p = NULL; - _cleanup_free_ void *data = NULL; + _cleanup_free_ char *data = NULL; size_t size; - assert_cc(offsetof(struct dmi_field_header, contents) == 5); - - if (asprintf(&p, "/sys/firmware/dmi/entries/11-%u/raw", i) < 0) - return log_oom(); - - r = read_virtual_file(p, sizeof(dmi_field_header) + CREDENTIALS_TOTAL_SIZE_MAX, (char**) &data, &size); + r = read_smbios11_field(i, CREDENTIALS_TOTAL_SIZE_MAX, &data, &size); if (r < 0) { /* Once we reach ENOENT there are no more DMI Type 11 fields around. */ - log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, "Failed to open '%s', ignoring: %m", p); + log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, "Failed to read SMBIOS type #11 object %u, ignoring: %m", i); break; } - if (size < offsetof(struct dmi_field_header, contents)) - return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "DMI field header of '%s' too short.", p); - - dmi_field_header = data; - if (dmi_field_header->type != 11 || - dmi_field_header->length != offsetof(struct dmi_field_header, contents)) - return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Invalid DMI field header."); - - r = parse_smbios_strings(c, dmi_field_header->contents, size - offsetof(struct dmi_field_header, contents)); + r = parse_smbios_strings(c, data, size); if (r < 0) return r; diff --git a/src/shared/meson.build b/src/shared/meson.build index c5106d87d55..a1c3b421ccf 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -157,6 +157,7 @@ shared_sources = files( 'service-util.c', 'sleep-config.c', 'smack-util.c', + 'smbios11.c', 'socket-label.c', 'socket-netlink.c', 'spawn-ask-password-agent.c', diff --git a/src/shared/smbios11.c b/src/shared/smbios11.c new file mode 100644 index 00000000000..50094278103 --- /dev/null +++ b/src/shared/smbios11.c @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "alloc-util.h" +#include "fileio.h" +#include "macro.h" +#include "smbios11.h" +#include "virt.h" + +int read_smbios11_field(unsigned i, size_t max_size, char **ret_data, size_t *ret_size) { + _cleanup_free_ char *p = NULL, *contents = NULL; + _cleanup_free_ void *data = NULL; + size_t size, contents_size; + int r; + + assert(ret_data); + assert(ret_size); + + /* Parses DMI OEM strings fields (SMBIOS type 11), as settable with qemu's -smbios type=11,value=… switch. */ + + if (detect_container() > 0) /* don't access /sys/ in a container */ + return -ENOENT; + + if (asprintf(&p, "/sys/firmware/dmi/entries/11-%u/raw", i) < 0) + return -ENOMEM; + + struct dmi_field_header { + uint8_t type; + uint8_t length; + uint16_t handle; + uint8_t count; + char contents[]; + } _packed_ *dmi_field_header; + + assert_cc(offsetof(struct dmi_field_header, contents) == 5); + + r = read_virtual_file( + p, + max_size >= SIZE_MAX - offsetof(struct dmi_field_header, contents) ? SIZE_MAX : + sizeof(dmi_field_header) + max_size, + (char**) &data, &size); + if (r < 0) + return r; + + if (size < offsetof(struct dmi_field_header, contents)) + return -EBADMSG; + + dmi_field_header = data; + if (dmi_field_header->type != 11 || + dmi_field_header->length != offsetof(struct dmi_field_header, contents)) + return -EBADMSG; + + contents_size = size - offsetof(struct dmi_field_header, contents); + contents = memdup_suffix0(dmi_field_header->contents, contents_size); + if (!contents) + return -ENOMEM; + + *ret_data = TAKE_PTR(contents); + *ret_size = contents_size; + + return r; /* NB! read_virtual_file() returns 0 on incomplete reads, and 1 in complete reads */ +} diff --git a/src/shared/smbios11.h b/src/shared/smbios11.h new file mode 100644 index 00000000000..ca8fe452605 --- /dev/null +++ b/src/shared/smbios11.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include + +int read_smbios11_field(unsigned i, size_t max_size, char **ret_data, size_t *ret_size);