]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-container.c
getty-generator: fix stripping /dev/
[thirdparty/systemd.git] / src / libsystemd-bus / bus-container.c
CommitLineData
a7893c6b
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <unistd.h>
23#include <fcntl.h>
24
25#include "util.h"
26#include "fileio.h"
27#include "bus-internal.h"
28#include "bus-socket.h"
29#include "bus-container.h"
30
31int bus_container_connect(sd_bus *b) {
b6741478 32 _cleanup_free_ char *s = NULL, *ns = NULL, *root = NULL, *class = NULL;
a7893c6b 33 _cleanup_close_ int nsfd = -1, rootfd = -1;
b6741478 34 char *p;
a7893c6b
LP
35 siginfo_t si;
36 pid_t leader, child;
37 int r;
38
39 assert(b);
40 assert(b->input_fd < 0);
41 assert(b->output_fd < 0);
42
b6741478 43 p = strappenda("/run/systemd/machines/", b->machine);
a7893c6b 44 r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
d21ed1ea
LP
45 if (r == -ENOENT)
46 return -EHOSTDOWN;
a7893c6b
LP
47 if (r < 0)
48 return r;
49 if (!s)
50 return -EIO;
51
52 if (!streq_ptr(class, "container"))
53 return -EIO;
54
55 r = parse_pid(s, &leader);
56 if (r < 0)
57 return r;
58 if (leader <= 1)
59 return -EIO;
60
61 r = asprintf(&ns, "/proc/%lu/ns/mnt", (unsigned long) leader);
62 if (r < 0)
63 return -ENOMEM;
64
65 nsfd = open(ns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
66 if (nsfd < 0)
67 return -errno;
68
69 r = asprintf(&root, "/proc/%lu/root", (unsigned long) leader);
70 if (r < 0)
71 return -ENOMEM;
72
04d39279 73 rootfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
a7893c6b
LP
74 if (rootfd < 0)
75 return -errno;
76
77 b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
78 if (b->input_fd < 0)
79 return -errno;
80
81 b->output_fd = b->input_fd;
82
83 r = bus_socket_setup(b);
84 if (r < 0)
85 return r;
86
87 child = fork();
88 if (child < 0)
89 return -errno;
90
91 if (child == 0) {
92 r = setns(nsfd, CLONE_NEWNS);
93 if (r < 0)
94 _exit(255);
95
96 if (fchdir(rootfd) < 0)
97 _exit(255);
98
99 if (chroot(".") < 0)
100 _exit(255);
101
a7893c6b
LP
102 r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
103 if (r < 0) {
104 if (errno == EINPROGRESS)
105 _exit(1);
106
107 _exit(255);
108 }
109
110 _exit(0);
111 }
112
113 r = wait_for_terminate(child, &si);
114 if (r < 0)
115 return r;
116
117 if (si.si_code != CLD_EXITED)
118 return -EIO;
119
120 if (si.si_status == 1)
121 return 1;
122
123 if (si.si_status != 0)
124 return -EIO;
125
126 return bus_socket_start_auth(b);
127}