]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-container.c
netdev: use "relaxed" parsing
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-container.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
a7893c6b
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2013 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
a7893c6b 21#include <fcntl.h>
cf0fbc49 22#include <unistd.h>
a7893c6b 23
3ffd4af2 24#include "bus-container.h"
a7893c6b
LP
25#include "bus-internal.h"
26#include "bus-socket.h"
3ffd4af2
LP
27#include "fd-util.h"
28#include "process-util.h"
29#include "util.h"
a7893c6b 30
bc9fd78c 31int bus_container_connect_socket(sd_bus *b) {
2b7d6d33 32 _cleanup_close_pair_ int pair[2] = { -1, -1 };
671c3419 33 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
2b7d6d33 34 int r, error_buf = 0;
2e87a1fd 35 pid_t child;
2b7d6d33 36 ssize_t n;
a7893c6b
LP
37
38 assert(b);
39 assert(b->input_fd < 0);
40 assert(b->output_fd < 0);
ee502e0c 41 assert(b->nspid > 0 || b->machine);
a7893c6b 42
ee502e0c
LP
43 if (b->nspid <= 0) {
44 r = container_get_leader(b->machine, &b->nspid);
45 if (r < 0)
46 return r;
47 }
a7893c6b 48
671c3419 49 r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
a7893c6b
LP
50 if (r < 0)
51 return r;
a7893c6b
LP
52
53 b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
54 if (b->input_fd < 0)
55 return -errno;
56
57 b->output_fd = b->input_fd;
58
8f04d2eb 59 bus_socket_setup(b);
a7893c6b 60
2b7d6d33
LP
61 if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
62 return -errno;
63
4c253ed1
LP
64 r = safe_fork("(sd-buscntr)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child);
65 if (r < 0)
66 return r;
67 if (r == 0) {
5d6cf65f 68 pid_t grandchild;
a7893c6b 69
2b7d6d33
LP
70 pair[0] = safe_close(pair[0]);
71
671c3419 72 r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
bc9fd78c 73 if (r < 0)
2b7d6d33 74 _exit(EXIT_FAILURE);
a7893c6b 75
5d6cf65f
LP
76 /* We just changed PID namespace, however it will only
77 * take effect on the children we now fork. Hence,
78 * let's fork another time, and connect from this
79 * grandchild, so that SO_PEERCRED of our connection
80 * comes from a process from within the container, and
81 * not outside of it */
a7893c6b 82
4c253ed1
LP
83 r = safe_fork("(sd-buscntr2)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &grandchild);
84 if (r < 0)
2b7d6d33 85 _exit(EXIT_FAILURE);
4c253ed1 86 if (r == 0) {
5d6cf65f
LP
87
88 r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
89 if (r < 0) {
2b7d6d33
LP
90 /* Try to send error up */
91 error_buf = errno;
92 (void) write(pair[1], &error_buf, sizeof(error_buf));
93 _exit(EXIT_FAILURE);
5d6cf65f
LP
94 }
95
96 _exit(EXIT_SUCCESS);
a7893c6b
LP
97 }
98
2e87a1fd 99 r = wait_for_terminate_and_check("(sd-buscntr2)", grandchild, 0);
5d6cf65f 100 if (r < 0)
2b7d6d33 101 _exit(EXIT_FAILURE);
5d6cf65f 102
2e87a1fd 103 _exit(r);
a7893c6b
LP
104 }
105
2b7d6d33
LP
106 pair[1] = safe_close(pair[1]);
107
2e87a1fd 108 r = wait_for_terminate_and_check("(sd-buscntr)", child, 0);
a7893c6b
LP
109 if (r < 0)
110 return r;
2e87a1fd
LP
111 if (r != EXIT_SUCCESS)
112 return -EPROTO;
a7893c6b 113
2b7d6d33
LP
114 n = read(pair[0], &error_buf, sizeof(error_buf));
115 if (n < 0)
116 return -errno;
117
118 if (n > 0) {
119 if (n != sizeof(error_buf))
120 return -EIO;
121
122 if (error_buf < 0)
123 return -EIO;
124
125 if (error_buf == EINPROGRESS)
126 return 1;
127
128 if (error_buf > 0)
129 return -error_buf;
130 }
131
a7893c6b
LP
132 return bus_socket_start_auth(b);
133}