Branch data Line data Source code
1 : : #include <unistd.h>
2 : : #include <stdarg.h>
3 : : #include "crtools.h"
4 : : #include "image.h"
5 : : #include "eventpoll.h"
6 : : #include "signalfd.h"
7 : : #include "inotify.h"
8 : : #include "sockets.h"
9 : : #include "uts_ns.h"
10 : : #include "ipc_ns.h"
11 : : #include "sk-inet.h"
12 : : #include "sk-packet.h"
13 : : #include "mount.h"
14 : : #include "net.h"
15 : : #include "protobuf.h"
16 : : #include "protobuf/inventory.pb-c.h"
17 : :
18 : 380 : int check_img_inventory(void)
19 : : {
20 : : int fd, ret;
21 : : InventoryEntry *he;
22 : :
23 : 380 : fd = open_image_ro(CR_FD_INVENTORY);
24 [ + - ]: 380 : if (fd < 0)
25 : : return -1;
26 : :
27 : 380 : ret = pb_read_one(fd, &he, PB_INVENTORY);
28 : 380 : close(fd);
29 [ + - ]: 380 : if (ret < 0)
30 : : return ret;
31 : :
32 : 380 : ret = he->img_version;
33 : 380 : inventory_entry__free_unpacked(he, NULL);
34 : :
35 [ - + ]: 380 : if (ret != CRTOOLS_IMAGES_V1) {
36 : 380 : pr_err("Not supported images version %u\n", ret);
37 : : return -1;
38 : : }
39 : :
40 : : return 0;
41 : : }
42 : :
43 : 166 : int write_img_inventory(void)
44 : : {
45 : : int fd;
46 : 166 : InventoryEntry he = INVENTORY_ENTRY__INIT;
47 : :
48 : 166 : pr_info("Writing image inventory (version %u)\n", CRTOOLS_IMAGES_V1);
49 : :
50 : 166 : fd = open_image(CR_FD_INVENTORY, O_DUMP);
51 [ + - ]: 166 : if (fd < 0)
52 : : return -1;
53 : :
54 : 166 : he.img_version = CRTOOLS_IMAGES_V1;
55 : :
56 [ + - ]: 166 : if (pb_write_one(fd, &he, PB_INVENTORY) < 0)
57 : : return -1;
58 : :
59 : 166 : close(fd);
60 : : return 0;
61 : : }
62 : :
63 : 0 : static void show_inventory(int fd, struct cr_options *o)
64 : : {
65 : : InventoryEntry *he;
66 : :
67 [ # # ]: 0 : if (pb_read_one(fd, &he, PB_INVENTORY) < 0)
68 : 0 : return;
69 : :
70 : 0 : pr_msg("Version: %u\n", he->img_version);
71 : 0 : inventory_entry__free_unpacked(he, NULL);
72 : : }
73 : :
74 : : /*
75 : : * The cr fd set is the set of files where the information
76 : : * about dumped processes is stored. Each file carries some
77 : : * small portion of info about the whole picture, see below
78 : : * for more details.
79 : : */
80 : :
81 : : #define FD_ENTRY(_name, _fmt, _show) \
82 : : [CR_FD_##_name] = { \
83 : : .fmt = _fmt ".img", \
84 : : .magic = _name##_MAGIC, \
85 : : .show = _show, \
86 : : }
87 : :
88 : 0 : static void show_raw_image(int fd, struct cr_options *opt) {};
89 : :
90 : : struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = {
91 : : FD_ENTRY(INVENTORY, "inventory", show_inventory),
92 : : FD_ENTRY(FDINFO, "fdinfo-%d", show_files),
93 : : FD_ENTRY(PAGES, "pages-%d", show_pages),
94 : : FD_ENTRY(SHMEM_PAGES, "pages-shmem-%ld", show_pages),
95 : : FD_ENTRY(REG_FILES, "reg-files", show_reg_files),
96 : : FD_ENTRY(EVENTFD, "eventfd", show_eventfds),
97 : : FD_ENTRY(EVENTPOLL, "eventpoll", show_eventpoll),
98 : : FD_ENTRY(EVENTPOLL_TFD, "eventpoll-tfd", show_eventpoll_tfd),
99 : : FD_ENTRY(SIGNALFD, "signalfd", show_signalfd),
100 : : FD_ENTRY(INOTIFY, "inotify", show_inotify),
101 : : FD_ENTRY(INOTIFY_WD, "inotify-wd", show_inotify_wd),
102 : : FD_ENTRY(CORE, "core-%d", show_core),
103 : : FD_ENTRY(MM, "mm-%d", show_mm),
104 : : FD_ENTRY(VMAS, "vmas-%d", show_vmas),
105 : : FD_ENTRY(PIPES, "pipes", show_pipes),
106 : : FD_ENTRY(PIPES_DATA, "pipes-data", show_pipes_data),
107 : : FD_ENTRY(FIFO, "fifo", show_fifo),
108 : : FD_ENTRY(FIFO_DATA, "fifo-data", show_fifo_data),
109 : : FD_ENTRY(PSTREE, "pstree", show_pstree),
110 : : FD_ENTRY(SIGACT, "sigacts-%d", show_sigacts),
111 : : FD_ENTRY(UNIXSK, "unixsk", show_unixsk),
112 : : FD_ENTRY(INETSK, "inetsk", show_inetsk),
113 : : FD_ENTRY(PACKETSK, "packetsk", show_packetsk),
114 : : FD_ENTRY(SK_QUEUES, "sk-queues", show_sk_queues),
115 : : FD_ENTRY(ITIMERS, "itimers-%d", show_itimers),
116 : : FD_ENTRY(CREDS, "creds-%d", show_creds),
117 : : FD_ENTRY(UTSNS, "utsns-%d", show_utsns),
118 : : FD_ENTRY(IPCNS_VAR, "ipcns-var-%d", show_ipc_var),
119 : : FD_ENTRY(IPCNS_SHM, "ipcns-shm-%d", show_ipc_shm),
120 : : FD_ENTRY(IPCNS_MSG, "ipcns-msg-%d", show_ipc_msg),
121 : : FD_ENTRY(IPCNS_SEM, "ipcns-sem-%d", show_ipc_sem),
122 : : FD_ENTRY(FS, "fs-%d", show_fs),
123 : : FD_ENTRY(REMAP_FPATH, "remap-fpath", show_remap_files),
124 : : FD_ENTRY(GHOST_FILE, "ghost-file-%x", show_ghost_file),
125 : : FD_ENTRY(TCP_STREAM, "tcp-stream-%x", show_tcp_stream),
126 : : FD_ENTRY(MOUNTPOINTS, "mountpoints-%d", show_mountpoints),
127 : : FD_ENTRY(NETDEV, "netdev-%d", show_netdevices),
128 : : FD_ENTRY(IFADDR, "ifaddr-%d", show_raw_image),
129 : : FD_ENTRY(ROUTE, "route-%d", show_raw_image),
130 : : FD_ENTRY(TMPFS, "tmpfs-%d.tar.gz", show_raw_image),
131 : : FD_ENTRY(TTY, "tty", show_tty),
132 : : FD_ENTRY(TTY_INFO, "tty-info", show_tty_info),
133 : : };
134 : :
135 : 598 : static struct cr_fdset *alloc_cr_fdset(int nr)
136 : : {
137 : : struct cr_fdset *cr_fdset;
138 : : unsigned int i;
139 : :
140 [ - + ]: 598 : cr_fdset = xmalloc(sizeof(*cr_fdset));
141 [ + - ]: 598 : if (cr_fdset == NULL)
142 : : return NULL;
143 : :
144 [ - + ]: 598 : cr_fdset->_fds = xmalloc(nr * sizeof(int));
145 [ + - ]: 598 : if (cr_fdset->_fds == NULL) {
146 [ # # ]: 0 : xfree(cr_fdset);
147 : : return NULL;
148 : : }
149 : :
150 [ + + ]: 8072 : for (i = 0; i < nr; i++)
151 : 7474 : cr_fdset->_fds[i] = -1;
152 : 598 : cr_fdset->fd_nr = nr;
153 : 598 : return cr_fdset;
154 : : }
155 : :
156 : 598 : static void __close_cr_fdset(struct cr_fdset *cr_fdset)
157 : : {
158 : : unsigned int i;
159 : :
160 [ + - ]: 598 : if (!cr_fdset)
161 : 598 : return;
162 : :
163 [ + + ]: 8072 : for (i = 0; i < cr_fdset->fd_nr; i++) {
164 [ + + ]: 7474 : if (cr_fdset->_fds[i] == -1)
165 : 598 : continue;
166 : 6876 : close_safe(&cr_fdset->_fds[i]);
167 : 6876 : cr_fdset->_fds[i] = -1;
168 : : }
169 : : }
170 : :
171 : 598 : void close_cr_fdset(struct cr_fdset **cr_fdset)
172 : : {
173 [ + - ][ + - ]: 598 : if (!cr_fdset || !*cr_fdset)
174 : 598 : return;
175 : :
176 : 598 : __close_cr_fdset(*cr_fdset);
177 : :
178 [ + - ]: 598 : xfree((*cr_fdset)->_fds);
179 [ + - ]: 598 : xfree(*cr_fdset);
180 : 598 : *cr_fdset = NULL;
181 : : }
182 : :
183 : 598 : static struct cr_fdset *cr_fdset_open(int pid, int from, int to,
184 : : unsigned long flags)
185 : : {
186 : : struct cr_fdset *fdset;
187 : : unsigned int i;
188 : 598 : int ret = -1;
189 : :
190 : 598 : fdset = alloc_cr_fdset(to - from);
191 [ + - ]: 598 : if (!fdset)
192 : : goto err;
193 : :
194 : 598 : from++;
195 : 598 : fdset->fd_off = from;
196 [ + + ]: 7474 : for (i = from; i < to; i++) {
197 : 6876 : ret = open_image(i, flags, pid);
198 [ - + ]: 6876 : if (ret < 0) {
199 [ # # ]: 0 : if (!(flags & O_CREAT))
200 : : /* caller should check himself */
201 : 0 : continue;
202 : : goto err;
203 : : }
204 : :
205 : 6876 : fdset->_fds[i - from] = ret;
206 : : }
207 : :
208 : 598 : return fdset;
209 : :
210 : : err:
211 : 598 : close_cr_fdset(&fdset);
212 : : return NULL;
213 : : }
214 : :
215 : 349 : struct cr_fdset *cr_task_fdset_open(int pid, int mode)
216 : : {
217 : 349 : return cr_fdset_open(pid, _CR_FD_TASK_FROM, _CR_FD_TASK_TO, mode);
218 : : }
219 : :
220 : 83 : struct cr_fdset *cr_ns_fdset_open(int pid, int mode)
221 : : {
222 : 83 : return cr_fdset_open(pid, _CR_FD_NS_FROM, _CR_FD_NS_TO, mode);
223 : : }
224 : :
225 : 166 : struct cr_fdset *cr_glob_fdset_open(int mode)
226 : : {
227 : 166 : return cr_fdset_open(-1 /* ignored */, _CR_FD_GLOB_FROM, _CR_FD_GLOB_TO, mode);
228 : : }
229 : :
230 : : static int image_dir_fd = -1;
231 : :
232 : 22405 : int open_image(int type, unsigned long flags, ...)
233 : : {
234 : : char path[PATH_MAX];
235 : : va_list args;
236 : : int ret;
237 : :
238 : 22405 : va_start(args, flags);
239 : 22405 : vsnprintf(path, PATH_MAX, fdset_template[type].fmt, args);
240 : 22405 : va_end(args);
241 : :
242 [ + + ]: 22405 : if (flags & O_EXCL) {
243 : 7288 : ret = unlinkat(image_dir_fd, path, 0);
244 [ - + ][ + - ]: 7288 : if (ret && errno != ENOENT) {
245 : 0 : pr_perror("Unable to unlink %s", path);
246 : 0 : goto err;
247 : : }
248 : : }
249 : :
250 : 22405 : ret = openat(image_dir_fd, path, flags, CR_FD_PERM);
251 [ + + ]: 22405 : if (ret < 0) {
252 : 76 : pr_perror("Unable to open %s", path);
253 : 76 : goto err;
254 : : }
255 : :
256 [ + + ]: 22329 : if (fdset_template[type].magic == RAW_IMAGE_MAGIC)
257 : : goto skip_magic;
258 : :
259 [ + + ]: 22009 : if (flags == O_RDONLY) {
260 : : u32 magic;
261 : :
262 [ + - ]: 14888 : if (read_img(ret, &magic) < 0)
263 : : goto err;
264 [ - + ]: 14888 : if (magic != fdset_template[type].magic) {
265 : 14888 : pr_err("Magic doesn't match for %s\n", path);
266 : : goto err;
267 : : }
268 : : } else {
269 [ + - ]: 22405 : if (write_img(ret, &fdset_template[type].magic))
270 : : goto err;
271 : : }
272 : :
273 : : skip_magic:
274 : : return ret;
275 : : err:
276 : : return -1;
277 : : }
278 : :
279 : 547 : int open_image_dir(void)
280 : : {
281 : : int fd;
282 : :
283 : 547 : image_dir_fd = get_service_fd(IMG_FD_OFF);
284 [ - + ]: 547 : if (image_dir_fd < 0) {
285 : 0 : pr_perror("Can't get image fd");
286 : 0 : return -1;
287 : : }
288 : :
289 : 547 : fd = open(".", O_RDONLY);
290 [ - + ]: 547 : if (fd < 0) {
291 : 0 : pr_perror("Can't open cwd");
292 : 0 : return -1;
293 : : }
294 : :
295 : 547 : pr_info("Image dir fd is %d\n", image_dir_fd);
296 : :
297 : 547 : return reopen_fd_as(image_dir_fd, fd);
298 : : }
299 : :
300 : 349 : void close_image_dir(void)
301 : : {
302 : 349 : close(image_dir_fd);
303 : 349 : image_dir_fd = -1;
304 : 349 : }
|