]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/import/import-common.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2015 Lennart Poettering
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.
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.
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/>.
22 #include <sys/prctl.h>
27 #include "btrfs-util.h"
28 #include "capability.h"
29 #include "signal-util.h"
30 #include "import-common.h"
32 int import_make_read_only_fd(int fd
) {
37 /* First, let's make this a read-only subvolume if it refers
39 r
= btrfs_subvol_set_read_only_fd(fd
, true);
40 if (r
== -ENOTTY
|| r
== -ENOTDIR
|| r
== -EINVAL
) {
43 /* This doesn't refer to a subvolume, or the file
44 * system isn't even btrfs. In that, case fall back to
49 return log_error_errno(errno
, "Failed to stat temporary image: %m");
52 if (fchmod(fd
, st
.st_mode
& 07555) < 0)
53 return log_error_errno(errno
, "Failed to chmod() final image: %m");
58 return log_error_errno(r
, "Failed to make subvolume read-only: %m");
63 int import_make_read_only(const char *path
) {
64 _cleanup_close_
int fd
= 1;
66 fd
= open(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
68 return log_error_errno(errno
, "Failed to open %s: %m", path
);
70 return import_make_read_only_fd(fd
);
73 int import_fork_tar_x(const char *path
, pid_t
*ret
) {
74 _cleanup_close_pair_
int pipefd
[2] = { -1, -1 };
81 if (pipe2(pipefd
, O_CLOEXEC
) < 0)
82 return log_error_errno(errno
, "Failed to create pipe for tar: %m");
86 return log_error_errno(errno
, "Failed to fork off tar: %m");
92 (1ULL << CAP_FOWNER
) |
93 (1ULL << CAP_FSETID
) |
95 (1ULL << CAP_SETFCAP
) |
96 (1ULL << CAP_DAC_OVERRIDE
);
100 reset_all_signal_handlers();
102 assert_se(prctl(PR_SET_PDEATHSIG
, SIGTERM
) == 0);
104 pipefd
[1] = safe_close(pipefd
[1]);
106 if (dup2(pipefd
[0], STDIN_FILENO
) != STDIN_FILENO
) {
107 log_error_errno(errno
, "Failed to dup2() fd: %m");
111 if (pipefd
[0] != STDIN_FILENO
)
112 pipefd
[0] = safe_close(pipefd
[0]);
114 null_fd
= open("/dev/null", O_WRONLY
|O_NOCTTY
);
116 log_error_errno(errno
, "Failed to open /dev/null: %m");
120 if (dup2(null_fd
, STDOUT_FILENO
) != STDOUT_FILENO
) {
121 log_error_errno(errno
, "Failed to dup2() fd: %m");
125 if (null_fd
!= STDOUT_FILENO
)
126 null_fd
= safe_close(null_fd
);
128 fd_cloexec(STDIN_FILENO
, false);
129 fd_cloexec(STDOUT_FILENO
, false);
130 fd_cloexec(STDERR_FILENO
, false);
132 if (unshare(CLONE_NEWNET
) < 0)
133 log_error_errno(errno
, "Failed to lock tar into network namespace, ignoring: %m");
135 r
= capability_bounding_set_drop(~retain
, true);
137 log_error_errno(r
, "Failed to drop capabilities, ignoring: %m");
139 execlp("tar", "tar", "--numeric-owner", "-C", path
, "-px", NULL
);
140 log_error_errno(errno
, "Failed to execute tar: %m");
144 pipefd
[0] = safe_close(pipefd
[0]);
153 int import_fork_tar_c(const char *path
, pid_t
*ret
) {
154 _cleanup_close_pair_
int pipefd
[2] = { -1, -1 };
161 if (pipe2(pipefd
, O_CLOEXEC
) < 0)
162 return log_error_errno(errno
, "Failed to create pipe for tar: %m");
166 return log_error_errno(errno
, "Failed to fork off tar: %m");
170 uint64_t retain
= (1ULL << CAP_DAC_OVERRIDE
);
174 reset_all_signal_handlers();
176 assert_se(prctl(PR_SET_PDEATHSIG
, SIGTERM
) == 0);
178 pipefd
[0] = safe_close(pipefd
[0]);
180 if (dup2(pipefd
[1], STDOUT_FILENO
) != STDOUT_FILENO
) {
181 log_error_errno(errno
, "Failed to dup2() fd: %m");
185 if (pipefd
[1] != STDOUT_FILENO
)
186 pipefd
[1] = safe_close(pipefd
[1]);
188 null_fd
= open("/dev/null", O_RDONLY
|O_NOCTTY
);
190 log_error_errno(errno
, "Failed to open /dev/null: %m");
194 if (dup2(null_fd
, STDIN_FILENO
) != STDIN_FILENO
) {
195 log_error_errno(errno
, "Failed to dup2() fd: %m");
199 if (null_fd
!= STDIN_FILENO
)
200 null_fd
= safe_close(null_fd
);
202 fd_cloexec(STDIN_FILENO
, false);
203 fd_cloexec(STDOUT_FILENO
, false);
204 fd_cloexec(STDERR_FILENO
, false);
206 if (unshare(CLONE_NEWNET
) < 0)
207 log_error_errno(errno
, "Failed to lock tar into network namespace, ignoring: %m");
209 r
= capability_bounding_set_drop(~retain
, true);
211 log_error_errno(r
, "Failed to drop capabilities, ignoring: %m");
213 execlp("tar", "tar", "--sparse", "-C", path
, "-c", ".", NULL
);
214 log_error_errno(errno
, "Failed to execute tar: %m");
218 pipefd
[1] = safe_close(pipefd
[1]);