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

systemd / systemd / 12959699887

24 Jan 2025 08:31PM UTC coverage: 71.472% (+0.009%) from 71.463%
12959699887

push

github

yuwata
homed: when setting up an idmapping map foreign UID range on itself

Now that nspawn can run unprivileged off directory trees owned by
the new "foreign" UID range let's make sure homed actually allows
files owned by that range in the home directories.

This is not enough to make nspawn just work in homed home dirs
unfortunately though. that's because homed applies an idmapping, and
nspawn would need to then to take that idmapped mount and apply another
one, and the kernel simply doesn't support stacked idmapped mounts.
There's work ongoing to address that in the kernel.

However, this is a first step, and should be enough to make things just
work should the kernel eventually support stacked idmapped mounts.

2 of 3 new or added lines in 1 file covered. (66.67%)

1544 existing lines in 49 files now uncovered.

291848 of 408338 relevant lines covered (71.47%)

709560.08 hits per line

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

22.22
/src/ssh-generator/ssh-proxy.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <net/if_arp.h>
4
#include <stdio.h>
5
#include <unistd.h>
6

7
#include "sd-varlink.h"
8

9
#include "fd-util.h"
10
#include "io-util.h"
11
#include "iovec-util.h"
12
#include "log.h"
13
#include "main-func.h"
14
#include "missing_socket.h"
15
#include "parse-util.h"
16
#include "socket-util.h"
17
#include "string-util.h"
18
#include "strv.h"
19
#include "varlink-util.h"
20

UNCOV
21
static int process_vsock_cid(unsigned cid, const char *port) {
×
UNCOV
22
        int r;
×
23

UNCOV
24
        assert(cid != VMADDR_CID_ANY);
×
UNCOV
25
        assert(port);
×
26

UNCOV
27
        union sockaddr_union sa = {
×
28
                .vm.svm_cid = cid,
29
                .vm.svm_family = AF_VSOCK,
30
        };
31

UNCOV
32
        r = vsock_parse_port(port, &sa.vm.svm_port);
×
UNCOV
33
        if (r < 0)
×
34
                return log_error_errno(r, "Failed to parse vsock port: %s", port);
×
35

UNCOV
36
        _cleanup_close_ int fd = socket(AF_VSOCK, SOCK_STREAM|SOCK_CLOEXEC, 0);
×
UNCOV
37
        if (fd < 0)
×
38
                return log_error_errno(errno, "Failed to allocate AF_VSOCK socket: %m");
×
39

UNCOV
40
        if (connect(fd, &sa.sa, SOCKADDR_LEN(sa)) < 0)
×
41
                return log_error_errno(errno, "Failed to connect to vsock:%u:%u: %m", sa.vm.svm_cid, sa.vm.svm_port);
×
42

43
        /* OpenSSH wants us to send a single byte along with the file descriptor, hence do so */
UNCOV
44
        r = send_one_fd_iov(STDOUT_FILENO, fd, &iovec_nul_byte, /* n_iovec= */ 1, /* flags= */ 0);
×
UNCOV
45
        if (r < 0)
×
46
                return log_error_errno(r, "Failed to send socket via STDOUT: %m");
×
47

UNCOV
48
        log_debug("Successfully sent AF_VSOCK socket via STDOUT.");
×
49
        return 0;
50

51
}
52

UNCOV
53
static int process_vsock_string(const char *host, const char *port) {
×
UNCOV
54
        unsigned cid;
×
UNCOV
55
        int r;
×
56

UNCOV
57
        assert(host);
×
UNCOV
58
        assert(port);
×
59

UNCOV
60
        r = vsock_parse_cid(host, &cid);
×
UNCOV
61
        if (r < 0)
×
62
                return log_error_errno(r, "Failed to parse vsock cid: %s", host);
×
63

UNCOV
64
        return process_vsock_cid(cid, port);
×
65
}
66

67
static int process_unix(const char *path) {
3✔
68
        int r;
3✔
69

70
        assert(path);
3✔
71

72
        /* We assume the path is absolute unless it starts with a dot (or is already explicitly absolute) */
73
        _cleanup_free_ char *prefixed = NULL;
3✔
74
        if (!STARTSWITH_SET(path, "/", "./")) {
3✔
75
                prefixed = strjoin("/", path);
3✔
76
                if (!prefixed)
3✔
77
                        return log_oom();
×
78

79
                path = prefixed;
80
        }
81

82
        _cleanup_close_ int fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
6✔
83
        if (fd < 0)
3✔
84
                return log_error_errno(errno, "Failed to allocate AF_UNIX socket: %m");
×
85

86
        r = connect_unix_path(fd, AT_FDCWD, path);
3✔
87
        if (r < 0)
3✔
88
                return log_error_errno(r, "Failed to connect to AF_UNIX socket %s: %m", path);
×
89

90
        r = send_one_fd_iov(STDOUT_FILENO, fd, &iovec_nul_byte, /* n_iovec= */ 1, /* flags= */ 0);
3✔
91
        if (r < 0)
3✔
92
                return log_error_errno(r, "Failed to send socket via STDOUT: %m");
×
93

94
        log_debug("Successfully sent AF_UNIX socket via STDOUT.");
3✔
95
        return 0;
96
}
97

98
static int process_vsock_mux(const char *path, const char *port) {
×
99
        int r;
×
100

101
        assert(path);
×
102
        assert(port);
×
103

104
        /* We assume the path is absolute unless it starts with a dot (or is already explicitly absolute) */
105
        _cleanup_free_ char *prefixed = NULL;
×
106
        if (!STARTSWITH_SET(path, "/", "./")) {
×
107
                prefixed = strjoin("/", path);
×
108
                if (!prefixed)
×
109
                        return log_oom();
×
110

111
                path = prefixed;
112
        }
113

114
        _cleanup_close_ int fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
×
115
        if (fd < 0)
×
116
                return log_error_errno(errno, "Failed to allocate AF_UNIX socket: %m");
×
117

118
        r = connect_unix_path(fd, AT_FDCWD, path);
×
119
        if (r < 0)
×
120
                return log_error_errno(r, "Failed to connect to AF_UNIX socket %s: %m", path);
×
121

122
        /* Based on the protocol as defined here:
123
         * https://github.com/cloud-hypervisor/cloud-hypervisor/blob/main/docs/vsock.md
124
         * https://github.com/firecracker-microvm/firecracker/blob/main/docs/vsock.md */
125
        _cleanup_free_ char *connect_cmd = NULL;
×
126
        connect_cmd = strjoin("CONNECT ", port, "\n");
×
127
        if (!connect_cmd)
×
128
                return log_oom();
×
129

130
        r = loop_write(fd, connect_cmd, SIZE_MAX);
×
131
        if (r < 0)
×
132
                return log_error_errno(r, "Failed to send CONNECT to %s:%s: %m", path, port);
×
133

134
        r = send_one_fd_iov(STDOUT_FILENO, fd, &iovec_nul_byte, /* n_iovec= */ 1, /* flags= */ 0);
×
135
        if (r < 0)
×
136
                return log_error_errno(r, "Failed to send socket via STDOUT: %m");
×
137

138
        log_debug("Successfully sent AF_UNIX socket via STDOUT.");
×
139
        return 0;
140
}
141

142
static int process_machine(const char *machine, const char *port) {
×
143
        _cleanup_(sd_varlink_unrefp) sd_varlink *vl = NULL;
×
144
        int r;
×
145

146
        assert(machine);
×
147
        assert(port);
×
148

149
        r = sd_varlink_connect_address(&vl, "/run/systemd/machine/io.systemd.Machine");
×
150
        if (r < 0)
×
151
                return log_error_errno(r, "Failed to connect to machined on /run/systemd/machine/io.systemd.Machine: %m");
×
152

153
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *result = NULL;
×
154
        r = varlink_callbo_and_log(
×
155
                        vl,
156
                        "io.systemd.Machine.List",
157
                        &result,
158
                        SD_JSON_BUILD_PAIR("name", SD_JSON_BUILD_STRING(machine)));
159
        if (r < 0)
×
160
                return r;
161

162
        uint32_t cid = VMADDR_CID_ANY;
×
163

164
        static const sd_json_dispatch_field dispatch_table[] = {
×
165
                { "vSockCid", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint32, 0, 0 },
166
                {}
167
        };
168

169
        r = sd_json_dispatch(result, dispatch_table, SD_JSON_ALLOW_EXTENSIONS, &cid);
×
170
        if (r < 0)
×
171
                return log_error_errno(r, "Failed to parse Varlink reply: %m");
×
172

173
        if (cid == VMADDR_CID_ANY)
×
174
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Machine has no AF_VSOCK CID assigned.");
×
175

176
        return process_vsock_cid(cid, port);
×
177
}
178

179
static int run(int argc, char* argv[]) {
3✔
180

181
        log_setup();
3✔
182

183
        if (argc != 3)
3✔
184
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected two arguments: host and port.");
×
185

186
        const char *host = argv[1], *port = argv[2];
3✔
187

188
        const char *p = startswith(host, "vsock/");
3✔
189
        if (p)
3✔
UNCOV
190
                return process_vsock_string(p, port);
×
191

192
        p = startswith(host, "unix/");
3✔
193
        if (p)
3✔
194
                return process_unix(p);
3✔
195

196
        p = startswith(host, "vsock-mux/");
×
197
        if (p)
×
198
                return process_vsock_mux(p, port);
×
199

200
        p = startswith(host, "machine/");
×
201
        if (p)
×
202
                return process_machine(p, port);
×
203

204
        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Don't know how to parse host name specification: %s", host);
×
205
}
206

207
DEFINE_MAIN_FUNCTION(run);
6✔
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