]> git.proxmox.com Git - systemd.git/blame - src/libsystemd/sd-bus/bus-container.c
New upstream version 236
[systemd.git] / src / libsystemd / sd-bus / bus-container.c
CommitLineData
52ad194e 1/* SPDX-License-Identifier: LGPL-2.1+ */
60f067b4
JS
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
60f067b4 21#include <fcntl.h>
db2df898 22#include <unistd.h>
60f067b4 23
db2df898 24#include "bus-container.h"
60f067b4
JS
25#include "bus-internal.h"
26#include "bus-socket.h"
db2df898
MP
27#include "fd-util.h"
28#include "process-util.h"
29#include "util.h"
60f067b4
JS
30
31int bus_container_connect_socket(sd_bus *b) {
d9dfd233 32 _cleanup_close_pair_ int pair[2] = { -1, -1 };
13d276d0 33 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
e735f4d4 34 pid_t child;
60f067b4 35 siginfo_t si;
d9dfd233
MP
36 int r, error_buf = 0;
37 ssize_t n;
60f067b4
JS
38
39 assert(b);
40 assert(b->input_fd < 0);
41 assert(b->output_fd < 0);
e735f4d4 42 assert(b->nspid > 0 || b->machine);
60f067b4 43
e735f4d4
MP
44 if (b->nspid <= 0) {
45 r = container_get_leader(b->machine, &b->nspid);
46 if (r < 0)
47 return r;
48 }
60f067b4 49
13d276d0 50 r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
60f067b4
JS
51 if (r < 0)
52 return r;
53
54 b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
55 if (b->input_fd < 0)
56 return -errno;
57
58 b->output_fd = b->input_fd;
59
60 bus_socket_setup(b);
61
d9dfd233
MP
62 if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
63 return -errno;
64
60f067b4
JS
65 child = fork();
66 if (child < 0)
67 return -errno;
68
69 if (child == 0) {
70 pid_t grandchild;
71
d9dfd233
MP
72 pair[0] = safe_close(pair[0]);
73
13d276d0 74 r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
60f067b4 75 if (r < 0)
d9dfd233 76 _exit(EXIT_FAILURE);
60f067b4
JS
77
78 /* We just changed PID namespace, however it will only
79 * take effect on the children we now fork. Hence,
80 * let's fork another time, and connect from this
81 * grandchild, so that SO_PEERCRED of our connection
82 * comes from a process from within the container, and
83 * not outside of it */
84
85 grandchild = fork();
86 if (grandchild < 0)
d9dfd233 87 _exit(EXIT_FAILURE);
60f067b4
JS
88
89 if (grandchild == 0) {
90
91 r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
92 if (r < 0) {
d9dfd233
MP
93 /* Try to send error up */
94 error_buf = errno;
95 (void) write(pair[1], &error_buf, sizeof(error_buf));
96 _exit(EXIT_FAILURE);
60f067b4
JS
97 }
98
99 _exit(EXIT_SUCCESS);
100 }
101
102 r = wait_for_terminate(grandchild, &si);
103 if (r < 0)
d9dfd233 104 _exit(EXIT_FAILURE);
60f067b4
JS
105
106 if (si.si_code != CLD_EXITED)
d9dfd233 107 _exit(EXIT_FAILURE);
60f067b4
JS
108
109 _exit(si.si_status);
110 }
111
d9dfd233
MP
112 pair[1] = safe_close(pair[1]);
113
60f067b4
JS
114 r = wait_for_terminate(child, &si);
115 if (r < 0)
116 return r;
117
d9dfd233
MP
118 n = read(pair[0], &error_buf, sizeof(error_buf));
119 if (n < 0)
120 return -errno;
121
122 if (n > 0) {
123 if (n != sizeof(error_buf))
124 return -EIO;
125
126 if (error_buf < 0)
127 return -EIO;
128
129 if (error_buf == EINPROGRESS)
130 return 1;
131
132 if (error_buf > 0)
133 return -error_buf;
134 }
135
60f067b4
JS
136 if (si.si_code != CLD_EXITED)
137 return -EIO;
138
60f067b4
JS
139 if (si.si_status != EXIT_SUCCESS)
140 return -EIO;
141
142 return bus_socket_start_auth(b);
143}