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

systemd / systemd / 19877670170

02 Dec 2025 04:56PM UTC coverage: 72.905% (+0.001%) from 72.904%
19877670170

push

github

web-flow
kernel-install: exit with option --json=help (#39974)

In that case, `parse_json_argument()` returns 0.

Follow-up for bdd36c003 (v255).

0 of 1 new or added line in 1 file covered. (0.0%)

367 existing lines in 34 files now uncovered.

310170 of 425446 relevant lines covered (72.9%)

1132258.26 hits per line

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

69.9
/src/nspawn/nspawn-register.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include "sd-bus.h"
4

5
#include "alloc-util.h"
6
#include "bus-error.h"
7
#include "bus-locator.h"
8
#include "bus-unit-util.h"
9
#include "bus-util.h"
10
#include "bus-wait-for-jobs.h"
11
#include "nspawn-mount.h"
12
#include "nspawn-register.h"
13
#include "nspawn-settings.h"
14
#include "pidref.h"
15
#include "special.h"
16
#include "stat-util.h"
17
#include "string-util.h"
18
#include "unit-def.h"
19
#include "unit-name.h"
20

21
static int append_machine_properties(
144✔
22
                sd_bus_message *m,
23
                CustomMount *mounts,
24
                unsigned n_mounts,
25
                int kill_signal,
26
                bool coredump_receive) {
27

28
        int r;
144✔
29

30
        assert(m);
144✔
31

32
        r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "closed");
144✔
33
        if (r < 0)
144✔
34
                return bus_log_create_error(r);
×
35

36
        /* If you make changes here, also make sure to update systemd-nspawn@.service, to keep the device
37
         * policies in sync regardless if we are run with or without the --keep-unit switch. */
38
        r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 3,
144✔
39
                                  /* Allow the container to access and create the API device node, so that
40
                                   * PrivateDevices= in the container can work fine. */
41
                                  "/dev/net/tun", "rwm",
42
                                  /* Allow the container to access ptys. However, do not permit the container
43
                                   * to ever create these device nodes. */
44
                                  "char-pts", "rw",
45
                                  /* Allow the container to access and create the FUSE API device node. */
46
                                  "/dev/fuse", "rwm");
47
        if (r < 0)
144✔
48
                return bus_log_create_error(r);
×
49

50
        FOREACH_ARRAY(cm, mounts, n_mounts) {
299✔
51
                if (cm->type != CUSTOM_MOUNT_BIND)
155✔
52
                        continue;
28✔
53

54
                r = is_device_node(cm->source);
127✔
55
                if (r == -ENOENT) {
127✔
56
                        /* The bind source might only appear as the image is put together, hence don't complain */
57
                        log_debug_errno(r, "Bind mount source %s not found, ignoring: %m", cm->source);
1✔
58
                        continue;
1✔
59
                }
60
                if (r < 0)
126✔
61
                        return log_error_errno(r, "Failed to stat %s: %m", cm->source);
×
62

63
                if (r) {
126✔
64
                        r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1,
×
65
                                                  cm->source, cm->read_only ? "r" : "rw");
×
66
                        if (r < 0)
×
67
                                return log_error_errno(r, "Failed to append message arguments: %m");
×
68
                }
69
        }
70

71
        if (kill_signal != 0) {
144✔
72
                r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal);
27✔
73
                if (r < 0)
27✔
74
                        return bus_log_create_error(r);
×
75

76
                r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed");
27✔
77
                if (r < 0)
27✔
78
                        return bus_log_create_error(r);
×
79
        }
80

81
        if (coredump_receive) {
144✔
82
                r = sd_bus_message_append(m, "(sv)", "CoredumpReceive", "b", true);
27✔
83
                if (r < 0)
27✔
84
                        return bus_log_create_error(r);
×
85
        }
86

87
        return 0;
88
}
89

90
static int append_controller_property(sd_bus *bus, sd_bus_message *m) {
144✔
91
        const char *unique;
144✔
92
        int r;
144✔
93

94
        assert(bus);
144✔
95
        assert(m);
144✔
96

97
        r = sd_bus_get_unique_name(bus, &unique);
144✔
98
        if (r < 0)
144✔
99
                return log_error_errno(r, "Failed to get unique name: %m");
×
100

101
        r = sd_bus_message_append(m, "(sv)", "Controller", "s", unique);
144✔
102
        if (r < 0)
144✔
103
                return bus_log_create_error(r);
×
104

105
        return 0;
106
}
107

108
static int can_set_coredump_receive(sd_bus *bus) {
27✔
109
        _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
×
110
        _cleanup_free_ char *path = NULL;
27✔
111
        int b, r;
27✔
112

113
        assert(bus);
27✔
114

115
        path = unit_dbus_path_from_name(SPECIAL_INIT_SCOPE);
27✔
116
        if (!path)
27✔
117
                return log_oom();
×
118

119
        r = sd_bus_get_property_trivial(
27✔
120
                        bus,
121
                        "org.freedesktop.systemd1",
122
                        path,
123
                        "org.freedesktop.systemd1.Scope",
124
                        "CoredumpReceive",
125
                        &e,
126
                        'b', &b);
127
        if (r < 0 && !sd_bus_error_has_names(&e, SD_BUS_ERROR_UNKNOWN_PROPERTY, SD_BUS_ERROR_PROPERTY_READ_ONLY))
27✔
128
                log_warning_errno(r, "Failed to determine if CoredumpReceive= can be set, assuming it cannot be: %s",
×
129
                                  bus_error_message(&e, r));
130

131
        return r >= 0;
27✔
132
}
133

134
static int register_machine_ex(
56✔
135
                sd_bus *bus,
136
                const char *machine_name,
137
                const PidRef *pid,
138
                const char *directory,
139
                sd_id128_t uuid,
140
                int local_ifindex,
141
                const char *service,
142
                sd_bus_error *error) {
143

144
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
56✔
145
        int r;
56✔
146

147
        assert(bus);
56✔
148
        assert(machine_name);
56✔
149
        assert(service);
56✔
150
        assert(error);
56✔
151

152
        r = bus_message_new_method_call(bus, &m,  bus_machine_mgr, "RegisterMachineEx");
56✔
153
        if (r < 0)
56✔
154
                return bus_log_create_error(r);
×
155

156
        r = sd_bus_message_append(m, "s", machine_name);
56✔
157
        if (r < 0)
56✔
158
                return bus_log_create_error(r);
×
159

160
        r = sd_bus_message_open_container(m, 'a', "(sv)");
56✔
161
        if (r < 0)
56✔
162
                return bus_log_create_error(r);
×
163

164
        r = sd_bus_message_append(
112✔
165
                        m,
166
                        "(sv)(sv)(sv)",
167
                        "Id", "ay", SD_BUS_MESSAGE_APPEND_ID128(uuid),
56✔
168
                        "Service", "s", service,
169
                        "Class", "s", "container");
170
        if (r < 0)
56✔
171
                return bus_log_create_error(r);
×
172

173
        if (pidref_is_set(pid)) {
56✔
174
                if (pid->fd >= 0) {
56✔
175
                        r = sd_bus_message_append(m, "(sv)", "LeaderPIDFD", "h", pid->fd);
56✔
176
                        if (r < 0)
56✔
177
                                return bus_log_create_error(r);
×
178
                }
179

180
                if (pid->fd_id > 0) {
56✔
181
                        r = sd_bus_message_append(m, "(sv)", "LeaderPIDFDID", "t", pid->fd_id);
×
182
                        if (r < 0)
×
183
                                return bus_log_create_error(r);
×
184

185
                        r = sd_bus_message_append(m, "(sv)", "LeaderPID", "u", pid->pid);
×
186
                        if (r < 0)
×
187
                                return bus_log_create_error(r);
×
188
                }
189
        }
190

191
        if (!isempty(directory)) {
56✔
192
                r = sd_bus_message_append(m, "(sv)", "RootDirectory", "s", directory);
54✔
193
                if (r < 0)
54✔
194
                        return bus_log_create_error(r);
×
195
        }
196

197
        if (local_ifindex > 0) {
56✔
198
                r = sd_bus_message_append(m, "(sv)", "NetworkInterfaces", "ai", 1, local_ifindex);
27✔
199
                if (r < 0)
27✔
200
                        return bus_log_create_error(r);
×
201
        }
202

203
        r = sd_bus_message_close_container(m);
56✔
204
        if (r < 0)
56✔
205
                return bus_log_create_error(r);
×
206

207
        return sd_bus_call(bus, m, 0, error, NULL);
56✔
208
}
209

210
int register_machine(
56✔
211
                sd_bus *bus,
212
                const char *machine_name,
213
                const PidRef *pid,
214
                const char *directory,
215
                sd_id128_t uuid,
216
                int local_ifindex,
217
                const char *service) {
218

219
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
56✔
220
        int r;
56✔
221

222
        assert(bus);
56✔
223
        assert(machine_name);
56✔
224
        assert(service);
56✔
225

226
        r = register_machine_ex(
56✔
227
                        bus,
228
                        machine_name,
229
                        pid,
230
                        directory,
231
                        uuid,
232
                        local_ifindex,
233
                        service,
234
                        &error);
235
        if (r >= 0)
56✔
236
                return 0;
UNCOV
237
        if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
×
UNCOV
238
                return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r));
×
239

240
        sd_bus_error_free(&error);
×
241

242
        r = bus_call_method(
×
243
                        bus,
244
                        bus_machine_mgr,
245
                        "RegisterMachineWithNetwork",
246
                        &error,
247
                        NULL,
248
                        "sayssusai",
249
                        machine_name,
250
                        SD_BUS_MESSAGE_APPEND_ID128(uuid),
×
251
                        service,
252
                        "container",
253
                        pidref_is_set(pid) ? (uint32_t) pid->pid : 0,
×
254
                        strempty(directory),
255
                        local_ifindex > 0 ? 1 : 0, local_ifindex);
256
        if (r < 0)
×
257
                return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r));
×
258

259
        return 0;
260
}
261

262
int unregister_machine(
53✔
263
                sd_bus *bus,
264
                const char *machine_name) {
265

266
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
×
267
        int r;
53✔
268

269
        assert(bus);
53✔
270

271
        r = bus_call_method(bus, bus_machine_mgr, "UnregisterMachine", &error, NULL, "s", machine_name);
53✔
272
        if (r < 0)
53✔
273
                log_debug("Failed to unregister machine: %s", bus_error_message(&error, r));
39✔
274

275
        return 0;
53✔
276
}
277

278
int allocate_scope(
144✔
279
                sd_bus *bus,
280
                const char *machine_name,
281
                const PidRef* pid,
282
                const char *slice,
283
                CustomMount *mounts,
284
                unsigned n_mounts,
285
                int kill_signal,
286
                char **properties,
287
                sd_bus_message *properties_message,
288
                StartMode start_mode,
289
                AllocateScopeFlags flags) {
290

291
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
288✔
292
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
144✔
293
        _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
×
294
        _cleanup_free_ char *scope = NULL;
144✔
295
        const char *object;
144✔
296
        int r;
144✔
297

298
        assert(bus);
144✔
299

300
        r = bus_wait_for_jobs_new(bus, &w);
144✔
301
        if (r < 0)
144✔
302
                return log_error_errno(r, "Could not watch job: %m");
×
303

304
        r = unit_name_mangle_with_suffix(machine_name, "as machine name", 0, ".scope", &scope);
144✔
305
        if (r < 0)
144✔
306
                return log_error_errno(r, "Failed to mangle scope name: %m");
×
307

308
        r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "StartTransientUnit");
144✔
309
        if (r < 0)
144✔
310
                return bus_log_create_error(r);
×
311

312
        r = sd_bus_message_append(m, "ss", scope, "fail");
144✔
313
        if (r < 0)
144✔
314
                return bus_log_create_error(r);
×
315

316
        /* Properties */
317
        r = sd_bus_message_open_container(m, 'a', "(sv)");
144✔
318
        if (r < 0)
144✔
319
                return bus_log_create_error(r);
×
320

321
        r = bus_append_scope_pidref(m, pid, FLAGS_SET(flags, ALLOCATE_SCOPE_ALLOW_PIDFD));
144✔
322
        if (r < 0)
144✔
323
                return bus_log_create_error(r);
×
324

325
        _cleanup_free_ char *description = strjoin("Container ", machine_name);
288✔
326
        if (!description)
144✔
327
                return log_oom();
×
328

329
        r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)(sv)",
144✔
330
                                  "Description", "s", description,
331
                                  "Delegate", "b", 1,
332
                                  "CollectMode", "s", "inactive-or-failed",
333
                                  "AddRef", "b", 1,
334
                                  "Slice", "s", isempty(slice) ? SPECIAL_MACHINE_SLICE : slice);
144✔
335
        if (r < 0)
144✔
336
                return bus_log_create_error(r);
×
337

338
        r = append_controller_property(bus, m);
144✔
339
        if (r < 0)
144✔
340
                return r;
341

342
        if (properties_message) {
144✔
343
                r = sd_bus_message_copy(m, properties_message, true);
1✔
344
                if (r < 0)
1✔
345
                        return bus_log_create_error(r);
×
346
        }
347

348
        r = append_machine_properties(
144✔
349
                        m,
350
                        mounts,
351
                        n_mounts,
352
                        kill_signal,
353
                        start_mode == START_BOOT && can_set_coredump_receive(bus) > 0);
144✔
354
        if (r < 0)
144✔
355
                return r;
356

357
        r = bus_append_unit_property_assignment_many(m, UNIT_SCOPE, properties);
144✔
358
        if (r < 0)
144✔
359
                return r;
360

361
        r = sd_bus_message_close_container(m);
144✔
362
        if (r < 0)
144✔
363
                return bus_log_create_error(r);
×
364

365
        /* No auxiliary units */
366
        r = sd_bus_message_append(
144✔
367
                        m,
368
                        "a(sa(sv))",
369
                        0);
370
        if (r < 0)
144✔
371
                return bus_log_create_error(r);
×
372

373
        r = sd_bus_call(bus, m, 0, &error, &reply);
144✔
374
        if (r < 0) {
144✔
375
                /* If this failed with a property we couldn't write, this is quite likely because the server
376
                 * doesn't support PIDFDs yet, let's try without. */
377
                if (FLAGS_SET(flags, ALLOCATE_SCOPE_ALLOW_PIDFD) &&
×
378
                    sd_bus_error_has_names(&error, SD_BUS_ERROR_UNKNOWN_PROPERTY, SD_BUS_ERROR_PROPERTY_READ_ONLY))
×
379
                        return allocate_scope(
×
380
                                        bus,
381
                                        machine_name,
382
                                        pid,
383
                                        slice,
384
                                        mounts,
385
                                        n_mounts,
386
                                        kill_signal,
387
                                        properties,
388
                                        properties_message,
389
                                        start_mode,
390
                                        flags & ~ALLOCATE_SCOPE_ALLOW_PIDFD);
×
391

392
                return log_error_errno(r, "Failed to allocate scope: %s", bus_error_message(&error, r));
×
393
        }
394

395
        r = sd_bus_message_read(reply, "o", &object);
144✔
396
        if (r < 0)
144✔
397
                return bus_log_parse_error(r);
×
398

399
        r = bus_wait_for_jobs_one(
144✔
400
                        w,
401
                        object,
402
                        BUS_WAIT_JOBS_LOG_ERROR,
403
                        /* extra_args= */ NULL);
404
        if (r < 0)
144✔
405
                return r;
×
406

407
        return 0;
408
}
409

410
int terminate_scope(
144✔
411
                sd_bus *bus,
412
                const char *machine_name) {
413

414
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
×
415
        _cleanup_free_ char *scope = NULL;
144✔
416
        int r;
144✔
417

418
        r = unit_name_mangle_with_suffix(machine_name, "to terminate", /* flags= */ 0, ".scope", &scope);
144✔
419
        if (r < 0)
144✔
420
                return log_error_errno(r, "Failed to mangle scope name: %m");
×
421

422
        r = bus_call_method(bus, bus_systemd_mgr, "AbandonScope", &error, /* ret_reply= */ NULL, "s", scope);
144✔
423
        if (r < 0) {
144✔
424
                log_debug_errno(r, "Failed to abandon scope '%s', ignoring: %s", scope, bus_error_message(&error, r));
136✔
425
                sd_bus_error_free(&error);
136✔
426
        }
427

428
        r = bus_call_method(
144✔
429
                        bus,
430
                        bus_systemd_mgr,
431
                        "KillUnit",
432
                        &error,
433
                        NULL,
434
                        "ssi",
435
                        scope,
436
                        "all",
437
                        (int32_t) SIGKILL);
438
        if (r < 0) {
144✔
439
                log_debug_errno(r, "Failed to SIGKILL scope '%s', ignoring: %s", scope, bus_error_message(&error, r));
×
440
                sd_bus_error_free(&error);
×
441
        }
442

443
        r = bus_call_method(bus, bus_systemd_mgr, "UnrefUnit", &error, /* ret_reply= */ NULL, "s", scope);
144✔
444
        if (r < 0)
144✔
445
                log_debug_errno(r, "Failed to drop reference to scope '%s', ignoring: %s", scope, bus_error_message(&error, r));
×
446

447
        return 0;
448
}
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