• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 29461261567

15 Jul 2026 04:59PM UTC coverage: 72.983% (+0.05%) from 72.936%
29461261567

push

github

yuwata
tpm2-util: keep the measurement log's torn-write marker intact

The userspace measurement log carries a sticky-bit marker while a writer
is between updating a measurement register and appending the matching
record, so that a writer dying in between leaves the log detectably
incomplete.

However, the next successful writer used to clear the marker again after
appending its own record, erasing the evidence that an earlier writer
had died and the log is still missing a record. Keep the marker set in
that case instead; the new record is appended and synced regardless. The
marker likewise stays set if the measurement itself fails, so that any
non-clean completion remains flagged: a spurious flag on a failed but
harmless measurement is preferable to erasing evidence of a real gap,
and PCR replay stays authoritative either way.

Finally, warn when systemd-pcrlock loads a marked log, so the resulting
PCR validation failures come with a hint at their cause.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>

11 of 12 new or added lines in 2 files covered. (91.67%)

2475 existing lines in 54 files now uncovered.

346100 of 474222 relevant lines covered (72.98%)

1321758.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.66
/src/shared/module-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <syslog.h>
4

5
#include "log.h"
6
#include "module-util.h"
7
#include "proc-cmdline.h"
8
#include "strv.h"
9

10
#if HAVE_KMOD
11

12
DLSYM_PROTOTYPE(kmod_list_next) = NULL;
13
DLSYM_PROTOTYPE(kmod_load_resources) = NULL;
14
DLSYM_PROTOTYPE(kmod_module_get_initstate) = NULL;
15
DLSYM_PROTOTYPE(kmod_module_get_module) = NULL;
16
DLSYM_PROTOTYPE(kmod_module_get_name) = NULL;
17
DLSYM_PROTOTYPE(kmod_module_new_from_lookup) = NULL;
18
DLSYM_PROTOTYPE(kmod_module_probe_insert_module) = NULL;
19
DLSYM_PROTOTYPE(kmod_module_unref) = NULL;
20
DLSYM_PROTOTYPE(kmod_module_unref_list) = NULL;
21
DLSYM_PROTOTYPE(kmod_new) = NULL;
22
DLSYM_PROTOTYPE(kmod_set_log_fn) = NULL;
23
DLSYM_PROTOTYPE(kmod_unref) = NULL;
24
DLSYM_PROTOTYPE(kmod_validate_resources) = NULL;
25

26
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
×
27
        char ***denylist = ASSERT_PTR(data);
×
28
        int r;
×
29

30
        if (proc_cmdline_key_streq(key, "module_blacklist")) {
×
31

32
                if (proc_cmdline_value_missing(key, value))
×
33
                        return 0;
34

35
                r = strv_split_and_extend(denylist, value, ",", /* filter_duplicates= */ true);
×
36
                if (r < 0)
×
37
                        return r;
×
38
        }
39

40
        return 0;
41
}
42

43
int module_load_and_warn(struct kmod_ctx *ctx, const char *module, bool verbose) {
4,391✔
44
        _cleanup_(kmod_module_unref_listp) struct kmod_list *modlist = NULL;
4,391✔
45
        _cleanup_strv_free_ char **denylist = NULL;
4,391✔
46
        bool denylist_parsed = false;
4,391✔
47
        struct kmod_list *itr;
4,391✔
48
        int r;
4,391✔
49

50
        assert(ctx);
4,391✔
51
        assert(module);
4,391✔
52

53
        /* verbose==true means we should log at non-debug level if we
54
         * fail to find or load the module. */
55

56
        log_debug("Loading module: %s", module);
4,391✔
57

58
        r = sym_kmod_module_new_from_lookup(ctx, module, &modlist);
4,391✔
59
        if (r < 0)
4,391✔
60
                return log_full_errno(verbose ? LOG_ERR : LOG_DEBUG, r,
×
61
                                      "Failed to look up module alias '%s': %m", module);
62

63
        if (!modlist)
4,391✔
64
                return log_full_errno(verbose ? LOG_ERR : LOG_DEBUG,
1,715✔
65
                                      SYNTHETIC_ERRNO(ENOENT),
66
                                      "Failed to find module '%s'", module);
67

68
        sym_kmod_list_foreach(itr, modlist) {
6,176✔
69
                _cleanup_(kmod_module_unrefp) struct kmod_module *mod = NULL;
3,500✔
70
                int state, err;
3,500✔
71

72
                mod = sym_kmod_module_get_module(itr);
3,500✔
73
                state = sym_kmod_module_get_initstate(mod);
3,500✔
74

75
                switch (state) {
3,500✔
76
                case KMOD_MODULE_BUILTIN:
77
                        log_full(verbose ? LOG_INFO : LOG_DEBUG,
1,641✔
78
                                 "Module '%s' is built in", sym_kmod_module_get_name(mod));
79
                        break;
80

81
                case KMOD_MODULE_LIVE:
82
                        log_debug("Module '%s' is already loaded", sym_kmod_module_get_name(mod));
673✔
83
                        break;
84

85
                default:
1,186✔
86
                        err = sym_kmod_module_probe_insert_module(
1,186✔
87
                                        mod,
88
                                        KMOD_PROBE_APPLY_BLACKLIST,
89
                                        /* extra_options= */ NULL,
90
                                        /* run_install= */ NULL,
91
                                        /* data= */ NULL,
92
                                        /* print_action= */ NULL);
93
                        if (err == 0)
1,186✔
94
                                log_full(verbose ? LOG_INFO : LOG_DEBUG,
990✔
95
                                         "Inserted module '%s'", sym_kmod_module_get_name(mod));
96
                        else if (err == KMOD_PROBE_APPLY_BLACKLIST)
196✔
97
                                log_full(verbose ? LOG_INFO : LOG_DEBUG,
×
98
                                         "Module '%s' is deny-listed (by kmod)", sym_kmod_module_get_name(mod));
99
                        else {
100
                                assert(err < 0);
196✔
101

102
                                if (err == -EPERM) {
196✔
103
                                        if (!denylist_parsed) {
×
104
                                                r = proc_cmdline_parse(parse_proc_cmdline_item, &denylist, 0);
×
105
                                                if (r < 0)
×
106
                                                        log_full_errno(!verbose ? LOG_DEBUG : LOG_WARNING,
×
107
                                                                       r,
108
                                                                       "Failed to parse kernel command line, ignoring: %m");
109

110
                                                denylist_parsed = true;
111
                                        }
112
                                        if (strv_contains(denylist, sym_kmod_module_get_name(mod))) {
×
113
                                                log_full(verbose ? LOG_INFO : LOG_DEBUG,
×
114
                                                         "Module '%s' is deny-listed (by kernel)", sym_kmod_module_get_name(mod));
115
                                                continue;
×
116
                                        }
117
                                }
118

119
                                log_full_errno(!verbose ? LOG_DEBUG :
196✔
120
                                               err == -ENODEV ? LOG_NOTICE :
121
                                               err == -ENOENT ? LOG_WARNING :
122
                                                                LOG_ERR,
123
                                               err,
124
                                               "Failed to insert module '%s': %m",
125
                                               sym_kmod_module_get_name(mod));
126
                                if (!IN_SET(err, -ENODEV, -ENOENT))
196✔
UNCOV
127
                                        r = err;
×
128
                        }
129
                }
130
        }
131

132
        return r;
133
}
134

135
_printf_(6,0) static void systemd_kmod_log(
×
136
                void *data,
137
                int priority,
138
                const char *file,
139
                int line,
140
                const char *fn,
141
                const char *format,
142
                va_list args) {
143

144
        log_internalv(priority, 0, file, line, fn, format, args);
×
145
}
×
146

147
int module_setup_context(struct kmod_ctx **ret) {
233✔
148
        _cleanup_(kmod_unrefp) struct kmod_ctx *ctx = NULL;
233✔
149
        int r;
233✔
150

151
        assert(ret);
233✔
152

153
        r = dlopen_libkmod(LOG_DEBUG);
233✔
154
        if (r < 0)
233✔
155
                return r;
156

157
        ctx = sym_kmod_new(NULL, NULL);
233✔
158
        if (!ctx)
233✔
159
                return -ENOMEM;
160

161
        (void) sym_kmod_load_resources(ctx);
233✔
162
        sym_kmod_set_log_fn(ctx, systemd_kmod_log, NULL);
233✔
163

164
        *ret = TAKE_PTR(ctx);
233✔
165
        return 0;
233✔
166
}
167

168
#endif
169

170
int dlopen_libkmod(int log_level) {
293✔
171
#if HAVE_KMOD
172
        static void *libkmod_dl = NULL;
293✔
173

174
        LIBKMOD_NOTE(recommended);
293✔
175

176
        return dlopen_many_sym_or_warn(
293✔
177
                        &libkmod_dl,
178
                        "libkmod.so.2",
179
                        log_level,
180
                        DLSYM_ARG(kmod_list_next),
181
                        DLSYM_ARG(kmod_load_resources),
182
                        DLSYM_ARG(kmod_module_get_initstate),
183
                        DLSYM_ARG(kmod_module_get_module),
184
                        DLSYM_ARG(kmod_module_get_name),
185
                        DLSYM_ARG(kmod_module_new_from_lookup),
186
                        DLSYM_ARG(kmod_module_probe_insert_module),
187
                        DLSYM_ARG(kmod_module_unref),
188
                        DLSYM_ARG(kmod_module_unref_list),
189
                        DLSYM_ARG(kmod_new),
190
                        DLSYM_ARG(kmod_set_log_fn),
191
                        DLSYM_ARG(kmod_unref),
192
                        DLSYM_ARG(kmod_validate_resources));
193
#else
194
        return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
195
                              "libkmod support is not compiled in.");
196
#endif
197
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc