]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: split out smbios type 11 reader into src/shared/smbios11.[ch]
authorLennart Poettering <lennart@poettering.net>
Sat, 11 May 2024 14:57:51 +0000 (16:57 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 12 Jun 2024 10:48:06 +0000 (12:48 +0200)
src/core/import-creds.c
src/shared/meson.build
src/shared/smbios11.c [new file with mode: 0644]
src/shared/smbios11.h [new file with mode: 0644]

index f27ffed4a0d50765eb439d20716ce6088299f137..4008ea43e9eea5eea8928b99b6ed5e2601d309da 100644 (file)
@@ -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;
 
index c5106d87d55665e9fa9f91357a1fae4af7bf7e7e..a1c3b421ccf7c8102a92371f3d0a857ffc0b0679 100644 (file)
@@ -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 (file)
index 0000000..5009427
--- /dev/null
@@ -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 (file)
index 0000000..ca8fe45
--- /dev/null
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include <sys/types.h>
+
+int read_smbios11_field(unsigned i, size_t max_size, char **ret_data, size_t *ret_size);