Branch data Line data Source code
1 : : #include <unistd.h>
2 : : #include <stdio.h>
3 : : #include <stdlib.h>
4 : : #include <errno.h>
5 : : #include <fcntl.h>
6 : : #include <stdlib.h>
7 : : #include <signal.h>
8 : : #include <string.h>
9 : : #include <utime.h>
10 : : #include <dirent.h>
11 : : #include <limits.h>
12 : : #include <sys/stat.h>
13 : : #include <sys/types.h>
14 : : #include <sys/inotify.h>
15 : : #include <sys/vfs.h>
16 : : #include <linux/magic.h>
17 : : #include <sys/wait.h>
18 : : #include <sys/poll.h>
19 : : #include <sys/mman.h>
20 : : #include <sys/mount.h>
21 : : #include <aio.h>
22 : :
23 : : #include <linux/fanotify.h>
24 : :
25 : : #include "compiler.h"
26 : : #include "asm/types.h"
27 : : #include "fdset.h"
28 : : #include "fsnotify.h"
29 : : #include "proc_parse.h"
30 : : #include "syscall.h"
31 : : #include "mount.h"
32 : : #include "image.h"
33 : : #include "util.h"
34 : : #include "files.h"
35 : : #include "files-reg.h"
36 : : #include "file-ids.h"
37 : : #include "log.h"
38 : : #include "list.h"
39 : : #include "lock.h"
40 : : #include "irmap.h"
41 : : #include "cr_options.h"
42 : :
43 : : #include "protobuf.h"
44 : : #include "protobuf/fsnotify.pb-c.h"
45 : : #include "protobuf/mnt.pb-c.h"
46 : :
47 : : #undef LOG_PREFIX
48 : : #define LOG_PREFIX "fsnotify: "
49 : :
50 : : struct fsnotify_mark_info {
51 : : struct list_head list;
52 : : union {
53 : : InotifyWdEntry *iwe;
54 : : FanotifyMarkEntry *fme;
55 : : };
56 : : struct file_remap *remap;
57 : : };
58 : :
59 : : struct fsnotify_file_info {
60 : : struct list_head list;
61 : : union {
62 : : InotifyFileEntry *ife;
63 : : FanotifyFileEntry *ffe;
64 : : };
65 : : struct list_head marks;
66 : : struct file_desc d;
67 : : };
68 : :
69 : : /* File handle */
70 : : typedef struct {
71 : : u32 bytes;
72 : : u32 type;
73 : : u64 __handle[16];
74 : : } fh_t;
75 : :
76 : : static LIST_HEAD(inotify_info_head);
77 : : static LIST_HEAD(fanotify_info_head);
78 : :
79 : : /* Checks if file descriptor @lfd is inotify */
80 : 17067 : int is_inotify_link(char *link)
81 : : {
82 : 17067 : return is_anon_link_type(link, "inotify");
83 : : }
84 : :
85 : : /* Checks if file descriptor @lfd is fanotify */
86 : 17051 : int is_fanotify_link(char *link)
87 : : {
88 : 17051 : return is_anon_link_type(link, "[fanotify]");
89 : : }
90 : :
91 : 52 : static void decode_handle(fh_t *handle, FhEntry *img)
92 : : {
93 : : memzero(handle, sizeof(*handle));
94 : :
95 : 52 : handle->type = img->type;
96 : 52 : handle->bytes = img->bytes;
97 : :
98 : 52 : memcpy(handle->__handle, img->handle,
99 : 52 : min(pb_repeated_size(img, handle),
100 : : sizeof(handle->__handle)));
101 : 52 : }
102 : :
103 : 52 : static int open_handle(unsigned int s_dev, unsigned long i_ino,
104 : : FhEntry *f_handle)
105 : : {
106 : : int mntfd, fd = -1;
107 : : fh_t handle;
108 : :
109 : 52 : decode_handle(&handle, f_handle);
110 : :
111 : 52 : pr_debug("Opening fhandle %x:%Lx...\n",
112 : : s_dev, (unsigned long long)handle.__handle[0]);
113 : :
114 : 52 : mntfd = open_mount(s_dev);
115 [ - + ]: 52 : if (mntfd < 0) {
116 : 0 : pr_perror("Mount root for 0x%08x not found\n", s_dev);
117 : 0 : goto out;
118 : : }
119 : :
120 : 52 : fd = sys_open_by_handle_at(mntfd, (void *)&handle, O_PATH);
121 [ - + ]: 52 : if (fd < 0) {
122 : 0 : errno = -fd;
123 : 0 : pr_perror("Can't open file handle for 0x%08x:0x%016lx",
124 : : s_dev, i_ino);
125 : : }
126 : :
127 : 52 : close(mntfd);
128 : : out:
129 : 52 : return fd;
130 : : }
131 : :
132 : 48 : int check_open_handle(unsigned int s_dev, unsigned long i_ino,
133 : : FhEntry *f_handle)
134 : : {
135 : 48 : int fd = -1;
136 : : char *path;
137 : :
138 : 48 : fd = open_handle(s_dev, i_ino, f_handle);
139 [ + - ]: 48 : if (fd >= 0) {
140 : : struct mount_info *mi;
141 : :
142 : 48 : pr_debug("\tHandle %x:%lx is openable\n", s_dev, i_ino);
143 : :
144 : 48 : mi = lookup_mnt_sdev(s_dev);
145 [ - + ]: 48 : if (mi == NULL) {
146 : 0 : pr_err("Unable to lookup a mount by dev %x\n", s_dev);
147 : 0 : goto err;
148 : : }
149 : :
150 : : /*
151 : : * Inode numbers are not restored for tmpfs content, but we can
152 : : * get file names, becasue tmpfs cache is not pruned.
153 : : */
154 [ - + ]: 48 : if ((mi->fstype->code == FSTYPE__TMPFS) ||
155 : : (mi->fstype->code == FSTYPE__DEVTMPFS)) {
156 : : char p[PATH_MAX];
157 : :
158 [ # # ]: 0 : if (read_fd_link(fd, p, sizeof(p)) < 0)
159 : : goto err;
160 : :
161 [ # # ]: 0 : path = xstrdup(p);
162 [ # # ]: 0 : if (path == NULL)
163 : : goto err;
164 : :
165 : 0 : goto out;
166 : : }
167 : :
168 [ - + ]: 48 : if (!opts.force_irmap)
169 : : /*
170 : : * If we're not forced to do irmap, then
171 : : * say we have no path for watch. Otherwise
172 : : * do irmap scan even if the handle is
173 : : * working.
174 : : *
175 : : * FIXME -- no need to open-by-handle if
176 : : * we are in force-irmap and not on tempfs
177 : : */
178 : : goto out_nopath;
179 : : }
180 : :
181 : 0 : pr_warn("\tHandle %x:%lx cannot be opened\n", s_dev, i_ino);
182 : 0 : path = irmap_lookup(s_dev, i_ino);
183 [ # # ]: 0 : if (!path) {
184 : 0 : pr_err("\tCan't dump that handle\n");
185 : 0 : return -1;
186 : : }
187 : : out:
188 : 0 : pr_debug("\tDumping %s as path for handle\n", path);
189 : 0 : f_handle->path = path;
190 : : out_nopath:
191 : 48 : close_safe(&fd);
192 : 48 : return 0;
193 : : err:
194 : 0 : close_safe(&fd);
195 : 0 : return -1;
196 : : }
197 : :
198 : 8 : static int dump_inotify_entry(union fdinfo_entries *e, void *arg)
199 : : {
200 : 8 : InotifyWdEntry *we = &e->ify;
201 : :
202 : 8 : we->id = *(u32 *)arg;
203 : 8 : pr_info("wd: wd 0x%08x s_dev 0x%08x i_ino 0x%16"PRIx64" mask 0x%08x\n",
204 : : we->wd, we->s_dev, we->i_ino, we->mask);
205 : 8 : pr_info("\t[fhandle] bytes 0x%08x type 0x%08x __handle 0x%016"PRIx64":0x%016"PRIx64"\n",
206 : : we->f_handle->bytes, we->f_handle->type,
207 : : we->f_handle->handle[0], we->f_handle->handle[1]);
208 : :
209 [ + - ]: 8 : if (check_open_handle(we->s_dev, we->i_ino, we->f_handle))
210 : : return -1;
211 : :
212 : 8 : return pb_write_one(fdset_fd(glob_fdset, CR_FD_INOTIFY_WD), we, PB_INOTIFY_WD);
213 : : }
214 : :
215 : 4 : static int dump_one_inotify(int lfd, u32 id, const struct fd_parms *p)
216 : : {
217 : 4 : InotifyFileEntry ie = INOTIFY_FILE_ENTRY__INIT;
218 : :
219 : 4 : ie.id = id;
220 : 4 : ie.flags = p->flags;
221 : 4 : ie.fown = (FownEntry *)&p->fown;
222 : :
223 : 4 : pr_info("id 0x%08x flags 0x%08x\n", ie.id, ie.flags);
224 [ + - ]: 4 : if (pb_write_one(fdset_fd(glob_fdset, CR_FD_INOTIFY_FILE), &ie, PB_INOTIFY_FILE))
225 : : return -1;
226 : :
227 : 4 : return parse_fdinfo(lfd, FD_TYPES__INOTIFY, dump_inotify_entry, &id);
228 : : }
229 : :
230 : 24 : static int pre_dump_inotify_entry(union fdinfo_entries *e, void *arg)
231 : : {
232 : : InotifyWdEntry *we = &e->ify;
233 : 24 : return irmap_queue_cache(we->s_dev, we->i_ino, we->f_handle);
234 : : }
235 : :
236 : 12 : static int pre_dump_one_inotify(int pid, int lfd)
237 : : {
238 : 12 : return parse_fdinfo_pid(pid, lfd, FD_TYPES__INOTIFY, pre_dump_inotify_entry, NULL);
239 : : }
240 : :
241 : : const struct fdtype_ops inotify_dump_ops = {
242 : : .type = FD_TYPES__INOTIFY,
243 : : .dump = dump_one_inotify,
244 : : .pre_dump = pre_dump_one_inotify,
245 : : };
246 : :
247 : 8 : static int dump_fanotify_entry(union fdinfo_entries *e, void *arg)
248 : : {
249 : : struct fsnotify_params *fsn_params = arg;
250 : 8 : FanotifyMarkEntry *fme = &e->ffy;
251 : :
252 : 8 : fme->id = fsn_params->id;
253 : :
254 [ + + ]: 8 : if (fme->type == MARK_TYPE__INODE) {
255 : :
256 [ - + ]: 4 : BUG_ON(!fme->ie);
257 : :
258 : 4 : pr_info("mark: s_dev 0x%08x i_ino 0x%016"PRIx64" mask 0x%08x\n",
259 : : fme->s_dev, fme->ie->i_ino, fme->mask);
260 : :
261 : 4 : pr_info("\t[fhandle] bytes 0x%08x type 0x%08x __handle 0x%016"PRIx64":0x%016"PRIx64"\n",
262 : : fme->ie->f_handle->bytes, fme->ie->f_handle->type,
263 : : fme->ie->f_handle->handle[0], fme->ie->f_handle->handle[1]);
264 : :
265 [ + - ]: 4 : if (check_open_handle(fme->s_dev, fme->ie->i_ino, fme->ie->f_handle))
266 : : return -1;
267 : : }
268 : :
269 [ + + ]: 8 : if (fme->type == MARK_TYPE__MOUNT) {
270 : : struct mount_info *m;
271 : :
272 [ - + ]: 4 : BUG_ON(!fme->me);
273 : :
274 : 4 : m = lookup_mnt_id(fme->me->mnt_id);
275 [ - + ]: 4 : if (!m) {
276 : 0 : pr_err("Can't find mnt_id %x\n", fme->me->mnt_id);
277 : 0 : return -1;
278 : : }
279 : 4 : fme->s_dev = m->s_dev;
280 : :
281 : 4 : pr_info("mark: s_dev 0x%08x mnt_id 0x%08x mask 0x%08x\n",
282 : : fme->s_dev, fme->me->mnt_id, fme->mask);
283 : :
284 : : }
285 : :
286 : 8 : return pb_write_one(fdset_fd(glob_fdset, CR_FD_FANOTIFY_MARK), fme, PB_FANOTIFY_MARK);
287 : : }
288 : :
289 : 4 : static int dump_one_fanotify(int lfd, u32 id, const struct fd_parms *p)
290 : : {
291 : 4 : FanotifyFileEntry fe = FANOTIFY_FILE_ENTRY__INIT;
292 : 4 : struct fsnotify_params fsn_params = { .id = id, };
293 : :
294 : 4 : fe.id = id;
295 : 4 : fe.flags = p->flags;
296 : 4 : fe.fown = (FownEntry *)&p->fown;
297 : :
298 [ + - ]: 4 : if (parse_fdinfo(lfd, FD_TYPES__FANOTIFY,
299 : : dump_fanotify_entry, &fsn_params) < 0)
300 : : return -1;
301 : :
302 : 4 : pr_info("id 0x%08x flags 0x%08x\n", fe.id, fe.flags);
303 : :
304 : 4 : fe.faflags = fsn_params.faflags;
305 : 4 : fe.evflags = fsn_params.evflags;
306 : :
307 : 4 : return pb_write_one(fdset_fd(glob_fdset, CR_FD_FANOTIFY_FILE), &fe, PB_FANOTIFY_FILE);
308 : : }
309 : :
310 : 24 : static int pre_dump_fanotify_entry(union fdinfo_entries *e, void *arg)
311 : : {
312 : : FanotifyMarkEntry *fme = &e->ffy;
313 : :
314 [ + + ]: 24 : if (fme->type == MARK_TYPE__INODE)
315 : 12 : return irmap_queue_cache(fme->s_dev, fme->ie->i_ino,
316 : 12 : fme->ie->f_handle);
317 : : else
318 : : return 0;
319 : : }
320 : :
321 : 12 : static int pre_dump_one_fanotify(int pid, int lfd)
322 : : {
323 : 12 : struct fsnotify_params fsn_params = { };
324 : 12 : return parse_fdinfo_pid(pid, lfd, FD_TYPES__FANOTIFY, pre_dump_fanotify_entry, &fsn_params);
325 : : }
326 : :
327 : : const struct fdtype_ops fanotify_dump_ops = {
328 : : .type = FD_TYPES__FANOTIFY,
329 : : .dump = dump_one_fanotify,
330 : : .pre_dump = pre_dump_one_fanotify,
331 : : };
332 : :
333 : 6 : static char *get_mark_path(const char *who, struct file_remap *remap,
334 : : FhEntry *f_handle, unsigned long i_ino,
335 : : unsigned int s_dev, char *buf, int *target)
336 : : {
337 : : char *path = NULL;
338 : :
339 [ + + ]: 6 : if (remap) {
340 : 2 : pr_debug("\t\tRestore %s watch for 0x%08x:0x%016lx (via %s)\n",
341 : : who, s_dev, i_ino, remap->path);
342 : 2 : return remap->path;
343 : : }
344 : :
345 [ - + ]: 4 : if (f_handle->path) {
346 : 0 : pr_debug("\t\tRestore with path hint %s\n", f_handle->path);
347 : 0 : return f_handle->path;
348 : : }
349 : :
350 : 4 : *target = open_handle(s_dev, i_ino, f_handle);
351 [ + - ]: 4 : if (*target < 0)
352 : : goto err;
353 : :
354 : : /*
355 : : * fanotify/inotify open syscalls want path to attach
356 : : * watch to. But the only thing we have is an FD obtained
357 : : * via fhandle. Fortunatelly, when trying to attach the
358 : : * /proc/pid/fd/ link, we will watch the inode the link
359 : : * points to, i.e. -- just what we want.
360 : : */
361 : :
362 : : sprintf(buf, "/proc/self/fd/%d", *target);
363 : : path = buf;
364 : :
365 [ + - ]: 4 : if (log_get_loglevel() >= LOG_DEBUG) {
366 : : char link[PATH_MAX];
367 : :
368 [ - + ]: 4 : if (read_fd_link(*target, link, sizeof(link)) < 0)
369 : 0 : link[0] = '\0';
370 : :
371 : 4 : pr_debug("\t\tRestore %s watch for 0x%08x:0x%016lx (via %s -> %s)\n",
372 : : who, s_dev, i_ino, path, link);
373 : : }
374 : : err:
375 : 4 : return path;
376 : : }
377 : :
378 : 8 : static int restore_one_inotify(int inotify_fd, struct fsnotify_mark_info *info)
379 : : {
380 : 4 : InotifyWdEntry *iwe = info->iwe;
381 : 4 : int ret = -1, target = -1;
382 : : char buf[PSFDS], *path;
383 : :
384 : 4 : path = get_mark_path("inotify", info->remap, iwe->f_handle,
385 : : iwe->i_ino, iwe->s_dev, buf, &target);
386 [ + - ]: 4 : if (!path)
387 : : goto err;
388 : :
389 : : /*
390 : : * FIXME The kernel allocates wd-s sequentially,
391 : : * this is suboptimal, but the kernel doesn't
392 : : * provide and API for this yet :(
393 : : */
394 : : while (1) {
395 : : int wd;
396 : :
397 : 4 : wd = inotify_add_watch(inotify_fd, path, iwe->mask);
398 [ - + ]: 4 : if (wd < 0) {
399 : 0 : pr_perror("Can't add watch for %d with %d", inotify_fd, iwe->wd);
400 : : break;
401 [ - + ]: 4 : } else if (wd == iwe->wd) {
402 : : ret = 0;
403 : : break;
404 [ # # ]: 0 : } else if (wd > iwe->wd) {
405 : 0 : pr_err("Unsorted watch %d found for %d with %d", wd, inotify_fd, iwe->wd);
406 : : break;
407 : : }
408 : :
409 : 0 : pr_debug("\t\tWatch got %d but %d expected\n", wd, iwe->wd);
410 : 0 : inotify_rm_watch(inotify_fd, wd);
411 : : }
412 : :
413 : : err:
414 [ + + ]: 4 : if (info->remap)
415 : 2 : remap_put(info->remap);
416 : :
417 : 4 : close_safe(&target);
418 : 4 : return ret;
419 : : }
420 : :
421 : 8 : static int restore_one_fanotify(int fd, struct fsnotify_mark_info *mark)
422 : : {
423 : 4 : FanotifyMarkEntry *fme = mark->fme;
424 : : unsigned int flags = FAN_MARK_ADD;
425 : 4 : int ret = -1, target = -1;
426 : : char buf[PSFDS], *path = NULL;
427 : :
428 [ + + ]: 4 : if (fme->type == MARK_TYPE__MOUNT) {
429 : : struct mount_info *m;
430 : :
431 : 2 : m = lookup_mnt_sdev(fme->s_dev);
432 [ - + ]: 2 : if (!m) {
433 : 0 : pr_err("Can't find mount s_dev %x\n", fme->s_dev);
434 : : return -1;
435 : : }
436 : :
437 : : flags |= FAN_MARK_MOUNT;
438 : 2 : path = m->mountpoint;
439 [ + - ]: 2 : } else if (fme->type == MARK_TYPE__INODE) {
440 : 2 : path = get_mark_path("fanotify", mark->remap,
441 : 2 : fme->ie->f_handle, fme->ie->i_ino,
442 : : fme->s_dev, buf, &target);
443 [ + - ]: 2 : if (!path)
444 : : goto err;
445 : : } else {
446 : 0 : pr_err("Bad fsnotify mark type %d\n", fme->type);
447 : : goto err;
448 : : }
449 : :
450 : 4 : flags |= fme->mflags;
451 : :
452 [ + - ]: 4 : if (mark->fme->mask) {
453 : 4 : ret = sys_fanotify_mark(fd, flags, fme->mask, AT_FDCWD, path);
454 [ - + ]: 4 : if (ret) {
455 : 0 : pr_err("Adding fanotify mask %x on %x/%s failed (%d)\n",
456 : : fme->mask, fme->id, path, ret);
457 : : goto err;
458 : : }
459 : : }
460 : :
461 [ + - ]: 4 : if (fme->ignored_mask) {
462 : 4 : ret = sys_fanotify_mark(fd, flags | FAN_MARK_IGNORED_MASK,
463 : : fme->ignored_mask, AT_FDCWD, path);
464 [ - + ]: 4 : if (ret) {
465 : 0 : pr_err("Adding fanotify ignored-mask %x on %x/%s failed (%d)\n",
466 : : fme->ignored_mask, fme->id, path, ret);
467 : : goto err;
468 : : }
469 : : }
470 : :
471 [ - + ]: 4 : if (mark->remap)
472 : 0 : remap_put(mark->remap);
473 : :
474 : : err:
475 : 4 : close_safe(&target);
476 : : return ret;
477 : : }
478 : :
479 : 2 : static int open_inotify_fd(struct file_desc *d)
480 : : {
481 : : struct fsnotify_file_info *info;
482 : 4 : struct fsnotify_mark_info *wd_info;
483 : : int tmp;
484 : :
485 : : info = container_of(d, struct fsnotify_file_info, d);
486 : :
487 : 2 : tmp = inotify_init1(info->ife->flags);
488 [ - + ]: 2 : if (tmp < 0) {
489 : 0 : pr_perror("Can't create inotify for 0x%08x", info->ife->id);
490 : 0 : return -1;
491 : : }
492 : :
493 [ + + ]: 6 : list_for_each_entry(wd_info, &info->marks, list) {
494 : 4 : pr_info("\tRestore %d wd for 0x%08x\n", wd_info->iwe->wd, wd_info->iwe->id);
495 [ - + ]: 4 : if (restore_one_inotify(tmp, wd_info)) {
496 : 0 : close_safe(&tmp);
497 : 0 : break;
498 : : }
499 : : }
500 : :
501 [ - + ]: 2 : if (restore_fown(tmp, info->ife->fown))
502 : 0 : close_safe(&tmp);
503 : :
504 : 2 : return tmp;
505 : : }
506 : :
507 : 2 : static int open_fanotify_fd(struct file_desc *d)
508 : : {
509 : : struct fsnotify_file_info *info;
510 : : struct fsnotify_mark_info *mark;
511 : : unsigned int flags = 0;
512 : : int ret;
513 : :
514 : : info = container_of(d, struct fsnotify_file_info, d);
515 : :
516 : 2 : flags = info->ffe->faflags;
517 [ - + ]: 2 : if (info->ffe->flags & O_CLOEXEC)
518 : 0 : flags |= FAN_CLOEXEC;
519 [ + - ]: 2 : if (info->ffe->flags & O_NONBLOCK)
520 : 2 : flags |= FAN_NONBLOCK;
521 : :
522 : 2 : ret = sys_fanotify_init(flags, info->ffe->evflags);
523 [ - + ]: 2 : if (ret < 0) {
524 : 0 : errno = -ret;
525 : 0 : pr_perror("Can't init fanotify mark (%d)", ret);
526 : 0 : return -1;
527 : : }
528 : :
529 [ + + ]: 6 : list_for_each_entry(mark, &info->marks, list) {
530 : 4 : pr_info("\tRestore fanotify for 0x%08x\n", mark->fme->id);
531 [ - + ]: 4 : if (restore_one_fanotify(ret, mark)) {
532 : 0 : close_safe(&ret);
533 : 0 : break;
534 : : }
535 : : }
536 : :
537 [ - + ]: 2 : if (restore_fown(ret, info->ffe->fown))
538 : 0 : close_safe(&ret);
539 : :
540 : 2 : return ret;
541 : : }
542 : :
543 : : static struct file_desc_ops inotify_desc_ops = {
544 : : .type = FD_TYPES__INOTIFY,
545 : : .open = open_inotify_fd,
546 : : };
547 : :
548 : : static struct file_desc_ops fanotify_desc_ops = {
549 : : .type = FD_TYPES__FANOTIFY,
550 : : .open = open_fanotify_fd,
551 : : };
552 : :
553 : 4 : static struct fsnotify_file_info *find_inotify_info(unsigned id)
554 : : {
555 : : struct fsnotify_file_info *p;
556 : : static struct fsnotify_file_info *last = NULL;
557 : :
558 [ + + ][ + - ]: 4 : if (last && last->ife->id == id) {
559 : : /*
560 : : * An optimization for clean dump image -- criu puts
561 : : * wd-s for one inotify in one row, thus sometimes
562 : : * we can avoid scanning the inotify_info_head.
563 : : */
564 : 2 : pr_debug("\t\tlast ify for %u found\n", id);
565 : 2 : return last;
566 : : }
567 : :
568 [ + - ]: 2 : list_for_each_entry(p, &inotify_info_head, list)
569 [ + - ]: 2 : if (p->ife->id == id) {
570 : 2 : last = p;
571 : 2 : return p;
572 : : }
573 : :
574 : 0 : pr_err("Can't find inotify with id 0x%08x\n", id);
575 : 0 : return NULL;
576 : : }
577 : :
578 : 4 : static int collect_inotify_mark(struct fsnotify_mark_info *mark)
579 : : {
580 : : struct fsnotify_file_info *p;
581 : : struct fsnotify_mark_info *m;
582 : :
583 : 4 : p = find_inotify_info(mark->iwe->id);
584 [ + - ]: 4 : if (!p)
585 : : return -1;
586 : :
587 : : /*
588 : : * We should put marks in wd ascending order. See comment
589 : : * in restore_one_inotify() for explanation.
590 : : */
591 [ + + ]: 4 : list_for_each_entry(m, &p->marks, list)
592 [ - + ]: 2 : if (m->iwe->wd > mark->iwe->wd)
593 : : break;
594 : :
595 : 4 : list_add_tail(&mark->list, &m->list);
596 : 4 : mark->remap = lookup_ghost_remap(mark->iwe->s_dev, mark->iwe->i_ino);
597 : 4 : return 0;
598 : : }
599 : :
600 : 4 : static int collect_fanotify_mark(struct fsnotify_mark_info *mark)
601 : : {
602 : : struct fsnotify_file_info *p;
603 : :
604 [ + - ]: 4 : list_for_each_entry(p, &fanotify_info_head, list) {
605 [ + - ]: 4 : if (p->ffe->id == mark->fme->id) {
606 : 4 : list_add(&mark->list, &p->marks);
607 [ + + ]: 4 : if (mark->fme->type == MARK_TYPE__INODE)
608 : 2 : mark->remap = lookup_ghost_remap(mark->fme->s_dev,
609 : 2 : mark->fme->ie->i_ino);
610 : : return 0;
611 : : }
612 : : }
613 : :
614 : 0 : pr_err("Can't find fanotify with id 0x%08x\n", mark->fme->id);
615 : 0 : return -1;
616 : : }
617 : :
618 : 2 : static int collect_one_inotify(void *o, ProtobufCMessage *msg)
619 : : {
620 : : struct fsnotify_file_info *info = o;
621 : :
622 : 2 : info->ife = pb_msg(msg, InotifyFileEntry);
623 : 2 : INIT_LIST_HEAD(&info->marks);
624 : 2 : list_add(&info->list, &inotify_info_head);
625 : 2 : pr_info("Collected id 0x%08x flags 0x%08x\n", info->ife->id, info->ife->flags);
626 : 2 : return file_desc_add(&info->d, info->ife->id, &inotify_desc_ops);
627 : : }
628 : :
629 : : struct collect_image_info inotify_cinfo = {
630 : : .fd_type = CR_FD_INOTIFY_FILE,
631 : : .pb_type = PB_INOTIFY_FILE,
632 : : .priv_size = sizeof(struct fsnotify_file_info),
633 : : .collect = collect_one_inotify,
634 : : .flags = COLLECT_OPTIONAL,
635 : : };
636 : :
637 : 2 : static int collect_one_fanotify(void *o, ProtobufCMessage *msg)
638 : : {
639 : : struct fsnotify_file_info *info = o;
640 : :
641 : 2 : info->ffe = pb_msg(msg, FanotifyFileEntry);
642 : 2 : INIT_LIST_HEAD(&info->marks);
643 : 2 : list_add(&info->list, &fanotify_info_head);
644 : 2 : pr_info("Collected id 0x%08x flags 0x%08x\n", info->ffe->id, info->ffe->flags);
645 : 2 : return file_desc_add(&info->d, info->ffe->id, &fanotify_desc_ops);
646 : : }
647 : :
648 : : struct collect_image_info fanotify_cinfo = {
649 : : .fd_type = CR_FD_FANOTIFY_FILE,
650 : : .pb_type = PB_FANOTIFY_FILE,
651 : : .priv_size = sizeof(struct fsnotify_file_info),
652 : : .collect = collect_one_fanotify,
653 : : .flags = COLLECT_OPTIONAL,
654 : : };
655 : :
656 : 4 : static int collect_one_inotify_mark(void *o, ProtobufCMessage *msg)
657 : : {
658 : : struct fsnotify_mark_info *mark = o;
659 : :
660 : 4 : mark->iwe = pb_msg(msg, InotifyWdEntry);
661 : 4 : INIT_LIST_HEAD(&mark->list);
662 : 4 : mark->remap = NULL;
663 : :
664 : 4 : return collect_inotify_mark(mark);
665 : : }
666 : :
667 : : struct collect_image_info inotify_mark_cinfo = {
668 : : .fd_type = CR_FD_INOTIFY_WD,
669 : : .pb_type = PB_INOTIFY_WD,
670 : : .priv_size = sizeof(struct fsnotify_mark_info),
671 : : .collect = collect_one_inotify_mark,
672 : : .flags = COLLECT_OPTIONAL,
673 : : };
674 : :
675 : 4 : static int collect_one_fanotify_mark(void *o, ProtobufCMessage *msg)
676 : : {
677 : : struct fsnotify_mark_info *mark = o;
678 : :
679 : 4 : mark->fme = pb_msg(msg, FanotifyMarkEntry);
680 : 4 : INIT_LIST_HEAD(&mark->list);
681 : 4 : mark->remap = NULL;
682 : :
683 : 4 : return collect_fanotify_mark(mark);
684 : : }
685 : :
686 : : struct collect_image_info fanotify_mark_cinfo = {
687 : : .fd_type = CR_FD_FANOTIFY_MARK,
688 : : .pb_type = PB_FANOTIFY_MARK,
689 : : .priv_size = sizeof(struct fsnotify_mark_info),
690 : : .collect = collect_one_fanotify_mark,
691 : : .flags = COLLECT_OPTIONAL,
692 : : };
|