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

systemd / systemd / 19086794632

04 Nov 2025 08:16PM UTC coverage: 72.165% (-0.1%) from 72.279%
19086794632

push

github

yuwata
TEST-64-UDEV-STORAGE: generate debugging logs

Let's see if it provides something useful for debugging issue #39544.

305891 of 423878 relevant lines covered (72.16%)

1224411.04 hits per line

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

66.98
/src/core/executor.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <getopt.h>
4
#include <stdlib.h>
5

6
#include "sd-messages.h"
7

8
#include "alloc-util.h"
9
#include "argv-util.h"
10
#include "build.h"
11
#include "capability-util.h"
12
#include "cgroup.h"
13
#include "dynamic-user.h"
14
#include "exec-invoke.h"
15
#include "execute.h"
16
#include "execute-serialize.h"
17
#include "exit-status.h"
18
#include "fd-util.h"
19
#include "fdset.h"
20
#include "fileio.h"
21
#include "getopt-defs.h"
22
#include "label-util.h"
23
#include "log.h"
24
#include "parse-util.h"
25
#include "pretty-print.h"
26
#include "selinux-util.h"
27
#include "static-destruct.h"
28

29
static FILE *arg_serialization = NULL;
30

31
STATIC_DESTRUCTOR_REGISTER(arg_serialization, fclosep);
32✔
32

33
static int help(void) {
×
34
        _cleanup_free_ char *link = NULL;
×
35
        int r;
×
36

37
        r = terminal_urlify_man("systemd", "1", &link);
×
38
        if (r < 0)
×
39
                return log_oom();
×
40

41
        printf("%s [OPTIONS...]\n\n"
×
42
               "%sSandbox and execute processes.%s\n\n"
43
               "  -h --help                Show this help and exit\n"
44
               "     --version             Print version string and exit\n"
45
               "     --log-target=TARGET   Set log target (console, journal,\n"
46
               "                                           journal-or-kmsg,\n"
47
               "                                           kmsg, null)\n"
48
               "     --log-level=LEVEL     Set log level (debug, info, notice,\n"
49
               "                                          warning, err, crit,\n"
50
               "                                          alert, emerg)\n"
51
               "     --log-color=BOOL      Highlight important messages\n"
52
               "     --log-location=BOOL   Include code location in messages\n"
53
               "     --log-time=BOOL       Prefix messages with current time\n"
54
               "     --deserialize=FD      Deserialize process config from FD\n"
55
               "\nSee the %s for details.\n",
56
               program_invocation_short_name,
57
               ansi_highlight(),
58
               ansi_normal(),
59
               link);
60

61
        return 0;
62
}
63

64
static int parse_argv(int argc, char *argv[]) {
12,251✔
65
        enum {
12,251✔
66
                COMMON_GETOPT_ARGS,
67
                ARG_VERSION,
68
                ARG_DESERIALIZE,
69
        };
70

71
        static const struct option options[] = {
12,251✔
72
                { "log-level",      required_argument, NULL, ARG_LOG_LEVEL      },
73
                { "log-target",     required_argument, NULL, ARG_LOG_TARGET     },
74
                { "log-color",      required_argument, NULL, ARG_LOG_COLOR      },
75
                { "log-location",   required_argument, NULL, ARG_LOG_LOCATION   },
76
                { "log-time",       required_argument, NULL, ARG_LOG_TIME       },
77
                { "help",           no_argument,       NULL, 'h'                },
78
                { "version",        no_argument,       NULL, ARG_VERSION        },
79
                { "deserialize",    required_argument, NULL, ARG_DESERIALIZE    },
80
                {}
81
        };
82

83
        int c, r;
12,251✔
84

85
        assert(argc >= 0);
12,251✔
86
        assert(argv);
12,251✔
87

88
        while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
49,004✔
89
                switch (c) {
36,753✔
90
                case 'h':
×
91
                        return help();
×
92

93
                case ARG_VERSION:
×
94
                        return version();
×
95

96
                case ARG_LOG_LEVEL:
12,251✔
97
                        r = log_set_max_level_from_string(optarg);
12,251✔
98
                        if (r < 0)
12,251✔
99
                                return log_error_errno(r, "Failed to parse log level \"%s\": %m", optarg);
×
100

101
                        break;
102

103
                case ARG_LOG_TARGET:
12,251✔
104
                        r = log_set_target_from_string(optarg);
12,251✔
105
                        if (r < 0)
12,251✔
106
                                return log_error_errno(r, "Failed to parse log target \"%s\": %m", optarg);
×
107

108
                        break;
109

110
                case ARG_LOG_COLOR:
×
111
                        r = log_show_color_from_string(optarg);
×
112
                        if (r < 0)
×
113
                                return log_error_errno(
×
114
                                                r,
115
                                                "Failed to parse log color setting \"%s\": %m",
116
                                                optarg);
117

118
                        break;
119

120
                case ARG_LOG_LOCATION:
×
121
                        r = log_show_location_from_string(optarg);
×
122
                        if (r < 0)
×
123
                                return log_error_errno(
×
124
                                                r,
125
                                                "Failed to parse log location setting \"%s\": %m",
126
                                                optarg);
127

128
                        break;
129

130
                case ARG_LOG_TIME:
×
131
                        r = log_show_time_from_string(optarg);
×
132
                        if (r < 0)
×
133
                                return log_error_errno(
×
134
                                                r,
135
                                                "Failed to parse log time setting \"%s\": %m",
136
                                                optarg);
137

138
                        break;
139

140
                case ARG_DESERIALIZE: {
12,251✔
141
                        _cleanup_close_ int fd = -EBADF;
12,251✔
142
                        FILE *f;
12,251✔
143

144
                        fd = parse_fd(optarg);
12,251✔
145
                        if (fd < 0)
12,251✔
146
                                return log_error_errno(fd,
×
147
                                                       "Failed to parse serialization fd \"%s\": %m",
148
                                                       optarg);
149

150
                        r = fd_cloexec(fd, /* cloexec= */ true);
12,251✔
151
                        if (r < 0)
12,251✔
152
                                return log_error_errno(r,
×
153
                                                       "Failed to set serialization fd %d to close-on-exec: %m",
154
                                                       fd);
155

156
                        f = take_fdopen(&fd, "r");
12,251✔
157
                        if (!f)
12,251✔
158
                                return log_error_errno(errno, "Failed to open serialization fd %d: %m", fd);
×
159

160
                        safe_fclose(arg_serialization);
12,251✔
161
                        arg_serialization = f;
12,251✔
162

163
                        break;
12,251✔
164
                }
165

166
                case '?':
167
                        return -EINVAL;
168

169
                default:
×
170
                        assert_not_reached();
×
171
                }
172

173
        if (!arg_serialization)
12,251✔
174
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No serialization fd specified.");
×
175

176
        return 1 /* work to do */;
177
}
178

179
static int run(int argc, char *argv[]) {
12,251✔
180
        _cleanup_fdset_free_ FDSet *fdset = NULL;
32✔
181
        _cleanup_(cgroup_context_done) CGroupContext cgroup_context = {};
32✔
182
        _cleanup_(exec_context_done) ExecContext context = {};
32✔
183
        _cleanup_(exec_command_done) ExecCommand command = {};
32✔
184
        _cleanup_(exec_params_deep_clear) ExecParameters params = EXEC_PARAMETERS_INIT(/* flags= */ 0);
32✔
185
        _cleanup_(exec_shared_runtime_done) ExecSharedRuntime shared = {
32✔
186
                .userns_storage_socket = EBADF_PAIR,
187
                .netns_storage_socket = EBADF_PAIR,
188
                .ipcns_storage_socket = EBADF_PAIR,
189
        };
190
        _cleanup_(dynamic_creds_done) DynamicCreds dynamic_creds = {};
32✔
191
        _cleanup_(exec_runtime_clear) ExecRuntime runtime = {
32✔
192
                .ephemeral_storage_socket = EBADF_PAIR,
193
                .shared = &shared,
194
                .dynamic_creds = &dynamic_creds,
195
        };
196
        int exit_status = EXIT_SUCCESS, r;
12,251✔
197

198
        exec_context_init(&context);
12,251✔
199
        cgroup_context_init(&cgroup_context);
12,251✔
200

201
        /* We might be starting the journal itself, we'll be told by the caller what to do */
202
        log_set_always_reopen_console(true);
12,251✔
203
        log_set_prohibit_ipc(true);
12,251✔
204
        log_setup();
12,251✔
205

206
        r = parse_argv(argc, argv);
12,251✔
207
        if (r <= 0)
12,251✔
208
                return r;
209

210
        /* Now that we know the intended log target, allow IPC and open the final log target. */
211
        log_set_prohibit_ipc(false);
12,251✔
212
        log_open();
12,251✔
213

214
        /* Clear ambient capabilities, so services do not inherit them implicitly. Dropping them does
215
         * not affect the permitted and effective sets which are important for the executor itself to
216
         * operate. */
217
        r = capability_ambient_set_apply(0, /* also_inherit= */ false);
12,251✔
218
        if (r < 0)
12,251✔
219
                log_warning_errno(r, "Failed to clear ambient capabilities, ignoring: %m");
×
220

221
        /* This call would collect all passed fds and enable CLOEXEC. We'll unset it in exec_invoke (flag_fds)
222
         * for fds that shall be passed to the child.
223
         * The serialization fd is set to CLOEXEC in parse_argv, so it's also filtered. */
224
        r = fdset_new_fill(/* filter_cloexec= */ 0, &fdset);
12,251✔
225
        if (r < 0)
12,251✔
226
                return log_error_errno(r, "Failed to create fd set: %m");
×
227

228
        /* Initialize lazily. SMACK is just a few operations, but the SELinux is very slow as it requires
229
         * loading the entire database in memory, so we will do it lazily only if it is actually needed, to
230
         * avoid wasting 2ms-10ms for each sd-executor that gets spawned. */
231
        r = mac_init_lazy();
12,251✔
232
        if (r < 0)
12,251✔
233
                return log_error_errno(r, "Failed to initialize MAC layer: %m");
×
234

235
        r = exec_deserialize_invocation(arg_serialization,
12,251✔
236
                                        fdset,
237
                                        &context,
238
                                        &command,
239
                                        &params,
240
                                        &runtime,
241
                                        &cgroup_context);
242
        if (r < 0)
12,251✔
243
                return log_error_errno(r, "Failed to deserialize: %m");
×
244

245
        LOG_CONTEXT_PUSH_EXEC(&context, &params);
35,423✔
246

247
        arg_serialization = safe_fclose(arg_serialization);
12,251✔
248
        fdset = fdset_free(fdset);
12,251✔
249

250
        r = exec_invoke(&command,
12,251✔
251
                        &context,
252
                        &params,
253
                        &runtime,
254
                        &cgroup_context,
255
                        &exit_status);
256
        if (r < 0) {
32✔
257
                const char *status = ASSERT_PTR(
31✔
258
                                exit_status_to_string(exit_status, EXIT_STATUS_LIBC | EXIT_STATUS_SYSTEMD));
259

260
                log_struct_errno(LOG_ERR, r,
31✔
261
                                 LOG_MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED_STR),
262
                                 LOG_EXEC_MESSAGE(&params, "Failed at step %s spawning %s: %m",
263
                                                  status, command.path),
264
                                 LOG_ITEM("EXECUTABLE=%s", command.path));
265
        } else
266
                /* r == 0: 'skip' is chosen in the confirm spawn prompt
267
                 * r > 0:  expected/ignored failure, do not log at error level */
268
                assert((r == 0) == (exit_status == EXIT_SUCCESS));
1✔
269

270
        return exit_status;
32✔
271
}
272

273
int main(int argc, char *argv[]) {
12,251✔
274
        int r;
12,251✔
275

276
        /* We use safe_fork() for spawning sd-pam helper process, which internally calls rename_process().
277
         * As the last step of renaming, all saved argvs are memzero()-ed. Hence, we need to save the argv
278
         * first to prevent showing "intense" cmdline. See #30352. */
279
        save_argc_argv(argc, argv);
12,251✔
280

281
        r = run(argc, argv);
12,251✔
282

283
        mac_selinux_finish();
32✔
284
        static_destruct();
32✔
285

286
        return r < 0 ? EXIT_FAILURE : r;
32✔
287
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc