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

systemd / systemd / 17992912793

24 Sep 2025 07:15PM UTC coverage: 72.205% (-0.08%) from 72.283%
17992912793

push

github

web-flow
libblkid → turn into dlopen() dependency (#39084)

Split out of #38861

153 of 207 new or added lines in 10 files covered. (73.91%)

1717 existing lines in 53 files now uncovered.

302842 of 419419 relevant lines covered (72.21%)

1052332.54 hits per line

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

60.24
/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(
143✔
22
                sd_bus_message *m,
23
                CustomMount *mounts,
24
                unsigned n_mounts,
25
                int kill_signal,
26
                bool coredump_receive) {
27

28
        int r;
143✔
29

30
        assert(m);
143✔
31

32
        r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "closed");
143✔
33
        if (r < 0)
143✔
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,
143✔
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)
143✔
48
                return bus_log_create_error(r);
×
49

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

54
                r = is_device_node(cm->source);
126✔
55
                if (r == -ENOENT) {
126✔
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)
125✔
61
                        return log_error_errno(r, "Failed to stat %s: %m", cm->source);
×
62

63
                if (r) {
125✔
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) {
143✔
72
                r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal);
26✔
73
                if (r < 0)
26✔
74
                        return bus_log_create_error(r);
×
75

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

81
        if (coredump_receive) {
143✔
82
                r = sd_bus_message_append(m, "(sv)", "CoredumpReceive", "b", true);
26✔
83
                if (r < 0)
26✔
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) {
143✔
91
        const char *unique;
143✔
92
        int r;
143✔
93

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

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

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

105
        return 0;
106
}
107

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

113
        assert(bus);
26✔
114

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

119
        r = sd_bus_get_property_trivial(
26✔
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))
26✔
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;
26✔
132
}
133

134
static int create_or_register_machine_ex(
109✔
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 *slice,
142
                CustomMount *mounts,
143
                unsigned n_mounts,
144
                int kill_signal,
145
                char **properties,
146
                sd_bus_message *properties_message,
147
                const char *service,
148
                StartMode start_mode,
149
                sd_bus_error *error,
150
                bool keep_unit) {
151

152
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
109✔
153
        int r;
109✔
154

155
        assert(error);
109✔
156

157
        r = bus_message_new_method_call(bus, &m,  bus_machine_mgr, keep_unit ? "RegisterMachineEx" : "CreateMachineEx");
198✔
158
        if (r < 0)
109✔
UNCOV
159
                return bus_log_create_error(r);
×
160

161
        r = sd_bus_message_append(m, "s", machine_name);
109✔
162
        if (r < 0)
109✔
UNCOV
163
                return bus_log_create_error(r);
×
164

165
        r = sd_bus_message_open_container(m, 'a', "(sv)");
109✔
166
        if (r < 0)
109✔
UNCOV
167
                return bus_log_create_error(r);
×
168

169
        r = sd_bus_message_append(
218✔
170
                        m,
171
                        "(sv)(sv)(sv)",
172
                        "Id", "ay", SD_BUS_MESSAGE_APPEND_ID128(uuid),
109✔
173
                        "Service", "s", service,
174
                        "Class", "s", "container");
175
        if (r < 0)
109✔
176
                return bus_log_create_error(r);
×
177

178
        if (pidref_is_set(pid)) {
109✔
179
                if (pid->fd >= 0) {
109✔
180
                        r = sd_bus_message_append(m, "(sv)", "LeaderPIDFD", "h", pid->fd);
109✔
181
                        if (r < 0)
109✔
UNCOV
182
                                return bus_log_create_error(r);
×
183
                }
184

185
                if (pid->fd_id > 0) {
109✔
UNCOV
186
                        r = sd_bus_message_append(m, "(sv)", "LeaderPIDFDID", "t", pid->fd_id);
×
UNCOV
187
                        if (r < 0)
×
UNCOV
188
                                return bus_log_create_error(r);
×
189

UNCOV
190
                        r = sd_bus_message_append(m, "(sv)", "LeaderPID", "u", pid->pid);
×
UNCOV
191
                        if (r < 0)
×
UNCOV
192
                                return bus_log_create_error(r);
×
193
                }
194
        }
195

196
        if (!isempty(directory)) {
109✔
197
                r = sd_bus_message_append(m, "(sv)", "RootDirectory", "s", directory);
106✔
198
                if (r < 0)
106✔
UNCOV
199
                        return bus_log_create_error(r);
×
200
        }
201

202
        if (local_ifindex > 0) {
109✔
203
                r = sd_bus_message_append(m, "(sv)", "NetworkInterfaces", "ai", 1, local_ifindex);
27✔
204
                if (r < 0)
27✔
UNCOV
205
                        return bus_log_create_error(r);
×
206
        }
207

208
        r = sd_bus_message_close_container(m);
109✔
209
        if (r < 0)
109✔
UNCOV
210
                return bus_log_create_error(r);
×
211

212
        if (!keep_unit) {
109✔
213
                r = sd_bus_message_open_container(m, 'a', "(sv)");
89✔
214
                if (r < 0)
89✔
UNCOV
215
                        return bus_log_create_error(r);
×
216

217
                if (!isempty(slice)) {
89✔
UNCOV
218
                        r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
×
UNCOV
219
                        if (r < 0)
×
UNCOV
220
                                return bus_log_create_error(r);
×
221
                }
222

223
                r = append_controller_property(bus, m);
89✔
224
                if (r < 0)
89✔
225
                        return r;
226

227
                r = append_machine_properties(
89✔
228
                                m,
229
                                mounts,
230
                                n_mounts,
231
                                kill_signal,
232
                                start_mode == START_BOOT && can_set_coredump_receive(bus) > 0);
89✔
233
                if (r < 0)
89✔
234
                        return r;
235

236
                if (properties_message) {
89✔
237
                        r = sd_bus_message_copy(m, properties_message, true);
1✔
238
                        if (r < 0)
1✔
UNCOV
239
                                return bus_log_create_error(r);
×
240
                }
241

242
                r = bus_append_unit_property_assignment_many(m, UNIT_SERVICE, properties);
89✔
243
                if (r < 0)
89✔
244
                        return r;
245

246
                r = sd_bus_message_close_container(m);
89✔
247
                if (r < 0)
89✔
UNCOV
248
                        return bus_log_create_error(r);
×
249
        }
250

251
        return sd_bus_call(bus, m, 0, error, NULL);
109✔
252
}
253

254
int register_machine(
109✔
255
                sd_bus *bus,
256
                const char *machine_name,
257
                const PidRef *pid,
258
                const char *directory,
259
                sd_id128_t uuid,
260
                int local_ifindex,
261
                const char *slice,
262
                CustomMount *mounts,
263
                unsigned n_mounts,
264
                int kill_signal,
265
                char **properties,
266
                sd_bus_message *properties_message,
267
                const char *service,
268
                StartMode start_mode,
269
                RegisterMachineFlags flags) {
270

271
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
109✔
272
        int r;
109✔
273

274
        assert(bus);
109✔
275

276
        r = create_or_register_machine_ex(
109✔
277
                        bus,
278
                        machine_name,
279
                        pid,
280
                        directory,
281
                        uuid,
282
                        local_ifindex,
283
                        slice,
284
                        mounts,
285
                        n_mounts,
286
                        kill_signal,
287
                        properties,
288
                        properties_message,
289
                        service,
290
                        start_mode,
291
                        &error,
292
                        FLAGS_SET(flags, REGISTER_MACHINE_KEEP_UNIT));
293
        if (r >= 0)
109✔
294
                return 0;
UNCOV
295
        if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
×
UNCOV
296
                return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r));
×
297
        if (FLAGS_SET(flags, REGISTER_MACHINE_KEEP_UNIT)) {
×
UNCOV
298
                r = bus_call_method(
×
299
                                bus,
300
                                bus_machine_mgr,
301
                                "RegisterMachineWithNetwork",
302
                                &error,
303
                                NULL,
304
                                "sayssusai",
305
                                machine_name,
UNCOV
306
                                SD_BUS_MESSAGE_APPEND_ID128(uuid),
×
307
                                service,
308
                                "container",
UNCOV
309
                                pidref_is_set(pid) ? (uint32_t) pid->pid : 0,
×
310
                                strempty(directory),
311
                                local_ifindex > 0 ? 1 : 0, local_ifindex);
312
        } else {
UNCOV
313
                _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
×
314

UNCOV
315
                r = bus_message_new_method_call(bus, &m,  bus_machine_mgr, "CreateMachineWithNetwork");
×
UNCOV
316
                if (r < 0)
×
317
                        return bus_log_create_error(r);
×
318

319
                r = sd_bus_message_append(
×
320
                                m,
321
                                "sayssusai",
322
                                machine_name,
UNCOV
323
                                SD_BUS_MESSAGE_APPEND_ID128(uuid),
×
324
                                service,
325
                                "container",
UNCOV
326
                                pidref_is_set(pid) ? (uint32_t) pid->pid : 0,
×
327
                                strempty(directory),
328
                                local_ifindex > 0 ? 1 : 0, local_ifindex);
UNCOV
329
                if (r < 0)
×
UNCOV
330
                        return bus_log_create_error(r);
×
331

UNCOV
332
                r = sd_bus_message_open_container(m, 'a', "(sv)");
×
UNCOV
333
                if (r < 0)
×
UNCOV
334
                        return bus_log_create_error(r);
×
335

UNCOV
336
                if (!isempty(slice)) {
×
337
                        r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
×
UNCOV
338
                        if (r < 0)
×
UNCOV
339
                                return bus_log_create_error(r);
×
340
                }
341

UNCOV
342
                r = append_controller_property(bus, m);
×
UNCOV
343
                if (r < 0)
×
344
                        return r;
345

UNCOV
346
                r = append_machine_properties(
×
347
                                m,
348
                                mounts,
349
                                n_mounts,
350
                                kill_signal,
351
                                start_mode == START_BOOT && can_set_coredump_receive(bus) > 0);
×
352
                if (r < 0)
×
353
                        return r;
354

UNCOV
355
                if (properties_message) {
×
UNCOV
356
                        r = sd_bus_message_copy(m, properties_message, true);
×
UNCOV
357
                        if (r < 0)
×
UNCOV
358
                                return bus_log_create_error(r);
×
359
                }
360

UNCOV
361
                r = bus_append_unit_property_assignment_many(m, UNIT_SERVICE, properties);
×
UNCOV
362
                if (r < 0)
×
363
                        return r;
364

UNCOV
365
                r = sd_bus_message_close_container(m);
×
366
                if (r < 0)
×
UNCOV
367
                        return bus_log_create_error(r);
×
368

UNCOV
369
                r = sd_bus_call(bus, m, 0, &error, NULL);
×
370
        }
371
        if (r < 0)
×
UNCOV
372
                return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r));
×
373

374
        return 0;
375
}
376

377
int unregister_machine(
106✔
378
                sd_bus *bus,
379
                const char *machine_name) {
380

UNCOV
381
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
×
382
        int r;
106✔
383

384
        assert(bus);
106✔
385

386
        r = bus_call_method(bus, bus_machine_mgr, "UnregisterMachine", &error, NULL, "s", machine_name);
106✔
387
        if (r < 0)
106✔
388
                log_debug("Failed to unregister machine: %s", bus_error_message(&error, r));
62✔
389

390
        return 0;
106✔
391
}
392

393
int allocate_scope(
54✔
394
                sd_bus *bus,
395
                const char *machine_name,
396
                const PidRef* pid,
397
                const char *slice,
398
                CustomMount *mounts,
399
                unsigned n_mounts,
400
                int kill_signal,
401
                char **properties,
402
                sd_bus_message *properties_message,
403
                StartMode start_mode,
404
                AllocateScopeFlags flags) {
405

406
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
108✔
407
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
54✔
UNCOV
408
        _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
×
409
        _cleanup_free_ char *scope = NULL;
54✔
410
        const char *object;
54✔
411
        int r;
54✔
412

413
        assert(bus);
54✔
414

415
        r = bus_wait_for_jobs_new(bus, &w);
54✔
416
        if (r < 0)
54✔
UNCOV
417
                return log_error_errno(r, "Could not watch job: %m");
×
418

419
        r = unit_name_mangle_with_suffix(machine_name, "as machine name", 0, ".scope", &scope);
54✔
420
        if (r < 0)
54✔
UNCOV
421
                return log_error_errno(r, "Failed to mangle scope name: %m");
×
422

423
        r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "StartTransientUnit");
54✔
424
        if (r < 0)
54✔
UNCOV
425
                return bus_log_create_error(r);
×
426

427
        r = sd_bus_message_append(m, "ss", scope, "fail");
54✔
428
        if (r < 0)
54✔
UNCOV
429
                return bus_log_create_error(r);
×
430

431
        /* Properties */
432
        r = sd_bus_message_open_container(m, 'a', "(sv)");
54✔
433
        if (r < 0)
54✔
UNCOV
434
                return bus_log_create_error(r);
×
435

436
        r = bus_append_scope_pidref(m, pid, FLAGS_SET(flags, ALLOCATE_SCOPE_ALLOW_PIDFD));
54✔
437
        if (r < 0)
54✔
UNCOV
438
                return bus_log_create_error(r);
×
439

440
        _cleanup_free_ char *description = strjoin("Container ", machine_name);
108✔
441
        if (!description)
54✔
UNCOV
442
                return log_oom();
×
443

444
        r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)(sv)",
54✔
445
                                  "Description", "s", description,
446
                                  "Delegate", "b", 1,
447
                                  "CollectMode", "s", "inactive-or-failed",
448
                                  "AddRef", "b", 1,
449
                                  "Slice", "s", isempty(slice) ? SPECIAL_MACHINE_SLICE : slice);
54✔
450
        if (r < 0)
54✔
UNCOV
451
                return bus_log_create_error(r);
×
452

453
        r = append_controller_property(bus, m);
54✔
454
        if (r < 0)
54✔
455
                return r;
456

457
        if (properties_message) {
54✔
UNCOV
458
                r = sd_bus_message_copy(m, properties_message, true);
×
UNCOV
459
                if (r < 0)
×
UNCOV
460
                        return bus_log_create_error(r);
×
461
        }
462

463
        r = append_machine_properties(
54✔
464
                        m,
465
                        mounts,
466
                        n_mounts,
467
                        kill_signal,
468
                        start_mode == START_BOOT && can_set_coredump_receive(bus) > 0);
54✔
469
        if (r < 0)
54✔
470
                return r;
471

472
        r = bus_append_unit_property_assignment_many(m, UNIT_SCOPE, properties);
54✔
473
        if (r < 0)
54✔
474
                return r;
475

476
        r = sd_bus_message_close_container(m);
54✔
477
        if (r < 0)
54✔
UNCOV
478
                return bus_log_create_error(r);
×
479

480
        /* No auxiliary units */
481
        r = sd_bus_message_append(
54✔
482
                        m,
483
                        "a(sa(sv))",
484
                        0);
485
        if (r < 0)
54✔
UNCOV
486
                return bus_log_create_error(r);
×
487

488
        r = sd_bus_call(bus, m, 0, &error, &reply);
54✔
489
        if (r < 0) {
54✔
490
                /* If this failed with a property we couldn't write, this is quite likely because the server
491
                 * doesn't support PIDFDs yet, let's try without. */
UNCOV
492
                if (FLAGS_SET(flags, ALLOCATE_SCOPE_ALLOW_PIDFD) &&
×
UNCOV
493
                    sd_bus_error_has_names(&error, SD_BUS_ERROR_UNKNOWN_PROPERTY, SD_BUS_ERROR_PROPERTY_READ_ONLY))
×
UNCOV
494
                        return allocate_scope(
×
495
                                        bus,
496
                                        machine_name,
497
                                        pid,
498
                                        slice,
499
                                        mounts,
500
                                        n_mounts,
501
                                        kill_signal,
502
                                        properties,
503
                                        properties_message,
504
                                        start_mode,
UNCOV
505
                                        flags & ~ALLOCATE_SCOPE_ALLOW_PIDFD);
×
506

UNCOV
507
                return log_error_errno(r, "Failed to allocate scope: %s", bus_error_message(&error, r));
×
508
        }
509

510
        r = sd_bus_message_read(reply, "o", &object);
54✔
511
        if (r < 0)
54✔
UNCOV
512
                return bus_log_parse_error(r);
×
513

514
        r = bus_wait_for_jobs_one(
54✔
515
                        w,
516
                        object,
517
                        BUS_WAIT_JOBS_LOG_ERROR,
518
                        /* extra_args= */ NULL);
519
        if (r < 0)
54✔
UNCOV
520
                return r;
×
521

522
        return 0;
523
}
524

525
int terminate_scope(
54✔
526
                sd_bus *bus,
527
                const char *machine_name) {
528

UNCOV
529
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
×
530
        _cleanup_free_ char *scope = NULL;
54✔
531
        int r;
54✔
532

533
        r = unit_name_mangle_with_suffix(machine_name, "to terminate", /* flags= */ 0, ".scope", &scope);
54✔
534
        if (r < 0)
54✔
UNCOV
535
                return log_error_errno(r, "Failed to mangle scope name: %m");
×
536

537
        r = bus_call_method(bus, bus_systemd_mgr, "AbandonScope", &error, /* ret_reply= */ NULL, "s", scope);
54✔
538
        if (r < 0) {
54✔
539
                log_debug_errno(r, "Failed to abandon scope '%s', ignoring: %s", scope, bus_error_message(&error, r));
49✔
540
                sd_bus_error_free(&error);
49✔
541
        }
542

543
        r = bus_call_method(
54✔
544
                        bus,
545
                        bus_systemd_mgr,
546
                        "KillUnit",
547
                        &error,
548
                        NULL,
549
                        "ssi",
550
                        scope,
551
                        "all",
552
                        (int32_t) SIGKILL);
553
        if (r < 0) {
54✔
UNCOV
554
                log_debug_errno(r, "Failed to SIGKILL scope '%s', ignoring: %s", scope, bus_error_message(&error, r));
×
UNCOV
555
                sd_bus_error_free(&error);
×
556
        }
557

558
        r = bus_call_method(bus, bus_systemd_mgr, "UnrefUnit", &error, /* ret_reply= */ NULL, "s", scope);
54✔
559
        if (r < 0)
54✔
UNCOV
560
                log_debug_errno(r, "Failed to drop reference to scope '%s', ignoring: %s", scope, bus_error_message(&error, r));
×
561

562
        return 0;
563
}
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