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

systemd / systemd / 16280725298

14 Jul 2025 08:16PM UTC coverage: 72.166% (-0.006%) from 72.172%
16280725298

push

github

web-flow
Two fixlets for coverage test (#38183)

302135 of 418667 relevant lines covered (72.17%)

773261.64 hits per line

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

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

28
        int r;
135✔
29

30
        assert(m);
135✔
31

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

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

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

63
                if (r) {
115✔
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) {
135✔
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) {
135✔
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) {
135✔
91
        const char *unique;
135✔
92
        int r;
135✔
93

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

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

101
        r = sd_bus_message_append(m, "(sv)", "Controller", "s", unique);
135✔
102
        if (r < 0)
135✔
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
int register_machine(
102✔
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
                RegisterMachineFlags flags) {
150

151
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
102✔
152
        int r;
102✔
153

154
        assert(bus);
102✔
155

156
        if (FLAGS_SET(flags, REGISTER_MACHINE_KEEP_UNIT)) {
102✔
157
                r = bus_call_method(
18✔
158
                                bus,
159
                                bus_machine_mgr,
160
                                "RegisterMachineWithNetwork",
161
                                &error,
162
                                NULL,
163
                                "sayssusai",
164
                                machine_name,
165
                                SD_BUS_MESSAGE_APPEND_ID128(uuid),
17✔
166
                                service,
167
                                "container",
168
                                pidref_is_set(pid) ? (uint32_t) pid->pid : 0,
17✔
169
                                strempty(directory),
170
                                local_ifindex > 0 ? 1 : 0, local_ifindex);
171
        } else {
172
                _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
85✔
173

174
                r = bus_message_new_method_call(bus, &m,  bus_machine_mgr, "CreateMachineWithNetwork");
85✔
175
                if (r < 0)
85✔
176
                        return bus_log_create_error(r);
×
177

178
                r = sd_bus_message_append(
87✔
179
                                m,
180
                                "sayssusai",
181
                                machine_name,
182
                                SD_BUS_MESSAGE_APPEND_ID128(uuid),
85✔
183
                                service,
184
                                "container",
185
                                pidref_is_set(pid) ? (uint32_t) pid->pid : 0,
85✔
186
                                strempty(directory),
187
                                local_ifindex > 0 ? 1 : 0, local_ifindex);
188
                if (r < 0)
85✔
189
                        return bus_log_create_error(r);
×
190

191
                r = sd_bus_message_open_container(m, 'a', "(sv)");
85✔
192
                if (r < 0)
85✔
193
                        return bus_log_create_error(r);
×
194

195
                if (!isempty(slice)) {
85✔
196
                        r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
×
197
                        if (r < 0)
×
198
                                return bus_log_create_error(r);
×
199
                }
200

201
                r = append_controller_property(bus, m);
85✔
202
                if (r < 0)
85✔
203
                        return r;
204

205
                r = append_machine_properties(
85✔
206
                                m,
207
                                mounts,
208
                                n_mounts,
209
                                kill_signal,
210
                                start_mode == START_BOOT && can_set_coredump_receive(bus) > 0);
85✔
211
                if (r < 0)
85✔
212
                        return r;
213

214
                if (properties_message) {
85✔
215
                        r = sd_bus_message_copy(m, properties_message, true);
1✔
216
                        if (r < 0)
1✔
217
                                return bus_log_create_error(r);
×
218
                }
219

220
                r = bus_append_unit_property_assignment_many(m, UNIT_SERVICE, properties);
85✔
221
                if (r < 0)
85✔
222
                        return r;
223

224
                r = sd_bus_message_close_container(m);
85✔
225
                if (r < 0)
85✔
226
                        return bus_log_create_error(r);
×
227

228
                r = sd_bus_call(bus, m, 0, &error, NULL);
85✔
229
        }
230
        if (r < 0)
102✔
231
                return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r));
×
232

233
        return 0;
234
}
235

236
int unregister_machine(
99✔
237
                sd_bus *bus,
238
                const char *machine_name) {
239

240
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
×
241
        int r;
99✔
242

243
        assert(bus);
99✔
244

245
        r = bus_call_method(bus, bus_machine_mgr, "UnregisterMachine", &error, NULL, "s", machine_name);
99✔
246
        if (r < 0)
99✔
247
                log_debug("Failed to unregister machine: %s", bus_error_message(&error, r));
67✔
248

249
        return 0;
99✔
250
}
251

252
int allocate_scope(
50✔
253
                sd_bus *bus,
254
                const char *machine_name,
255
                const PidRef* pid,
256
                const char *slice,
257
                CustomMount *mounts,
258
                unsigned n_mounts,
259
                int kill_signal,
260
                char **properties,
261
                sd_bus_message *properties_message,
262
                StartMode start_mode,
263
                AllocateScopeFlags flags) {
264

265
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
100✔
266
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
50✔
267
        _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
×
268
        _cleanup_free_ char *scope = NULL;
50✔
269
        const char *object;
50✔
270
        int r;
50✔
271

272
        assert(bus);
50✔
273

274
        r = bus_wait_for_jobs_new(bus, &w);
50✔
275
        if (r < 0)
50✔
276
                return log_error_errno(r, "Could not watch job: %m");
×
277

278
        r = unit_name_mangle_with_suffix(machine_name, "as machine name", 0, ".scope", &scope);
50✔
279
        if (r < 0)
50✔
280
                return log_error_errno(r, "Failed to mangle scope name: %m");
×
281

282
        r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "StartTransientUnit");
50✔
283
        if (r < 0)
50✔
284
                return bus_log_create_error(r);
×
285

286
        r = sd_bus_message_append(m, "ss", scope, "fail");
50✔
287
        if (r < 0)
50✔
288
                return bus_log_create_error(r);
×
289

290
        /* Properties */
291
        r = sd_bus_message_open_container(m, 'a', "(sv)");
50✔
292
        if (r < 0)
50✔
293
                return bus_log_create_error(r);
×
294

295
        r = bus_append_scope_pidref(m, pid, FLAGS_SET(flags, ALLOCATE_SCOPE_ALLOW_PIDFD));
50✔
296
        if (r < 0)
50✔
297
                return bus_log_create_error(r);
×
298

299
        _cleanup_free_ char *description = strjoin("Container ", machine_name);
100✔
300
        if (!description)
50✔
301
                return log_oom();
×
302

303
        r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)(sv)",
50✔
304
                                  "Description", "s", description,
305
                                  "Delegate", "b", 1,
306
                                  "CollectMode", "s", "inactive-or-failed",
307
                                  "AddRef", "b", 1,
308
                                  "Slice", "s", isempty(slice) ? SPECIAL_MACHINE_SLICE : slice);
50✔
309
        if (r < 0)
50✔
310
                return bus_log_create_error(r);
×
311

312
        r = append_controller_property(bus, m);
50✔
313
        if (r < 0)
50✔
314
                return r;
315

316
        if (properties_message) {
50✔
317
                r = sd_bus_message_copy(m, properties_message, true);
×
318
                if (r < 0)
×
319
                        return bus_log_create_error(r);
×
320
        }
321

322
        r = append_machine_properties(
50✔
323
                        m,
324
                        mounts,
325
                        n_mounts,
326
                        kill_signal,
327
                        start_mode == START_BOOT && can_set_coredump_receive(bus) > 0);
50✔
328
        if (r < 0)
50✔
329
                return r;
330

331
        r = bus_append_unit_property_assignment_many(m, UNIT_SCOPE, properties);
50✔
332
        if (r < 0)
50✔
333
                return r;
334

335
        r = sd_bus_message_close_container(m);
50✔
336
        if (r < 0)
50✔
337
                return bus_log_create_error(r);
×
338

339
        /* No auxiliary units */
340
        r = sd_bus_message_append(
50✔
341
                        m,
342
                        "a(sa(sv))",
343
                        0);
344
        if (r < 0)
50✔
345
                return bus_log_create_error(r);
×
346

347
        r = sd_bus_call(bus, m, 0, &error, &reply);
50✔
348
        if (r < 0) {
50✔
349
                /* If this failed with a property we couldn't write, this is quite likely because the server
350
                 * doesn't support PIDFDs yet, let's try without. */
351
                if (FLAGS_SET(flags, ALLOCATE_SCOPE_ALLOW_PIDFD) &&
×
352
                    sd_bus_error_has_names(&error, SD_BUS_ERROR_UNKNOWN_PROPERTY, SD_BUS_ERROR_PROPERTY_READ_ONLY))
×
353
                        return allocate_scope(
×
354
                                        bus,
355
                                        machine_name,
356
                                        pid,
357
                                        slice,
358
                                        mounts,
359
                                        n_mounts,
360
                                        kill_signal,
361
                                        properties,
362
                                        properties_message,
363
                                        start_mode,
364
                                        flags & ~ALLOCATE_SCOPE_ALLOW_PIDFD);
×
365

366
                return log_error_errno(r, "Failed to allocate scope: %s", bus_error_message(&error, r));
×
367
        }
368

369
        r = sd_bus_message_read(reply, "o", &object);
50✔
370
        if (r < 0)
50✔
371
                return bus_log_parse_error(r);
×
372

373
        r = bus_wait_for_jobs_one(
50✔
374
                        w,
375
                        object,
376
                        BUS_WAIT_JOBS_LOG_ERROR,
377
                        /* extra_args= */ NULL);
378
        if (r < 0)
50✔
379
                return r;
×
380

381
        return 0;
382
}
383

384
int terminate_scope(
50✔
385
                sd_bus *bus,
386
                const char *machine_name) {
387

388
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
×
389
        _cleanup_free_ char *scope = NULL;
50✔
390
        int r;
50✔
391

392
        r = unit_name_mangle_with_suffix(machine_name, "to terminate", /* flags= */ 0, ".scope", &scope);
50✔
393
        if (r < 0)
50✔
394
                return log_error_errno(r, "Failed to mangle scope name: %m");
×
395

396
        r = bus_call_method(bus, bus_systemd_mgr, "AbandonScope", &error, /* ret_reply= */ NULL, "s", scope);
50✔
397
        if (r < 0) {
50✔
398
                log_debug_errno(r, "Failed to abandon scope '%s', ignoring: %s", scope, bus_error_message(&error, r));
48✔
399
                sd_bus_error_free(&error);
48✔
400
        }
401

402
        r = bus_call_method(
50✔
403
                        bus,
404
                        bus_systemd_mgr,
405
                        "KillUnit",
406
                        &error,
407
                        NULL,
408
                        "ssi",
409
                        scope,
410
                        "all",
411
                        (int32_t) SIGKILL);
412
        if (r < 0) {
50✔
413
                log_debug_errno(r, "Failed to SIGKILL scope '%s', ignoring: %s", scope, bus_error_message(&error, r));
×
414
                sd_bus_error_free(&error);
×
415
        }
416

417
        r = bus_call_method(bus, bus_systemd_mgr, "UnrefUnit", &error, /* ret_reply= */ NULL, "s", scope);
50✔
418
        if (r < 0)
50✔
419
                log_debug_errno(r, "Failed to drop reference to scope '%s', ignoring: %s", scope, bus_error_message(&error, r));
×
420

421
        return 0;
422
}
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