<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p dir="ltr"><br>
4 июля 2016 г. 20:05 пользователь Pavel Emelianov <xemul@virtuozzo.com> написал:<br>
><br>
> On 06/30/2016 07:24 PM, Stanislav Kinsburskiy wrote:<br>
> > The correct place to get fd open flags for file mappings is<br>
> > /proc/<pid>/map_files.<br>
> > An attempt tp speculate on "shared" and "maywrite" bits doesn't garantee,<br>
> > that file will be opened with correct permissions on restore.<br>
> > Here is an example:<br>
> > <br>
> > Process mapping (read/write):<br>
> > <br>
> > # cat /proc/481943/maps | grep 7f7108077000-7f7108078000<br>
> > 7f7108077000-7f7108078000 rw-p 00001000 00:35 7 <snip><br>
> > <br>
> > 1) Before suspend:<br>
> > <br>
> > # ls -l /proc/481427/map_files/7f7108077000-7f7108078000<br>
> > lrw------- <snip> /proc/481427/map_files/7f7108077000-7f7108078000 -> <snip><br>
> > <br>
> > 2) After restore:<br>
> > <br>
> > # ls -l /proc/481943/map_files/7f7108077000-7f7108078000<br>
> > lr-------- <snip> /proc/481943/map_files/7f7108077000-7f7108078000 -> <snip><br>
> > <br>
> > Write bit is lost.<br>
> > <br>
> > This patch set vma->e->fdflags as /proc/<pid>/map_files/<vma> open mode.<br>
> > <br>
> > Signed-off-by: Stanislav Kinsburskiy <skinsbursky@virtuozzo.com><br>
> > ---<br>
> > criu/proc_parse.c | 51 ++++++++++++++++++++++++++++++++++-----------------<br>
> > criu/util.c | 3 ++-<br>
> > 2 files changed, 36 insertions(+), 18 deletions(-)<br>
> > <br>
> > diff --git a/criu/proc_parse.c b/criu/proc_parse.c<br>
> > index 5210226..8e36916 100644<br>
> > --- a/criu/proc_parse.c<br>
> > +++ b/criu/proc_parse.c<br>
> > @@ -82,8 +82,6 @@ static bool is_vma_range_fmt(char *line)<br>
> > static int parse_vmflags(char *buf, struct vma_area *vma_area)<br>
> > {<br>
> > char *tok;<br>
> > - bool shared = false;<br>
> > - bool maywrite = false;<br>
> > <br>
> > if (!buf[0])<br>
> > return 0;<br>
> > @@ -95,12 +93,6 @@ static int parse_vmflags(char *buf, struct vma_area *vma_area)<br>
> > #define _vmflag_match(_t, _s) (_t[0] == _s[0] && _t[1] == _s[1])<br>
> > <br>
> > do {<br>
> > - /* open() block */<br>
> > - if (_vmflag_match(tok, "sh"))<br>
> > - shared = true;<br>
> > - else if (_vmflag_match(tok, "mw"))<br>
> > - maywrite = true;<br>
> > -<br>
> > /* mmap() block */<br>
> > if (_vmflag_match(tok, "gd"))<br>
> > vma_area->e->flags |= MAP_GROWSDOWN;<br>
> > @@ -144,12 +136,6 @@ static int parse_vmflags(char *buf, struct vma_area *vma_area)<br>
> > <br>
> > #undef _vmflag_match<br>
> > <br>
> > - if (shared && maywrite)<br>
> > - vma_area->e->fdflags = O_RDWR;<br>
> > - else<br>
> > - vma_area->e->fdflags = O_RDONLY;<br>
> > - vma_area->e->has_fdflags = true;<br>
> > -<br>
> > if (vma_area->e->madv)<br>
> > vma_area->e->has_madv = true;<br>
> > <br>
> > @@ -175,12 +161,46 @@ static inline int vfi_equal(struct vma_file_info *a, struct vma_file_info *b)<br>
> > (a->dev_min ^ b->dev_min)) == 0;<br>
> > }<br>
> > <br>
> > +static int vma_get_mapfile_flags(struct vma_area *vma, DIR *mfd, char *path)<br>
> > +{<br>
> > + struct stat stat;<br>
> > +<br>
> > + if (fstatat(dirfd(mfd), path, &stat, AT_SYMLINK_NOFOLLOW) < 0) {<br>
> > + if (errno == ENOENT) {<br>
> > + /* Just mapping w/o map_files link */<br>
> > + return 0;<br>
> > + }<br>
> > + pr_perror("Failed fstatat on map %"PRIx64"", vma->e->start);<br>
> > + return -1;<br>
> > + }<br>
> > +<br>
> > + switch(stat.st_mode & 0600) {<br>
> > + case 0200:<br>
> > + vma->e->fdflags = O_WRONLY;<br>
> > + break;<br>
> > + case 0400:<br>
> > + vma->e->fdflags = O_RDONLY;<br>
> > + break;<br>
> > + case 0600:<br>
> > + vma->e->fdflags = O_RDWR;<br>
> > + break;<br>
> > + }<br>
> > + vma->e->has_fdflags = true;<br>
> > + return 0;<br>
> > +}<br>
> > +<br>
> > static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd,<br>
> > struct vma_file_info *vfi, struct vma_file_info *prev_vfi)<br>
> > {<br>
> > char path[32];<br>
> > int flags;<br>
> > <br>
> > + /* Figure out if it's file mapping */<br>
> > + snprintf(path, sizeof(path), "%"PRIx64"-%"PRIx64, vma->e->start, vma->e->end);<br>
> > +<br>
> > + if (vma_get_mapfile_flags(vma, mfd, path))<br>
> > + return -1;<br>
><br>
> Can we re-use the vmfd borrowing logic for fdflags too?<br>
></p>
<p dir="ltr">You mean in the cycle below?<br>
Yes, but then we have to add check for fdflags to vfi_equal, shouldn't we?</p>
<p dir="ltr">> > +<br>
> > if (prev_vfi->vma && vfi_equal(vfi, prev_vfi)) {<br>
> > struct vma_area *prev = prev_vfi->vma;<br>
> > <br>
> > @@ -209,9 +229,6 @@ static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd,<br>
> > return 0;<br>
> > }<br>
> > <br>
> > - /* Figure out if it's file mapping */<br>
> > - snprintf(path, sizeof(path), "%"PRIx64"-%"PRIx64, vma->e->start, vma->e->end);<br>
> > -<br>
> > /*<br>
> > * Note that we "open" it in dumper process space<br>
> > * so later we might refer to it via /proc/self/fd/vm_file_fd<br>
> > diff --git a/criu/util.c b/criu/util.c<br>
> > index e8ebe61..07bc16e 100644<br>
> > --- a/criu/util.c<br>
> > +++ b/criu/util.c<br>
> > @@ -161,12 +161,13 @@ void pr_vma(unsigned int loglevel, const struct vma_area *vma_area)<br>
> > return;<br>
> > <br>
> > vma_opt_str(vma_area, opt);<br>
> > - print_on_level(loglevel, "%#"PRIx64"-%#"PRIx64" (%"PRIi64"K) prot %#x flags %#x st %#x off %#"PRIx64" "<br>
> > + print_on_level(loglevel, "%#"PRIx64"-%#"PRIx64" (%"PRIi64"K) prot %#x flags %#x fdflags %#o st %#x off %#"PRIx64" "<br>
> > "%s shmid: %#"PRIx64"\n",<br>
> > vma_area->e->start, vma_area->e->end,<br>
> > KBYTES(vma_area_len(vma_area)),<br>
> > vma_area->e->prot,<br>
> > vma_area->e->flags,<br>
> > + vma_area->e->fdflags,<br>
> > vma_area->e->status,<br>
> > vma_area->e->pgoff,<br>
> > opt, vma_area->e->shmid);<br>
> > <br>
> > _______________________________________________<br>
> > CRIU mailing list<br>
> > CRIU@openvz.org<br>
> > https://lists.openvz.org/mailman/listinfo/criu<br>
> > .<br>
> > <br>
><br>
</p>
</body>
</html>